TombEngine/TR5Main/Objects/TR5/tr5_traps.cpp
2020-01-07 17:32:49 +01:00

359 lines
No EOL
7.9 KiB
C++

#include "../newobjects.h"
#include "../oldobjects.h"
#include "../../Game/lara.h"
#include "../../Game/draw.h"
#include "../../Global/global.h"
#include "../../Game/items.h"
#include "../../Game/collide.h"
#include "../../Game/effects.h"
#include "../../Game/laramisc.h"
#include "../../Game/Box.h"
#include "../../Game/tomb4fx.h"
#include "../../Game/switch.h"
#include "../../Game/spotcam.h"
short SPyoffs[8] =
{
0xFC00, 0x0000, 0xFE00, 0x0000, 0x0000, 0x0000, 0xFE00, 0x0000
};
short SPxzoffs[8] =
{
0x0000, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0xFE00, 0x0000
};
short SPDETyoffs[8] =
{
0x0400, 0x0200, 0x0200, 0x0200, 0x0000, 0x0200, 0x0200, 0x0200
};
void InitialiseTeethSpikes(short itemNumber)
{
short rotations[] = { -ANGLE(180), -ANGLE(135), -ANGLE(90), -ANGLE(45), ANGLE(0), ANGLE(45), ANGLE(90), ANGLE(135) };
ITEM_INFO* item = &Items[itemNumber];
item->status = ITEM_INVISIBLE;
int angle;
if (item->triggerFlags & 8)
{
angle = item->triggerFlags & 7;
item->pos.xRot = rotations[angle];
item->pos.yRot = ANGLE(90);
item->pos.zPos -= SPxzoffs[angle];
}
else
{
angle = item->triggerFlags & 7;
item->pos.zRot = rotations[angle];
item->pos.xPos += SPxzoffs[angle];
}
item->itemFlags[0] = 1024;
item->itemFlags[2] = 0;
item->pos.yPos += SPyoffs[angle];
}
int CollidedWithTeethSpikes(ITEM_INFO* item)
{
short angle;
int x;
int z;
if (item->triggerFlags & 8)
{
angle = item->triggerFlags & 7;
x = item->pos.xPos & 0xFFFFFE00 | 0x200;
z = (item->pos.zPos + SPxzoffs[angle]) & 0xFFFFFE00 | 0x200;
}
else
{
angle = item->triggerFlags & 7;
x = (item->pos.xPos - SPxzoffs[angle]) & 0xFFFFFE00 | 0x200;
z = item->pos.zPos & 0xFFFFFE00 | 0x200;
}
int delta = -((angle & 1) != 0);
delta = delta & 0xFF4C;
delta += 480;
int y = item->pos.yPos + SPDETyoffs[angle];
short* frames = GetBestFrame(LaraItem);
if (LaraItem->pos.yPos + frames[2] <= y && LaraItem->pos.yPos + frames[3] >= y - 900)
{
if (LaraItem->pos.xPos + frames[0] <= (x + delta) && LaraItem->pos.xPos + frames[1] >= (x - delta))
{
if (LaraItem->pos.zPos + frames[4] <= (z + delta) && LaraItem->pos.zPos + frames[5] >= (z - delta))
return 1;
}
}
return 0;
}
void ControlTeethSpikes(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
if (!TriggerActive(item) || item->itemFlags[2])
{
if (TriggerActive(item))
{
item->itemFlags[1] -= item->itemFlags[0];
item->itemFlags[0] += (item->itemFlags[0] >> 3) + 32;
if (item->itemFlags[1] < 0)
{
item->itemFlags[0] = 1024;
item->itemFlags[1] = 0;
item->status = ITEM_INVISIBLE;
}
if (item->triggerFlags & 0x20)
{
item->itemFlags[2] = 1;
}
else
{
if (item->itemFlags[2])
{
item->itemFlags[2]--;
}
}
}
else if (!item->timer)
{
item->itemFlags[0] += (item->itemFlags[0] >> 3) + 32;
if (item->itemFlags[1] > 0)
{
item->itemFlags[1] -= item->itemFlags[0];
if (item->itemFlags[1] < 0)
item->itemFlags[1] = 0;
}
}
}
else
{
if (item->itemFlags[0] == 1024)
SoundEffect(SFX_TEETH_SPIKES, &item->pos, 0);
item->status = ITEM_ACTIVE;
if (LaraItem->hitPoints > 0 && CollidedWithTeethSpikes(item))
{
short* itemFrames = GetBestFrame(item);
short* laraFrames = GetBestFrame(LaraItem);
short angle = item->triggerFlags & 7;
int numBloods = 0;
if ((item->itemFlags[0] > 1024 || LaraItem->gravityStatus) && angle > 2 && angle < 6)
{
if (LaraItem->fallspeed > 6 || item->itemFlags[0] > 1024)
{
LaraItem->hitPoints = -1;
numBloods = 20;
}
}
else if (LaraItem->speed < 30)
{
numBloods = 0;
}
else
{
LaraItem->hitPoints -= 8;
numBloods = (GetRandomControl() & 3) + 2;
}
int laraY1 = LaraItem->pos.yPos + laraFrames[2];
int laraY2 = LaraItem->pos.yPos + laraFrames[3];
short triggerFlags = item->triggerFlags & 0xF;
int itemY1;
int itemY2;
if (triggerFlags != 8 && triggerFlags)
{
itemY1 = itemFrames[2];
itemY2 = itemFrames[3];
}
else
{
itemY1 = -itemFrames[3];
itemY2 = -itemFrames[2];
}
if (laraY1 < item->pos.yPos + itemY1)
laraY1 = itemY1 + item->pos.yPos;
if (laraY2 > item->pos.yPos + itemY2)
laraY2 = itemY2 + item->pos.yPos;
long dy = laraY1 - laraY2;
int modulus = (HIDWORD(dy) ^ dy) - HIDWORD(dy) + 1;
angle = item->triggerFlags & 7;
if (angle == 2 || angle == 6)
numBloods /= 2;
for (int i = 0; i < numBloods; i++)
{
TriggerBlood(
(GetRandomControl() & 0x7F) + LaraItem->pos.xPos - 64,
laraY2 - GetRandomControl() % modulus,
(GetRandomControl() & 0x7F) + LaraItem->pos.zPos - 64,
2 * GetRandomControl(),
1);
}
if (LaraItem->hitPoints <= 0)
{
short roomNumber = LaraItem->roomNumber;
FLOOR_INFO* floor = GetFloor(LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos, &roomNumber);
int height = GetFloorHeight(floor, LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos);
if (item->pos.yPos >= LaraItem->pos.yPos && height - LaraItem->pos.yPos < 50)
{
LaraItem->animNumber = ANIMATION_LARA_SPIKED;
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase;
LaraItem->currentAnimState = STATE_LARA_DEATH;
LaraItem->goalAnimState = STATE_LARA_DEATH;
LaraItem->gravityStatus = false;
}
}
}
item->itemFlags[0] += 128;
item->itemFlags[1] += item->itemFlags[0];
if (item->itemFlags[1] >= 5120)
{
item->itemFlags[1] = 5120;
if (item->itemFlags[0] <= 1024)
{
item->itemFlags[0] = 0;
if (!(item->triggerFlags & 0x10))
{
if (LaraItem->hitPoints > 0)
item->itemFlags[2] = 64;
}
}
else
{
item->itemFlags[0] = -item->itemFlags[0] >> 1;
}
}
}
}
void InitialiseRaisingCog(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
short itemNos[32];
int numSwitchItems = GetSwitchTrigger(item, itemNos, 1);
if (numSwitchItems > 0)
{
for (int i = 0; i < numSwitchItems; i++)
{
ITEM_INFO* currentItem = &Items[itemNos[i]];
if (currentItem->objectNumber == ID_TRIGGER_TRIGGERER)
{
item->itemFlags[1] = currentItem->roomNumber;
}
if (currentItem->objectNumber == ID_PULLEY || currentItem->objectNumber == ID_TRIGGER_TRIGGERER)
{
currentItem->itemFlags[1] = 1;
PulleyItemNumber = itemNos[i];
}
}
}
}
void RaisingCogControl(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
if (TriggerActive(item))
{
if (item->itemFlags[0] >= 3)
{
AnimateItem(item);
}
else
{
if (item->itemFlags[2] >= 256)
{
item->itemFlags[2] = 0;
item->itemFlags[0]++;
if (item->itemFlags[0] == 3)
{
short itemNos[32];
short numItems = GetSwitchTrigger(item, itemNos, 1);
if (numItems > 0)
{
for (int i = 0; i < numItems; i++)
{
ITEM_INFO* currentItem = &Items[itemNos[i]];
if (item->objectNumber == ID_PULLEY)
{
if (currentItem->roomNumber == item->itemFlags[1])
{
currentItem->itemFlags[1] = 0;
currentItem->collidable = true;
}
else
{
currentItem->itemFlags[1] = 1;
}
}
else if (item->objectNumber == ID_TRIGGER_TRIGGERER)
{
AddActiveItem(itemNos[i]);
currentItem->status = ITEM_ACTIVE;
currentItem->aiBits = (GUARD | MODIFY | AMBUSH | PATROL1 | FOLLOW);
}
}
}
}
RemoveActiveItem(itemNumber);
item->status = ITEM_INACTIVE;
item->aiBits = 0;
}
else
{
if (!item->itemFlags[2])
{
InitialiseSpotCam(item->itemFlags[2]);
UseSpotCam = 1;
}
int flags = 0;
if (item->itemFlags[2] >= 31)
{
if (item->itemFlags[2] <= 224)
flags = 31;
else
flags = 255 - item->itemFlags[2];
}
else
{
flags = item->itemFlags[2];
}
SoundEffect(SFX_BLK_PLAT_RAISE_LOW, &item->pos, (flags << 8) | 8);
item->itemFlags[2] += 2;
item->pos.yPos -= 2;
}
}
}
}