Generic object file cleanup

This commit is contained in:
Sezz 2022-02-24 14:22:30 +11:00
parent 20775d8e9a
commit c2fb6cd159
50 changed files with 1528 additions and 1538 deletions

View file

@ -49,7 +49,10 @@ void ApproachLaraTargetAngle(ITEM_INFO* item, short targetAngle, float rate)
auto* info = GetLaraInfo(item);
if (!rate)
{
TENLog(std::string("ApproachLaraTargetAngle() attempted division by zero!"), LogLevel::Warning);
return;
}
rate = abs(rate);
@ -438,7 +441,10 @@ void SetCornerAnimation(ITEM_INFO* item, COLL_INFO* coll, bool flip)
void ResetLaraLean(ITEM_INFO* item, float rate, bool resetRoll, bool resetPitch)
{
if (!rate)
{
TENLog(std::string("ResetLaraLean() attempted division by zero!"), LogLevel::Warning);
return;
}
rate = abs(rate);
@ -464,7 +470,10 @@ void ResetLaraFlex(ITEM_INFO* item, float rate)
auto* info = GetLaraInfo(item);
if (!rate)
{
TENLog(std::string("ResetLaraFlex() attempted division by zero!"), LogLevel::Warning);
return;
}
rate = abs(rate);

View file

@ -2,13 +2,16 @@
#include "Game/collision/floordata.h"
struct ITEM_INFO;
struct DOORPOS_DATA {
struct DOORPOS_DATA
{
FLOOR_INFO* floor;
FLOOR_INFO data;
short block;
};
struct DOOR_DATA {
struct DOOR_DATA
{
DOORPOS_DATA d1;
DOORPOS_DATA d1flip;
DOORPOS_DATA d2;

View file

@ -28,51 +28,54 @@ namespace TEN::Entities::Doors
-384, 384,
0, 0,
-1024, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10),
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f),
};
void DoubleDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void DoubleDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* doorItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& !(item->Status && item->Airborne)
&& !(l->HitStatus)
&& Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
!laraItem->HitStatus &&
!(doorItem->Status && doorItem->Airborne) &&
laraInfo->Control.HandStatus == HandStatus::Free ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
item->Position.yRot ^= ANGLE(180);
if (TestLaraPosition(&DoubleDoorBounds, item, l))
{
if (MoveLaraPosition(&DoubleDoorPos, item, l))
{
SetAnimation(l, LA_DOUBLEDOOR_OPEN_PUSH);
doorItem->Position.yRot ^= ANGLE(180.0f);
AddActiveItem(itemNum);
if (TestLaraPosition(&DoubleDoorBounds, doorItem, laraItem))
{
if (MoveLaraPosition(&DoubleDoorPos, doorItem, laraItem))
{
SetAnimation(laraItem, LA_DOUBLEDOOR_OPEN_PUSH);
item->Status = ITEM_ACTIVE;
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
ResetLaraFlex(l);
AddActiveItem(itemNumber);
ResetLaraFlex(laraItem);
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
doorItem->Status = ITEM_ACTIVE;
}
else
laraInfo->interactedItem = itemNumber;
doorItem->Position.yRot ^= ANGLE(180.0f);
}
else
{
Lara.interactedItem = itemNum;
}
item->Position.yRot ^= ANGLE(180);
}
else
if (laraInfo->Control.IsMoving &&
laraInfo->interactedItem == itemNumber)
{
if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
}
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Doors
{
void DoubleDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void DoubleDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -13,8 +13,9 @@
#include "Game/collision/sphere.h"
#include "Objects/Generic/Switches/cog_switch.h"
#include "Objects/objectslist.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_struct.h"
#include "Specific/trmath.h"
#include "Game/misc.h"
#include "Game/itemdata/door_data.h"
@ -31,220 +32,223 @@ namespace TEN::Entities::Doors
-512, 512,
-1024, 0,
0, 512,
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80)
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f)
};
void InitialiseDoor(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* doorItem = &g_Level.Items[itemNumber];
if (item->ObjectNumber == ID_SEQUENCE_DOOR1)
item->Flags &= 0xBFFFu;
if (doorItem->ObjectNumber == ID_SEQUENCE_DOOR1)
doorItem->Flags &= 0xBFFFu;
if (item->ObjectNumber == ID_LIFT_DOORS1 || item->ObjectNumber == ID_LIFT_DOORS2)
item->ItemFlags[0] = 4096;
if (doorItem->ObjectNumber == ID_LIFT_DOORS1 || doorItem->ObjectNumber == ID_LIFT_DOORS2)
doorItem->ItemFlags[0] = 4096;
item->Data = ITEM_DATA(DOOR_DATA());
DOOR_DATA* door = item->Data;
doorItem->Data = ITEM_DATA(DOOR_DATA());
auto* doorData = (DOOR_DATA*)doorItem->Data;
door->opened = false;
door->dptr1 = nullptr;
door->dptr2 = nullptr;
door->dptr3 = nullptr;
door->dptr4 = nullptr;
doorData->opened = false;
doorData->dptr1 = nullptr;
doorData->dptr2 = nullptr;
doorData->dptr3 = nullptr;
doorData->dptr4 = nullptr;
short boxNumber, twoRoom;
int xOffset = 0;
int zOffset = 0;
if (item->Position.yRot == 0)
zOffset = -WALL_SIZE;
else if (item->Position.yRot == ANGLE(180))
zOffset = WALL_SIZE;
else if (item->Position.yRot == ANGLE(90))
xOffset = -WALL_SIZE;
if (doorItem->Position.yRot == 0)
zOffset = -SECTOR(1);
else if (doorItem->Position.yRot == ANGLE(180.0f))
zOffset = SECTOR(1);
else if (doorItem->Position.yRot == ANGLE(90.0f))
xOffset = -SECTOR(1);
else
xOffset = WALL_SIZE;
xOffset = SECTOR(1);
auto r = &g_Level.Rooms[item->RoomNumber];
door->d1.floor = GetSector(r, item->Position.xPos - r->x + xOffset, item->Position.zPos - r->z + zOffset);
auto* r = &g_Level.Rooms[doorItem->RoomNumber];
doorData->d1.floor = GetSector(r, doorItem->Position.xPos - r->x + xOffset, doorItem->Position.zPos - r->z + zOffset);
auto roomNumber = door->d1.floor->WallPortal;
auto roomNumber = doorData->d1.floor->WallPortal;
if (roomNumber == NO_ROOM)
boxNumber = door->d1.floor->Box;
boxNumber = doorData->d1.floor->Box;
else
{
auto b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, item->Position.xPos - b->x + xOffset, item->Position.zPos - b->z + zOffset)->Box;
auto* b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, doorItem->Position.xPos - b->x + xOffset, doorItem->Position.zPos - b->z + zOffset)->Box;
}
door->d1.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
door->d1.data = *door->d1.floor;
doorData->d1.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
doorData->d1.data = *doorData->d1.floor;
if (r->flippedRoom != -1)
{
r = &g_Level.Rooms[r->flippedRoom];
door->d1flip.floor = GetSector(r, item->Position.xPos - r->x + xOffset, item->Position.zPos - r->z + zOffset);
doorData->d1flip.floor = GetSector(r, doorItem->Position.xPos - r->x + xOffset, doorItem->Position.zPos - r->z + zOffset);
roomNumber = door->d1flip.floor->WallPortal;
roomNumber = doorData->d1flip.floor->WallPortal;
if (roomNumber == NO_ROOM)
boxNumber = door->d1flip.floor->Box;
boxNumber = doorData->d1flip.floor->Box;
else
{
auto b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, item->Position.xPos - b->x + xOffset, item->Position.zPos - b->z + zOffset)->Box;
auto* b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, doorItem->Position.xPos - b->x + xOffset, doorItem->Position.zPos - b->z + zOffset)->Box;
}
door->d1flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
door->d1flip.data = *door->d1flip.floor;
doorData->d1flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
doorData->d1flip.data = *doorData->d1flip.floor;
}
else
door->d1flip.floor = NULL;
doorData->d1flip.floor = NULL;
twoRoom = door->d1.floor->WallPortal;
twoRoom = doorData->d1.floor->WallPortal;
ShutThatDoor(&door->d1, door);
ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&doorData->d1, doorData);
ShutThatDoor(&doorData->d1flip, doorData);
if (twoRoom == NO_ROOM)
{
door->d2.floor = NULL;
door->d2flip.floor = NULL;
doorData->d2.floor = NULL;
doorData->d2flip.floor = NULL;
}
else
{
r = &g_Level.Rooms[twoRoom];
door->d2.floor = GetSector(r, item->Position.xPos - r->x, item->Position.zPos - r->z);
doorData->d2.floor = GetSector(r, doorItem->Position.xPos - r->x, doorItem->Position.zPos - r->z);
roomNumber = door->d2.floor->WallPortal;
roomNumber = doorData->d2.floor->WallPortal;
if (roomNumber == NO_ROOM)
boxNumber = door->d2.floor->Box;
boxNumber = doorData->d2.floor->Box;
else
{
auto b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, item->Position.xPos - b->x, item->Position.zPos - b->z)->Box;
auto* b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, doorItem->Position.xPos - b->x, doorItem->Position.zPos - b->z)->Box;
}
door->d2.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
door->d2.data = *door->d2.floor;
doorData->d2.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
doorData->d2.data = *doorData->d2.floor;
if (r->flippedRoom != -1)
{
r = &g_Level.Rooms[r->flippedRoom];
door->d2flip.floor = GetSector(r, item->Position.xPos - r->x, item->Position.zPos - r->z);
doorData->d2flip.floor = GetSector(r, doorItem->Position.xPos - r->x, doorItem->Position.zPos - r->z);
roomNumber = door->d2flip.floor->WallPortal;
roomNumber = doorData->d2flip.floor->WallPortal;
if (roomNumber == NO_ROOM)
boxNumber = door->d2flip.floor->Box;
boxNumber = doorData->d2flip.floor->Box;
else
{
auto b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, item->Position.xPos - b->x, item->Position.zPos - b->z)->Box;
auto* b = &g_Level.Rooms[roomNumber];
boxNumber = GetSector(b, doorItem->Position.xPos - b->x, doorItem->Position.zPos - b->z)->Box;
}
door->d2flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
door->d2flip.data = *door->d2flip.floor;
doorData->d2flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX;
doorData->d2flip.data = *doorData->d2flip.floor;
}
else
door->d2flip.floor = NULL;
doorData->d2flip.floor = NULL;
ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d2flip, door);
ShutThatDoor(&doorData->d2, doorData);
ShutThatDoor(&doorData->d2flip, doorData);
roomNumber = item->RoomNumber;
roomNumber = doorItem->RoomNumber;
ItemNewRoom(itemNumber, twoRoom);
item->RoomNumber = roomNumber;
item->InDrawRoom = true;
doorItem->RoomNumber = roomNumber;
doorItem->InDrawRoom = true;
}
}
void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void DoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* doorItem = &g_Level.Items[itemNumber];
if (item->TriggerFlags == 2
&& item->Status == ITEM_NOT_ACTIVE && !item->Airborne // CHECK
&& ((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& !l->HitStatus
&& Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum))
if (doorItem->TriggerFlags == 2 &&
doorItem->Status == ITEM_NOT_ACTIVE && !doorItem->Airborne && // CHECK
((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM) &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
!laraItem->HitStatus &&
laraInfo->Control.HandStatus == HandStatus::Free ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber))
{
item->Position.yRot ^= ANGLE(180);
if (TestLaraPosition(&CrowbarDoorBounds, item, l))
doorItem->Position.yRot ^= ANGLE(180.0f);
if (TestLaraPosition(&CrowbarDoorBounds, doorItem, laraItem))
{
if (!Lara.Control.IsMoving)
if (!laraInfo->Control.IsMoving)
{
if (g_Gui.GetInventoryItemChosen() == NO_ITEM)
{
if (g_Gui.IsObjectInInventory(ID_CROWBAR_ITEM))
{
g_Gui.SetEnterInventory(ID_CROWBAR_ITEM);
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
}
else
{
if (OldPickupPos.x != l->Position.xPos || OldPickupPos.y != l->Position.yPos || OldPickupPos.z != l->Position.zPos)
if (OldPickupPos.x != laraItem->Position.xPos || OldPickupPos.y != laraItem->Position.yPos || OldPickupPos.z != laraItem->Position.zPos)
{
OldPickupPos.x = l->Position.xPos;
OldPickupPos.y = l->Position.yPos;
OldPickupPos.z = l->Position.zPos;
OldPickupPos.x = laraItem->Position.xPos;
OldPickupPos.y = laraItem->Position.yPos;
OldPickupPos.z = laraItem->Position.zPos;
SayNo();
}
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
}
return;
}
if (g_Gui.GetInventoryItemChosen() != ID_CROWBAR_ITEM)
{
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
return;
}
}
g_Gui.SetInventoryItemChosen(NO_ITEM);
if (MoveLaraPosition(&CrowbarDoorPos, item, l))
if (MoveLaraPosition(&CrowbarDoorPos, doorItem, laraItem))
{
SetAnimation(l, LA_DOOR_OPEN_CROWBAR);
item->Position.yRot ^= ANGLE(180);
SetAnimation(laraItem, LA_DOOR_OPEN_CROWBAR);
doorItem->Position.yRot ^= ANGLE(180.0f);
AddActiveItem(itemNum);
item->Flags |= IFLAG_ACTIVATION_MASK;
item->Status = ITEM_ACTIVE;
item->TargetState = LS_RUN_FORWARD;
Lara.Control.IsMoving = 0;
Lara.Control.HandStatus = HandStatus::Busy;
AddActiveItem(itemNumber);
laraInfo->Control.IsMoving = 0;
laraInfo->Control.HandStatus = HandStatus::Busy;
doorItem->Flags |= IFLAG_ACTIVATION_MASK;
doorItem->Status = ITEM_ACTIVE;
doorItem->TargetState = LS_RUN_FORWARD;
return;
}
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = 0;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = 0;
laraInfo->Control.HandStatus = HandStatus::Free;
}
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
}
if (TestBoundsCollide(item, l, coll->Setup.Radius))
if (TestBoundsCollide(doorItem, laraItem, coll->Setup.Radius))
{
if (TestCollision(item, l))
if (TestCollision(doorItem, laraItem))
{
if (coll->Setup.EnableObjectPush)
{
if (!(item->ObjectNumber >= ID_LIFT_DOORS1 && item->ObjectNumber <= ID_LIFT_DOORS2) || item->ItemFlags[0])
if (!(doorItem->ObjectNumber >= ID_LIFT_DOORS1 &&
doorItem->ObjectNumber <= ID_LIFT_DOORS2) || doorItem->ItemFlags[0])
{
ItemPushItem(item, l, coll, FALSE, TRUE);
ItemPushItem(doorItem, laraItem, coll, FALSE, TRUE);
}
}
}
@ -253,48 +257,48 @@ namespace TEN::Entities::Doors
void DoorControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
DOOR_DATA* door = (DOOR_DATA*)item->Data;
auto* doorItem = &g_Level.Items[itemNumber];
auto* doorData = (DOOR_DATA*)doorItem->Data;
// Doors with OCB = 1 are raisable with cog switchs
if (item->TriggerFlags == 1)
if (doorItem->TriggerFlags == 1)
{
if (item->ItemFlags[0])
if (doorItem->ItemFlags[0])
{
BOUNDING_BOX* bounds = GetBoundsAccurate(item);
auto* bounds = GetBoundsAccurate(doorItem);
item->ItemFlags[0]--;
item->Position.yPos -= TEN::Entities::Switches::COG_DOOR_SPEED;
doorItem->ItemFlags[0]--;
doorItem->Position.yPos -= TEN::Entities::Switches::COG_DOOR_SPEED;
int y = bounds->Y1 + item->ItemFlags[2] - STEP_SIZE;
if (item->Position.yPos < y)
int y = bounds->Y1 + doorItem->ItemFlags[2] - STEP_SIZE;
if (doorItem->Position.yPos < y)
{
item->Position.yPos = y;
item->ItemFlags[0] = 0;
doorItem->Position.yPos = y;
doorItem->ItemFlags[0] = 0;
}
if (!door->opened)
if (!doorData->opened)
{
OpenThatDoor(&door->d1, door);
OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door);
door->opened = true;
OpenThatDoor(&doorData->d1, doorData);
OpenThatDoor(&doorData->d2, doorData);
OpenThatDoor(&doorData->d1flip, doorData);
OpenThatDoor(&doorData->d2flip, doorData);
doorData->opened = true;
}
}
else
{
if (item->Position.yPos < item->StartPosition.yPos)
item->Position.yPos += 4;
if (item->Position.yPos >= item->StartPosition.yPos)
if (doorItem->Position.yPos < doorItem->StartPosition.yPos)
doorItem->Position.yPos += 4;
if (doorItem->Position.yPos >= doorItem->StartPosition.yPos)
{
item->Position.yPos = item->StartPosition.yPos;
if (door->opened)
doorItem->Position.yPos = doorItem->StartPosition.yPos;
if (doorData->opened)
{
ShutThatDoor(&door->d1, door);
ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door);
door->opened = false;
ShutThatDoor(&doorData->d1, doorData);
ShutThatDoor(&doorData->d2, doorData);
ShutThatDoor(&doorData->d1flip, doorData);
ShutThatDoor(&doorData->d2flip, doorData);
doorData->opened = false;
}
}
}
@ -302,38 +306,34 @@ namespace TEN::Entities::Doors
return;
}
if (item->ObjectNumber < ID_LIFT_DOORS1 || item->ObjectNumber > ID_LIFT_DOORS2)
if (doorItem->ObjectNumber < ID_LIFT_DOORS1 || doorItem->ObjectNumber > ID_LIFT_DOORS2)
{
if (TriggerActive(item))
if (TriggerActive(doorItem))
{
if (item->ActiveState == 0)
if (doorItem->ActiveState == 0)
doorItem->TargetState = 1;
else if (!doorData->opened)
{
item->TargetState = 1;
}
else if (!door->opened)
{
OpenThatDoor(&door->d1, door);
OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door);
door->opened = true;
OpenThatDoor(&doorData->d1, doorData);
OpenThatDoor(&doorData->d2, doorData);
OpenThatDoor(&doorData->d1flip, doorData);
OpenThatDoor(&doorData->d2flip, doorData);
doorData->opened = true;
}
}
else
{
item->Status = ITEM_ACTIVE;
doorItem->Status = ITEM_ACTIVE;
if (item->ActiveState == 1)
if (doorItem->ActiveState == 1)
doorItem->TargetState = 0;
else if (doorData->opened)
{
item->TargetState = 0;
}
else if (door->opened)
{
ShutThatDoor(&door->d1, door);
ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door);
door->opened = false;
ShutThatDoor(&doorData->d1, doorData);
ShutThatDoor(&doorData->d2, doorData);
ShutThatDoor(&doorData->d1flip, doorData);
ShutThatDoor(&doorData->d2flip, doorData);
doorData->opened = false;
}
}
}
@ -381,7 +381,7 @@ namespace TEN::Entities::Doors
}*/
}
AnimateItem(item);
AnimateItem(doorItem);
}
void OpenThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
@ -433,10 +433,8 @@ namespace TEN::Entities::Doors
g_Level.Boxes[boxIndex].flags |= BLOCKED;
for (int i = 0; i < ActiveCreatures.size(); i++)
{
ActiveCreatures[i]->LOT.targetBox = NO_BOX;
}
}
}
}
}

View file

@ -1,7 +1,7 @@
#pragma once
struct COLL_INFO;
struct ITEM_INFO;
struct COLL_INFO;
struct ROOM_INFO;
struct DOORPOS_DATA;
struct DOOR_DATA;
@ -9,7 +9,7 @@ struct DOOR_DATA;
namespace TEN::Entities::Doors
{
void InitialiseDoor(short itemNumber);
void DoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void DoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void DoorControl(short itemNumber);
void OpenThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd);
void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd);

View file

@ -11,6 +11,7 @@
#include "Sound/sound.h"
#include "Game/animation.h"
#include "Game/collision/sphere.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara.h"
#include "Specific/trmath.h"
@ -28,6 +29,7 @@ namespace TEN::Entities::Doors
STATE_PUSHPULL_KICK_DOOR_PUSH = 2,
STATE_PUSHPULL_KICK_DOOR_PULL = 3
};
PHD_VECTOR PullDoorPos(-201, 0, 322);
PHD_VECTOR PushDoorPos(201, 0, -702);
PHD_VECTOR KickDoorPos(0, 0, -917);
@ -37,119 +39,112 @@ namespace TEN::Entities::Doors
-384, 384,
0, 0,
-1024, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10),
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f),
};
void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void PushPullKickDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* doorItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& item->Status != ITEM_ACTIVE
&& !(l->HitStatus)
&& Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
!laraItem->HitStatus &&
doorItem->Status != ITEM_ACTIVE &&
laraInfo->Control.HandStatus == HandStatus::Free ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
bool pull = false;
if (l->RoomNumber == item->RoomNumber)
if (laraItem->RoomNumber == doorItem->RoomNumber)
{
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
pull = true;
}
if (TestLaraPosition(&PushPullKickDoorBounds, item, l))
if (TestLaraPosition(&PushPullKickDoorBounds, doorItem, laraItem))
{
bool openTheDoor = false;
if (pull)
{
if (MoveLaraPosition(&PullDoorPos, item, l))
if (MoveLaraPosition(&PullDoorPos, doorItem, laraItem))
{
SetAnimation(l, LA_DOOR_OPEN_PULL);
item->TargetState = STATE_PUSHPULL_KICK_DOOR_PULL;
SetAnimation(laraItem, LA_DOOR_OPEN_PULL);
doorItem->TargetState = STATE_PUSHPULL_KICK_DOOR_PULL;
openTheDoor = true;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
}
else
{
if (item->ObjectNumber >= ID_KICK_DOOR1)
if (doorItem->ObjectNumber >= ID_KICK_DOOR1)
{
if (MoveLaraPosition(&KickDoorPos, item, l))
if (MoveLaraPosition(&KickDoorPos, doorItem, laraItem))
{
SetAnimation(l, LA_DOOR_OPEN_KICK);
item->TargetState = STATE_PUSHPULL_KICK_DOOR_PUSH;
SetAnimation(laraItem, LA_DOOR_OPEN_KICK);
doorItem->TargetState = STATE_PUSHPULL_KICK_DOOR_PUSH;
openTheDoor = true;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
}
else
{
if (MoveLaraPosition(&PushDoorPos, item, l))
if (MoveLaraPosition(&PushDoorPos, doorItem, laraItem))
{
SetAnimation(l, LA_DOOR_OPEN_PUSH);
item->TargetState = STATE_PUSHPULL_KICK_DOOR_PUSH;
SetAnimation(laraItem, LA_DOOR_OPEN_PUSH);
doorItem->TargetState = STATE_PUSHPULL_KICK_DOOR_PUSH;
openTheDoor = true;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
}
}
if (openTheDoor)
{
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
item->Status = ITEM_ACTIVE;
l->ActiveState = LS_MISC_CONTROL;
l->TargetState = LS_IDLE;
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
laraItem->ActiveState = LS_MISC_CONTROL;
laraItem->TargetState = LS_IDLE;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
doorItem->Status = ITEM_ACTIVE;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving &&
laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
if (pull)
item->Position.yRot ^= ANGLE(180);
doorItem->Position.yRot ^= ANGLE(180.0f);
}
else if (item->ActiveState <= STATE_PUSHPULL_KICK_DOOR_CLOSED)
DoorCollision(itemNum, l, coll);
else if (doorItem->ActiveState <= STATE_PUSHPULL_KICK_DOOR_CLOSED)
DoorCollision(itemNumber, laraItem, coll);
}
void PushPullKickDoorControl(short itemNumber)
{
ITEM_INFO* item;
DOOR_DATA* door;
auto* doorItem = &g_Level.Items[itemNumber];
auto* doorData = (DOOR_DATA*)doorItem->Data;
item = &g_Level.Items[itemNumber];
door = (DOOR_DATA*)item->Data;
if (!door->opened)
if (!doorData->opened)
{
OpenThatDoor(&door->d1, door);
OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door);
door->opened = true;
OpenThatDoor(&doorData->d1, doorData);
OpenThatDoor(&doorData->d2, doorData);
OpenThatDoor(&doorData->d1flip, doorData);
OpenThatDoor(&doorData->d2flip, doorData);
doorData->opened = true;
}
AnimateItem(item);
AnimateItem(doorItem);
}
}

View file

@ -6,5 +6,5 @@ struct COLL_INFO;
namespace TEN::Entities::Doors
{
void PushPullKickDoorControl(short itemNumber);
void PushPullKickDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void PushPullKickDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -25,52 +25,52 @@ namespace TEN::Entities::Doors
{
void SequenceDoorControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
DOOR_DATA* door = (DOOR_DATA*)item->Data;
auto* doorItem = &g_Level.Items[itemNumber];
auto* doorData = (DOOR_DATA*)doorItem->Data;
if (CurrentSequence == 3)
{
if (SequenceResults[Sequences[0]][Sequences[1]][Sequences[2]] == item->TriggerFlags)
if (SequenceResults[Sequences[0]][Sequences[1]][Sequences[2]] == doorItem->TriggerFlags)
{
if (item->ActiveState == 1)
item->TargetState = 1;
if (doorItem->ActiveState == 1)
doorItem->TargetState = 1;
else
item->TargetState = 0;
doorItem->TargetState = 0;
TestTriggers(item, true);
TestTriggers(doorItem, true);
}
CurrentSequence = 4;
}
if (item->ActiveState == item->TargetState)
if (doorItem->ActiveState == doorItem->TargetState)
{
if (item->ActiveState == 1)
if (doorItem->ActiveState == 1)
{
if (!door->opened)
if (!doorData->opened)
{
OpenThatDoor(&door->d1, door);
OpenThatDoor(&door->d2, door);
OpenThatDoor(&door->d1flip, door);
OpenThatDoor(&door->d2flip, door);
door->opened = true;
item->Flags |= 0x3E;
OpenThatDoor(&doorData->d1, doorData);
OpenThatDoor(&doorData->d2, doorData);
OpenThatDoor(&doorData->d1flip, doorData);
OpenThatDoor(&doorData->d2flip, doorData);
doorData->opened = true;
doorItem->Flags |= 0x3E;
}
}
else
{
if (door->opened)
if (doorData->opened)
{
ShutThatDoor(&door->d1, door);
ShutThatDoor(&door->d2, door);
ShutThatDoor(&door->d1flip, door);
ShutThatDoor(&door->d2flip, door);
door->opened = false;
item->Flags &= 0xC1;
ShutThatDoor(&doorData->d1, doorData);
ShutThatDoor(&doorData->d2, doorData);
ShutThatDoor(&doorData->d1flip, doorData);
ShutThatDoor(&doorData->d2flip, doorData);
doorData->opened = false;
doorItem->Flags &= 0xC1;
}
}
}
AnimateItem(item);
AnimateItem(doorItem);
}
}

View file

@ -23,24 +23,24 @@ namespace TEN::Entities::Doors
{
void InitialiseSteelDoor(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* doorItem = &g_Level.Items[itemNumber];
item->MeshBits = 1;
item->Position.yPos -= 1024;
doorItem->MeshBits = 1;
doorItem->Position.yPos -= 1024;
}
void SteelDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void SteelDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* doorItem = &g_Level.Items[itemNumber];
if (item->ItemFlags[0] != 3)
if (doorItem->ItemFlags[0] != 3)
{
if (TestBoundsCollide(item, l, coll->Setup.Radius))
if (TestBoundsCollide(doorItem, laraItem, coll->Setup.Radius))
{
if (TestCollision(item, l))
if (TestCollision(doorItem, laraItem))
{
if (coll->Setup.EnableObjectPush)
ItemPushItem(item, l, coll, 0, 1);
ItemPushItem(doorItem, laraItem, coll, 0, 1);
}
}
}

View file

@ -6,5 +6,5 @@ struct COLL_INFO;
namespace TEN::Entities::Doors
{
void InitialiseSteelDoor(short itemNumber);
void SteelDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void SteelDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -11,6 +11,7 @@
#include "Sound/sound.h"
#include "Game/animation.h"
#include "Game/collision/sphere.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara.h"
#include "Specific/trmath.h"
@ -27,60 +28,59 @@ namespace TEN::Entities::Doors
-256, 256,
-1024, 0,
-1024, 0,
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80)
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f)
};
void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void UnderwaterDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* doorItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION
&& l->ActiveState == LS_UNDERWATER_STOP
&& !(item->Status && item->Airborne)
&& Lara.Control.WaterStatus == WaterStatus::Underwater
&& Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_UNDERWATER_STOP &&
laraInfo->Control.WaterStatus == WaterStatus::Underwater &&
!(doorItem->Status && doorItem->Airborne) &&
laraInfo->Control.HandStatus == HandStatus::Free ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
l->Position.yRot ^= ANGLE(180.0f);
laraItem->Position.yRot ^= ANGLE(180.0f);
if (TestLaraPosition(&UnderwaterDoorBounds, item, l))
if (TestLaraPosition(&UnderwaterDoorBounds, doorItem, laraItem))
{
if (MoveLaraPosition(&UnderwaterDoorPos, item, l))
if (MoveLaraPosition(&UnderwaterDoorPos, doorItem, laraItem))
{
SetAnimation(l, LA_UNDERWATER_DOOR_OPEN);
l->VerticalVelocity = 0;
item->Status = ITEM_ACTIVE;
SetAnimation(laraItem, LA_UNDERWATER_DOOR_OPEN);
laraItem->VerticalVelocity = 0;
doorItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
item->TargetState = LS_RUN_FORWARD;
doorItem->TargetState = LS_RUN_FORWARD;
AnimateItem(item);
AnimateItem(doorItem);
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
}
else
laraInfo->interactedItem = itemNumber;
laraItem->Position.yRot ^= ANGLE(180.0f);
}
else
{
Lara.interactedItem = itemNum;
}
l->Position.yRot ^= ANGLE(180);
}
else
if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
l->Position.yRot ^= ANGLE(180);
laraItem->Position.yRot ^= ANGLE(180.0f);
}
}
else if (item->Status == ITEM_ACTIVE)
{
ObjectCollision(itemNum, l, coll);
}
else if (doorItem->Status == ITEM_ACTIVE)
ObjectCollision(itemNumber, laraItem, coll);
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Doors
{
void UnderwaterDoorCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void UnderwaterDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -1,6 +1,7 @@
#include "framework.h"
#include "Objects/Generic/Object/burning_torch.h"
#include "Game/Lara/lara_flare.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara.h"
#include "Game/animation.h"
#include "Game/items.h"
@ -20,7 +21,7 @@ namespace TEN::Entities::Generic
{
void TriggerTorchFlame(char fxObj, char node)
{
SPARKS* spark = &Sparks[GetFreeSpark()];
auto* spark = &Sparks[GetFreeSpark()];
spark->on = true;
@ -75,20 +76,21 @@ namespace TEN::Entities::Generic
break;
}
if (TrInput & IN_DRAW
&& !(LaraItem->Airborne)
&& !LaraItem->VerticalVelocity
&& LaraItem->ActiveState != LS_JUMP_PREPARE
&& LaraItem->ActiveState != LS_JUMP_UP
&& LaraItem->ActiveState != LS_JUMP_FORWARD
&& LaraItem->ActiveState != LS_JUMP_BACK
&& LaraItem->ActiveState != LS_JUMP_LEFT
&& LaraItem->ActiveState != LS_JUMP_RIGHT
|| Lara.Control.WaterStatus == WaterStatus::Underwater)
if (TrInput & IN_DRAW &&
!LaraItem->VerticalVelocity &&
!LaraItem->Airborne &&
LaraItem->ActiveState != LS_JUMP_PREPARE &&
LaraItem->ActiveState != LS_JUMP_UP &&
LaraItem->ActiveState != LS_JUMP_FORWARD &&
LaraItem->ActiveState != LS_JUMP_BACK &&
LaraItem->ActiveState != LS_JUMP_LEFT &&
LaraItem->ActiveState != LS_JUMP_RIGHT ||
Lara.Control.WaterStatus == WaterStatus::Underwater)
{
Lara.LeftArm.Locked = true;
Lara.LeftArm.FrameNumber = 1;
Lara.LeftArm.AnimNumber = Objects[ID_LARA_TORCH_ANIM].animIndex + 1;
if (Lara.Control.WaterStatus == WaterStatus::Underwater)
Lara.LitTorch = false;
}
@ -139,7 +141,9 @@ namespace TEN::Entities::Generic
Lara.meshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND;
CreateFlare(LaraItem, ID_BURNING_TORCH_ITEM, false);
}
break;
case 3:
if (LaraItem->ActiveState != LS_MISC_CONTROL)
{
@ -149,7 +153,9 @@ namespace TEN::Entities::Generic
Lara.LitTorch = LaraItem->ItemFlags[3] & 1;
Lara.LeftArm.AnimNumber = Objects[ID_LARA_TORCH_ANIM].animIndex;
}
break;
default:
break;
}
@ -161,12 +167,7 @@ namespace TEN::Entities::Generic
if (Lara.LitTorch)
{
PHD_VECTOR pos;
pos.x = -32;
pos.y = 64;
pos.z = 256;
PHD_VECTOR pos = { -32, 64, 256 };
GetLaraJointPosition(&pos, LM_LHAND);
TriggerDynamicLight(pos.x, pos.y, pos.z, 12 - (GetRandomControl() & 1), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 96, 0);
@ -197,7 +198,7 @@ namespace TEN::Entities::Generic
void TorchControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
int oldX = item->Position.xPos;
int oldY = item->Position.yPos;
@ -274,7 +275,7 @@ namespace TEN::Entities::Generic
if (!LOS(&pos1, &pos2))
{
int l = sqrt(SQUARE(pos1.x - pos2.x) + SQUARE(pos1.y - pos2.y) + SQUARE(pos1.z - pos2.z)) * STEP_SIZE;
int l = sqrt(pow(pos1.x - pos2.x, 2) + pow(pos1.y - pos2.y, 2) + pow(pos1.z - pos2.z, 2)) * CLICK(1);
if (l + 8 > 31)
l = 31;
@ -284,28 +285,30 @@ namespace TEN::Entities::Generic
}
}
void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void FireCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* laraInfo = GetLaraInfo(laraItem);
auto* torchItem = &g_Level.Items[itemNumber];
if (Lara.Control.WeaponControl.GunType != WEAPON_TORCH
|| Lara.Control.HandStatus != HandStatus::WeaponReady
|| Lara.LeftArm.Locked
|| Lara.LitTorch == (item->Status == ITEM_ACTIVE)
|| item->Timer == -1
|| !(TrInput & IN_ACTION)
|| l->ActiveState != LS_IDLE
|| l->AnimNumber != LA_STAND_IDLE
|| l->Airborne)
if (
!(TrInput & IN_ACTION) ||
laraItem->ActiveState != LS_IDLE ||
laraItem->AnimNumber != LA_STAND_IDLE ||
laraItem->Airborne ||
laraInfo->Control.WeaponControl.GunType != WEAPON_TORCH ||
laraInfo->Control.HandStatus != HandStatus::WeaponReady ||
laraInfo->LeftArm.Locked ||
laraInfo->LitTorch == (torchItem->Status == ITEM_ACTIVE) ||
torchItem->Timer == -1)
{
if (item->ObjectNumber == ID_BURNING_ROOTS)
ObjectCollision(itemNumber, l, coll);
if (torchItem->ObjectNumber == ID_BURNING_ROOTS)
ObjectCollision(itemNumber, laraItem, coll);
}
else
{
short rot = item->Position.yRot;
short rot = torchItem->Position.yRot;
switch (item->ObjectNumber)
switch (torchItem->ObjectNumber)
{
case ID_FLAME_EMITTER:
FireBounds.boundingBox.X1 = -256;
@ -315,6 +318,7 @@ namespace TEN::Entities::Generic
FireBounds.boundingBox.Z1 = -800;
FireBounds.boundingBox.Z2 = 800;
break;
case ID_FLAME_EMITTER2:
FireBounds.boundingBox.X1 = -256;
FireBounds.boundingBox.X2 = 256;
@ -323,6 +327,7 @@ namespace TEN::Entities::Generic
FireBounds.boundingBox.Z1 = -600;
FireBounds.boundingBox.Z2 = 600;
break;
case ID_BURNING_ROOTS:
FireBounds.boundingBox.X1 = -384;
FireBounds.boundingBox.X2 = 384;
@ -333,39 +338,41 @@ namespace TEN::Entities::Generic
break;
}
item->Position.yRot = l->Position.yRot;
torchItem->Position.yRot = laraItem->Position.yRot;
if (TestLaraPosition(&FireBounds, item, l))
if (TestLaraPosition(&FireBounds, torchItem, laraItem))
{
if (item->ObjectNumber == ID_BURNING_ROOTS)
{
l->AnimNumber = LA_TORCH_LIGHT_5;
}
if (torchItem->ObjectNumber == ID_BURNING_ROOTS)
laraItem->AnimNumber = LA_TORCH_LIGHT_5;
else
{
int dy = abs(l->Position.yPos - item->Position.yPos);
l->ItemFlags[3] = 1;
l->AnimNumber = (dy >> 8) + LA_TORCH_LIGHT_1;
}
l->ActiveState = LS_MISC_CONTROL;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Flare.ControlLeft = false;
Lara.LeftArm.Locked = true;
Lara.interactedItem = itemNumber;
int dy = abs(laraItem->Position.yPos - torchItem->Position.yPos);
laraItem->ItemFlags[3] = 1;
laraItem->AnimNumber = (dy >> 8) + LA_TORCH_LIGHT_1;
}
item->Position.yRot = rot;
laraItem->ActiveState = LS_MISC_CONTROL;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Flare.ControlLeft = false;
laraInfo->LeftArm.Locked = true;
laraInfo->interactedItem = itemNumber;
}
if (Lara.interactedItem == itemNumber && item->Status != ITEM_ACTIVE && l->ActiveState == LS_MISC_CONTROL)
torchItem->Position.yRot = rot;
}
if (laraItem->ActiveState == LS_MISC_CONTROL &&
laraInfo->interactedItem == itemNumber &&
torchItem->Status != ITEM_ACTIVE)
{
if (l->AnimNumber >= LA_TORCH_LIGHT_1 && l->AnimNumber <= LA_TORCH_LIGHT_5)
if (laraItem->AnimNumber >= LA_TORCH_LIGHT_1 &&
laraItem->AnimNumber <= LA_TORCH_LIGHT_5)
{
if (l->FrameNumber - g_Level.Anims[l->AnimNumber].frameBase == 40)
if (laraItem->FrameNumber - g_Level.Anims[laraItem->AnimNumber].frameBase == 40)
{
TestTriggers(item, true, item->Flags & IFLAG_ACTIVATION_MASK);
item->Flags |= 0x3E00;
item->ItemFlags[3] = 0;
item->Status = ITEM_ACTIVE;
TestTriggers(torchItem, true, torchItem->Flags & IFLAG_ACTIVATION_MASK);
torchItem->Flags |= 0x3E00;
torchItem->ItemFlags[3] = 0;
torchItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNumber);
}
}

View file

@ -11,5 +11,5 @@ namespace TEN::Entities::Generic
void GetFlameTorch();
void TorchControl(short itemNumber);
void LaraTorch(PHD_VECTOR* src, PHD_VECTOR* target, int rot, int color);
void FireCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void FireCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -12,7 +12,7 @@ int GetOffset(short angle, int x, int z);
template <int tilt>
std::optional<int> BridgeFloor(short itemNumber, int x, int y, int z)
{
auto item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
auto bboxHeight = GetBridgeItemIntersect(itemNumber, x, y, z, false);
if (bboxHeight.has_value() && tilt != 0)
@ -20,13 +20,14 @@ std::optional<int> BridgeFloor(short itemNumber, int x, int y, int z)
const auto height = item->Position.yPos + tilt * (GetOffset(item->Position.yRot, x, z) / 4 + SECTOR(1) / 8);
return std::optional{ height };
}
return bboxHeight;
}
template <int tilt>
std::optional<int> BridgeCeiling(short itemNumber, int x, int y, int z)
{
auto item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
auto bboxHeight = GetBridgeItemIntersect(itemNumber, x, y, z, true);
if (bboxHeight.has_value() && tilt != 0)

View file

@ -16,165 +16,187 @@ using namespace TEN::Renderer;
using namespace TEN::Floordata;
OBJECT_COLLISION_BOUNDS CeilingTrapDoorBounds = {-256, 256, 0, 900, -768, -256, -1820, 1820, -5460, 5460, -1820, 1820};
OBJECT_COLLISION_BOUNDS CeilingTrapDoorBounds =
{
-256, 256,
0, 900,
-768, -256,
-1820, 1820,
-5460, 5460,
-1820, 1820
};
static PHD_VECTOR CeilingTrapDoorPos = { 0, 1056, -480 };
OBJECT_COLLISION_BOUNDS FloorTrapDoorBounds = {-256, 256, 0, 0, -1024, -256, -1820, 1820, -5460, 5460, -1820, 1820};
OBJECT_COLLISION_BOUNDS FloorTrapDoorBounds =
{
-256, 256,
0, 0,
-1024, -256,
-1820, 1820,
-5460, 5460,
-1820, 1820
};
static PHD_VECTOR FloorTrapDoorPos = { 0, 0, -655 };
void InitialiseTrapDoor(short itemNumber)
{
ITEM_INFO* item;
item = &g_Level.Items[itemNumber];
auto* trapDoorItem = &g_Level.Items[itemNumber];
TEN::Floordata::UpdateBridgeItem(itemNumber);
CloseTrapDoor(itemNumber);
}
void TrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void TrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item;
auto* trapDoorItem = &g_Level.Items[itemNumber];
item = &g_Level.Items[itemNumber];
if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd)
ObjectCollision(itemNumber, l, coll);
if (trapDoorItem->ActiveState == 1 &&
trapDoorItem->FrameNumber == g_Level.Anims[trapDoorItem->AnimNumber].frameEnd)
{
ObjectCollision(itemNumber, laraItem, coll);
}
}
void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
auto item = &g_Level.Items[itemNumber];
bool itemIsAbove = item->Position.yPos <= l->Position.yPos - LARA_HEIGHT + LARA_HEADROOM;
bool result = TestLaraPosition(&CeilingTrapDoorBounds, item, l);
l->Position.yRot += ANGLE(180);
bool result2 = TestLaraPosition(&CeilingTrapDoorBounds, item, l);
l->Position.yRot += ANGLE(180);
auto* laraInfo = GetLaraInfo(laraItem);
auto* trapDoorItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION && item->Status != ITEM_ACTIVE && l->ActiveState == LS_JUMP_UP && l->Airborne && Lara.Control.HandStatus == HandStatus::Free && itemIsAbove && (result || result2))
bool itemIsAbove = trapDoorItem->Position.yPos <= laraItem->Position.yPos - LARA_HEIGHT + LARA_HEADROOM;
bool result = TestLaraPosition(&CeilingTrapDoorBounds, trapDoorItem, laraItem);
laraItem->Position.yRot += ANGLE(180.0f);
bool result2 = TestLaraPosition(&CeilingTrapDoorBounds, trapDoorItem, laraItem);
laraItem->Position.yRot += ANGLE(180.0f);
if (TrInput & IN_ACTION &&
trapDoorItem->Status != ITEM_ACTIVE &&
laraItem->ActiveState == LS_JUMP_UP &&
laraItem->Airborne &&
laraInfo->Control.HandStatus == HandStatus::Free &&
itemIsAbove &&
(result || result2))
{
AlignLaraPosition(&CeilingTrapDoorPos, item, l);
AlignLaraPosition(&CeilingTrapDoorPos, trapDoorItem, laraItem);
if (result2)
l->Position.yRot += ANGLE(180);
laraItem->Position.yRot += ANGLE(180.0f);
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
l->Airborne = false;
l->VerticalVelocity = 0;
l->AnimNumber = LA_TRAPDOOR_CEILING_OPEN;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->ActiveState = LS_FREEFALL_BIS;
ResetLaraFlex(laraItem);
laraItem->VerticalVelocity = 0;
laraItem->Airborne = false;
laraItem->AnimNumber = LA_TRAPDOOR_CEILING_OPEN;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->ActiveState = LS_FREEFALL_BIS;
laraInfo->Control.HandStatus = HandStatus::Busy;
AddActiveItem(itemNumber);
item->Status = ITEM_ACTIVE;
item->TargetState = 1;
trapDoorItem->Status = ITEM_ACTIVE;
trapDoorItem->TargetState = 1;
UseForcedFixedCamera = 1;
ForcedFixedCamera.x = item->Position.xPos - phd_sin(item->Position.yRot) * 1024;
ForcedFixedCamera.y = item->Position.yPos + 1024;
ForcedFixedCamera.z = item->Position.zPos - phd_cos(item->Position.yRot) * 1024;
ForcedFixedCamera.roomNumber = item->RoomNumber;
ForcedFixedCamera.x = trapDoorItem->Position.xPos - phd_sin(trapDoorItem->Position.yRot) * 1024;
ForcedFixedCamera.y = trapDoorItem->Position.yPos + 1024;
ForcedFixedCamera.z = trapDoorItem->Position.zPos - phd_cos(trapDoorItem->Position.yRot) * 1024;
ForcedFixedCamera.roomNumber = trapDoorItem->RoomNumber;
}
else
{
if (item->ActiveState == 1)
if (trapDoorItem->ActiveState == 1)
UseForcedFixedCamera = 0;
}
if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd)
ObjectCollision(itemNumber, l, coll);
if (trapDoorItem->ActiveState == 1 &&
trapDoorItem->FrameNumber == g_Level.Anims[trapDoorItem->AnimNumber].frameEnd)
{
ObjectCollision(itemNumber, laraItem, coll);
}
}
void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item;
auto* laraInfo = GetLaraInfo(laraItem);
auto* trapDoorItem = &g_Level.Items[itemNumber];
item = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION && item->Status != ITEM_ACTIVE && l->ActiveState == LS_IDLE && l->AnimNumber == LA_STAND_IDLE && Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNumber)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraInfo->Control.HandStatus == HandStatus::Free &&
trapDoorItem->Status != ITEM_ACTIVE ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
if (TestLaraPosition(&FloorTrapDoorBounds, item, l))
if (TestLaraPosition(&FloorTrapDoorBounds, trapDoorItem, laraItem))
{
if (MoveLaraPosition(&FloorTrapDoorPos, item, l))
if (MoveLaraPosition(&FloorTrapDoorPos, trapDoorItem, laraItem))
{
l->AnimNumber = LA_TRAPDOOR_FLOOR_OPEN;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->ActiveState = LS_TRAPDOOR_FLOOR_OPEN;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
ResetLaraFlex(laraItem);
laraItem->AnimNumber = LA_TRAPDOOR_FLOOR_OPEN;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->ActiveState = LS_TRAPDOOR_FLOOR_OPEN;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
AddActiveItem(itemNumber);
item->Status = ITEM_ACTIVE;
item->TargetState = 1;
trapDoorItem->Status = ITEM_ACTIVE;
trapDoorItem->TargetState = 1;
UseForcedFixedCamera = 1;
ForcedFixedCamera.x = item->Position.xPos - phd_sin(item->Position.yRot) * 2048;
ForcedFixedCamera.y = item->Position.yPos - 2048;
if (ForcedFixedCamera.y < g_Level.Rooms[item->RoomNumber].maxceiling)
ForcedFixedCamera.y = g_Level.Rooms[item->RoomNumber].maxceiling;
ForcedFixedCamera.z = item->Position.zPos - phd_cos(item->Position.yRot) * 2048;
ForcedFixedCamera.roomNumber = item->RoomNumber;
ForcedFixedCamera.x = trapDoorItem->Position.xPos - phd_sin(trapDoorItem->Position.yRot) * 2048;
ForcedFixedCamera.y = trapDoorItem->Position.yPos - 2048;
if (ForcedFixedCamera.y < g_Level.Rooms[trapDoorItem->RoomNumber].maxceiling)
ForcedFixedCamera.y = g_Level.Rooms[trapDoorItem->RoomNumber].maxceiling;
ForcedFixedCamera.z = trapDoorItem->Position.zPos - phd_cos(trapDoorItem->Position.yRot) * 2048;
ForcedFixedCamera.roomNumber = trapDoorItem->RoomNumber;
}
else
{
Lara.interactedItem =itemNumber;
}
laraInfo->interactedItem =itemNumber;
}
}
else
{
if (item->ActiveState == 1)
if (trapDoorItem->ActiveState == 1)
UseForcedFixedCamera = 0;
}
if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd)
ObjectCollision(itemNumber, l, coll);
if (trapDoorItem->ActiveState == 1 && trapDoorItem->FrameNumber == g_Level.Anims[trapDoorItem->AnimNumber].frameEnd)
ObjectCollision(itemNumber, laraItem, coll);
}
void TrapDoorControl(short itemNumber)
{
ITEM_INFO* item;
auto* trapDoorItem = &g_Level.Items[itemNumber];
item = &g_Level.Items[itemNumber];
if (TriggerActive(item))
if (TriggerActive(trapDoorItem))
{
if (!item->ActiveState && item->TriggerFlags >= 0)
{
item->TargetState = 1;
}
else if (item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd && CurrentLevel == 14 && item->ObjectNumber == ID_TRAPDOOR1)
{
item->Status = ITEM_INVISIBLE;
}
if (!trapDoorItem->ActiveState && trapDoorItem->TriggerFlags >= 0)
trapDoorItem->TargetState = 1;
else if (trapDoorItem->FrameNumber == g_Level.Anims[trapDoorItem->AnimNumber].frameEnd && CurrentLevel == 14 && trapDoorItem->ObjectNumber == ID_TRAPDOOR1)
trapDoorItem->Status = ITEM_INVISIBLE;
}
else
{
item->Status = ITEM_ACTIVE;
trapDoorItem->Status = ITEM_ACTIVE;
if (item->ActiveState == 1)
{
item->TargetState = 0;
}
if (trapDoorItem->ActiveState == 1)
trapDoorItem->TargetState = 0;
}
AnimateItem(item);
AnimateItem(trapDoorItem);
if (item->ActiveState == 1 && (item->ItemFlags[2] || JustLoaded))
{
if (trapDoorItem->ActiveState == 1 && (trapDoorItem->ItemFlags[2] || JustLoaded))
OpenTrapDoor(itemNumber);
}
else if (!item->ActiveState && !item->ItemFlags[2])
{
else if (!trapDoorItem->ActiveState && !trapDoorItem->ItemFlags[2])
CloseTrapDoor(itemNumber);
}
}
void CloseTrapDoor(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
item->ItemFlags[2] = 1;
auto* trapDoorItem = &g_Level.Items[itemNumber];
trapDoorItem->ItemFlags[2] = 1;
}
void OpenTrapDoor(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
item->ItemFlags[2] = 0;
auto* trapDoorItem = &g_Level.Items[itemNumber];
trapDoorItem->ItemFlags[2] = 0;
}
int TrapDoorFloorBorder(short itemNumber)
@ -189,8 +211,8 @@ int TrapDoorCeilingBorder(short itemNumber)
std::optional<int> TrapDoorFloor(short itemNumber, int x, int y, int z)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
if (!item->MeshBits || item->ItemFlags[2] == 0)
ITEM_INFO* trapDoorItem = &g_Level.Items[itemNumber];
if (!trapDoorItem->MeshBits || trapDoorItem->ItemFlags[2] == 0)
return std::nullopt;
return GetBridgeItemIntersect(itemNumber, x, y, z, false);
@ -198,9 +220,9 @@ std::optional<int> TrapDoorFloor(short itemNumber, int x, int y, int z)
std::optional<int> TrapDoorCeiling(short itemNumber, int x, int y, int z)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
ITEM_INFO* trapDoorItem = &g_Level.Items[itemNumber];
if (!item->MeshBits || item->ItemFlags[2] == 0)
if (!trapDoorItem->MeshBits || trapDoorItem->ItemFlags[2] == 0)
return std::nullopt;
return GetBridgeItemIntersect(itemNumber, x, y, z, true);

View file

@ -4,9 +4,9 @@
#include "Game/control/control.h"
void InitialiseTrapDoor(short itemNumber);
void TrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void TrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void TrapDoorControl(short itemNumber);
void CloseTrapDoor(short itemNumber);
void OpenTrapDoor(short itemNumber);

View file

@ -19,15 +19,29 @@ int lastWaterfallY = 0;
PHD_VECTOR TightRopePos = { 0, 0, 0 };
OBJECT_COLLISION_BOUNDS TightRopeBounds =
{ -256, 256, 0, 0, -256, 256, ANGLE(-10), ANGLE(10), ANGLE(-30), ANGLE(30), ANGLE(-10), ANGLE(10) };
{
-256, 256,
0, 0,
-256, 256,
ANGLE(-10.0f), ANGLE(10.0f),
ANGLE(-30.0f), ANGLE(30.0f),
ANGLE(-10.0f), ANGLE(10.0f)
};
OBJECT_COLLISION_BOUNDS ParallelBarsBounds =
{ -640, 640, 704, 832, -96, 96, ANGLE(-10), ANGLE(10), ANGLE(-30), ANGLE(30), ANGLE(-10), ANGLE(10) };
{
-640, 640,
704, 832,
-96, 96,
ANGLE(-10.0f), ANGLE(10.0f),
ANGLE(-30.0f), ANGLE(30.0f),
ANGLE(-10.0f), ANGLE(10.0f)
};
void ControlAnimatingSlots(short itemNumber)
{
// TODO: TR5 has here a series of hardcoded OCB codes, this function actually is just a placeholder
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
if (TriggerActive(item))
AnimateItem(item);
@ -35,7 +49,7 @@ void ControlAnimatingSlots(short itemNumber)
void ControlTriggerTriggerer(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
FLOOR_INFO* floor = GetFloor(item->Position.xPos, item->Position.yPos, item->Position.zPos, &item->RoomNumber);
if (floor->Flags.MarkTriggerer)
@ -81,7 +95,7 @@ void AnimateWaterfalls()
void ControlWaterfall(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
int dx = item->Position.xPos - LaraItem->Position.xPos;
int dy = item->Position.yPos - LaraItem->Position.yPos;
@ -102,219 +116,194 @@ void ControlWaterfall(short itemNumber)
}
}
void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void TightropeCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* tightropeItem = &g_Level.Items[itemNumber];
if (((TrInput & IN_ACTION) == 0
|| l->ActiveState != LS_IDLE
|| l->AnimNumber != LA_STAND_IDLE
|| l->Status == ITEM_INVISIBLE
|| Lara.Control.HandStatus != HandStatus::Free)
&& (!Lara.Control.IsMoving || Lara.interactedItem !=itemNum))
if ((!(TrInput & IN_ACTION) ||
laraItem->ActiveState != LS_IDLE ||
laraItem->AnimNumber != LA_STAND_IDLE ||
laraItem->Status == ITEM_INVISIBLE ||
laraInfo->Control.HandStatus != HandStatus::Free) &&
(!laraInfo->Control.IsMoving || laraInfo->interactedItem !=itemNumber))
{
#ifdef NEW_TIGHTROPE
if(l->ActiveState == LS_TIGHTROPE_WALK &&
l->TargetState != LS_TIGHTROPE_DISMOUNT &&
!Lara.Control.TightropeControl.CanDismount)
if (laraItem->ActiveState == LS_TIGHTROPE_WALK &&
laraItem->TargetState != LS_TIGHTROPE_DISMOUNT &&
!laraInfo->Control.TightropeControl.CanDismount)
{
if(item->Position.yRot == l->Position.yRot)
if (tightropeItem->Position.yRot == laraItem->Position.yRot)
{
if(abs(item->Position.xPos - l->Position.xPos) + abs(item->Position.zPos - l->Position.zPos) < 640)
Lara.Control.TightropeControl.CanDismount = true;
if (abs(tightropeItem->Position.xPos - laraItem->Position.xPos) + abs(tightropeItem->Position.zPos - laraItem->Position.zPos) < 640)
laraInfo->Control.TightropeControl.CanDismount = true;
}
}
#else // !NEW_TIGHTROPE
if(l->ActiveState == LS_TIGHTROPE_WALK &&
l->TargetState != LS_TIGHTROPE_DISMOUNT &&
!Lara.Control.TightropeControl.Off)
if (laraItem->ActiveState == LS_TIGHTROPE_WALK &&
laraItem->TargetState != LS_TIGHTROPE_DISMOUNT &&
!laraInfo->Control.TightropeControl.Off)
{
if(item->Position.yRot == l->Position.yRot)
if (item->Position.yRot == laraItem->Position.yRot)
{
if(abs(item->Position.xPos - l->Position.xPos) + abs(item->Position.zPos - l->Position.zPos) < 640)
Lara.tightRopeOff = true;
if (abs(item->Position.xPos - laraItem->Position.xPos) + abs(item->Position.zPos - laraItem->Position.zPos) < 640)
laraInfo->tightRopeOff = true;
}
}
#endif
}
else
{
item->Position.yRot += -ANGLE(180);
tightropeItem->Position.yRot += -ANGLE(180.0f);
if (TestLaraPosition(&TightRopeBounds, item, l))
if (TestLaraPosition(&TightRopeBounds, tightropeItem, laraItem))
{
if (MoveLaraPosition(&TightRopePos, item, l))
if (MoveLaraPosition(&TightRopePos, tightropeItem, laraItem))
{
l->ActiveState = LS_TIGHTROPE_ENTER;
l->AnimNumber = LA_TIGHTROPE_START;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
laraItem->ActiveState = LS_TIGHTROPE_ENTER;
laraItem->AnimNumber = LA_TIGHTROPE_START;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
ResetLaraFlex(laraItem);
#ifdef NEW_TIGHTROPE
Lara.Control.TightropeControl.Balance = 0;
Lara.Control.TightropeControl.CanDismount = false;
Lara.Control.TightropeControl.TightropeItem = itemNum;
Lara.Control.TightropeControl.TimeOnTightrope = 0;
laraInfo->Control.TightropeControl.Balance = 0;
laraInfo->Control.TightropeControl.CanDismount = false;
laraInfo->Control.TightropeControl.TightropeItem = itemNumber;
laraInfo->Control.TightropeControl.TimeOnTightrope = 0;
#else // !NEW_TIGHTROPE
Lara.tightRopeOnCount = 60;
Lara.tightRopeOff = 0;
Lara.tightRopeFall = 0;
laraInfo->Control.TightropeControl.OnCount = 60;
laraInfo->Control.TightropeControl.Off = 0;
laraInfo->Control.TightropeControl.Fall = 0;
#endif
}
else
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
item->Position.yRot += -ANGLE(180);
tightropeItem->Position.yRot += -ANGLE(180.0f);
}
else
{
if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
Lara.Control.IsMoving = false;
if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
laraInfo->Control.IsMoving = false;
item->Position.yRot += -ANGLE(180);
tightropeItem->Position.yRot += -ANGLE(180.0f);
}
}
}
void ParallelBarsCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void HorizontalBarCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION && l->ActiveState == LS_REACH && l->AnimNumber == LA_REACH)
auto* laraInfo = GetLaraInfo(laraItem);
auto* barItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_REACH &&
laraItem->AnimNumber == LA_REACH)
{
int test1 = TestLaraPosition(&ParallelBarsBounds, item, l);
int test1 = TestLaraPosition(&ParallelBarsBounds, barItem, laraItem);
int test2 = 0;
if (!test1)
{
item->Position.yRot += -ANGLE(180);
test2 = TestLaraPosition(&ParallelBarsBounds, item, l);
item->Position.yRot += -ANGLE(180);
barItem->Position.yRot += -ANGLE(180.0f);
test2 = TestLaraPosition(&ParallelBarsBounds, barItem, laraItem);
barItem->Position.yRot += -ANGLE(180);
}
if (test1 || test2)
{
l->ActiveState = LS_MISC_CONTROL;
l->AnimNumber = LA_SWINGBAR_GRAB;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->VerticalVelocity = false;
l->Airborne = false;
laraItem->ActiveState = LS_MISC_CONTROL;
laraItem->AnimNumber = LA_SWINGBAR_GRAB;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->VerticalVelocity = false;
laraItem->Airborne = false;
ResetLaraFlex(item);
ResetLaraFlex(barItem);
if (test1)
l->Position.yRot = item->Position.yRot;
laraItem->Position.yRot = barItem->Position.yRot;
else
l->Position.yRot = item->Position.yRot + -ANGLE(180);
PHD_VECTOR pos1;
pos1.x = 0;
pos1.y = -128;
pos1.z = 512;
PHD_VECTOR pos2;
pos2.x = 0;
pos2.y = -128;
pos2.z = 512;
laraItem->Position.yRot = barItem->Position.yRot + -ANGLE(180.0f);
PHD_VECTOR pos1 = { 0, -128, 512 };
GetLaraJointPosition(&pos1, LM_LHAND);
PHD_VECTOR pos2 = { 0, -128, 512 };
GetLaraJointPosition(&pos2, LM_RHAND);
if (l->Position.yRot & 0x4000)
l->Position.xPos += item->Position.xPos - ((pos1.x + pos2.x) >> 1);
if (laraItem->Position.yRot & 0x4000)
laraItem->Position.xPos += barItem->Position.xPos - ((pos1.x + pos2.x) >> 1);
else
l->Position.zPos += item->Position.zPos - ((pos1.z + pos2.z) / 2);
l->Position.yPos += item->Position.yPos - ((pos1.y + pos2.y) / 2);
laraItem->Position.zPos += barItem->Position.zPos - ((pos1.z + pos2.z) / 2);
laraItem->Position.yPos += barItem->Position.yPos - ((pos1.y + pos2.y) / 2);
Lara.interactedItem = itemNumber;
laraInfo->interactedItem = itemNumber;
}
else
{
ObjectCollision(itemNumber, l, coll);
}
}
else if (l->ActiveState != LS_HORIZONTAL_BAR_SWING)
{
ObjectCollision(itemNumber, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
}
else if (laraItem->ActiveState != LS_HORIZONTAL_BAR_SWING)
ObjectCollision(itemNumber, laraItem, coll);
}
void CutsceneRopeControl(short itemNumber)
{
ITEM_INFO* item;
PHD_VECTOR pos1;
PHD_VECTOR pos2;
int dx;
int dy;
int dz;
auto* ropeItem = &g_Level.Items[itemNumber];
item = &g_Level.Items[itemNumber];
PHD_VECTOR pos1 = { -128, -72, -16 };
GetJointAbsPosition(&g_Level.Items[ropeItem->ItemFlags[2]], &pos1, 0);
pos1.x = -128;
pos1.y = -72;
pos1.z = -16;
GetJointAbsPosition(&g_Level.Items[item->ItemFlags[2]], &pos1, 0);
PHD_VECTOR pos2 = { 830, -12, 0 };
GetJointAbsPosition(&g_Level.Items[ropeItem->ItemFlags[3]], &pos2, 0);
pos2.x = 830;
pos2.z = -12;
pos2.y = 0;
GetJointAbsPosition(&g_Level.Items[item->ItemFlags[3]], &pos2, 0);
ropeItem->Position.xPos = pos2.x;
ropeItem->Position.yPos = pos2.y;
ropeItem->Position.zPos = pos2.z;
item->Position.xPos = pos2.x;
item->Position.yPos = pos2.y;
item->Position.zPos = pos2.z;
int dx = (pos2.x - pos1.x) * (pos2.x - pos1.x);
int dy = (pos2.y - pos1.y) * (pos2.y - pos1.y);
int dz = (pos2.z - pos1.z) * (pos2.z - pos1.z);
dx = (pos2.x - pos1.x) * (pos2.x - pos1.x);
dy = (pos2.y - pos1.y) * (pos2.y - pos1.y);
dz = (pos2.z - pos1.z) * (pos2.z - pos1.z);
item->ItemFlags[1] = ((sqrt(dx + dy + dz) * 2) + sqrt(dx + dy + dz)) * 2;
item->Position.xRot = -4869;
ropeItem->ItemFlags[1] = ((sqrt(dx + dy + dz) * 2) + sqrt(dx + dy + dz)) * 2;
ropeItem->Position.xRot = -4869;
}
void HybridCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll)
void HybridCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* coll)
{
ITEM_INFO* item;
item = &g_Level.Items[itemNum];
auto* item = &g_Level.Items[itemNumber];
/*if (gfCurrentLevel == LVL5_SINKING_SUBMARINE)
{
if (item->frameNumber < g_Level.Anims[item->animNumber].frame_end)
{
ObjectCollision(itemNum, laraitem, coll);
ObjectCollision(itemNumber, laraitem, coll);
}
}*/
}
void InitialiseTightRope(short itemNumber)
void InitialiseTightrope(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* tightropeItem = &g_Level.Items[itemNumber];
if (item->Position.yRot > 0)
if (tightropeItem->Position.yRot > 0)
{
if (item->Position.yRot == ANGLE(90))
item->Position.xPos -= 256;
if (tightropeItem->Position.yRot == ANGLE(90.0f))
tightropeItem->Position.xPos -= 256;
}
else if (item->Position.yRot)
else if (tightropeItem->Position.yRot)
{
if (item->Position.yRot == -ANGLE(180))
{
item->Position.zPos += 256;
}
else if (item->Position.yRot == -ANGLE(90))
{
item->Position.xPos += 256;
}
if (tightropeItem->Position.yRot == -ANGLE(180.0f))
tightropeItem->Position.zPos += CLICK(1);
else if (tightropeItem->Position.yRot == -ANGLE(90.0f))
tightropeItem->Position.xPos += CLICK(1);
}
else
{
item->Position.zPos -= 256;
}
tightropeItem->Position.zPos -= CLICK(1);
}
void InitialiseAnimating(short itemNumber)
{
/*ITEM_INFO* item = &g_Level.Items[itemNumber];
/*auto* item = &g_Level.Items[itemNumber];
item->ActiveState = 0;
item->animNumber = Objects[item->objectNumber].animIndex;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;*/
@ -322,7 +311,7 @@ void InitialiseAnimating(short itemNumber)
void AnimatingControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
if (!TriggerActive(item))
return;
@ -342,12 +331,11 @@ void AnimatingControl(short itemNumber)
void HighObject2Control(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
if (!TriggerActive(item))
return;
if (!item->ItemFlags[2])
{
int div = item->TriggerFlags % 10 << 10;
@ -359,7 +347,7 @@ void HighObject2Control(short itemNumber)
if (--item->ItemFlags[2] < 15)
{
SPARKS* spark = &Sparks[GetFreeSpark()];
auto* spark = &Sparks[GetFreeSpark()];
spark->on = 1;
spark->sR = -1;
spark->sB = 16;

View file

@ -12,12 +12,12 @@ void ControlAnimatingSlots(short itemNumber);
void ControlTriggerTriggerer(short itemNumber);
void AnimateWaterfalls();
void ControlWaterfall(short itemNumber);
void TightRopeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void ParallelBarsCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void TightropeCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void HorizontalBarCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void CutsceneRopeControl(short itemNumber);
void HybridCollision(short itemNum, ITEM_INFO* laraitem, COLL_INFO* coll);
void HybridCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void InitialiseSmashObject(short itemNumber);
void InitialiseTightRope(short itemNumber);
void InitialiseTightrope(short itemNumber);
void HighObject2Control(short itemNumber);
void InitialiseAnimating(short itemNumber);
void AnimatingControl(short itemNumber);

View file

@ -5,6 +5,7 @@
#include "Game/items.h"
#include "Game/control/lot.h"
#include "Specific/input.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara_tests.h"
#include "Game/Lara/lara.h"
@ -22,94 +23,98 @@ namespace TEN::Entities::Generic
-256, 256,
0, 0,
-512, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void PoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
auto item = &g_Level.Items[itemNumber];
auto isLara = (!item->Data.is<LaraInfo*>());
auto* laraInfo = GetLaraInfo(laraItem);
auto* poleItem = &g_Level.Items[itemNumber];
if (isLara &&
TrInput & IN_ACTION &&
Lara.Control.HandStatus == HandStatus::Free &&
l->ActiveState == LS_IDLE &&
l->AnimNumber == LA_STAND_IDLE || Lara.Control.IsMoving &&
Lara.interactedItem == itemNumber)
{
short rot = item->Position.yRot;
item->Position.yRot = l->Position.yRot;
bool isLara = !poleItem->Data.is<LaraInfo*>();
if (TestLaraPosition(&PoleBounds, item, l))
if (TrInput & IN_ACTION && isLara &&
laraInfo->Control.HandStatus == HandStatus::Free &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE || laraInfo->Control.IsMoving &&
laraInfo->interactedItem == itemNumber)
{
if (MoveLaraPosition(&PolePos, item, l))
short rot = poleItem->Position.yRot;
poleItem->Position.yRot = laraItem->Position.yRot;
if (TestLaraPosition(&PoleBounds, poleItem, laraItem))
{
l->AnimNumber = LA_STAND_TO_POLE;
l->ActiveState = LS_POLE_IDLE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
if (MoveLaraPosition(&PolePos, poleItem, laraItem))
{
laraItem->AnimNumber = LA_STAND_TO_POLE;
laraItem->ActiveState = LS_POLE_IDLE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
}
else
laraInfo->interactedItem = itemNumber;
poleItem->Position.yRot = rot;
}
else
{
Lara.interactedItem = itemNumber;
if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
item->Position.yRot = rot;
poleItem->Position.yRot = rot;
}
}
else if (TrInput & IN_ACTION && isLara &&
laraInfo->Control.HandStatus == HandStatus::Free &&
laraItem->Airborne &&
laraItem->VerticalVelocity > (int)laraInfo->Control.HandStatus && // ?????
laraItem->ActiveState == LS_REACH || laraItem->ActiveState == LS_JUMP_UP)
{
if (TestBoundsCollide(poleItem, laraItem, 100) &&
TestLaraPoleCollision(laraItem, coll, true, -CLICK(1)) &&
TestLaraPoleCollision(laraItem, coll, false))
{
if (TestCollision(poleItem, laraItem))
{
short rot = poleItem->Position.yRot;
poleItem->Position.yRot = laraItem->Position.yRot;
if (laraItem->ActiveState == LS_REACH)
{
PolePosR.y = laraItem->Position.yPos - poleItem->Position.yPos + 10;
AlignLaraPosition(&PolePosR, poleItem, laraItem);
laraItem->AnimNumber = LA_REACH_TO_POLE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
}
else
{
if (Lara.Control.IsMoving && Lara.interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
PolePosR.y = laraItem->Position.yPos - poleItem->Position.yPos + 66;
AlignLaraPosition(&PolePosR, poleItem, laraItem);
laraItem->AnimNumber = LA_JUMP_UP_TO_POLE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
}
item->Position.yRot = rot;
}
}
else if (isLara &&
TrInput & IN_ACTION &&
Lara.Control.HandStatus == HandStatus::Free &&
l->Airborne &&
l->VerticalVelocity > (int)Lara.Control.HandStatus &&
l->ActiveState == LS_REACH || l->ActiveState == LS_JUMP_UP)
{
if (TestBoundsCollide(item, l, 100) &&
TestLaraPoleCollision(l, coll, true, -STEP_SIZE) &&
TestLaraPoleCollision(l, coll, false))
{
if (TestCollision(item, l))
{
short rot = item->Position.yRot;
item->Position.yRot = l->Position.yRot;
if (l->ActiveState == LS_REACH)
{
PolePosR.y = l->Position.yPos - item->Position.yPos + 10;
AlignLaraPosition(&PolePosR, item, l);
l->AnimNumber = LA_REACH_TO_POLE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
}
else
{
PolePosR.y = l->Position.yPos - item->Position.yPos + 66;
AlignLaraPosition(&PolePosR, item, l);
l->AnimNumber = LA_JUMP_UP_TO_POLE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
}
l->Airborne = false;
l->VerticalVelocity = false;
l->ActiveState = LS_POLE_IDLE;
Lara.Control.HandStatus = HandStatus::Busy;
item->Position.yRot = rot;
laraItem->ActiveState = LS_POLE_IDLE;
laraItem->VerticalVelocity = 0;
laraItem->Airborne = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
poleItem->Position.yRot = rot;
}
}
}
else
{
if (!isLara ||
((l->ActiveState < LS_POLE_IDLE || l->ActiveState > LS_POLE_TURN_COUNTER_CLOCKWISE) && l->ActiveState != LS_JUMP_BACK))
ObjectCollision(itemNumber, l, coll);
if (!isLara || ((laraItem->ActiveState < LS_POLE_IDLE ||
laraItem->ActiveState > LS_POLE_TURN_COUNTER_CLOCKWISE) &&
laraItem->ActiveState != LS_JUMP_BACK))
{
ObjectCollision(itemNumber, laraItem, coll);
}
}
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Generic
{
void PoleCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void PoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -5,6 +5,7 @@
#include "Game/items.h"
#include "Game/control/lot.h"
#include "Specific/input.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara.h"
#include "Specific/trmath.h"
@ -23,11 +24,10 @@ namespace TEN::Entities::Generic
void InitialiseRope(short itemNumber)
{
PHD_VECTOR itemPos;
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
short roomNumber = item->RoomNumber;
PHD_VECTOR itemPos;
itemPos.x = item->Position.xPos;
itemPos.y = item->Position.yPos;
itemPos.z = item->Position.zPos;
@ -35,13 +35,9 @@ namespace TEN::Entities::Generic
FLOOR_INFO* floor = GetFloor(itemPos.x, itemPos.y, itemPos.z, &roomNumber);
itemPos.y = GetCeiling(floor, itemPos.x, itemPos.y, itemPos.z);
PHD_VECTOR pos;
pos.x = 0;
pos.y = 16384;
pos.z = 0;
PHD_VECTOR pos = { 0, 16384, 0 };
ROPE_STRUCT rope;
PrepareRope(&rope, &itemPos, &pos, 128, item);
PrepareRope(&rope, &itemPos, &pos, CLICK(0.5f), item);
item->TriggerFlags = Ropes.size();
@ -154,106 +150,98 @@ namespace TEN::Entities::Generic
angle[0] = phd_atan(sqrt(SQUARE(matrix[M22]) + SQUARE(matrix[M02])), matrix[M12]);
if (matrix[M12] >= 0 && angle[0] > 0 || matrix[M12] < 0 && angle[0] < 0)
angle[0] = -angle[0];
angle[1] = phd_atan(matrix[M22], matrix[M02]);
angle[2] = phd_atan(matrix[M00] * phd_cos(angle[1]) - matrix[M20] * phd_sin(angle[1]), matrix[M21] * phd_sin(angle[1]) - matrix[M01] * phd_cos(angle[1]));
}
void RopeControl(short itemNumber)
{
ITEM_INFO* item;
ROPE_STRUCT* rope;
auto* item = &g_Level.Items[itemNumber];
auto* rope = &Ropes[item->TriggerFlags];
item = &g_Level.Items[itemNumber];
rope = &Ropes[item->TriggerFlags];
if (TriggerActive(item))
{
rope->active = 1;
RopeDynamics(rope);
}
else
{
rope->active = 0;
}
}
void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void RopeCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item;
ROPE_STRUCT* rope;
BOUNDING_BOX* frame;
int segment;
auto* laraInfo = GetLaraInfo(laraItem);
auto* ropeItem = &g_Level.Items[itemNumber];
auto* rope = &Ropes[ropeItem->TriggerFlags];
item = &g_Level.Items[itemNumber];
rope = &Ropes[item->TriggerFlags];
if (TrInput & IN_ACTION
&& Lara.Control.HandStatus == HandStatus::Free
&& (l->ActiveState == LS_REACH
|| l->ActiveState == LS_JUMP_UP)
&& l->Airborne
&& l->VerticalVelocity > 0
&& rope->active)
if (TrInput & IN_ACTION &&
laraInfo->Control.HandStatus == HandStatus::Free &&
(laraItem->ActiveState == LS_REACH || laraItem->ActiveState == LS_JUMP_UP) &&
laraItem->Airborne &&
laraItem->VerticalVelocity > 0&&
rope->active)
{
frame = GetBoundsAccurate(l);
auto* frame = GetBoundsAccurate(laraItem);
segment = RopeNodeCollision(
int segment = RopeNodeCollision(
rope,
l->Position.xPos,
l->Position.yPos + frame->Y1 + 512,
l->Position.zPos + frame->Z2 * phd_cos(l->Position.yRot),
l->ActiveState == LS_REACH ? 128 : 320);
laraItem->Position.xPos,
laraItem->Position.yPos + frame->Y1 + 512,
laraItem->Position.zPos + frame->Z2 * phd_cos(laraItem->Position.yRot),
laraItem->ActiveState == LS_REACH ? 128 : 320);
if (segment >= 0)
{
if (l->ActiveState == LS_REACH)
if (laraItem->ActiveState == LS_REACH)
{
l->AnimNumber = LA_REACH_TO_ROPE_SWING;
l->ActiveState = LS_ROPE_SWING;
Lara.Control.RopeControl.Frame = g_Level.Anims[LA_ROPE_SWING].frameBase + 32 << 8;
Lara.Control.RopeControl.DFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 60 << 8;
laraItem->AnimNumber = LA_REACH_TO_ROPE_SWING;
laraItem->ActiveState = LS_ROPE_SWING;
laraInfo->Control.RopeControl.Frame = g_Level.Anims[LA_ROPE_SWING].frameBase + 32 << 8;
laraInfo->Control.RopeControl.DFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 60 << 8;
}
else
{
l->AnimNumber = LA_JUMP_UP_TO_ROPE_START;
l->ActiveState = LS_ROPE_IDLE;
laraItem->AnimNumber = LA_JUMP_UP_TO_ROPE_START;
laraItem->ActiveState = LS_ROPE_IDLE;
}
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->Airborne = false;
l->VerticalVelocity = 0;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->VerticalVelocity = 0;
laraItem->Airborne = false;
Lara.Control.HandStatus = HandStatus::Busy;
Lara.Control.RopeControl.Ptr = item->TriggerFlags;
Lara.Control.RopeControl.Segment = segment;
Lara.Control.RopeControl.Y = l->Position.yRot;
laraInfo->Control.HandStatus = HandStatus::Busy;
laraInfo->Control.RopeControl.Ptr = ropeItem->TriggerFlags;
laraInfo->Control.RopeControl.Segment = segment;
laraInfo->Control.RopeControl.Y = laraItem->Position.yRot;
DelAlignLaraToRope(l);
DelAlignLaraToRope(laraItem);
CurrentPendulum.velocity.x = 0;
CurrentPendulum.velocity.y = 0;
CurrentPendulum.velocity.z = 0;
ApplyVelocityToRope(segment, l->Position.yRot, 16 * LaraItem->Velocity);
ApplyVelocityToRope(segment, laraItem->Position.yRot, 16 * laraItem->Velocity);
}
}
}
void RopeDynamics(ROPE_STRUCT* rope)
{
int flag, i;
PENDULUM* pendulumPointer;
PHD_VECTOR vec, vec2;
flag = 0;
int flag = 0;
if (rope->coiled)
{
--rope->coiled;
if (!rope->coiled)
{
for (i = 0; i < ROPE_SEGMENTS; ++i)
for (int i = 0; i < ROPE_SEGMENTS; ++i)
rope->velocity[i].y = 0;
}
}
if (Lara.Control.RopeControl.Ptr != -1 && rope == &Ropes[Lara.Control.RopeControl.Ptr])
{
pendulumPointer = &CurrentPendulum;
@ -268,12 +256,13 @@ namespace TEN::Entities::Generic
pendulumPointer = &AlternatePendulum;
if (Lara.Control.RopeControl.Ptr == -1 && CurrentPendulum.rope)
{
for (i = 0; i < CurrentPendulum.node; i++)
for (int i = 0; i < CurrentPendulum.node; i++)
{
CurrentPendulum.rope->velocity[i].x = CurrentPendulum.rope->velocity[CurrentPendulum.node].x;
CurrentPendulum.rope->velocity[i].y = CurrentPendulum.rope->velocity[CurrentPendulum.node].y;
CurrentPendulum.rope->velocity[i].z = CurrentPendulum.rope->velocity[CurrentPendulum.node].z;
}
CurrentPendulum.position.x = 0;
CurrentPendulum.position.y = 0;
CurrentPendulum.position.z = 0;
@ -286,6 +275,7 @@ namespace TEN::Entities::Generic
CurrentPendulum.rope = NULL;
}
}
if (Lara.Control.RopeControl.Ptr != -1)
{
vec.x = pendulumPointer->position.x - rope->segment[0].x;
@ -293,7 +283,7 @@ namespace TEN::Entities::Generic
vec.z = pendulumPointer->position.z - rope->segment[0].z;
NormaliseRopeVector(&vec);
for (i = pendulumPointer->node; i >= 0; --i)
for (int i = pendulumPointer->node; i >= 0; --i)
{
rope->segment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * vec.x >> FP_SHIFT);
rope->segment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * vec.y >> FP_SHIFT);
@ -314,7 +304,7 @@ namespace TEN::Entities::Generic
rope->segment[pendulumPointer->node].y = pendulumPointer->position.y;
rope->segment[pendulumPointer->node].z = pendulumPointer->position.z;
for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
for (int i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
{
rope->segment[i].x -= vec2.x;
rope->segment[i].y -= vec2.y;
@ -325,6 +315,7 @@ namespace TEN::Entities::Generic
rope->velocity[i].z = 0;
}
}
ModelRigidRope(
rope,
pendulumPointer,
@ -341,7 +332,8 @@ namespace TEN::Entities::Generic
pendulumPointer->velocity.x -= pendulumPointer->velocity.x >> 8;
pendulumPointer->velocity.z -= pendulumPointer->velocity.z >> 8;
}
for (i = pendulumPointer->node; i < ROPE_SEGMENTS - 1; ++i)
for (int i = pendulumPointer->node; i < ROPE_SEGMENTS - 1; ++i)
ModelRigid(
&rope->segment[i],
&rope->segment[i + 1],
@ -349,14 +341,14 @@ namespace TEN::Entities::Generic
&rope->velocity[i + 1],
rope->segmentLength);
for (i = 0; i < ROPE_SEGMENTS; ++i)
for (int i = 0; i < ROPE_SEGMENTS; ++i)
{
rope->segment[i].x += rope->velocity[i].x;
rope->segment[i].y += rope->velocity[i].y;
rope->segment[i].z += rope->velocity[i].z;
}
for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
for (int i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
{
rope->velocity[i].y += 3 << FP_SHIFT;
@ -371,6 +363,7 @@ namespace TEN::Entities::Generic
rope->velocity[i].z -= rope->velocity[i].z >> 4;
}
}
rope->segment[0].x = 0;
rope->segment[0].y = 0;
rope->segment[0].z = 0;
@ -379,7 +372,7 @@ namespace TEN::Entities::Generic
rope->velocity[0].y = 0;
rope->velocity[0].z = 0;
for (i = 0; i < ROPE_SEGMENTS - 1; ++i)
for (INT i = 0; i < ROPE_SEGMENTS - 1; ++i)
{
rope->normalisedSegment[i].x = rope->segment[i + 1].x - rope->segment[i].x;
rope->normalisedSegment[i].y = rope->segment[i + 1].y - rope->segment[i].y;
@ -397,7 +390,7 @@ namespace TEN::Entities::Generic
rope->meshSegment[1].y = rope->segment[0].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].y >> FP_SHIFT);
rope->meshSegment[1].z = rope->segment[0].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].z >> FP_SHIFT);
for (i = 2; i < ROPE_SEGMENTS; i++)
for (int i = 2; i < ROPE_SEGMENTS; i++)
{
rope->meshSegment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].x >> FP_SHIFT);
rope->meshSegment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].y >> FP_SHIFT);
@ -414,14 +407,14 @@ namespace TEN::Entities::Generic
rope->meshSegment[pendulumPointer->node + 1].y = rope->segment[pendulumPointer->node].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].y >> FP_SHIFT);
rope->meshSegment[pendulumPointer->node + 1].z = rope->segment[pendulumPointer->node].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].z >> FP_SHIFT);
for (i = pendulumPointer->node + 1; i < ROPE_SEGMENTS - 1; ++i)
for (int i = pendulumPointer->node + 1; i < ROPE_SEGMENTS - 1; ++i)
{
rope->meshSegment[i + 1].x = rope->meshSegment[i].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].x >> FP_SHIFT);
rope->meshSegment[i + 1].y = rope->meshSegment[i].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].y >> FP_SHIFT);
rope->meshSegment[i + 1].z = rope->meshSegment[i].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].z >> FP_SHIFT);
}
for (i = 0; i < pendulumPointer->node; i++)
for (int i = 0; i < pendulumPointer->node; i++)
{
rope->meshSegment[i].x = rope->segment[i].x;
rope->meshSegment[i].y = rope->segment[i].y;
@ -432,20 +425,20 @@ namespace TEN::Entities::Generic
int RopeNodeCollision(ROPE_STRUCT* rope, int x, int y, int z, int radius)
{
int dx, dy, dz;
for (int i = 0; i < ROPE_SEGMENTS - 2; ++i)
{
if (y > rope->position.y + (rope->meshSegment[i].y >> FP_SHIFT)
&& y < rope->position.y + (rope->meshSegment[i + 1].y >> FP_SHIFT))
{
dx = x - ((rope->meshSegment[i + 1].x + rope->meshSegment[i].x) >> (FP_SHIFT + 1)) - rope->position.x;
dy = y - ((rope->meshSegment[i + 1].y + rope->meshSegment[i].y) >> (FP_SHIFT + 1)) - rope->position.y;
dz = z - ((rope->meshSegment[i + 1].z + rope->meshSegment[i].z) >> (FP_SHIFT + 1)) - rope->position.z;
if (SQUARE(dx) + SQUARE(dy) + SQUARE(dz) < SQUARE(radius + 64))
int dx = x - ((rope->meshSegment[i + 1].x + rope->meshSegment[i].x) >> (FP_SHIFT + 1)) - rope->position.x;
int dy = y - ((rope->meshSegment[i + 1].y + rope->meshSegment[i].y) >> (FP_SHIFT + 1)) - rope->position.y;
int dz = z - ((rope->meshSegment[i + 1].z + rope->meshSegment[i].z) >> (FP_SHIFT + 1)) - rope->position.z;
if (pow(dx, 2) + pow(dy, 2) + pow(dz, 2) < pow(radius + 64, 2))
return i;
}
}
return -1;
}
@ -456,9 +449,7 @@ namespace TEN::Entities::Generic
void SetPendulumVelocity(int x, int y, int z)
{
int node;
node = 2 * (CurrentPendulum.node >> 1);
int node = 2 * (CurrentPendulum.node >> 1);
if (node < ROPE_SEGMENTS)
{
int val = 4096 / (ROPE_SEGMENTS - node) * 256;
@ -493,13 +484,11 @@ namespace TEN::Entities::Generic
void ModelRigidRope(ROPE_STRUCT* rope, PENDULUM* pendulumPointer, PHD_VECTOR* ropeVelocity, PHD_VECTOR* pendulumVelocity, int value)
{
PHD_VECTOR vec;
int result;
vec.x = pendulumPointer->position.x + pendulumVelocity->x - rope->segment[0].x;
vec.y = pendulumPointer->position.y + pendulumVelocity->y - rope->segment[0].y;
vec.z = pendulumPointer->position.z + pendulumVelocity->z - rope->segment[0].z;
result = 65536 * sqrt(abs(SQUARE(vec.x >> FP_SHIFT) + SQUARE(vec.y >> FP_SHIFT) + SQUARE(vec.z >> FP_SHIFT))) - value;
int result = 65536 * sqrt(abs(pow(vec.x >> FP_SHIFT, 2) + pow(vec.y >> FP_SHIFT, 2) + pow(vec.z >> FP_SHIFT, 2))) - value;
NormaliseRopeVector(&vec);
pendulumVelocity->x -= (int64_t)result * vec.x >> FP_SHIFT;
@ -510,13 +499,11 @@ namespace TEN::Entities::Generic
void ModelRigid(PHD_VECTOR* segment, PHD_VECTOR* nextSegment, PHD_VECTOR* velocity, PHD_VECTOR* nextVelocity, int length)
{
PHD_VECTOR vec;
int result;
vec.x = nextSegment->x + nextVelocity->x - segment->x - velocity->x;
vec.y = nextSegment->y + nextVelocity->y - segment->y - velocity->y;
vec.z = nextSegment->z + nextVelocity->z - segment->z - velocity->z;
result = (65536 * sqrt(abs(SQUARE(vec.x >> FP_SHIFT) + SQUARE(vec.y >> FP_SHIFT) + SQUARE(vec.z >> FP_SHIFT))) - length) / 2;
int result = (65536 * sqrt(abs(pow(vec.x >> FP_SHIFT, 2) + pow(vec.y >> FP_SHIFT, 2) + pow(vec.z >> FP_SHIFT, 2))) - length) / 2;
NormaliseRopeVector(&vec);
vec.x = (int64_t)result * vec.x >> FP_SHIFT;
@ -535,14 +522,10 @@ namespace TEN::Entities::Generic
void UpdateRopeSwing(ITEM_INFO* item)
{
if (Lara.Control.RopeControl.MaxXForward > 9000)
{
Lara.Control.RopeControl.MaxXForward = 9000;
}
if (Lara.Control.RopeControl.MaxXBackward > 9000)
{
Lara.Control.RopeControl.MaxXBackward = 9000;
}
if (Lara.Control.RopeControl.Direction)
{
@ -552,15 +535,14 @@ namespace TEN::Entities::Generic
Lara.Control.RopeControl.Direction = 0;
Lara.Control.RopeControl.MaxXBackward = 0;
int frame = 15 * Lara.Control.RopeControl.MaxXForward / 18000 + g_Level.Anims[LA_ROPE_SWING].frameBase + 47 << 8;
if (frame > Lara.Control.RopeControl.DFrame)
{
Lara.Control.RopeControl.DFrame = frame;
RopeSwing = 1;
}
else
{
RopeSwing = 0;
}
SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->Position, 0);
}
@ -573,7 +555,6 @@ namespace TEN::Entities::Generic
else if (Lara.Control.RopeControl.FrameRate < 512)
{
int num = RopeSwing ? 31 : 7;
Lara.Control.RopeControl.FrameRate += num * Lara.Control.RopeControl.MaxXBackward / 9000 + 1;
}
}
@ -584,6 +565,7 @@ namespace TEN::Entities::Generic
Lara.Control.RopeControl.ArcBack = Lara.Control.RopeControl.LastX;
Lara.Control.RopeControl.Direction = 1;
Lara.Control.RopeControl.MaxXForward = 0;
int frame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.Control.RopeControl.MaxXBackward / 18000 + 17 << 8;
if (frame < Lara.Control.RopeControl.DFrame)
{
@ -591,23 +573,19 @@ namespace TEN::Entities::Generic
RopeSwing = 1;
}
else
{
RopeSwing = 0;
}
SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->Position, 0);
}
else if (Lara.Control.RopeControl.LastX > 0 && Lara.Control.RopeControl.Frame == Lara.Control.RopeControl.DFrame)
{
RopeSwing = 0;
Lara.Control.RopeControl.DFrame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.Control.RopeControl.MaxXForward / 18000 + 17 << 8;
Lara.Control.RopeControl.FrameRate = 15 * Lara.Control.RopeControl.MaxXForward / 9000 + 1;
}
else if (Lara.Control.RopeControl.FrameRate < 512)
{
int num = RopeSwing ? 31 : 7;
Lara.Control.RopeControl.FrameRate += num * Lara.Control.RopeControl.MaxXForward / 9000 + 1;
}
}
@ -646,22 +624,15 @@ namespace TEN::Entities::Generic
Lara.Control.HandStatus = HandStatus::Free;
if (item->FrameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 42)
{
item->AnimNumber = LA_ROPE_SWING_TO_REACH_1;
}
else if (item->FrameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 21)
{
item->AnimNumber = LA_ROPE_SWING_TO_REACH_2;
}
else
{
item->AnimNumber = LA_ROPE_SWING_TO_REACH_3;
}
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
item->ActiveState = LS_REACH;
item->TargetState = LS_REACH;
Lara.Control.RopeControl.Ptr = -1;
}
}
@ -687,20 +658,21 @@ namespace TEN::Entities::Generic
void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll)
{
if (!(TrInput & IN_ACTION))
{
FallFromRope(item);
}
else
{
Camera.targetAngle = ANGLE(30.0f);
if (Lara.Control.RopeControl.Count)
{
if (!Lara.Control.RopeControl.Flag)
{
--Lara.Control.RopeControl.Count;
Lara.Control.RopeControl.Offset += Lara.Control.RopeControl.DownVel;
if (!Lara.Control.RopeControl.Count)
Lara.Control.RopeControl.Flag = 1;
return;
}
}

View file

@ -21,16 +21,17 @@ namespace TEN::Entities::Switches
-512, 512,
0, 0,
-1536, -512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR CogSwitchPos(0, 0, -856);
void CogSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void CogSwitchCollision(short itemNum, ITEM_INFO* laraItem, COLL_INFO* coll)
{
auto item = &g_Level.Items[itemNum];
auto triggerIndex = GetTriggerIndex(item);
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNum];
auto* triggerIndex = GetTriggerIndex(switchItem);
int targetItemNum;
ITEM_INFO* target = nullptr;
@ -57,39 +58,39 @@ namespace TEN::Entities::Switches
if (door == nullptr)
{
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNum, laraItem, coll);
return;
}
// Door is found, attach to it.
if (item->Status == ITEM_NOT_ACTIVE)
if (switchItem->Status == ITEM_NOT_ACTIVE)
{
if (!(item->Flags & ONESHOT)
&& (TrInput & IN_ACTION
&& Lara.Control.HandStatus == HandStatus::Free
&& !item->Airborne
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
|| Lara.Control.IsMoving
&& Lara.interactedItem == itemNum))
if (!(switchItem->Flags & ONESHOT) &&
(TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraInfo->Control.HandStatus == HandStatus::Free &&
!switchItem->Airborne ||
laraInfo->Control.IsMoving &&
laraInfo->interactedItem == itemNum))
{
if (TestLaraPosition(&CogSwitchBounds, item, l))
if (TestLaraPosition(&CogSwitchBounds, switchItem, laraItem))
{
if (MoveLaraPosition(&CogSwitchPos, item, l))
if (MoveLaraPosition(&CogSwitchPos, switchItem, laraItem))
{
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
Lara.interactedItem = targetItemNum;
l->AnimNumber = LA_COGWHEEL_GRAB;
l->TargetState = LS_COGWHEEL;
l->ActiveState = LS_COGWHEEL;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
ResetLaraFlex(laraItem);
laraItem->AnimNumber = LA_COGWHEEL_GRAB;
laraItem->TargetState = LS_COGWHEEL;
laraItem->ActiveState = LS_COGWHEEL;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
laraInfo->interactedItem = targetItemNum;
AddActiveItem(itemNum);
item->TargetState = SWITCH_ON;
item->Status = ITEM_ACTIVE;
switchItem->TargetState = SWITCH_ON;
switchItem->Status = ITEM_ACTIVE;
if (door != NULL)
{
@ -101,51 +102,50 @@ namespace TEN::Entities::Switches
}
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNum;
return;
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNum)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNum, laraItem, coll);
}
}
void CogSwitchControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* switchItem = &g_Level.Items[itemNumber];
AnimateItem(item);
AnimateItem(switchItem);
if (item->ActiveState == SWITCH_ON)
if (switchItem->ActiveState == SWITCH_ON)
{
if (item->TargetState == SWITCH_ON && !(TrInput & IN_ACTION))
if (switchItem->TargetState == SWITCH_ON && !(TrInput & IN_ACTION))
{
LaraItem->TargetState = LS_IDLE;
item->TargetState = SWITCH_OFF;
switchItem->TargetState = SWITCH_OFF;
}
if (LaraItem->AnimNumber == LA_COGWHEEL_PULL)
{
if (LaraItem->FrameNumber == g_Level.Anims[LaraItem->AnimNumber].frameBase + 10)
{
ITEM_INFO* doorItem = &g_Level.Items[Lara.interactedItem];
auto* doorItem = &g_Level.Items[Lara.interactedItem];
doorItem->ItemFlags[0] = COG_DOOR_TURN;
}
}
}
else
{
if (item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd)
if (switchItem->FrameNumber == g_Level.Anims[switchItem->AnimNumber].frameEnd)
{
item->ActiveState = SWITCH_OFF;
item->Status = ITEM_NOT_ACTIVE;
switchItem->ActiveState = SWITCH_OFF;
switchItem->Status = ITEM_NOT_ACTIVE;
RemoveActiveItem(itemNumber);

View file

@ -9,5 +9,5 @@ namespace TEN::Entities::Switches
constexpr auto COG_DOOR_SPEED = 12;
void CogSwitchControl(short itemNumber);
void CogSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void CogSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -21,9 +21,9 @@ namespace TEN::Entities::Switches
-256, 256,
0, 0,
-512, -256,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR CrowbarPos2 = { 89, 0, 328 };
@ -33,86 +33,81 @@ namespace TEN::Entities::Switches
-256, 256,
0, 0,
256, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
void CrowbarSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void CrowbarSwitchCollision(short itemNumber, ITEM_INFO* laraitem, COLL_INFO* coll)
{
auto* laraInfo = GetLaraInfo(laraitem);
ITEM_INFO* switchItem = &g_Level.Items[itemNumber];
int doSwitch = 0;
ITEM_INFO* item = &g_Level.Items[itemNum];
if ((((TrInput & IN_ACTION) || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& Lara.Control.HandStatus == HandStatus::Free
&& item->ItemFlags[0] == 0)
|| (Lara.Control.IsMoving && Lara.interactedItem == itemNum))
if (((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM) &&
laraitem->ActiveState == LS_IDLE &&
laraitem->AnimNumber == LA_STAND_IDLE &&
laraInfo->Control.HandStatus == HandStatus::Free &&
switchItem->ItemFlags[0] == 0) ||
(laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber))
{
if (item->ActiveState == SWITCH_ON)
if (switchItem->ActiveState == SWITCH_ON)
{
l->Position.yRot ^= (short)ANGLE(180);
laraitem->Position.yRot ^= (short)ANGLE(180.0f);
if (TestLaraPosition(&CrowbarBounds2, item, l))
if (TestLaraPosition(&CrowbarBounds2, switchItem, laraitem))
{
if (Lara.Control.IsMoving || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
if (laraInfo->Control.IsMoving || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
{
if (MoveLaraPosition(&CrowbarPos2, item, l))
if (MoveLaraPosition(&CrowbarPos2, switchItem, laraitem))
{
doSwitch = 1;
l->AnimNumber = LA_CROWBAR_USE_ON_FLOOR;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->TargetState = SWITCH_OFF;
laraitem->AnimNumber = LA_CROWBAR_USE_ON_FLOOR;
laraitem->FrameNumber = g_Level.Anims[laraitem->AnimNumber].frameBase;
switchItem->TargetState = SWITCH_OFF;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
g_Gui.SetInventoryItemChosen(NO_ITEM);
}
else
{
doSwitch = -1;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
l->Position.yRot ^= (short)ANGLE(180);
laraitem->Position.yRot ^= (short)ANGLE(180.0f);
}
else
{
if (TestLaraPosition(&CrowbarBounds, item, l))
if (TestLaraPosition(&CrowbarBounds, switchItem, laraitem))
{
if (Lara.Control.IsMoving || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
if (laraInfo->Control.IsMoving || g_Gui.GetInventoryItemChosen() == ID_CROWBAR_ITEM)
{
if (MoveLaraPosition(&CrowbarPos, item, l))
if (MoveLaraPosition(&CrowbarPos, switchItem, laraitem))
{
doSwitch = 1;
l->AnimNumber = LA_CROWBAR_USE_ON_FLOOR;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->TargetState = SWITCH_ON;
laraitem->AnimNumber = LA_CROWBAR_USE_ON_FLOOR;
laraitem->FrameNumber = g_Level.Anims[laraitem->AnimNumber].frameBase;
switchItem->TargetState = SWITCH_ON;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
g_Gui.SetInventoryItemChosen(NO_ITEM);
}
else
{
doSwitch = -1;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
}
@ -121,35 +116,33 @@ namespace TEN::Entities::Switches
{
if (doSwitch == -1)
{
if (Lara.Crowbar)
if (laraInfo->Crowbar)
g_Gui.SetEnterInventory(ID_CROWBAR_ITEM);
else
{
if (OldPickupPos.x != l->Position.xPos || OldPickupPos.y != l->Position.yPos || OldPickupPos.z != l->Position.zPos)
if (OldPickupPos.x != laraitem->Position.xPos || OldPickupPos.y != laraitem->Position.yPos || OldPickupPos.z != laraitem->Position.zPos)
{
OldPickupPos.x = l->Position.xPos;
OldPickupPos.y = l->Position.yPos;
OldPickupPos.z = l->Position.zPos;
OldPickupPos.x = laraitem->Position.xPos;
OldPickupPos.y = laraitem->Position.yPos;
OldPickupPos.z = laraitem->Position.zPos;
SayNo();
}
}
}
else
{
l->TargetState = LS_SWITCH_DOWN;
l->ActiveState = LS_SWITCH_DOWN;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
item->Status = ITEM_ACTIVE;
ResetLaraFlex(laraitem);
laraitem->TargetState = LS_SWITCH_DOWN;
laraitem->ActiveState = LS_SWITCH_DOWN;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AnimateItem(item);
AddActiveItem(itemNumber);
AnimateItem(switchItem);
}
}
else
{
ObjectCollision(itemNum, l, coll);
}
ObjectCollision(itemNumber, laraitem, coll);
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void CrowbarSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void CrowbarSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -17,9 +17,9 @@ namespace TEN::Entities::Switches
-384, 384,
0, 256,
0, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR FullBlockSwitchPos = { 0, 0, 0 };
@ -29,79 +29,80 @@ namespace TEN::Entities::Switches
byte Sequences[3];
byte CurrentSequence;
void FullBlockSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void FullBlockSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
if ((!(TrInput & IN_ACTION)
|| item->Status
|| item->Flags & 0x100
|| CurrentSequence >= 3
|| Lara.Control.HandStatus != HandStatus::Free
|| l->ActiveState != LS_IDLE
|| l->AnimNumber != LA_STAND_IDLE)
&& (!Lara.Control.IsMoving || Lara.interactedItem !=itemNum))
if ((!(TrInput & IN_ACTION) ||
laraItem->ActiveState != LS_IDLE ||
laraItem->AnimNumber != LA_STAND_IDLE ||
laraInfo->Control.HandStatus != HandStatus::Free ||
switchItem->Status ||
switchItem->Flags & 0x100 ||
CurrentSequence >= 3) &&
(!laraInfo->Control.IsMoving || laraInfo->interactedItem !=itemNumber))
{
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
return;
}
if (TestLaraPosition(&FullBlockSwitchBounds, item, l))
if (TestLaraPosition(&FullBlockSwitchBounds, switchItem, laraItem))
{
if (MoveLaraPosition(&FullBlockSwitchPos, item, l))
if (MoveLaraPosition(&FullBlockSwitchPos, switchItem, laraItem))
{
if (item->ActiveState == 1)
if (switchItem->ActiveState == 1)
{
l->ActiveState = LS_SWITCH_DOWN;
l->AnimNumber = LA_BUTTON_GIANT_PUSH;
item->TargetState = 0;
laraItem->ActiveState = LS_SWITCH_DOWN;
laraItem->AnimNumber = LA_BUTTON_GIANT_PUSH;
switchItem->TargetState = 0;
}
l->TargetState = LS_IDLE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AnimateItem(item);
laraItem->TargetState = LS_IDLE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
switchItem->Status = ITEM_ACTIVE;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
AddActiveItem(itemNumber);
AnimateItem(switchItem);
ResetLaraFlex(laraItem);
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
}
else
{
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
void FullBlockSwitchControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
ITEM_INFO* switchItem = &g_Level.Items[itemNumber];
if (item->AnimNumber != Objects[item->ObjectNumber].animIndex + 2
|| CurrentSequence >= 3
|| item->ItemFlags[0])
if (switchItem->AnimNumber != Objects[switchItem->ObjectNumber].animIndex + 2 ||
CurrentSequence >= 3 ||
switchItem->ItemFlags[0])
{
if (CurrentSequence >= 4)
{
item->ItemFlags[0] = 0;
item->TargetState = SWITCH_ON;
item->Status = ITEM_NOT_ACTIVE;
switchItem->ItemFlags[0] = 0;
switchItem->TargetState = SWITCH_ON;
switchItem->Status = ITEM_NOT_ACTIVE;
if (++CurrentSequence >= 7)
CurrentSequence = 0;
}
}
else
{
item->ItemFlags[0] = 1;
Sequences[CurrentSequence++] = item->TriggerFlags;
switchItem->ItemFlags[0] = 1;
Sequences[CurrentSequence++] = switchItem->TriggerFlags;
}
AnimateItem(item);
AnimateItem(switchItem);
}
}

View file

@ -11,5 +11,5 @@ namespace TEN::Entities::Switches
extern byte CurrentSequence;
void FullBlockSwitchControl(short itemNumber);
void FullBlockSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void FullBlockSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -16,73 +16,73 @@ namespace TEN::Entities::Switches
0, 0,
0, 0,
0, 0,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR SwitchPos = { 0, 0, 0 };
void SwitchControl(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* switchItem = &g_Level.Items[itemNumber];
item->Flags |= 0x3E00;
switchItem->Flags |= 0x3E00;
if (!TriggerActive(item) && !(item->Flags & ONESHOT))
if (!TriggerActive(switchItem) && !(switchItem->Flags & ONESHOT))
{
if (item->ObjectNumber == ID_JUMP_SWITCH)
if (switchItem->ObjectNumber == ID_JUMP_SWITCH)
{
item->TargetState = SWITCH_OFF;
item->Timer = 0;
AnimateItem(item);
switchItem->TargetState = SWITCH_OFF;
switchItem->Timer = 0;
AnimateItem(switchItem);
}
else
{
item->TargetState = SWITCH_ON;
item->Timer = 0;
switchItem->TargetState = SWITCH_ON;
switchItem->Timer = 0;
}
}
AnimateItem(item);
AnimateItem(switchItem);
}
void SwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void SwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
if (TrInput & IN_ACTION
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& Lara.Control.HandStatus == HandStatus::Free
&& item->Status == ITEM_NOT_ACTIVE
&& !(item->Flags & 0x100)
&& item->TriggerFlags >= 0
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
{
BOUNDING_BOX* bounds = GetBoundsAccurate(item);
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
if (item->TriggerFlags == 3 && item->ActiveState == SWITCH_ON
|| item->TriggerFlags >= 5 && item->TriggerFlags <= 7
&& item->ActiveState == SWITCH_OFF)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraInfo->Control.HandStatus == HandStatus::Free &&
switchItem->Status == ITEM_NOT_ACTIVE &&
!(switchItem->Flags & 0x100) &&
switchItem->TriggerFlags >= 0 ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
auto* bounds = GetBoundsAccurate(switchItem);
if (switchItem->TriggerFlags == 3 && switchItem->ActiveState == SWITCH_ON ||
switchItem->TriggerFlags >= 5 && switchItem->TriggerFlags <= 7 &&
switchItem->ActiveState == SWITCH_OFF)
{
return;
}
SwitchBounds.boundingBox.X1 = bounds->X1 - 256;
SwitchBounds.boundingBox.X2 = bounds->X2 + 256;
if (item->TriggerFlags)
if (switchItem->TriggerFlags)
{
SwitchBounds.boundingBox.Z1 = bounds->Z1 - 512;
SwitchBounds.boundingBox.Z2 = bounds->Z2 + 512;
if (item->TriggerFlags == 3)
{
if (switchItem->TriggerFlags == 3)
SwitchPos.z = bounds->Z1 - 256;
}
else
{
SwitchPos.z = bounds->Z1 - 128;
}
}
else
{
SwitchBounds.boundingBox.Z1 = bounds->Z1 - 200;
@ -90,72 +90,68 @@ namespace TEN::Entities::Switches
SwitchPos.z = bounds->Z1 - 64;
}
if (TestLaraPosition(&SwitchBounds, item, l))
if (TestLaraPosition(&SwitchBounds, switchItem, laraItem))
{
if (MoveLaraPosition(&SwitchPos, item, l))
if (MoveLaraPosition(&SwitchPos, switchItem, laraItem))
{
if (item->ActiveState == SWITCH_ON) /* Switch down */
if (switchItem->ActiveState == SWITCH_ON) /* Switch down */
{
if (item->TriggerFlags)
if (switchItem->TriggerFlags)
{
l->AnimNumber = LA_HOLESWITCH_ACTIVATE;
l->ActiveState = LS_HOLE;
laraItem->AnimNumber = LA_HOLESWITCH_ACTIVATE;
laraItem->ActiveState = LS_HOLE;
}
else
{
l->ActiveState = LS_SWITCH_UP;
l->AnimNumber = LA_WALLSWITCH_DOWN;
laraItem->ActiveState = LS_SWITCH_UP;
laraItem->AnimNumber = LA_WALLSWITCH_DOWN;
}
item->TargetState = SWITCH_OFF;
switchItem->TargetState = SWITCH_OFF;
}
else /* Switch up */
{
if (item->TriggerFlags)
if (switchItem->TriggerFlags)
{
if (item->TriggerFlags == 3)
{
l->AnimNumber = LA_BUTTON_LARGE_PUSH;
}
if (switchItem->TriggerFlags == 3)
laraItem->AnimNumber = LA_BUTTON_LARGE_PUSH;
else
{
l->AnimNumber = LA_HOLESWITCH_ACTIVATE;
l->ActiveState = LS_HOLE;
laraItem->AnimNumber = LA_HOLESWITCH_ACTIVATE;
laraItem->ActiveState = LS_HOLE;
}
}
else
{
l->ActiveState = LS_SWITCH_DOWN;
l->AnimNumber = LA_WALLSWITCH_UP;
laraItem->ActiveState = LS_SWITCH_DOWN;
laraItem->AnimNumber = LA_WALLSWITCH_UP;
}
item->TargetState = SWITCH_ON;
switchItem->TargetState = SWITCH_ON;
}
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
ResetLaraFlex(l);
ResetLaraFlex(laraItem);
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
AddActiveItem(itemNum);
item->Status = ITEM_ACTIVE;
AnimateItem(item);
AddActiveItem(itemNumber);
switchItem->Status = ITEM_ACTIVE;
AnimateItem(switchItem);
}
else
{
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
return;
}
if (l->ActiveState != LS_SWITCH_DOWN && l->ActiveState != LS_SWITCH_UP)
ObjectCollision(itemNum, l, coll);
if (laraItem->ActiveState != LS_SWITCH_DOWN && laraItem->ActiveState != LS_SWITCH_UP)
ObjectCollision(itemNumber, laraItem, coll);
}
}

View file

@ -12,5 +12,5 @@ namespace TEN::Entities::Switches
};
void SwitchControl(short itemNumber);
void SwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void SwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -3,6 +3,7 @@
#include "Game/control/control.h"
#include "Specific/input.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_helpers.h"
#include "Objects/Generic/Switches/generic_switch.h"
#include "Specific/level.h"
#include "Game/collision/collide_item.h"
@ -15,39 +16,39 @@ namespace TEN::Entities::Switches
-128, 128,
-256, 256,
384, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR JumpSwitchPos = { 0, -208, 256 };
void JumpSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void JumpSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
if ((TrInput & IN_ACTION)
&& Lara.Control.HandStatus == HandStatus::Free
&& (l->ActiveState == LS_REACH || l->ActiveState == LS_JUMP_UP)
&& (l->Status || l->Airborne)
&& l->VerticalVelocity > 0
&& !item->ActiveState)
if (TrInput & IN_ACTION &&
(laraItem->ActiveState == LS_REACH || laraItem->ActiveState == LS_JUMP_UP) &&
(laraItem->Status || laraItem->Airborne) &&
laraItem->VerticalVelocity > 0 &&
laraInfo->Control.HandStatus == HandStatus::Free &&
!switchItem->ActiveState)
{
if (TestLaraPosition(&JumpSwitchBounds, item, l))
if (TestLaraPosition(&JumpSwitchBounds, switchItem, laraItem))
{
AlignLaraPosition(&JumpSwitchPos, item, l);
AlignLaraPosition(&JumpSwitchPos, switchItem, laraItem);
l->ActiveState = LS_SWITCH_DOWN;
l->AnimNumber = LA_JUMPSWITCH_PULL;
l->VerticalVelocity = 0;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->Airborne = false;
Lara.Control.HandStatus = HandStatus::Busy;
laraItem->ActiveState = LS_SWITCH_DOWN;
laraItem->AnimNumber = LA_JUMPSWITCH_PULL;
laraItem->VerticalVelocity = 0;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->Airborne = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->TargetState = SWITCH_ON;
switchItem->Status = ITEM_ACTIVE;
item->TargetState = SWITCH_ON;
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
}
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void JumpSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void JumpSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -18,87 +18,86 @@ namespace TEN::Entities::Switches
-256, 256,
0, 0,
-512, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR PulleyPos = { 0, 0, -148 };
void InitialisePulleySwitch(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* switchItem = &g_Level.Items[itemNumber];
item->ItemFlags[3] = item->TriggerFlags;
item->TriggerFlags = abs(item->TriggerFlags);
switchItem->ItemFlags[3] = switchItem->TriggerFlags;
switchItem->TriggerFlags = abs(switchItem->TriggerFlags);
if (item->Status == ITEM_INVISIBLE)
if (switchItem->Status == ITEM_INVISIBLE)
{
item->ItemFlags[1] = 1;
item->Status = ITEM_NOT_ACTIVE;
switchItem->ItemFlags[1] = 1;
switchItem->Status = ITEM_NOT_ACTIVE;
}
}
void PulleySwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void PulleySwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
if ((TrInput & IN_ACTION)
&& Lara.Control.HandStatus == HandStatus::Free
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& l->Airborne == false
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraItem->Airborne == false &&
laraInfo->Control.HandStatus == HandStatus::Free ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
short oldYrot = item->Position.yRot;
item->Position.yRot = l->Position.yRot;
if (TestLaraPosition(&PulleyBounds, item, l))
short oldYrot = switchItem->Position.yRot;
switchItem->Position.yRot = laraItem->Position.yRot;
if (TestLaraPosition(&PulleyBounds, switchItem, laraItem))
{
if (item->ItemFlags[1])
if (switchItem->ItemFlags[1])
{
if (OldPickupPos.x != l->Position.xPos || OldPickupPos.y != l->Position.yPos || OldPickupPos.z != l->Position.zPos)
if (OldPickupPos.x != laraItem->Position.xPos || OldPickupPos.y != laraItem->Position.yPos || OldPickupPos.z != laraItem->Position.zPos)
{
OldPickupPos.x = l->Position.xPos;
OldPickupPos.y = l->Position.yPos;
OldPickupPos.z = l->Position.zPos;
OldPickupPos.x = laraItem->Position.xPos;
OldPickupPos.y = laraItem->Position.yPos;
OldPickupPos.z = laraItem->Position.zPos;
SayNo();
}
}
else if (MoveLaraPosition(&PulleyPos, item, l))
else if (MoveLaraPosition(&PulleyPos, switchItem, laraItem))
{
l->AnimNumber = LA_PULLEY_GRAB;
l->ActiveState = LS_PULLEY;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
laraItem->AnimNumber = LA_PULLEY_GRAB;
laraItem->ActiveState = LS_PULLEY;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
item->Position.yRot = oldYrot;
item->Status = ITEM_ACTIVE;
switchItem->Position.yRot = oldYrot;
switchItem->Status = ITEM_ACTIVE;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
Lara.interactedItem = itemNum;
laraInfo->Control.IsMoving = false;
ResetLaraFlex(laraItem);
laraInfo->Control.HandStatus = HandStatus::Busy;
laraInfo->interactedItem = itemNumber;
}
else
laraInfo->interactedItem = itemNumber;
switchItem->Position.yRot = oldYrot;
}
else
{
Lara.interactedItem = itemNum;
}
item->Position.yRot = oldYrot;
}
else
if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
item->Position.yRot = oldYrot;
switchItem->Position.yRot = oldYrot;
}
}
else if (l->ActiveState != LS_PULLEY)
{
ObjectCollision(itemNum, l, coll);
}
else if (laraItem->ActiveState != LS_PULLEY)
ObjectCollision(itemNumber, laraItem, coll);
}
}

View file

@ -6,5 +6,5 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void InitialisePulleySwitch(short itemNumber);
void PulleySwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void PulleySwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -18,9 +18,9 @@ namespace TEN::Entities::Switches
-256, 256,
0, 0,
-768, -512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR RailSwitchPos2 = { 0, 0, 550 };
@ -30,105 +30,102 @@ namespace TEN::Entities::Switches
-256, 256,
0, 0,
512, 768,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
void RailSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void RailSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
int flag = 0;
ITEM_INFO* item = &g_Level.Items[itemNum];
if ((!(TrInput & IN_ACTION)
|| l->ActiveState != LS_IDLE
|| l->AnimNumber != LA_STAND_IDLE
|| Lara.Control.HandStatus != HandStatus::Free)
&& (!Lara.Control.IsMoving
|| Lara.interactedItem != itemNum))
if ((!(TrInput & IN_ACTION) ||
laraItem->ActiveState != LS_IDLE ||
laraItem->AnimNumber != LA_STAND_IDLE ||
laraInfo->Control.HandStatus != HandStatus::Free) &&
(!laraInfo->Control.IsMoving ||
laraInfo->interactedItem != itemNumber))
{
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
}
else if (item->ActiveState)
else if (switchItem->ActiveState)
{
if (item->ActiveState == SWITCH_ON)
if (switchItem->ActiveState == SWITCH_ON)
{
l->Position.yRot ^= (short)ANGLE(180);
laraItem->Position.yRot ^= (short)ANGLE(180.0f);
if (TestLaraPosition(&RailSwitchBounds2, item, l))
if (TestLaraPosition(&RailSwitchBounds2, switchItem, laraItem))
{
if (MoveLaraPosition(&RailSwitchPos2, item, l))
if (MoveLaraPosition(&RailSwitchPos2, switchItem, laraItem))
{
item->TargetState = SWITCH_OFF;
switchItem->TargetState = SWITCH_OFF;
flag = 1;
}
else
{
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
l->Position.yRot ^= (short)ANGLE(180);
laraItem->Position.yRot ^= (short)ANGLE(180.0f);
if (flag)
{
l->AnimNumber = LA_LEVER_PUSH;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->TargetState = LS_LEVERSWITCH_PUSH;
l->ActiveState = LS_LEVERSWITCH_PUSH;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AnimateItem(item);
ResetLaraFlex(laraItem);
laraItem->AnimNumber = LA_LEVER_PUSH;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->TargetState = LS_LEVERSWITCH_PUSH;
laraItem->ActiveState = LS_LEVERSWITCH_PUSH;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNumber);
AnimateItem(switchItem);
return;
}
}
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
}
else
{
if (TestLaraPosition(&RailSwitchBounds, item, l))
if (TestLaraPosition(&RailSwitchBounds, switchItem, laraItem))
{
if (MoveLaraPosition(&RailSwitchPos, item, l))
if (MoveLaraPosition(&RailSwitchPos, switchItem, laraItem))
{
item->TargetState = SWITCH_ON;
l->AnimNumber = LA_LEVER_PUSH;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->TargetState = LS_LEVERSWITCH_PUSH;
l->ActiveState = LS_LEVERSWITCH_PUSH;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
ResetLaraFlex(laraItem);
laraItem->AnimNumber = LA_LEVER_PUSH;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->TargetState = LS_LEVERSWITCH_PUSH;
laraItem->ActiveState = LS_LEVERSWITCH_PUSH;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->TargetState = SWITCH_ON;
switchItem->Status = ITEM_ACTIVE;
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AnimateItem(item);
AddActiveItem(itemNumber);
AnimateItem(switchItem);
}
else
{
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
}
else if (Lara.Control.IsMoving)
else if (laraInfo->Control.IsMoving)
{
if (Lara.interactedItem == itemNum)
if (laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
}
}
}

View file

@ -5,5 +5,5 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void RailSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void RailSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -16,11 +16,9 @@
void ProcessExplodingSwitchType8(ITEM_INFO* item)
{
PHD_VECTOR pos;
pos.x = 0;
pos.y = 0;
pos.z = 0;
PHD_VECTOR pos = { 0, 0, 0 };
GetJointAbsPosition(item, &pos, 0);
TestTriggers(pos.x, pos.y, pos.z, item->RoomNumber, true);
ExplodeItemNode(item, Objects[item->ObjectNumber].nmeshes - 1, 0, 64);
item->MeshBits |= 1 << ((Objects[item->ObjectNumber].nmeshes & 0xFF) - 2);
@ -28,15 +26,16 @@ void ProcessExplodingSwitchType8(ITEM_INFO* item)
void InitialiseShootSwitch(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
if (item->TriggerFlags == 444)
item->MeshBits &= ~(1 << (Objects[item->ObjectNumber].nmeshes - 2));
auto* switchItem = &g_Level.Items[itemNumber];
if (switchItem->TriggerFlags == 444)
switchItem->MeshBits &= ~(1 << (Objects[switchItem->ObjectNumber].nmeshes - 2));
}
void ShootSwitchCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
void ShootSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* switchItem = &g_Level.Items[itemNumber];
if (item->ObjectNumber == ID_SHOOT_SWITCH1 && !(item->MeshBits & 1))
item->Status = ITEM_INVISIBLE;
if (switchItem->ObjectNumber == ID_SHOOT_SWITCH1 && !(switchItem->MeshBits & 1))
switchItem->Status = ITEM_INVISIBLE;
}

View file

@ -2,6 +2,7 @@
struct COLL_INFO;
struct ITEM_INFO;
void ProcessExplodingSwitchType8(ITEM_INFO* item);
void InitialiseShootSwitch(short itemNumber);
void ShootSwitchCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll);
void ShootSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);

View file

@ -27,9 +27,9 @@ namespace TEN::Entities::Switches
512, 896,
0, 0,
-512, 0,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR TurnSwitchPos = { 650, 0, 138 };
@ -39,70 +39,69 @@ namespace TEN::Entities::Switches
512, 896,
0, 0,
0, 512,
-ANGLE(10), ANGLE(10),
-ANGLE(30), ANGLE(30),
-ANGLE(10), ANGLE(10)
-ANGLE(10.0f), ANGLE(10.0f),
-ANGLE(30.0f), ANGLE(30.0f),
-ANGLE(10.0f), ANGLE(10.0f)
};
PHD_VECTOR TurnSwitchPosA = { 650, 0, -138 };
void TurnSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void TurnSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
int doSwitch = 0;
if (item->ActiveState == TURN_SWITCH_STOP
&& TrInput & IN_ACTION
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& l->Airborne == false
&& Lara.Control.HandStatus == HandStatus::Free
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraItem->Airborne == false &&
laraInfo->Control.HandStatus == HandStatus::Free &&
switchItem->ActiveState == TURN_SWITCH_STOP ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
if (TestLaraPosition(&TurnSwitchBoundsA, item, l))
if (TestLaraPosition(&TurnSwitchBoundsA, switchItem, laraItem))
{
if (MoveLaraPosition(&TurnSwitchPosA, item, l))
if (MoveLaraPosition(&TurnSwitchPosA, switchItem, laraItem))
{
l->AnimNumber = LA_TURNSWITCH_GRAB_COUNTER_CLOCKWISE;
l->FrameNumber = g_Level.Anims[LA_TURNSWITCH_GRAB_COUNTER_CLOCKWISE].frameBase;
item->AnimNumber = Objects[item->ObjectNumber].animIndex + 4;
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
item->ItemFlags[0] = TURN_SWITCH_ANTICLOCKWISE;
ForcedFixedCamera.x = item->Position.xPos - 1024 * phd_sin(item->Position.yRot);
ForcedFixedCamera.z = item->Position.zPos - 1024 * phd_cos(item->Position.yRot);
laraItem->AnimNumber = LA_TURNSWITCH_GRAB_COUNTER_CLOCKWISE;
laraItem->FrameNumber = g_Level.Anims[LA_TURNSWITCH_GRAB_COUNTER_CLOCKWISE].frameBase;
switchItem->AnimNumber = Objects[switchItem->ObjectNumber].animIndex + 4;
switchItem->FrameNumber = g_Level.Anims[switchItem->AnimNumber].frameBase;
switchItem->ItemFlags[0] = TURN_SWITCH_ANTICLOCKWISE;
ForcedFixedCamera.x = switchItem->Position.xPos - 1024 * phd_sin(switchItem->Position.yRot);
ForcedFixedCamera.z = switchItem->Position.zPos - 1024 * phd_cos(switchItem->Position.yRot);
doSwitch = -1;
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
}
else
{
l->Position.yRot ^= (short)ANGLE(180);
if (TestLaraPosition(&TurnSwitchBoundsC, item, l))
laraItem->Position.yRot ^= (short)ANGLE(180.0f);
if (TestLaraPosition(&TurnSwitchBoundsC, switchItem, laraItem))
{
if (MoveLaraPosition(&TurnSwitchPos, item, l))
if (MoveLaraPosition(&TurnSwitchPos, switchItem, laraItem))
{
l->AnimNumber = LA_TURNSWITCH_GRAB_CLOCKWISE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->ItemFlags[0] = TURN_SWITCH_CLOCKWISE;
ForcedFixedCamera.x = item->Position.xPos + 1024 * phd_sin(item->Position.yRot);
ForcedFixedCamera.z = item->Position.zPos + 1024 * phd_cos(item->Position.yRot);
laraItem->AnimNumber = LA_TURNSWITCH_GRAB_CLOCKWISE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
switchItem->ItemFlags[0] = TURN_SWITCH_CLOCKWISE;
ForcedFixedCamera.x = switchItem->Position.xPos + 1024 * phd_sin(switchItem->Position.yRot);
ForcedFixedCamera.z = switchItem->Position.zPos + 1024 * phd_cos(switchItem->Position.yRot);
doSwitch = 1;
}
else
laraInfo->interactedItem = itemNumber;
}
else if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.interactedItem = itemNum;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
else if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
}
l->Position.yRot ^= (short)ANGLE(180);
laraItem->Position.yRot ^= (short)ANGLE(180.0f);
}
}
@ -110,21 +109,21 @@ namespace TEN::Entities::Switches
{
short ItemNos[8];
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
l->ActiveState = LA_REACH;
laraInfo->Control.IsMoving = false;
ResetLaraFlex(laraItem);
laraInfo->Control.HandStatus = HandStatus::Busy;
laraItem->ActiveState = LA_REACH;
UseForcedFixedCamera = true;
ForcedFixedCamera.y = item->Position.yPos - 2048;
ForcedFixedCamera.roomNumber = item->RoomNumber;
ForcedFixedCamera.y = switchItem->Position.yPos - 2048;
ForcedFixedCamera.roomNumber = switchItem->RoomNumber;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
item->Status = ITEM_ACTIVE;
item->ItemFlags[1] = 0;
switchItem->Status = ITEM_ACTIVE;
switchItem->ItemFlags[1] = 0;
if (GetSwitchTrigger(item, ItemNos, 0))
if (GetSwitchTrigger(switchItem, ItemNos, 0))
{
if (!TriggerActive(&g_Level.Items[ItemNos[0]]))
{
@ -135,7 +134,7 @@ namespace TEN::Entities::Switches
}
else
{
if (coll->Setup.EnableObjectPush && TestBoundsCollide(item, l, coll->Setup.Radius))
if (coll->Setup.EnableObjectPush && TestBoundsCollide(switchItem, laraItem, coll->Setup.Radius))
{
GlobalCollisionBounds.X1 = -512;
GlobalCollisionBounds.X2 = 512;
@ -144,96 +143,94 @@ namespace TEN::Entities::Switches
GlobalCollisionBounds.Z1 = -512;
GlobalCollisionBounds.Z2 = 512;
ItemPushItem(item, l, coll, 0, 2);
ItemPushItem(switchItem, laraItem, coll, 0, 2);
GlobalCollisionBounds.X1 = 256;
GlobalCollisionBounds.X2 = 1024;
GlobalCollisionBounds.Z1 = -128;
GlobalCollisionBounds.Z2 = 128;
ItemPushItem(item, l, coll, 0, 2);
ItemPushItem(switchItem, laraItem, coll, 0, 2);
}
}
}
void TurnSwitchControl(short itemNum)
void TurnSwitchControl(short itemNumber)
{
ITEM_INFO* l = LaraItem;
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraItem = LaraItem;
auto* switchItem = &g_Level.Items[itemNumber];
if (g_Level.Items[itemNum].ItemFlags[0] == TURN_SWITCH_CLOCKWISE)
if (g_Level.Items[itemNumber].ItemFlags[0] == TURN_SWITCH_CLOCKWISE)
{
if (item->AnimNumber == Objects[item->ObjectNumber].animIndex + 2)
if (switchItem->AnimNumber == Objects[switchItem->ObjectNumber].animIndex + 2)
{
item->Position.yRot += ANGLE(90);
switchItem->Position.yRot += ANGLE(90.0f);
if (TrInput & IN_ACTION)
{
l->AnimNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_START;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
laraItem->AnimNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_START;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
item->AnimNumber = Objects[item->ObjectNumber].animIndex + 1;
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
switchItem->AnimNumber = Objects[switchItem->ObjectNumber].animIndex + 1;
switchItem->FrameNumber = g_Level.Anims[switchItem->AnimNumber].frameBase;
}
}
if (l->AnimNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_END
&& l->FrameNumber == g_Level.Anims[l->AnimNumber].frameEnd &&
!item->ItemFlags[1])
item->ItemFlags[1] = 1;
if (laraItem->AnimNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_END &&
laraItem->FrameNumber == g_Level.Anims[laraItem->AnimNumber].frameEnd &&
!switchItem->ItemFlags[1])
switchItem->ItemFlags[1] = 1;
if (l->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase &&
l->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 43
||
l->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 58 &&
l->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 115)
if (laraItem->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase &&
laraItem->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 43 ||
laraItem->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 58 &&
laraItem->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_CLOCKWISE_START].frameBase + 115)
{
SoundEffect(SFX_TR4_PUSHABLE_SOUND, &item->Position, 2);
SoundEffect(SFX_TR4_PUSHABLE_SOUND, &switchItem->Position, 2);
}
}
else
{
if (item->AnimNumber == Objects[ID_TURN_SWITCH].animIndex + 6)
if (switchItem->AnimNumber == Objects[ID_TURN_SWITCH].animIndex + 6)
{
item->Position.yRot -= ANGLE(90);
switchItem->Position.yRot -= ANGLE(90.0f);
if (TrInput & IN_ACTION)
{
l->AnimNumber = LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->AnimNumber = Objects[item->ObjectNumber].animIndex + 5;
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
laraItem->AnimNumber = LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
switchItem->AnimNumber = Objects[switchItem->ObjectNumber].animIndex + 5;
switchItem->FrameNumber = g_Level.Anims[switchItem->AnimNumber].frameBase;
}
}
if (l->AnimNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END && l->FrameNumber == g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END].frameEnd &&
!item->ItemFlags[1])
item->ItemFlags[1] = 1;
if (laraItem->AnimNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END && laraItem->FrameNumber == g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END].frameEnd &&
!switchItem->ItemFlags[1])
switchItem->ItemFlags[1] = 1;
if (l->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase &&
l->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 43
||
l->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 58 &&
l->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 115)
if (laraItem->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase &&
laraItem->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 43 ||
laraItem->FrameNumber >= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 58 &&
laraItem->FrameNumber <= g_Level.Anims[LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START].frameBase + 115)
{
SoundEffect(SFX_TR4_PUSHABLE_SOUND, &item->Position, 2);
SoundEffect(SFX_TR4_PUSHABLE_SOUND, &switchItem->Position, 2);
}
}
AnimateItem(item);
AnimateItem(switchItem);
if (item->ItemFlags[1] == 1)
if (switchItem->ItemFlags[1] == 1)
{
l->AnimNumber = LA_STAND_IDLE;
l->ActiveState = LS_IDLE;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
item->AnimNumber = Objects[item->ObjectNumber].animIndex;
item->FrameNumber = g_Level.Anims[item->AnimNumber].frameBase;
item->Status = ITEM_NOT_ACTIVE;
laraItem->AnimNumber = LA_STAND_IDLE;
laraItem->ActiveState = LS_IDLE;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
switchItem->AnimNumber = Objects[switchItem->ObjectNumber].animIndex;
switchItem->FrameNumber = g_Level.Anims[switchItem->AnimNumber].frameBase;
switchItem->Status = ITEM_NOT_ACTIVE;
RemoveActiveItem(itemNum);
RemoveActiveItem(itemNumber);
Lara.Control.HandStatus = HandStatus::Free;
UseForcedFixedCamera = 0;
item->ItemFlags[1] = 2;
switchItem->ItemFlags[1] = 2;
}
}
}

View file

@ -6,5 +6,5 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void TurnSwitchControl(short itemNumber);
void TurnSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void TurnSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -1,6 +1,7 @@
#include "framework.h"
#include "Specific/input.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_helpers.h"
#include "Objects/Generic/Switches/underwater_switch.h"
#include "Objects/Generic/Switches/generic_switch.h"
#include "Game/camera.h"
@ -17,11 +18,10 @@ namespace TEN::Entities::Switches
-1024, 1024,
-1024, 1024,
-1024, 512,
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80)
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f)
};
PHD_VECTOR UnderwaterSwitchPos = { 0, 0, 108 };
OBJECT_COLLISION_BOUNDS CeilingUnderwaterSwitchBounds1 =
@ -29,11 +29,10 @@ namespace TEN::Entities::Switches
-256, 256,
-1280, -512,
-512, 0,
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80)
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f)
};
PHD_VECTOR CeilingUnderwaterSwitchPos1 = { 0, -736, -416 };
OBJECT_COLLISION_BOUNDS CeilingUnderwaterSwitchBounds2 =
@ -41,59 +40,55 @@ namespace TEN::Entities::Switches
-256, 256,
-1280, -512,
0, 512,
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80),
-ANGLE(80), ANGLE(80)
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f),
-ANGLE(80.0f), ANGLE(80.0f)
};
PHD_VECTOR CeilingUnderwaterSwitchPos2 = { 0, -736, 416 };
void UnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void UnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* switchItem = &g_Level.Items[itemNumber];
if (item->TriggerFlags == 0)
{
WallUnderwaterSwitchCollision(itemNum, l, coll);
}
if (switchItem->TriggerFlags == 0)
WallUnderwaterSwitchCollision(itemNumber, laraItem, coll);
else
{
CeilingUnderwaterSwitchCollision(itemNum, l, coll);
}
CeilingUnderwaterSwitchCollision(itemNumber, laraItem, coll);
}
void WallUnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void WallUnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
if (TrInput & IN_ACTION)
{
if (item->Status == ITEM_NOT_ACTIVE
&& Lara.Control.WaterStatus == WaterStatus::Underwater
&& Lara.Control.HandStatus == HandStatus::Free
&& l->ActiveState == LS_UNDERWATER_STOP)
if (switchItem->Status == ITEM_NOT_ACTIVE &&
laraInfo->Control.WaterStatus == WaterStatus::Underwater &&
laraInfo->Control.HandStatus == HandStatus::Free &&
laraItem->ActiveState == LS_UNDERWATER_STOP)
{
if (TestLaraPosition(&UnderwaterSwitchBounds, item, l))
if (TestLaraPosition(&UnderwaterSwitchBounds, switchItem, laraItem))
{
if (item->ActiveState == SWITCH_ON
|| item->ActiveState == SWITCH_OFF)
if (switchItem->ActiveState == SWITCH_ON ||
switchItem->ActiveState == SWITCH_OFF)
{
if (MoveLaraPosition(&UnderwaterSwitchPos, item, l))
if (MoveLaraPosition(&UnderwaterSwitchPos, switchItem, laraItem))
{
l->VerticalVelocity = 0;
l->TargetState = LS_SWITCH_DOWN;
laraItem->VerticalVelocity = 0;
laraItem->TargetState = LS_SWITCH_DOWN;
do
{
AnimateLara(l);
} while (l->TargetState != LS_SWITCH_DOWN);
AnimateLara(laraItem);
} while (laraItem->TargetState != LS_SWITCH_DOWN);
l->TargetState = LS_UNDERWATER_STOP;
Lara.Control.HandStatus = HandStatus::Busy;
item->TargetState = item->ActiveState != SWITCH_ON;
item->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AnimateItem(item);
laraItem->TargetState = LS_UNDERWATER_STOP;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->TargetState = switchItem->ActiveState != SWITCH_ON;
switchItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNumber);
AnimateItem(switchItem);
}
}
}
@ -101,58 +96,60 @@ namespace TEN::Entities::Switches
}
}
void CeilingUnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void CeilingUnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
auto* laraInfo = GetLaraInfo(laraItem);
auto* switchItem = &g_Level.Items[itemNumber];
int flag = 0;
if (TrInput & IN_ACTION
&& Lara.Control.WaterStatus == WaterStatus::Underwater
&& l->ActiveState == LS_UNDERWATER_STOP
&& l->AnimNumber == LA_UNDERWATER_IDLE
&& Lara.Control.HandStatus == HandStatus::Free
&& (item->ActiveState == SWITCH_OFF)
|| Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (TrInput & IN_ACTION &&
laraItem->ActiveState == LS_UNDERWATER_STOP &&
laraItem->AnimNumber == LA_UNDERWATER_IDLE &&
laraInfo->Control.WaterStatus == WaterStatus::Underwater &&
laraInfo->Control.HandStatus == HandStatus::Free &&
switchItem->ActiveState == SWITCH_OFF ||
laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
if (TestLaraPosition(&CeilingUnderwaterSwitchBounds1, item, l))
if (TestLaraPosition(&CeilingUnderwaterSwitchBounds1, switchItem, laraItem))
{
if (MoveLaraPosition(&CeilingUnderwaterSwitchPos1, item, l))
if (MoveLaraPosition(&CeilingUnderwaterSwitchPos1, switchItem, laraItem))
flag = 1;
else
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
else
{
l->Position.yRot ^= 0x8000;
laraItem->Position.yRot ^= 0x8000;
if (TestLaraPosition(&CeilingUnderwaterSwitchBounds2, item, l))
if (TestLaraPosition(&CeilingUnderwaterSwitchBounds2, switchItem, laraItem))
{
if (MoveLaraPosition(&CeilingUnderwaterSwitchPos2, item, l))
if (MoveLaraPosition(&CeilingUnderwaterSwitchPos2, switchItem, laraItem))
flag = 1;
else
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
}
l->Position.yRot ^= 0x8000;
laraItem->Position.yRot ^= 0x8000;
}
if (flag)
{
l->ActiveState = LS_SWITCH_DOWN;
l->AnimNumber = LA_UNDERWATER_CEILING_SWITCH_PULL;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
l->VerticalVelocity = 0;
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Busy;
item->TargetState = SWITCH_ON;
item->Status = ITEM_ACTIVE;
laraItem->ActiveState = LS_SWITCH_DOWN;
laraItem->AnimNumber = LA_UNDERWATER_CEILING_SWITCH_PULL;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraItem->VerticalVelocity = 0;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Busy;
switchItem->TargetState = SWITCH_ON;
switchItem->Status = ITEM_ACTIVE;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
ForcedFixedCamera.x = item->Position.xPos - 1024 * phd_sin(item->Position.yRot + ANGLE(90));
ForcedFixedCamera.y = item->Position.yPos - 1024;
ForcedFixedCamera.z = item->Position.zPos - 1024 * phd_cos(item->Position.yRot + ANGLE(90));
ForcedFixedCamera.roomNumber = item->RoomNumber;
ForcedFixedCamera.x = switchItem->Position.xPos - 1024 * phd_sin(switchItem->Position.yRot + ANGLE(90));
ForcedFixedCamera.y = switchItem->Position.yPos - 1024;
ForcedFixedCamera.z = switchItem->Position.zPos - 1024 * phd_cos(switchItem->Position.yRot + ANGLE(90));
ForcedFixedCamera.roomNumber = switchItem->RoomNumber;
}
}
}

View file

@ -5,7 +5,7 @@ struct COLL_INFO;
namespace TEN::Entities::Switches
{
void UnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void CeilingUnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void WallUnderwaterSwitchCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void UnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void CeilingUnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void WallUnderwaterSwitchCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
}

View file

@ -17,167 +17,182 @@
using namespace TEN::Entities::Switches;
enum PuzzleType {
short puzzleItem;
enum PuzzleType
{
PUZZLETYPE_NORMAL,
PUZZLETYPE_SPECIFIC,
PUZZLETYPE_CUTSCENE,
PUZZLETYPE_ANIM_AFTER
};
/*vars*/
short puzzleItem;
/*bounds*/
OBJECT_COLLISION_BOUNDS PuzzleBounds =
{ 0, 0, -256, 256, 0, 0, ANGLE(-10), ANGLE(10), ANGLE(-30), ANGLE(30), ANGLE(-10), ANGLE(10) };
{
0, 0,
-256, 256,
0, 0,
ANGLE(-10.0f), ANGLE(10.0f),
ANGLE(-30.0f), ANGLE(30.0f),
ANGLE(-10.0f), ANGLE(10.0f)
};
static PHD_VECTOR KeyHolePosition(0, 0, 312);
OBJECT_COLLISION_BOUNDS KeyHoleBounds =
{ -256, 256, 0, 0, 0, 412, ANGLE(-10), ANGLE(10), ANGLE(-30), ANGLE(30), ANGLE(-10), ANGLE(10) };
/*puzzles*/
void PuzzleHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
-256, 256,
0, 0,
0, 412,
ANGLE(-10.0f), ANGLE(10.0f),
ANGLE(-30.0f), ANGLE(30.0f),
ANGLE(-10.0f), ANGLE(10.0f)
};
// Puzzles
void PuzzleHoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
auto* laraInfo = GetLaraInfo(laraItem);
auto* receptableItem = &g_Level.Items[itemNumber];
int flag = PUZZLETYPE_NORMAL;
if (item->TriggerFlags >= 0)
if (receptableItem->TriggerFlags >= 0)
{
if (item->TriggerFlags <= 1024)
if (receptableItem->TriggerFlags <= 1024)
{
if (receptableItem->TriggerFlags &&
receptableItem->TriggerFlags != 999 &&
receptableItem->TriggerFlags != 998)
{
if (item->TriggerFlags && item->TriggerFlags != 999 && item->TriggerFlags != 998)
flag = PUZZLETYPE_ANIM_AFTER;
}
}
else
flag = PUZZLETYPE_CUTSCENE;
}
else
flag = PUZZLETYPE_SPECIFIC;
if (((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM)
&& !BinocularRange
&& Lara.Control.HandStatus == HandStatus::Free
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE
&& GetKeyTrigger(&g_Level.Items[itemNum]))
|| (Lara.Control.IsMoving
&& Lara.interactedItem == itemNum))
if (((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM) &&
!BinocularRange &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE &&
laraInfo->Control.HandStatus == HandStatus::Free &&
GetKeyTrigger(&g_Level.Items[itemNumber])) ||
(laraInfo->Control.IsMoving &&
laraInfo->interactedItem == itemNumber))
{
short oldYrot = item->Position.yRot;
BOUNDING_BOX* bounds = GetBoundsAccurate(item);
short oldYrot = receptableItem->Position.yRot;
auto* bounds = GetBoundsAccurate(receptableItem);
PuzzleBounds.boundingBox.X1 = bounds->X1 - 256;
PuzzleBounds.boundingBox.X2 = bounds->X2 + 256;
PuzzleBounds.boundingBox.Z1 = bounds->Z1 - 256;
PuzzleBounds.boundingBox.Z2 = bounds->Z2 + 256;
if (TestLaraPosition(&PuzzleBounds, item, l))
if (TestLaraPosition(&PuzzleBounds, receptableItem, laraItem))
{
PHD_VECTOR pos;
pos.x = 0;
pos.y = 0;
pos.z = 0;
if (!Lara.Control.IsMoving)
if (!laraInfo->Control.IsMoving)
{
if (g_Gui.GetInventoryItemChosen() == NO_ITEM)
{
if (g_Gui.IsObjectInInventory(item->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)))
g_Gui.SetEnterInventory(item->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1));
if (g_Gui.IsObjectInInventory(receptableItem->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)))
g_Gui.SetEnterInventory(receptableItem->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1));
item->Position.yRot = oldYrot;
receptableItem->Position.yRot = oldYrot;
return;
}
if (g_Gui.GetInventoryItemChosen() != item->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1))
if (g_Gui.GetInventoryItemChosen() != receptableItem->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1))
{
item->Position.yRot = oldYrot;
receptableItem->Position.yRot = oldYrot;
return;
}
}
pos.z = bounds->Z1 - 100;
if (flag != PUZZLETYPE_CUTSCENE)
{
if (!MoveLaraPosition(&pos, item, l))
PHD_VECTOR pos = { 0, 0, bounds->Z1 - 100 };
if (!MoveLaraPosition(&pos, receptableItem, laraItem))
{
Lara.interactedItem = itemNum;
laraInfo->interactedItem = itemNumber;
g_Gui.SetInventoryItemChosen(NO_ITEM);
item->Position.yRot = oldYrot;
receptableItem->Position.yRot = oldYrot;
return;
}
}
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(item->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1);
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(receptableItem->ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1);
if (flag == PUZZLETYPE_SPECIFIC)
{
l->ActiveState = LS_MISC_CONTROL;
l->AnimNumber = -item->TriggerFlags;
if (l->AnimNumber != LA_TRIDENT_SET)
PuzzleDone(item, itemNum);
laraItem->ActiveState = LS_MISC_CONTROL;
laraItem->AnimNumber = -receptableItem->TriggerFlags;
if (laraItem->AnimNumber != LA_TRIDENT_SET)
PuzzleDone(receptableItem, itemNumber);
}
else
{
l->AnimNumber = LA_USE_PUZZLE;
l->ActiveState = LS_INSERT_PUZZLE;
item->ItemFlags[0] = 1;
laraItem->AnimNumber = LA_USE_PUZZLE;
laraItem->ActiveState = LS_INSERT_PUZZLE;
receptableItem->ItemFlags[0] = 1;
}
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
item->Flags |= 0x20;
Lara.interactedItem = itemNum;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
ResetLaraFlex(laraItem);
laraInfo->Control.HandStatus = HandStatus::Busy;
receptableItem->Flags |= 0x20;
laraInfo->interactedItem = itemNumber;
g_Gui.SetInventoryItemChosen(NO_ITEM);
item->Position.yRot = oldYrot;
receptableItem->Position.yRot = oldYrot;
return;
}
if (Lara.Control.IsMoving)
if (laraInfo->Control.IsMoving)
{
if (Lara.interactedItem == itemNum)
if (laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}
item->Position.yRot = oldYrot;
receptableItem->Position.yRot = oldYrot;
}
else
{
if (!Lara.Control.IsMoving && Lara.interactedItem == itemNum || Lara.interactedItem != itemNum)
if (!laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber || laraInfo->interactedItem != itemNumber)
{
if (Lara.interactedItem == itemNum)
if (laraInfo->interactedItem == itemNumber)
{
if (l->ActiveState != LS_MISC_CONTROL)
if (laraItem->ActiveState != LS_MISC_CONTROL)
{
if (flag != PUZZLETYPE_CUTSCENE)
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
return;
}
}
if (l->ActiveState == LS_MISC_CONTROL)
if (laraItem->ActiveState == LS_MISC_CONTROL)
return;
if (flag != PUZZLETYPE_CUTSCENE)
ObjectCollision(itemNum, l, coll);
ObjectCollision(itemNumber, laraItem, coll);
return;
}
}
}
void PuzzleDoneCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
void PuzzleDoneCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
if (g_Level.Items[itemNum].TriggerFlags - 998 > 1)
{
ObjectCollision(itemNum, l, coll);
}
if (g_Level.Items[itemNumber].TriggerFlags - 998 > 1)
ObjectCollision(itemNumber, laraItem, coll);
}
void PuzzleDone(ITEM_INFO* item, short itemNum)
void PuzzleDone(ITEM_INFO* item, short itemNumber)
{
item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 };
item->AnimNumber = Objects[item->ObjectNumber].animIndex;
@ -186,7 +201,7 @@ void PuzzleDone(ITEM_INFO* item, short itemNum)
item->TargetState = g_Level.Anims[item->AnimNumber].ActiveState;
item->ActiveState = g_Level.Anims[item->AnimNumber].ActiveState;
AddActiveItem(itemNum);
AddActiveItem(itemNumber);
item->Flags |= IFLAG_ACTIVATION_MASK;
item->Status = ITEM_ACTIVE;
@ -195,7 +210,8 @@ void PuzzleDone(ITEM_INFO* item, short itemNum)
void DoPuzzle()
{
puzzleItem = Lara.interactedItem;
ITEM_INFO* item = &g_Level.Items[puzzleItem];
auto* item = &g_Level.Items[puzzleItem];
int flag = 0;
if (item->TriggerFlags >= 0)
@ -225,93 +241,94 @@ void DoPuzzle()
}
}
if (LaraItem->AnimNumber == LA_TRIDENT_SET)
{
PuzzleDone(item, puzzleItem);
}
}
}
/*keys*/
void KeyHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
// Keys
void KeyHoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll)
{
ITEM_INFO* item = &g_Level.Items[itemNum];
if (g_Level.Items[itemNum].TriggerFlags == 1 && item->ObjectNumber == ID_KEY_HOLE8)
auto* laraInfo = GetLaraInfo(laraItem);
auto* keyHoleItem = &g_Level.Items[itemNumber];
if (g_Level.Items[itemNumber].TriggerFlags == 1 &&
keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
{
if (item->ItemFlags[3])
if (keyHoleItem->ItemFlags[3])
{
item->ItemFlags[3]--;
if (!item->ItemFlags[3])
item->MeshBits = 2;
keyHoleItem->ItemFlags[3]--;
if (!keyHoleItem->ItemFlags[3])
keyHoleItem->MeshBits = 2;
}
}
if (!((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM)
&& !BinocularRange
&& Lara.Control.HandStatus == HandStatus::Free
&& l->ActiveState == LS_IDLE
&& l->AnimNumber == LA_STAND_IDLE)
&& (!Lara.Control.IsMoving || Lara.interactedItem != itemNum))
if (!((TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM) &&
!BinocularRange &&
laraItem->ActiveState == LS_IDLE &&
laraItem->AnimNumber == LA_STAND_IDLE) &&
laraInfo->Control.HandStatus == HandStatus::Free &&
(!laraInfo->Control.IsMoving || laraInfo->interactedItem != itemNumber))
{
if (item->ObjectNumber < ID_KEY_HOLE6)
ObjectCollision(itemNum, l, coll);
if (keyHoleItem->ObjectNumber < ID_KEY_HOLE6)
ObjectCollision(itemNumber, laraItem, coll);
}
else
{
if (TestLaraPosition(&KeyHoleBounds, item, l))
if (TestLaraPosition(&KeyHoleBounds, keyHoleItem, laraItem))
{
if (!Lara.Control.IsMoving)//TROYE INVENTORY FIX ME
if (!laraInfo->Control.IsMoving) //TROYE INVENTORY FIX ME
{
if (item->Status != ITEM_NOT_ACTIVE)
if (keyHoleItem->Status != ITEM_NOT_ACTIVE)
return;
if (g_Gui.GetInventoryItemChosen() == NO_ITEM)
{
if (g_Gui.IsObjectInInventory(item->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)))
g_Gui.SetEnterInventory(item->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1));
if (g_Gui.IsObjectInInventory(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)))
g_Gui.SetEnterInventory(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1));
return;
}
if (g_Gui.GetInventoryItemChosen() != item->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1))
if (g_Gui.GetInventoryItemChosen() != keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1))
return;
}
if (MoveLaraPosition(&KeyHolePosition, item, l))
if (MoveLaraPosition(&KeyHolePosition, keyHoleItem, laraItem))
{
if (item->ObjectNumber == ID_KEY_HOLE8)
l->AnimNumber = LA_KEYCARD_USE;
if (keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
laraItem->AnimNumber = LA_KEYCARD_USE;
else
{
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(item->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1);
l->AnimNumber = LA_USE_KEY;
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1);
laraItem->AnimNumber = LA_USE_KEY;
}
l->ActiveState = LS_INSERT_KEY;
l->FrameNumber = g_Level.Anims[l->AnimNumber].frameBase;
Lara.Control.IsMoving = false;
ResetLaraFlex(l);
Lara.Control.HandStatus = HandStatus::Busy;
item->Flags |= 0x20;
item->Status = ITEM_ACTIVE;
if (item->TriggerFlags == 1 && item->ObjectNumber == ID_KEY_HOLE8)
laraItem->ActiveState = LS_INSERT_KEY;
laraItem->FrameNumber = g_Level.Anims[laraItem->AnimNumber].frameBase;
laraInfo->Control.IsMoving = false;
ResetLaraFlex(laraItem);
laraInfo->Control.HandStatus = HandStatus::Busy;
keyHoleItem->Flags |= 0x20;
keyHoleItem->Status = ITEM_ACTIVE;
if (keyHoleItem->TriggerFlags == 1 && keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
{
item->ItemFlags[3] = 92;
keyHoleItem->ItemFlags[3] = 92;
g_Gui.SetInventoryItemChosen(NO_ITEM);
return;
}
}
else
{
Lara.interactedItem = itemNum;
}
laraInfo->interactedItem = itemNumber;
g_Gui.SetInventoryItemChosen(NO_ITEM);
return;
}
if (Lara.Control.IsMoving && Lara.interactedItem == itemNum)
if (laraInfo->Control.IsMoving && laraInfo->interactedItem == itemNumber)
{
Lara.Control.IsMoving = false;
Lara.Control.HandStatus = HandStatus::Free;
laraInfo->Control.IsMoving = false;
laraInfo->Control.HandStatus = HandStatus::Free;
}
}

View file

@ -2,10 +2,12 @@
struct ITEM_INFO;
struct COLL_INFO;
/*puzzles*/
void PuzzleHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void PuzzleDoneCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
void PuzzleDone(ITEM_INFO* item, short itemNum);
// Puzzles
void PuzzleHoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void PuzzleDoneCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);
void PuzzleDone(ITEM_INFO* item, short itemNumber);
void DoPuzzle();
/*keys*/
void KeyHoleCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll);
// Keys
void KeyHoleCollision(short itemNumber, ITEM_INFO* laraItem, COLL_INFO* coll);

View file

@ -4,6 +4,7 @@
#include "Game/animation.h"
#include "Game/control/box.h"
#include "Game/collision/collide_item.h"
#include "Game/collision/collide_room.h"
#include "Game/effects/effects.h"
#include "Game/effects/tomb4fx.h"
#include "Game/items.h"
@ -14,7 +15,8 @@
#include "Specific/level.h"
#include "Specific/setup.h"
enum centaur_anims {
enum CentaurAnims
{
CENTAUR_EMPTY,
CENTAUR_STOP,
CENTAUR_SHOOT,
@ -23,42 +25,35 @@ enum centaur_anims {
CENTAUR_DEATH,
CENTAUR_WARNING};
BITE_INFO centaur_rocket = { 11, 415, 41, 13 };
BITE_INFO centaur_rear = { 50, 30, 0, 5 };
BITE_INFO CentaurRocket = { 11, 415, 41, 13 };
BITE_INFO CentaurRear = { 50, 30, 0, 5 };
#define BOMB_SPEED 256
#define CENTAUR_TOUCH 0x30199
#define CENTAUR_DIE_ANIM 8
#define CENTAUR_TURN ANGLE(4)
#define CENTAUR_TURN ANGLE(4.0f)
#define CENTAUR_REAR_CHANCE 0x60
#define CENTAUR_REAR_RANGE SQUARE(WALL_SIZE*3/2)
#define CENTAUR_REAR_RANGE pow(SECTOR(3) / 2, 2)
#define FLYER_PART_DAMAGE 100
#define CENTAUR_REAR_DAMAGE 200
void ControlCentaurBomb(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
auto* item = &g_Level.Items[itemNumber];
int oldX = item->Position.xPos;
int oldY = item->Position.yPos;
int oldZ = item->Position.zPos;
short roomNumber = item->RoomNumber;
bool aboveWater = false;
item->Position.zRot += ANGLE(35);
item->Position.zRot += ANGLE(35.0f);
if (!(g_Level.Rooms[item->RoomNumber].flags & ENV_FLAG_WATER))
{
item->Position.xRot -= ANGLE(1);
item->Position.xRot -= ANGLE(1.0f);
if (item->Position.xRot < -16384)
item->Position.xRot = -16384;
item->VerticalVelocity = -BOMB_SPEED * phd_sin(item->Position.xRot);
item->Velocity = BOMB_SPEED * phd_cos(item->Position.xRot);
aboveWater = true;
@ -82,38 +77,35 @@ void ControlCentaurBomb(short itemNumber)
item->Position.yPos += item->Velocity * phd_sin(-item->Position.xRot);
item->Position.zPos += item->Velocity * phd_cos(item->Position.xRot) * phd_cos(item->Position.yRot);
roomNumber = item->RoomNumber;
FLOOR_INFO * floor = GetFloor(item->Position.xPos, item->Position.yPos, item->Position.zPos, &roomNumber);
auto probe = GetCollisionResult(item);
if (GetFloorHeight(floor, item->Position.xPos, item->Position.yPos, item->Position.zPos) < item->Position.yPos ||
GetCeiling(floor, item->Position.xPos, item->Position.yPos, item->Position.zPos) > item->Position.yPos)
if (probe.Position.Floor < item->Position.yPos ||
probe.Position.Ceiling > item->Position.yPos)
{
item->Position.xPos = oldX;
item->Position.yPos = oldY;
item->Position.zPos = oldZ;
if (g_Level.Rooms[item->RoomNumber].flags & ENV_FLAG_WATER)
{
if (TestEnvironment(ENV_FLAG_WATER, item->RoomNumber))
TriggerUnderwaterExplosion(item, 0);
}
else
{
item->Position.yPos -= 128;
item->Position.yPos -= CLICK(0.5f);
TriggerShockwave(&item->Position, 48, 304, 96, 0, 96, 128, 24, 0, 0);
TriggerExplosionSparks(oldX, oldY, oldZ, 3, -2, 0, item->RoomNumber);
for (int x = 0; x < 2; x++)
TriggerExplosionSparks(oldX, oldY, oldZ, 3, -1, 0, item->RoomNumber);
}
return;
}
if (item->RoomNumber != roomNumber)
ItemNewRoom(itemNumber, roomNumber);
if (item->RoomNumber != probe.RoomNumber)
ItemNewRoom(itemNumber, probe.RoomNumber);
if ((g_Level.Rooms[item->RoomNumber].flags & ENV_FLAG_WATER) && aboveWater)
{
if (TestEnvironment(ENV_FLAG_WATER, item->RoomNumber) && aboveWater)
SetupRipple(item->Position.xPos, g_Level.Rooms[item->RoomNumber].minfloor, item->Position.zPos, (GetRandomControl() & 7) + 8, 0, Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_RIPPLES);
}
int n = 0;
bool foundCollidedObjects = false;
@ -127,17 +119,15 @@ void ControlCentaurBomb(short itemNumber)
if (CollidedItems[0])
{
ITEM_INFO* currentItem = CollidedItems[0];
auto* currentItem = CollidedItems[0];
int k = 0;
do
{
OBJECT_INFO* currentObj = &Objects[currentItem->ObjectNumber];
auto* currentObj = &Objects[currentItem->ObjectNumber];
if (currentObj->intelligent && currentObj->collision && currentItem->Status == ITEM_ACTIVE && !currentObj->undead)
{
DoExplosiveDamageOnBaddie(LaraItem, currentItem, item, WEAPON_CROSSBOW);
}
k++;
currentItem = CollidedItems[k];
@ -152,18 +142,13 @@ static void RocketGun(ITEM_INFO* v)
itemNum = CreateItem();
if (itemNum != NO_ITEM)
{
PHD_VECTOR pos;
ITEM_INFO* item;
item = &g_Level.Items[itemNum];
auto* item = &g_Level.Items[itemNum];
item->ObjectNumber = ID_PROJ_BOMB;
item->Shade = 16 * 256;
item->RoomNumber = v->RoomNumber;
pos.x = 11;
pos.y = 415;
pos.z = 41;
PHD_VECTOR pos = { 11, 415, 41 };
GetJointAbsPosition(v, &pos, 13);
item->Position.xPos = pos.x;
@ -183,20 +168,16 @@ static void RocketGun(ITEM_INFO* v)
}
}
void CentaurControl(short itemNum)
void CentaurControl(short itemNumber)
{
ITEM_INFO *item;
CREATURE_INFO *centaur;
short angle, head, fx_number;
AI_INFO info;
auto* item = &g_Level.Items[itemNumber];
auto* creatureInfo = (CREATURE_INFO*)item->Data;
item = &g_Level.Items[itemNum];
if (!CreatureActive(itemNum))
if (!CreatureActive(itemNumber))
return;
centaur = (CREATURE_INFO *)item->Data;
head = angle = 0;
short head = 0;
short angle = 0;
if (item->HitPoints <= 0)
{
@ -209,6 +190,7 @@ void CentaurControl(short itemNum)
}
else
{
AI_INFO info;
CreatureAIInfo(item, &info);
if (info.ahead)
@ -230,6 +212,7 @@ void CentaurControl(short itemNum)
item->TargetState = CENTAUR_AIM;
else
item->TargetState = CENTAUR_RUN;
break;
case CENTAUR_RUN:
@ -248,6 +231,7 @@ void CentaurControl(short itemNum)
item->RequiredState = CENTAUR_WARNING;
item->TargetState = CENTAUR_STOP;
}
break;
case CENTAUR_AIM:
@ -257,6 +241,7 @@ void CentaurControl(short itemNum)
item->TargetState = CENTAUR_SHOOT;
else
item->TargetState = CENTAUR_STOP;
break;
case CENTAUR_SHOOT:
@ -265,30 +250,32 @@ void CentaurControl(short itemNum)
item->RequiredState = CENTAUR_AIM;
RocketGun(item);
}
break;
case CENTAUR_WARNING:
if (!item->RequiredState && (item->TouchBits & CENTAUR_TOUCH))
if (!item->RequiredState && item->TouchBits & CENTAUR_TOUCH)
{
CreatureEffect(item, &centaur_rear, DoBloodSplat);
CreatureEffect(item, &CentaurRear, DoBloodSplat);
LaraItem->HitPoints -= CENTAUR_REAR_DAMAGE;
LaraItem->HitStatus = 1;
item->RequiredState = CENTAUR_STOP;
}
break;
}
}
CreatureJoint(item, 0, head);
CreatureAnimation(itemNum, angle, 0);
CreatureAnimation(itemNumber, angle, 0);
if (item->Status == ITEM_DEACTIVATED)
{
SoundEffect(171, &item->Position, NULL);
ExplodingDeath(itemNum, 0xffffffff, FLYER_PART_DAMAGE);
KillItem(itemNum);
ExplodingDeath(itemNumber, 0xffffffff, FLYER_PART_DAMAGE);
KillItem(itemNumber);
item->Status = ITEM_DEACTIVATED;
}
}

View file

@ -1,4 +1,4 @@
#pragma once
void CentaurControl(short itemNum);
void CentaurControl(short itemNumber);
void ControlCentaurBomb(short itemNumber);

View file

@ -187,8 +187,8 @@ void ObjectObjects()
obj = &Objects[ID_TIGHT_ROPE];
if (obj->loaded)
{
obj->initialise = InitialiseTightRope;
obj->collision = TightRopeCollision;
obj->initialise = InitialiseTightrope;
obj->collision = TightropeCollision;
obj->drawRoutine = nullptr;
obj->saveFlags = true;
obj->usingDrawAnimatingItem = false;
@ -197,7 +197,7 @@ void ObjectObjects()
obj = &Objects[ID_PARALLEL_BARS];
if (obj->loaded)
{
obj->collision = ParallelBarsCollision;
obj->collision = HorizontalBarCollision;
}
obj = &Objects[ID_EARTHQUAKE];