Enable mass pickup (#859)

* Enable mass pickup
* Update Changes.txt
* Remove getThisItemPlease
* Fix sarcophagus pickups
* Fix legacy pickup triggers not working
* Update Changes.txt
* Align pickups to surfaces
* Update pickup.cpp
* Update pickup.cpp
* Update Changes.txt
This commit is contained in:
Anatoly 2022-11-20 05:29:08 +02:00 committed by GitHub
parent 847b162e0a
commit 697aea87eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 121 additions and 54 deletions

View file

@ -1,6 +1,9 @@
Version 1.0.4
=============
* Add Flow.EnableMassPickup option in Gameflow.lua to enable/disable mass pickup.
* Automatically align pickups to floor surface.
* Fix legacy pickup triggers not working.
* Fix lasersight always displaying with revolver and crossbow.
* Fix incorrect string IDs for item combine, HK and revolver with lasersight.

View file

@ -20,6 +20,10 @@ Flow.SetTotalSecretCount(5)
Flow.EnableFlyCheat(true)
-- Disable/enable mass pickup (collect all pickups at once)
Flow.EnableMassPickup(true)
--------------------------------------------------
-- Title level

View file

@ -179,21 +179,22 @@ int KeyTrigger(short itemNum)
return oldkey;
}
int PickupTrigger(short itemNum)
bool PickupTrigger(short itemNum)
{
ItemInfo* item = &g_Level.Items[itemNum];
if (item->Flags & IFLAG_KILLED
|| (item->Status != ITEM_INVISIBLE
|| item->ItemFlags[3] != 1
|| item->TriggerFlags & 0x80))
if (((item->Flags & IFLAG_CLEAR_BODY) && (item->Flags & IFLAG_KILLED)) ||
item->Status != ITEM_INVISIBLE ||
item->ItemFlags[3] != 1 ||
item->TriggerFlags & 0x80)
{
return 0;
return false;
}
KillItem(itemNum);
item->Flags |= IFLAG_CLEAR_BODY;
return 1;
return true;
}
void RefreshCamera(short type, short* data)

View file

@ -64,7 +64,7 @@ bool GetKeyTrigger(ItemInfo* item);
int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch);
int SwitchTrigger(short itemNumber, short timer);
int KeyTrigger(short itemNum);
int PickupTrigger(short itemNum);
bool PickupTrigger(short itemNum);
void RefreshCamera(short type, short* data);
int TriggerActive(ItemInfo* item);
short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z);

View file

@ -28,6 +28,7 @@
#include "Specific/level.h"
#include "Math/Math.h"
#include "Specific/setup.h"
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
using namespace TEN::Entities::Generic;
using namespace TEN::Input;
@ -141,7 +142,6 @@ const ObjectCollisionBounds MSBounds =
int NumRPickups;
short RPickups[16];
short getThisItemPlease = NO_ITEM;
Vector3i OldPickupPos;
bool SetInventoryCount(GAME_OBJECT_ID objectID, int count)
@ -224,15 +224,59 @@ void CollectCarriedItems(ItemInfo* item)
item->CarriedItem = NO_ITEM;
}
void CollectMultiplePickups(int itemNumber)
{
auto* firstItem = &g_Level.Items[itemNumber];
GetCollidedObjects(firstItem, LARA_RADIUS, true, CollidedItems, CollidedMeshes, true);
for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++)
{
auto* currentItem = CollidedItems[i];
if (!currentItem)
currentItem = firstItem;
if (!Objects[currentItem->ObjectNumber].isPickup)
continue;
AddDisplayPickup(currentItem->ObjectNumber);
if (currentItem->TriggerFlags & 0x100)
{
for (int i = 0; i < g_Level.NumItems; i++)
{
if (g_Level.Items[i].ObjectNumber == currentItem->ObjectNumber)
KillItem(i);
}
}
if (currentItem->TriggerFlags & 0xC0)
{
currentItem->Status = ITEM_INVISIBLE;
currentItem->Flags |= TRIGGERED;
currentItem->ItemFlags[3] = 1;
}
//currentItem->Pose.Orientation = prevOrient;
KillItem(currentItem->Index);
if (currentItem == firstItem)
break;
}
}
void DoPickup(ItemInfo* laraItem)
{
if (getThisItemPlease == NO_ITEM)
auto* lara = GetLaraInfo(laraItem);
if (lara->InteractedItem == NO_ITEM)
return;
auto* lara = GetLaraInfo(laraItem);
short pickupItemNumber = getThisItemPlease;
short pickupItemNumber = lara->InteractedItem;
auto* pickupItem = &g_Level.Items[pickupItemNumber];
if (!Objects[pickupItem->ObjectNumber].isPickup)
return;
auto prevOrient = pickupItem->Pose.Orientation;
if (pickupItem->ObjectNumber == ID_BURNING_TORCH_ITEM)
@ -243,7 +287,7 @@ void DoPickup(ItemInfo* laraItem)
KillItem(pickupItemNumber);
pickupItem->Pose.Orientation = prevOrient;
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
return;
}
else if (pickupItem->ObjectNumber == ID_FLARE_ITEM)
@ -259,7 +303,7 @@ void DoPickup(ItemInfo* laraItem)
KillItem(pickupItemNumber);
pickupItem->Pose.Orientation = prevOrient;
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
return;
}
else if (laraItem->Animation.ActiveState == LS_PICKUP_FLARE)
@ -270,7 +314,7 @@ void DoPickup(ItemInfo* laraItem)
lara->Control.HandStatus = HandStatus::Special;
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
KillItem(pickupItemNumber);
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
return;
}
}
@ -289,7 +333,7 @@ void DoPickup(ItemInfo* laraItem)
}
pickupItem->Pose.Orientation = prevOrient;
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
return;
}
else
@ -301,9 +345,16 @@ void DoPickup(ItemInfo* laraItem)
KillItem(pickupItemNumber);
}
else if (laraItem->Animation.ActiveState == LS_PICKUP ||
laraItem->Animation.ActiveState == LS_PICKUP_FROM_CHEST ||
laraItem->Animation.ActiveState == LS_HOLE)
laraItem->Animation.ActiveState == LS_PICKUP_FROM_CHEST ||
laraItem->Animation.ActiveState == LS_HOLE)
{
if (g_GameFlow->IsMassPickupEnabled())
{
CollectMultiplePickups(lara->InteractedItem);
lara->InteractedItem = NO_ITEM;
return;
}
AddDisplayPickup(pickupItem->ObjectNumber);
if (pickupItem->TriggerFlags & 0x100)
{
@ -323,13 +374,13 @@ void DoPickup(ItemInfo* laraItem)
pickupItem->Pose.Orientation = prevOrient;
KillItem(pickupItemNumber);
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
return;
}
}
}
getThisItemPlease = NO_ITEM;
lara->InteractedItem = NO_ITEM;
}
void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
@ -372,14 +423,12 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
{
if (item->ObjectNumber == ID_FLARE_ITEM)
{
getThisItemPlease = itemNumber;
laraItem->Animation.AnimNumber = LA_UNDERWATER_PICKUP_FLARE;
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
laraItem->Animation.Velocity.y = 0;
}
else
{
getThisItemPlease = itemNumber;
laraItem->Animation.AnimNumber = LA_UNDERWATER_PICKUP;
laraItem->Animation.ActiveState = LS_PICKUP;
}
@ -398,7 +447,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
{
if (lara->InteractedItem == itemNumber)
{
getThisItemPlease = itemNumber;
lara->Control.IsMoving = false;
lara->Control.HandStatus = HandStatus::Free;
}
@ -468,7 +516,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
}
else if (MoveLaraPosition(HiddenPickUpPosition, item, laraItem))
{
getThisItemPlease = itemNumber;
laraItem->Animation.AnimNumber = LA_HOLESWITCH_ACTIVATE;
laraItem->Animation.ActiveState = LS_HOLE;
flag = true;
@ -517,9 +564,9 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
g_Gui.SetInventoryItemChosen(NO_ITEM);
}
if (MoveLaraPosition(CrowbarPickUpPosition, item, laraItem))
{
getThisItemPlease = itemNumber;
laraItem->Animation.AnimNumber = LA_CROWBAR_PRY_WALL_FAST;
laraItem->Animation.ActiveState = LS_PICKUP;
item->Status = ITEM_ACTIVE;
@ -565,12 +612,10 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
{
if (triggerFlags == 3 || triggerFlags == 7)
{
getThisItemPlease = itemNumber;
SetAnimation(laraItem, LA_PICKUP_PEDESTAL_HIGH);
}
else
{
getThisItemPlease = itemNumber;
SetAnimation(laraItem, LA_PICKUP_PEDESTAL_LOW);
}
@ -608,7 +653,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
if (MoveLaraPosition(JobyCrowPickUpPosition, item, laraItem))
{
getThisItemPlease = itemNumber;
SetAnimation(laraItem, LA_CROWBAR_PRY_WALL_SLOW);
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNumber);
@ -650,7 +694,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
if (item->ObjectNumber == ID_FLARE_ITEM)
{
getThisItemPlease = itemNumber;
laraItem->Animation.AnimNumber = LA_CROUCH_PICKUP_FLARE;
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
lara->InteractedItem = itemNumber;
@ -658,7 +701,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
break;
}
getThisItemPlease = itemNumber;
laraItem->Animation.TargetState = LS_PICKUP;
}
else
@ -678,7 +720,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
}
else
{
getThisItemPlease = itemNumber;
laraItem->Animation.TargetState = LS_PICKUP;
}
@ -692,8 +733,6 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
break;
}
getThisItemPlease = itemNumber;
if (item->ObjectNumber == ID_FLARE_ITEM)
{
laraItem->Animation.AnimNumber = LA_PICKUP;
@ -906,8 +945,22 @@ void InitialisePickup(short itemNumber)
}
else
{
if (triggerFlags == 0 || triggerFlags == 3 || triggerFlags == 4 || triggerFlags == 7 || triggerFlags == 8 || triggerFlags == 11)
if (triggerFlags == 0 ||
triggerFlags == 3 ||
triggerFlags == 4 ||
triggerFlags == 7 ||
triggerFlags == 8 ||
triggerFlags == 11)
{
if (triggerFlags == 0)
{
auto coll = GetCollision(item);
item->Pose.Position.y = coll.Position.Floor;
AlignEntityToSurface(item, Vector2(Objects[item->ObjectNumber].radius));
}
item->Pose.Position.y -= bounds.Y2;
}
if ((item->TriggerFlags & 0x80) != 0)
{

View file

@ -18,6 +18,7 @@ int GetInventoryCount(GAME_OBJECT_ID objectID);
void CollectCarriedItems(ItemInfo* item);
void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void RegeneratePickups();
void CollectMultiplePickups(int itemNumber);
GameBoundingBox* FindPlinth(ItemInfo* item);
void PickupControl(short itemNumber);

View file

@ -67,29 +67,12 @@ void SarcophagusCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* c
}
}
else if (laraItem->Animation.AnimNumber != LA_PICKUP_SARCOPHAGUS ||
laraItem->Animation.FrameNumber != g_Level.Anims[LA_PICKUP_SARCOPHAGUS].frameBase + 113)
laraItem->Animation.FrameNumber != g_Level.Anims[LA_PICKUP_SARCOPHAGUS].frameBase + 113)
{
ObjectCollision(itemNumber, laraItem, coll);
}
else
{
short linkNumber;
for (linkNumber = g_Level.Items[g_Level.Rooms[sarcItem->RoomNumber].itemNumber].NextItem; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem)
{
auto* currentItem = &g_Level.Items[linkNumber];
if (linkNumber != itemNumber &&
currentItem->Pose.Position.x == sarcItem->Pose.Position.x &&
currentItem->Pose.Position.z == sarcItem->Pose.Position.z)
{
if (Objects[currentItem->ObjectNumber].isPickup)
{
PickedUpObject(currentItem->ObjectNumber);
currentItem->Status = ITEM_INVISIBLE;
currentItem->ItemFlags[3] = 1;
AddDisplayPickup(currentItem->ObjectNumber);
}
}
}
CollectMultiplePickups(sarcItem->Index);
}
}

View file

@ -25,6 +25,7 @@ public:
virtual int GetNumLevels() const = 0;
virtual char const* GetString(const char* id) const = 0;
virtual bool IsFlyCheatEnabled() const = 0;
virtual bool IsMassPickupEnabled() const = 0;
virtual bool HasCrawlExtended() const = 0;
virtual bool HasCrouchRoll() const = 0;
virtual bool HasCrawlspaceDive() const = 0;

View file

@ -125,6 +125,7 @@ static constexpr char ScriptReserved_SetSecretCount[] = "SetSecretCount";
static constexpr char ScriptReserved_SetTotalSecretCount[] = "SetTotalSecretCount";
static constexpr char ScriptReserved_AddSecret[] = "AddSecret";
static constexpr char ScriptReserved_EnableFlyCheat[] = "EnableFlyCheat";
static constexpr char ScriptReserved_EnableMassPickup[] = "EnableMassPickup";
// Flow Functions
static constexpr char ScriptReserved_SetStrings[] = "SetStrings";

View file

@ -120,6 +120,13 @@ Must be true or false
*/
table_flow.set_function(ScriptReserved_EnableFlyCheat, &FlowHandler::EnableFlyCheat, this);
/*** Enable or disable mass pickup.
Must be true or false
@function EnableMassPickup
@tparam bool true or false
*/
table_flow.set_function(ScriptReserved_EnableMassPickup, &FlowHandler::EnableMassPickup, this);
/*** settings.lua.
These functions are called in settings.lua, a file which holds your local settings.
settings.lua shouldn't be bundled with any finished levels/games.
@ -333,6 +340,16 @@ void FlowHandler::EnableFlyCheat(bool flyCheat)
FlyCheat = flyCheat;
}
bool FlowHandler::IsMassPickupEnabled() const
{
return MassPickup;
}
void FlowHandler::EnableMassPickup(bool massPickup)
{
MassPickup = massPickup;
}
bool FlowHandler::DoFlow()
{
// We start with the title level, if no other index is specified

View file

@ -26,6 +26,7 @@ public:
int FogOutDistance{ 0 };
bool PlayAnyLevel{ true };
bool FlyCheat{ true };
bool MassPickup{ true };
bool DebugMode{ false };
// New animation flag table
@ -39,7 +40,7 @@ public:
void AddLevel(Level const& level);
void LoadFlowScript();
char const * GetString(const char* id) const;
char const* GetString(const char* id) const;
void SetStrings(sol::nested<std::unordered_map<std::string, std::vector<std::string>>> && src);
void SetLanguageNames(sol::as_table_t<std::vector<std::string>> && src);
void SetAnimations(Animations const & src);
@ -58,6 +59,8 @@ public:
void SetTotalSecretCount(int secretsNumber);
bool IsFlyCheatEnabled() const;
void EnableFlyCheat(bool flyCheat);
bool IsMassPickupEnabled() const;
void EnableMassPickup(bool massPickup);
bool CanPlayAnyLevel() const;
bool HasCrawlExtended() const override { return Anims.HasCrawlExtended; }