2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
2020-05-27 19:07:34 +02:00
|
|
|
#include "tr5_pushableblock.h"
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "lara.h"
|
|
|
|
#include "draw.h"
|
2020-05-30 15:55:23 +02:00
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "items.h"
|
|
|
|
#include "collide.h"
|
|
|
|
#include "effect.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "level.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "sound.h"
|
2019-12-24 08:51:54 +01:00
|
|
|
|
2020-07-25 18:02:35 +02:00
|
|
|
OBJECT_COLLISION_BOUNDS PushableBlockBounds = {
|
2019-12-27 08:25:27 +01:00
|
|
|
0x0000, 0x0000, 0xFF00, 0x0000,
|
|
|
|
0x0000, 0x0000, 0xF8E4, 0x071C,
|
|
|
|
0xEAAC, 0x1554, 0xF8E4, 0x071C
|
|
|
|
};
|
|
|
|
|
|
|
|
PHD_VECTOR PushableBlockPos = { 0, 0, 0 };
|
|
|
|
int DoPushPull = 0;
|
|
|
|
|
2019-12-24 08:51:54 +01:00
|
|
|
void ClearMovableBlockSplitters(int x, int y, int z, short roomNumber)
|
|
|
|
{
|
|
|
|
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber);
|
2020-07-21 09:56:47 +02:00
|
|
|
g_Level.Boxes[floor->box].flags &= (~BLOCKED);
|
|
|
|
short height = g_Level.Boxes[floor->box].height;
|
2019-12-24 08:51:54 +01:00
|
|
|
short baseRoomNumber = roomNumber;
|
|
|
|
|
|
|
|
floor = GetFloor(x + 1024, y, z, &roomNumber);
|
|
|
|
if (floor->box != NO_BOX)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Boxes[floor->box].height == height && (g_Level.Boxes[floor->box].flags & BLOCKABLE) && (g_Level.Boxes[floor->box].flags & BLOCKED))
|
2019-12-24 08:51:54 +01:00
|
|
|
ClearMovableBlockSplitters(x + 1024, y, z, roomNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
roomNumber = baseRoomNumber;
|
|
|
|
floor = GetFloor(x - 1024, y, z, &roomNumber);
|
|
|
|
if (floor->box != NO_BOX)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Boxes[floor->box].height == height && (g_Level.Boxes[floor->box].flags & BLOCKABLE) && (g_Level.Boxes[floor->box].flags & BLOCKED))
|
2019-12-24 08:51:54 +01:00
|
|
|
ClearMovableBlockSplitters(x - 1024, y, z, roomNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
roomNumber = baseRoomNumber;
|
|
|
|
floor = GetFloor(x, y, z + 1024, &roomNumber);
|
|
|
|
if (floor->box != NO_BOX)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Boxes[floor->box].height == height && (g_Level.Boxes[floor->box].flags & BLOCKABLE) && (g_Level.Boxes[floor->box].flags & BLOCKED))
|
2019-12-24 08:51:54 +01:00
|
|
|
ClearMovableBlockSplitters(x, y, z + 1024, roomNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
roomNumber = baseRoomNumber;
|
|
|
|
floor = GetFloor(x, y, z - 1024, &roomNumber);
|
|
|
|
if (floor->box != NO_BOX)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Boxes[floor->box].height == height && (g_Level.Boxes[floor->box].flags & BLOCKABLE) && (g_Level.Boxes[floor->box].flags & BLOCKED))
|
2019-12-24 08:51:54 +01:00
|
|
|
ClearMovableBlockSplitters(x, y, z - 1024, roomNumber);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 19:07:34 +02:00
|
|
|
void InitialisePushableBlock(short itemNum)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2020-05-27 19:07:34 +02:00
|
|
|
|
|
|
|
ClearMovableBlockSplitters(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
|
|
|
|
|
2020-11-11 15:01:45 -03:00
|
|
|
//if (item->status != ITEM_INVISIBLE && item->triggerFlags >= 64)
|
|
|
|
// AlterFloorHeight(item, -((item->triggerFlags - 64) * 256));
|
2020-05-27 19:07:34 +02:00
|
|
|
}
|
|
|
|
|
2019-12-24 08:51:54 +01:00
|
|
|
void PushableBlockControl(short itemNumber)
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
2019-12-24 08:51:54 +01:00
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = 0;
|
|
|
|
pos.y = 0;
|
|
|
|
pos.z = 0;
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
short quadrant = (unsigned short)(LaraItem->pos.yRot + ANGLE(45)) / ANGLE(90);
|
2019-12-27 08:25:27 +01:00
|
|
|
|
|
|
|
int x, z;
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
ROOM_INFO* r;
|
|
|
|
int height;
|
|
|
|
short roomNumber;
|
|
|
|
|
|
|
|
switch (LaraItem->animNumber)
|
|
|
|
{
|
2020-08-04 20:32:07 +10:00
|
|
|
case LA_PUSHABLE_PUSH:
|
2020-07-21 09:56:47 +02:00
|
|
|
if ((LaraItem->frameNumber < g_Level.Anims[LaraItem->animNumber].frameBase + 30
|
2020-09-07 20:01:28 +02:00
|
|
|
|| LaraItem->frameNumber > g_Level.Anims[LaraItem->animNumber].frameBase + 67)
|
|
|
|
&& (LaraItem->frameNumber < g_Level.Anims[LaraItem->animNumber].frameBase + 78
|
|
|
|
|| LaraItem->frameNumber > g_Level.Anims[LaraItem->animNumber].frameBase + 125)
|
|
|
|
&& (LaraItem->frameNumber < g_Level.Anims[LaraItem->animNumber].frameBase + 140
|
|
|
|
|| LaraItem->frameNumber > g_Level.Anims[LaraItem->animNumber].frameBase + 160))
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
if (DoPushPull)
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_PUSH_BLOCK_END, &item->pos, 2);
|
|
|
|
DoPushPull = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_PUSHABLE_SOUND, &item->pos, 2);
|
|
|
|
DoPushPull = 1;
|
|
|
|
}
|
|
|
|
|
2020-04-29 06:43:53 +02:00
|
|
|
GetLaraJointPosition(&pos, LM_LHAND);
|
2019-12-27 08:25:27 +01:00
|
|
|
|
|
|
|
switch (quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
z = pos.z + item->itemFlags[2] - LaraItem->itemFlags[2];
|
2020-09-07 20:01:28 +02:00
|
|
|
if (abs(item->pos.zPos - z) < 512 && item->pos.zPos < z)
|
2019-12-27 08:25:27 +01:00
|
|
|
item->pos.zPos = z;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
x = pos.x + item->itemFlags[0] - LaraItem->itemFlags[0];
|
|
|
|
if (abs(item->pos.xPos - x) < 512 && item->pos.xPos < x)
|
|
|
|
item->pos.xPos = x;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
z = pos.z + item->itemFlags[2] - LaraItem->itemFlags[2];
|
|
|
|
if (abs(item->pos.zPos - z) < 512 && item->pos.zPos > z)
|
|
|
|
item->pos.zPos = z;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
x = pos.x + item->itemFlags[0] - LaraItem->itemFlags[0];
|
|
|
|
if (abs(item->pos.xPos - x) < 512 && item->pos.xPos > x)
|
|
|
|
item->pos.xPos = x;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
if (LaraItem->frameNumber == g_Level.Anims[LaraItem->animNumber].frameEnd - 1)
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
{
|
2020-09-07 20:01:28 +02:00
|
|
|
if (!TestBlockPush(item, 1024, quadrant))
|
2020-08-04 20:32:07 +10:00
|
|
|
LaraItem->goalAnimState = LS_STOP;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-08-04 20:32:07 +10:00
|
|
|
LaraItem->goalAnimState = LS_STOP;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-08-04 20:32:07 +10:00
|
|
|
case LA_PUSHABLE_PULL:
|
2020-07-21 09:56:47 +02:00
|
|
|
if ((LaraItem->frameNumber < g_Level.Anims[LaraItem->animNumber].frameBase + 40
|
|
|
|
|| LaraItem->frameNumber > g_Level.Anims[LaraItem->animNumber].frameBase + 122)
|
|
|
|
&& (LaraItem->frameNumber < g_Level.Anims[LaraItem->animNumber].frameBase + 130
|
|
|
|
|| LaraItem->frameNumber > g_Level.Anims[LaraItem->animNumber].frameBase + 170))
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
if (DoPushPull)
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_PUSH_BLOCK_END, &item->pos, 2);
|
|
|
|
DoPushPull = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SoundEffect(SFX_PUSHABLE_SOUND, &item->pos, 2);
|
|
|
|
DoPushPull = 1;
|
|
|
|
}
|
|
|
|
|
2020-04-29 06:43:53 +02:00
|
|
|
GetLaraJointPosition(&pos, LM_LHAND);
|
2020-09-07 20:01:28 +02:00
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
switch (quadrant)
|
|
|
|
{
|
2020-11-07 18:52:33 +01:00
|
|
|
case NORTH:
|
2019-12-27 08:25:27 +01:00
|
|
|
z = pos.z + item->itemFlags[2] - LaraItem->itemFlags[2];
|
|
|
|
if (abs(item->pos.zPos - z) < 512 && item->pos.zPos > z)
|
|
|
|
item->pos.zPos = z;
|
|
|
|
break;
|
|
|
|
|
2020-11-07 18:52:33 +01:00
|
|
|
case EAST:
|
2019-12-27 08:25:27 +01:00
|
|
|
x = pos.x + item->itemFlags[0] - LaraItem->itemFlags[0];
|
|
|
|
if (abs(item->pos.xPos - x) < 512 && item->pos.xPos > x)
|
|
|
|
item->pos.xPos = x;
|
|
|
|
break;
|
|
|
|
|
2020-11-07 18:52:33 +01:00
|
|
|
case SOUTH:
|
2019-12-27 08:25:27 +01:00
|
|
|
z = pos.z + item->itemFlags[2] - LaraItem->itemFlags[2];
|
|
|
|
if (abs(item->pos.zPos - z) < 512 && item->pos.zPos < z)
|
|
|
|
item->pos.zPos = z;
|
|
|
|
break;
|
|
|
|
|
2020-11-07 18:52:33 +01:00
|
|
|
case WEST:
|
2019-12-27 08:25:27 +01:00
|
|
|
x = pos.x + item->itemFlags[0] - LaraItem->itemFlags[0];
|
|
|
|
if (abs(item->pos.xPos - x) < 512 && item->pos.xPos < x)
|
|
|
|
item->pos.xPos = x;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
if (LaraItem->frameNumber == g_Level.Anims[LaraItem->animNumber].frameEnd - 1)
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
if (TrInput & IN_ACTION)
|
|
|
|
{
|
|
|
|
if (!TestBlockPull(item, 1024, quadrant))
|
2020-08-04 20:32:07 +10:00
|
|
|
LaraItem->goalAnimState = LS_STOP;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-08-04 20:32:07 +10:00
|
|
|
LaraItem->goalAnimState = LS_STOP;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-08-04 20:32:07 +10:00
|
|
|
case LA_PUSHABLE_PUSH_TO_STAND:
|
|
|
|
case LA_PUSHABLE_PULL_TO_STAND:
|
|
|
|
if (LaraItem->frameNumber == g_Level.Anims[LA_PUSHABLE_PUSH_TO_STAND].frameBase
|
|
|
|
|| LaraItem->frameNumber == g_Level.Anims[LA_PUSHABLE_PULL_TO_STAND].frameBase)
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
item->pos.xPos = item->pos.xPos & 0xFFFFFE00 | 0x200;
|
|
|
|
item->pos.zPos = item->pos.zPos & 0xFFFFFE00 | 0x200;
|
|
|
|
}
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
if (LaraItem->frameNumber == g_Level.Anims[LaraItem->animNumber].frameEnd)
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
|
|
|
roomNumber = item->roomNumber;
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos - 256, item->pos.zPos, &roomNumber);
|
|
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos - 256, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, 1, item->flags & 0x3E00);
|
|
|
|
RemoveActiveItem(itemNumber);
|
2020-05-30 15:55:23 +02:00
|
|
|
item->status = ITEM_NOT_ACTIVE;
|
2020-11-01 07:51:11 +01:00
|
|
|
|
|
|
|
if (item->triggerFlags >= 64)
|
|
|
|
{
|
2020-11-11 15:01:45 -03:00
|
|
|
//AlterFloorHeight(item, -((item->triggerFlags - 64) * 256));
|
2020-11-01 07:51:11 +01:00
|
|
|
AdjustStopperFlag(item, item->itemFlags[0] + 0x8000, 0);
|
|
|
|
}
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
2020-10-17 17:04:39 +02:00
|
|
|
break;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
|
2020-09-07 20:01:28 +02:00
|
|
|
void PushableBlockCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
2019-12-24 08:51:54 +01:00
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
short roomNumber = item->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos - 256, item->pos.zPos, &roomNumber);
|
|
|
|
|
|
|
|
if ((!(TrInput & IN_ACTION)
|
2020-08-04 20:32:07 +10:00
|
|
|
|| l->currentAnimState != LS_STOP
|
|
|
|
|| l->animNumber != LA_STAND_IDLE
|
2019-12-27 08:25:27 +01:00
|
|
|
|| l->gravityStatus
|
|
|
|
|| Lara.gunStatus
|
|
|
|
|| item->status == ITEM_INVISIBLE
|
|
|
|
|| item->triggerFlags < 0)
|
|
|
|
&& (!Lara.isMoving || Lara.generalPtr != item))
|
|
|
|
{
|
2020-11-01 07:51:11 +01:00
|
|
|
if ((l->currentAnimState != LS_PUSHABLE_GRAB
|
2020-08-04 20:32:07 +10:00
|
|
|
|| (l->frameNumber != g_Level.Anims[LA_PUSHABLE_GRAB].frameBase + 19)
|
2020-11-01 07:51:11 +01:00
|
|
|
|| Lara.cornerX != (int)item))
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
2020-11-01 07:51:11 +01:00
|
|
|
if (item->triggerFlags < 64)
|
|
|
|
ObjectCollision(itemNum, l, coll);
|
2019-12-27 08:25:27 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
short quadrant = (unsigned short)(LaraItem->pos.yRot + ANGLE(45)) / ANGLE(90);
|
2019-12-27 08:25:27 +01:00
|
|
|
|
|
|
|
if (TrInput & IN_FORWARD)
|
|
|
|
{
|
|
|
|
if (!TestBlockPush(item, 1024, quadrant))
|
|
|
|
return;
|
2020-08-04 20:32:07 +10:00
|
|
|
l->goalAnimState = LS_PUSHABLE_PUSH;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else if (TrInput & IN_BACK)
|
|
|
|
{
|
|
|
|
if (!TestBlockPull(item, 1024, quadrant))
|
|
|
|
return;
|
2020-08-04 20:32:07 +10:00
|
|
|
l->goalAnimState = LS_PUSHABLE_PULL;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->status = ITEM_ACTIVE;
|
|
|
|
AddActiveItem(itemNum);
|
|
|
|
Lara.headYrot = 0;
|
|
|
|
Lara.headXrot = 0;
|
|
|
|
Lara.torsoYrot = 0;
|
|
|
|
Lara.torsoXrot = 0;
|
2020-09-07 20:01:28 +02:00
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
PHD_VECTOR pos;
|
|
|
|
pos.x = 0;
|
|
|
|
pos.y = 0;
|
|
|
|
pos.z = 0;
|
|
|
|
|
2020-04-29 06:43:53 +02:00
|
|
|
GetLaraJointPosition(&pos, LM_LHAND);
|
2019-12-27 08:25:27 +01:00
|
|
|
|
|
|
|
l->itemFlags[0] = pos.x;
|
|
|
|
l->itemFlags[2] = pos.z;
|
|
|
|
|
|
|
|
item->itemFlags[0] = item->pos.xPos;
|
|
|
|
item->itemFlags[2] = item->pos.zPos;
|
2020-11-01 07:51:11 +01:00
|
|
|
|
|
|
|
if (item->triggerFlags >= 64)
|
|
|
|
{
|
2020-11-11 15:01:45 -03:00
|
|
|
//AlterFloorHeight(item, ((item->triggerFlags - 64) * 256));
|
2020-11-07 18:52:33 +01:00
|
|
|
AdjustStopperFlag(item, item->itemFlags[0], 0);
|
2020-11-01 07:51:11 +01:00
|
|
|
}
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
short roomNumber = l->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos - 256, item->pos.zPos, &roomNumber);
|
|
|
|
if (roomNumber == item->roomNumber)
|
|
|
|
{
|
2020-10-17 17:04:39 +02:00
|
|
|
BOUNDING_BOX* bounds = GetBoundsAccurate(item);
|
|
|
|
|
|
|
|
PushableBlockBounds.boundingBox.X1 = (bounds->X1 / 2) - 100;
|
|
|
|
PushableBlockBounds.boundingBox.X2 = (bounds->X2 / 2) + 100;
|
|
|
|
PushableBlockBounds.boundingBox.Z1 = bounds->Z1 - 200;
|
|
|
|
PushableBlockBounds.boundingBox.Z2 = 0;
|
2020-09-07 20:01:28 +02:00
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
short rot = item->pos.yRot;
|
|
|
|
item->pos.yRot = (l->pos.yRot + ANGLE(45)) & 0xC000;
|
2019-12-27 08:25:27 +01:00
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
if (TestLaraPosition(&PushableBlockBounds, item, l))
|
|
|
|
{
|
2020-11-07 18:52:33 +01:00
|
|
|
unsigned short quadrant = (unsigned short)((item->pos.yRot / 0x4000) + ((rot + 0x2000) / 0x4000));
|
|
|
|
if (quadrant & 1)
|
2020-10-17 17:04:39 +02:00
|
|
|
PushableBlockPos.z = bounds->X1 - 35;
|
|
|
|
else
|
|
|
|
PushableBlockPos.z = bounds->Z1 - 35;
|
2020-09-07 20:01:28 +02:00
|
|
|
|
2020-11-07 18:52:33 +01:00
|
|
|
if (item->triggerFlags > 64)
|
|
|
|
{
|
|
|
|
// For now don't use auto-align function because it can collide with climb up moves of Lara
|
|
|
|
|
|
|
|
LaraItem->pos.xRot = item->pos.xRot;
|
|
|
|
LaraItem->pos.yRot = item->pos.yRot;
|
|
|
|
LaraItem->pos.zRot = item->pos.zRot;
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
l->animNumber = LA_PUSHABLE_GRAB;
|
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
|
|
|
l->currentAnimState = LS_PUSHABLE_GRAB;
|
|
|
|
l->goalAnimState = LS_PUSHABLE_GRAB;
|
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
Lara.cornerX = (int)item;
|
|
|
|
item->pos.yRot = rot;
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-07 18:52:33 +01:00
|
|
|
if (MoveLaraPosition(&PushableBlockPos, item, l))
|
|
|
|
{
|
|
|
|
l->animNumber = LA_PUSHABLE_GRAB;
|
|
|
|
l->frameNumber = g_Level.Anims[l->animNumber].frameBase;
|
|
|
|
l->currentAnimState = LS_PUSHABLE_GRAB;
|
|
|
|
l->goalAnimState = LS_PUSHABLE_GRAB;
|
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
Lara.cornerX = (int)item;
|
|
|
|
item->pos.yRot = rot;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Lara.generalPtr = item;
|
|
|
|
item->pos.yRot = rot;
|
|
|
|
}
|
2019-12-27 08:25:27 +01:00
|
|
|
}
|
2020-10-17 17:04:39 +02:00
|
|
|
}
|
2019-12-27 08:25:27 +01:00
|
|
|
else
|
|
|
|
{
|
2020-10-17 17:04:39 +02:00
|
|
|
if (Lara.isMoving && Lara.generalPtr == item)
|
2019-12-27 08:25:27 +01:00
|
|
|
{
|
2020-10-17 17:04:39 +02:00
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
2020-09-07 20:01:28 +02:00
|
|
|
}
|
2020-10-17 17:04:39 +02:00
|
|
|
item->pos.yRot = rot;
|
|
|
|
}
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
int TestBlockMovable(ITEM_INFO* item, int blokhite)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
short roomNumber = item->roomNumber;
|
|
|
|
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
if (floor->floor == NO_HEIGHT / 256)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (floor->floor * 256 != item->pos.yPos - blokhite)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
int TestBlockPush(ITEM_INFO* item, int blockhite, unsigned short quadrant)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
int x = item->pos.xPos;
|
|
|
|
int y = item->pos.yPos;
|
|
|
|
int z = item->pos.zPos;
|
2020-10-17 17:04:39 +02:00
|
|
|
|
2019-12-24 08:51:54 +01:00
|
|
|
short roomNum = item->roomNumber;
|
|
|
|
switch (quadrant)
|
|
|
|
{
|
|
|
|
case NORTH:
|
|
|
|
z += 1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EAST:
|
|
|
|
x += 1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOUTH:
|
|
|
|
z -= 1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WEST:
|
|
|
|
x -= 1024;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
FLOOR_INFO* floor = GetFloor(x, y, z, &roomNum);
|
2020-07-21 09:56:47 +02:00
|
|
|
ROOM_INFO* r = &g_Level.Rooms[roomNum];
|
2019-12-27 08:25:27 +01:00
|
|
|
if (XZ_GET_SECTOR(r, x - r->x, z - r->z).stopper)
|
2019-12-24 08:51:54 +01:00
|
|
|
return 0;
|
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
if (GetFloorHeight(floor, x, y - 256, z) != y)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
GetFloorHeight(floor, x, y, z);
|
|
|
|
if (HeightType)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int ceiling = y - blockhite + 100;
|
|
|
|
floor = GetFloor(x, ceiling, z, &roomNum);
|
|
|
|
if (GetCeiling(floor, x, ceiling, z) > ceiling)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int oldX = item->pos.xPos;
|
|
|
|
int oldZ = item->pos.zPos;
|
|
|
|
item->pos.xPos = x;
|
|
|
|
item->pos.zPos = z;
|
2020-11-07 18:52:33 +01:00
|
|
|
GetCollidedObjects(item, 256, 1, &CollidedItems[0], 0, 1);
|
2019-12-27 08:25:27 +01:00
|
|
|
item->pos.xPos = oldX;
|
|
|
|
item->pos.zPos = oldZ;
|
|
|
|
|
2020-09-07 20:01:28 +02:00
|
|
|
return CollidedItems[0] == NULL;
|
2019-12-24 08:51:54 +01:00
|
|
|
}
|
|
|
|
|
2020-10-17 17:04:39 +02:00
|
|
|
int TestBlockPull(ITEM_INFO* item, int blockhite, short quadrant)
|
2019-12-24 08:51:54 +01:00
|
|
|
{
|
|
|
|
int xadd = 0;
|
|
|
|
int zadd = 0;
|
|
|
|
|
|
|
|
switch (quadrant)
|
|
|
|
{
|
|
|
|
case NORTH:
|
|
|
|
zadd = -1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EAST:
|
|
|
|
xadd = -1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOUTH:
|
|
|
|
zadd = 1024;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WEST:
|
|
|
|
xadd = 1024;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = item->pos.xPos + xadd;
|
|
|
|
int y = item->pos.yPos;
|
|
|
|
int z = item->pos.zPos + zadd;
|
|
|
|
short roomNum = item->roomNumber;
|
2020-10-17 17:04:39 +02:00
|
|
|
FLOOR_INFO* floor = GetFloor(x, y - 256, z, &roomNum);
|
2019-12-24 08:51:54 +01:00
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
ROOM_INFO* r = &g_Level.Rooms[roomNum];
|
2019-12-27 08:25:27 +01:00
|
|
|
if (XZ_GET_SECTOR(r, x - r->x, z - r->z).stopper)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (GetFloorHeight(floor, x, y - 256, z) != y)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (GetFloor(x, y - blockhite, z, &quadrant)->ceiling * 256 > y - blockhite)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int oldX = item->pos.xPos;
|
|
|
|
int oldZ = item->pos.zPos;
|
|
|
|
item->pos.xPos = x;
|
|
|
|
item->pos.zPos = z;
|
2020-11-07 18:52:33 +01:00
|
|
|
GetCollidedObjects(item, 256, 1, &CollidedItems[0], 0, 1);
|
2019-12-27 08:25:27 +01:00
|
|
|
item->pos.xPos = oldX;
|
|
|
|
item->pos.zPos = oldZ;
|
|
|
|
|
|
|
|
if (CollidedItems[0] != NULL)
|
2019-12-24 08:51:54 +01:00
|
|
|
return 0;
|
|
|
|
|
2019-12-27 08:25:27 +01:00
|
|
|
x += xadd;
|
|
|
|
z += zadd;
|
|
|
|
roomNum = item->roomNumber;
|
|
|
|
floor = GetFloor(x, y - 256, z, &roomNum);
|
|
|
|
|
|
|
|
if (GetFloorHeight(floor, x, y - 256, z) != y)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (GetFloor(x, y - 762, z, &roomNum)->ceiling * 256 > y - 762)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
x = LaraItem->pos.xPos + xadd;
|
|
|
|
z = LaraItem->pos.zPos + zadd;
|
|
|
|
|
|
|
|
roomNum = LaraItem->roomNumber;
|
|
|
|
GetFloor(x, y, z, &roomNum);
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
r = &g_Level.Rooms[roomNum];
|
2019-12-27 08:25:27 +01:00
|
|
|
if (XZ_GET_SECTOR(r, x - r->x, z - r->z).stopper)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
oldX = LaraItem->pos.xPos;
|
|
|
|
oldZ = LaraItem->pos.zPos;
|
|
|
|
LaraItem->pos.xPos = x;
|
|
|
|
LaraItem->pos.zPos = z;
|
2020-11-07 18:52:33 +01:00
|
|
|
GetCollidedObjects(LaraItem, 256, 1, &CollidedItems[0], 0, 1);
|
2019-12-27 08:25:27 +01:00
|
|
|
LaraItem->pos.xPos = oldX;
|
|
|
|
LaraItem->pos.zPos = oldZ;
|
|
|
|
|
|
|
|
return (CollidedItems[0] == NULL);
|
2020-10-17 17:04:39 +02:00
|
|
|
}
|
2020-11-11 15:01:45 -03:00
|
|
|
|
|
|
|
std::tuple<std::optional<int>, bool> PushableBlockFloor(short itemNumber, int x, int y, int z)
|
|
|
|
{
|
|
|
|
const auto& item = g_Level.Items[itemNumber];
|
|
|
|
if (item.status != ITEM_INVISIBLE && item.triggerFlags >= 64 && abs(item.pos.xPos - x) <= SECTOR(1) / 2 && abs(item.pos.zPos - z) <= SECTOR(1) / 2)
|
|
|
|
{
|
|
|
|
auto height = item.pos.yPos - (item.triggerFlags - 64) * CLICK(1);
|
|
|
|
return std::make_tuple(std::optional{height}, y > height && y < item.pos.yPos);
|
|
|
|
}
|
|
|
|
return std::make_tuple(std::nullopt, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::tuple<std::optional<int>, bool> PushableBlockCeiling(short itemNumber, int x, int y, int z)
|
|
|
|
{
|
|
|
|
const auto& item = g_Level.Items[itemNumber];
|
|
|
|
if (item.status != ITEM_INVISIBLE && item.triggerFlags >= 64 && abs(item.pos.xPos - x) <= SECTOR(1) / 2 && abs(item.pos.zPos - z) <= SECTOR(1) / 2)
|
|
|
|
{
|
|
|
|
auto height = item.pos.yPos - (item.triggerFlags - 64) * CLICK(1);
|
|
|
|
return std::make_tuple(std::optional{item.pos.yPos}, y > height && y < item.pos.yPos);
|
|
|
|
}
|
|
|
|
return std::make_tuple(std::nullopt, false);
|
|
|
|
}
|