2020-12-21 13:16:29 -03:00
|
|
|
#include "framework.h"
|
2021-12-22 16:23:57 +03:00
|
|
|
#include "Game/items.h"
|
2021-12-24 03:32:19 +03:00
|
|
|
|
2021-12-22 16:23:57 +03:00
|
|
|
#include "Game/control/control.h"
|
|
|
|
#include "Game/collision/floordata.h"
|
|
|
|
#include "Game/effects/effects.h"
|
2021-12-24 03:32:19 +03:00
|
|
|
#include "Game/Lara/lara.h"
|
|
|
|
#include "Specific/setup.h"
|
|
|
|
#include "Specific/level.h"
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-09-17 15:32:55 +03:00
|
|
|
using namespace TEN::Floordata;
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
void ClearItem(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2022-02-09 16:55:46 +11:00
|
|
|
ROOM_INFO* room = &g_Level.Rooms[item->RoomNumber];
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Collidable = true;
|
|
|
|
item->Data = nullptr;
|
|
|
|
item->StartPosition = item->Position;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void KillItem(short itemNum)
|
|
|
|
{
|
|
|
|
if (InItemControlLoop)
|
|
|
|
{
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo] = itemNum | 0x8000;
|
|
|
|
ItemNewRoomNo++;
|
|
|
|
}
|
2021-05-26 01:58:30 -05:00
|
|
|
else// if (NextItemActive != NO_ITEM)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
|
|
|
|
DetatchSpark(itemNum, SP_ITEM);
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Active = false;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (NextItemActive == itemNum)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
NextItemActive = item->NextActive;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
short linknum;
|
2022-02-09 16:55:46 +11:00
|
|
|
for (linknum = NextItemActive; linknum != NO_ITEM; linknum = g_Level.Items[linknum].NextActive)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[linknum].NextActive == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[linknum].NextActive = item->NextActive;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->RoomNumber != NO_ROOM)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Rooms[item->RoomNumber].itemNumber == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
short linknum;
|
2022-02-09 16:55:46 +11:00
|
|
|
for (linknum = g_Level.Rooms[item->RoomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].NextItem)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[linknum].NextItem == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[linknum].NextItem = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item == Lara.target)
|
|
|
|
Lara.target = NULL;
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (Objects[item->ObjectNumber].floor != nullptr)
|
2021-11-23 01:31:09 +03:00
|
|
|
UpdateBridgeItem(itemNum, true);
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
if (itemNum >= g_Level.NumItems)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->NextItem = NextItemFree;
|
2020-12-21 13:16:29 -03:00
|
|
|
NextItemFree = itemNum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Flags |= IFLAG_KILLED;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveAllItemsInRoom(short roomNumber, short objectNumber)
|
|
|
|
{
|
|
|
|
ROOM_INFO* room = &g_Level.Rooms[roomNumber];
|
|
|
|
short currentItemNum = room->itemNumber;
|
|
|
|
|
|
|
|
while (currentItemNum != NO_ITEM)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[currentItemNum];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->ObjectNumber == objectNumber)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
RemoveActiveItem(currentItemNum);
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Status = ITEM_NOT_ACTIVE;
|
|
|
|
item->Flags &= 0xC1;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
currentItemNum = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddActiveItem(short itemNumber)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Flags |= 0x20;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (Objects[item->ObjectNumber].control == NULL)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Status = ITEM_NOT_ACTIVE;
|
2020-12-21 13:16:29 -03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (!item->Active)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Active = true;
|
|
|
|
item->NextActive = NextItemActive;
|
2020-12-21 13:16:29 -03:00
|
|
|
NextItemActive = itemNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ItemNewRoom(short itemNumber, short roomNumber)
|
|
|
|
{
|
|
|
|
if (InItemControlLoop)
|
|
|
|
{
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo] = itemNumber;
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo + 1] = roomNumber;
|
|
|
|
ItemNewRoomNo++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->RoomNumber != NO_ROOM)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
ROOM_INFO* r = &g_Level.Rooms[item->RoomNumber];
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (r->itemNumber == itemNumber)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
r->itemNumber = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
for (short linknum = r->itemNumber; linknum != -1; linknum = g_Level.Items[linknum].NextItem)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[linknum].NextItem == itemNumber)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[linknum].NextItem = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->RoomNumber = roomNumber;
|
|
|
|
item->NextItem = g_Level.Rooms[roomNumber].itemNumber;
|
2020-12-21 13:16:29 -03:00
|
|
|
g_Level.Rooms[roomNumber].itemNumber = itemNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EffectNewRoom(short fxNumber, short roomNumber)
|
|
|
|
{
|
|
|
|
if (InItemControlLoop)
|
|
|
|
{
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo] = fxNumber;
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo + 1] = roomNumber;
|
|
|
|
ItemNewRoomNo++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FX_INFO* fx = &EffectList[fxNumber];
|
|
|
|
ROOM_INFO* r = &g_Level.Rooms[fx->roomNumber];
|
|
|
|
|
|
|
|
if (r->fxNumber == fxNumber)
|
|
|
|
{
|
|
|
|
r->fxNumber = fx->nextFx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
short linknum;
|
|
|
|
for (linknum = r->fxNumber; linknum != -1; linknum = EffectList[linknum].nextFx)
|
|
|
|
{
|
|
|
|
if (EffectList[linknum].nextFx == fxNumber)
|
|
|
|
{
|
|
|
|
EffectList[linknum].nextFx = fx->nextFx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fx->roomNumber = roomNumber;
|
|
|
|
fx->nextFx = g_Level.Rooms[roomNumber].fxNumber;
|
|
|
|
g_Level.Rooms[roomNumber].fxNumber = fxNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KillEffect(short fxNumber)
|
|
|
|
{
|
|
|
|
if (InItemControlLoop)
|
|
|
|
{
|
|
|
|
ItemNewRooms[2 * ItemNewRoomNo] = fxNumber | 0x8000;
|
|
|
|
ItemNewRoomNo++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FX_INFO* fx = &EffectList[fxNumber];
|
|
|
|
DetatchSpark(fxNumber, SP_FX);
|
|
|
|
|
|
|
|
if (NextFxActive == fxNumber)
|
|
|
|
{
|
|
|
|
NextFxActive = fx->nextActive;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (short linknum = NextFxActive; linknum != NO_ITEM; linknum = EffectList[linknum].nextActive)
|
|
|
|
{
|
|
|
|
if (EffectList[linknum].nextActive == fxNumber)
|
|
|
|
{
|
|
|
|
EffectList[linknum].nextActive = fx->nextActive;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_Level.Rooms[fx->roomNumber].fxNumber == fxNumber)
|
|
|
|
{
|
|
|
|
g_Level.Rooms[fx->roomNumber].fxNumber = fx->nextFx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (short linknum = g_Level.Rooms[fx->roomNumber].fxNumber; linknum != NO_ITEM; linknum = EffectList[linknum].nextFx)
|
|
|
|
{
|
|
|
|
if (EffectList[linknum].nextFx == fxNumber)
|
|
|
|
{
|
|
|
|
EffectList[linknum].nextFx = fx->nextFx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fx->nextFx = NextFxFree;
|
|
|
|
NextFxFree = fxNumber;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
short CreateNewEffect(short roomNum)
|
|
|
|
{
|
|
|
|
short fxNumber = NextFxFree;
|
|
|
|
|
|
|
|
if (NextFxFree != NO_ITEM)
|
|
|
|
{
|
|
|
|
FX_INFO* fx = &EffectList[NextFxFree];
|
|
|
|
NextFxFree = fx->nextFx;
|
|
|
|
ROOM_INFO* r = &g_Level.Rooms[roomNum];
|
|
|
|
fx->roomNumber = roomNum;
|
|
|
|
fx->nextFx = r->fxNumber;
|
|
|
|
r->fxNumber = fxNumber;
|
|
|
|
fx->nextActive = NextFxActive;
|
|
|
|
NextFxActive = fxNumber;
|
|
|
|
fx->shade = GRAY555;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fxNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitialiseFXArray(int allocmem)
|
|
|
|
{
|
|
|
|
|
|
|
|
FX_INFO* fx;
|
|
|
|
|
|
|
|
NextFxActive = NO_ITEM;
|
|
|
|
NextFxFree = 0;
|
|
|
|
for (int i = 0; i < NUM_EFFECTS; i++)
|
|
|
|
{
|
|
|
|
fx = &EffectList[i];
|
|
|
|
fx->nextFx = i + 1;
|
|
|
|
}
|
|
|
|
EffectList[NUM_EFFECTS - 1].nextFx = NO_ITEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveDrawnItem(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Rooms[item->RoomNumber].itemNumber == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
for (short linknum = g_Level.Rooms[item->RoomNumber].itemNumber; linknum != NO_ITEM; linknum = g_Level.Items[linknum].NextItem)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[linknum].NextItem == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[linknum].NextItem = item->NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveActiveItem(short itemNum)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[itemNum].Active)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[itemNum].Active = false;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (NextItemActive == itemNum)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
NextItemActive = g_Level.Items[itemNum].NextActive;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
for (short linknum = NextItemActive; linknum != NO_ITEM; linknum = g_Level.Items[linknum].NextActive)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[linknum].NextActive == itemNum)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[linknum].NextActive = g_Level.Items[itemNum].NextActive;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitialiseItem(short itemNum)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->AnimNumber = Objects[item->ObjectNumber].animIndex;
|
|
|
|
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->RequiredState = 0;
|
|
|
|
item->TargetState = g_Level.Anims[item->AnimNumber].ActiveState;
|
|
|
|
item->ActiveState = g_Level.Anims[item->AnimNumber].ActiveState;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Position.zRot = 0;
|
|
|
|
item->Position.xRot = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 13:20:57 +11:00
|
|
|
item->VerticalVelocity = 0;
|
|
|
|
item->Velocity = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->ItemFlags[3] = 0;
|
|
|
|
item->ItemFlags[2] = 0;
|
|
|
|
item->ItemFlags[1] = 0;
|
|
|
|
item->ItemFlags[0] = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Active = false;
|
|
|
|
item->Status = ITEM_NOT_ACTIVE;
|
2022-02-09 13:20:57 +11:00
|
|
|
item->Airborne = false;
|
2022-02-09 16:55:46 +11:00
|
|
|
item->HitStatus = false;
|
|
|
|
item->Collidable = true;
|
|
|
|
item->LookedAt = false;
|
|
|
|
item->Poisoned = false;
|
|
|
|
item->AIBits = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Timer = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->HitPoints = Objects[item->ObjectNumber].HitPoints;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->ObjectNumber == ID_HK_ITEM ||
|
|
|
|
item->ObjectNumber == ID_HK_AMMO_ITEM ||
|
|
|
|
item->ObjectNumber == ID_CROSSBOW_ITEM ||
|
|
|
|
item->ObjectNumber == ID_REVOLVER_ITEM)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->MeshBits = 1;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->MeshBits = -1;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->TouchBits = 0;
|
|
|
|
item->AfterDeath = 0;
|
|
|
|
item->FiredWeapon = 0;
|
|
|
|
item->SwapMeshFlags = 0;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->Flags & IFLAG_INVISIBLE)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Flags &= ~IFLAG_INVISIBLE;
|
|
|
|
item->Status = ITEM_INVISIBLE;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
2022-02-09 16:55:46 +11:00
|
|
|
else if (Objects[item->ObjectNumber].intelligent)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Status = ITEM_INVISIBLE;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if ((item->Flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Flags &= ~IFLAG_ACTIVATION_MASK;
|
|
|
|
item->Flags |= IFLAG_REVERSE;
|
2020-12-21 13:16:29 -03:00
|
|
|
AddActiveItem(itemNum);
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Status = ITEM_ACTIVE;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
ROOM_INFO* r = &g_Level.Rooms[item->RoomNumber];
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->NextItem = r->itemNumber;
|
2020-12-21 13:16:29 -03:00
|
|
|
r->itemNumber = itemNum;
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
FLOOR_INFO* floor = GetSector(r, item->Position.xPos - r->x, item->Position.zPos - r->z);
|
|
|
|
item->Floor = floor->FloorHeight(item->Position.xPos, item->Position.zPos);
|
|
|
|
item->BoxNumber = floor->Box;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (Objects[item->ObjectNumber].nmeshes > 0)
|
2021-12-18 23:08:09 +03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Mutator.resize(Objects[item->ObjectNumber].nmeshes);
|
|
|
|
for (int i = 0; i < item->Mutator.size(); i++)
|
|
|
|
item->Mutator[i] = {};
|
2021-12-18 23:08:09 +03:00
|
|
|
}
|
|
|
|
else
|
2022-02-09 16:55:46 +11:00
|
|
|
item->Mutator.clear();
|
2021-09-24 13:50:31 +03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (Objects[item->ObjectNumber].initialise != NULL)
|
|
|
|
Objects[item->ObjectNumber].initialise(itemNum);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
short CreateItem()
|
|
|
|
{
|
|
|
|
short itemNum = 0;
|
|
|
|
|
|
|
|
if (NextItemFree == -1) return NO_ITEM;
|
|
|
|
|
|
|
|
itemNum = NextItemFree;
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[NextItemFree].Flags = 0;
|
|
|
|
g_Level.Items[NextItemFree].LuaName = "";
|
|
|
|
NextItemFree = g_Level.Items[NextItemFree].NextItem;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
return itemNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitialiseItemArray(int numitems)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[g_Level.NumItems];
|
|
|
|
|
|
|
|
NextItemActive = NO_ITEM;
|
|
|
|
NextItemFree = g_Level.NumItems;
|
|
|
|
|
|
|
|
if (g_Level.NumItems + 1 < numitems)
|
|
|
|
{
|
|
|
|
for (int i = g_Level.NumItems + 1; i < numitems; i++, item++)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
item->NextItem = i;
|
|
|
|
item->Active = false;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
item->NextItem = NO_ITEM;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-07-11 16:55:20 +01:00
|
|
|
short SpawnItem(ITEM_INFO* item, GAME_OBJECT_ID objectNumber)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
short itemNumber = CreateItem();
|
|
|
|
if (itemNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
ITEM_INFO* spawn = &g_Level.Items[itemNumber];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
spawn->ObjectNumber = objectNumber;
|
|
|
|
spawn->RoomNumber = item->RoomNumber;
|
|
|
|
memcpy(&spawn->Position, &item->Position, sizeof(PHD_3DPOS));
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
InitialiseItem(itemNumber);
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
spawn->Status = ITEM_NOT_ACTIVE;
|
|
|
|
spawn->Shade = 0x4210;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return itemNumber;
|
|
|
|
}
|
|
|
|
|
2021-07-11 16:55:20 +01:00
|
|
|
int GlobalItemReplace(short search, GAME_OBJECT_ID replace)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
int changed = 0;
|
|
|
|
for (int i = 0; i < g_Level.Rooms.size(); i++)
|
|
|
|
{
|
|
|
|
ROOM_INFO* room = &g_Level.Rooms[i];
|
2022-02-09 16:55:46 +11:00
|
|
|
for (short itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].NextItem)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[itemNumber].ObjectNumber == search)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
g_Level.Items[itemNumber].ObjectNumber = replace;
|
2020-12-21 13:16:29 -03:00
|
|
|
changed++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2022-02-02 18:28:23 +11:00
|
|
|
// Offset values are used to account for the fact that room traversal can ONLY occur at portals.
|
|
|
|
// TODO: There is one edge case offsets don't fix. @Sezz 2022.02.02
|
|
|
|
void UpdateItemRoom(ITEM_INFO* item, int height, int xOffset, int zOffset)
|
2021-09-17 15:32:55 +03:00
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
float c = phd_cos(item->Position.yRot);
|
|
|
|
float s = phd_sin(item->Position.yRot);
|
2022-02-02 18:28:23 +11:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
int x = item->Position.xPos + roundf(c * xOffset + s * zOffset);
|
|
|
|
int y = height + item->Position.yPos;
|
|
|
|
int z = item->Position.zPos + roundf(-s * xOffset + c * zOffset);
|
|
|
|
item->Location = GetRoom(item->Location, x, y, z);
|
|
|
|
item->Floor = GetFloorHeight(item->Location, x, z).value_or(NO_HEIGHT);
|
2021-09-17 15:32:55 +03:00
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->RoomNumber != item->Location.roomNumber)
|
|
|
|
ItemNewRoom(FindItem(item), item->Location.roomNumber);
|
2021-09-17 15:32:55 +03:00
|
|
|
}
|
|
|
|
|
2021-09-15 14:24:03 +03:00
|
|
|
std::vector<int> FindAllItems(short objectNumber)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-02-07 17:12:41 -03:00
|
|
|
std::vector<int> itemList;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
for (int i = 0; i < g_Level.NumItems; i++)
|
|
|
|
{
|
2022-02-09 16:55:46 +11:00
|
|
|
if (g_Level.Items[i].ObjectNumber == objectNumber)
|
2021-02-07 17:12:41 -03:00
|
|
|
itemList.push_back(i);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
2021-02-07 17:12:41 -03:00
|
|
|
return itemList;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
2021-06-09 22:48:18 -05:00
|
|
|
|
2021-09-15 14:24:03 +03:00
|
|
|
ITEM_INFO* FindItem(int object_number)
|
2021-06-09 22:48:18 -05:00
|
|
|
{
|
|
|
|
ITEM_INFO* item;
|
|
|
|
|
|
|
|
for (int i = 0; i < g_Level.NumItems; i++)
|
|
|
|
{
|
|
|
|
item = &g_Level.Items[i];
|
|
|
|
|
2022-02-09 16:55:46 +11:00
|
|
|
if (item->ObjectNumber == object_number)
|
2021-06-09 22:48:18 -05:00
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-17 15:32:55 +03:00
|
|
|
|
|
|
|
int FindItem(ITEM_INFO* item)
|
|
|
|
{
|
|
|
|
if (item == LaraItem)
|
2022-02-12 16:25:59 +11:00
|
|
|
return Lara.ItemNumber;
|
2021-09-17 15:32:55 +03:00
|
|
|
|
|
|
|
for (int i = 0; i < g_Level.NumItems; i++)
|
|
|
|
if (item == &g_Level.Items[i])
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|