#include "framework.h" #include "Objects/Generic/Object/generic_trapdoor.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" #include "Game/collision/floordata.h" #include "Specific/input.h" #include "Game/camera.h" #include "Game/control/control.h" #include "Specific/level.h" #include "Game/animation.h" #include "Game/items.h" #include "Renderer/Renderer11.h" #include "Game/collision/collide_item.h" using namespace TEN::Renderer; using namespace TEN::Floordata; 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}; static PHD_VECTOR FloorTrapDoorPos = {0, 0, -655}; void InitialiseTrapDoor(short itemNumber) { ITEM_INFO* item; item = &g_Level.Items[itemNumber]; TEN::Floordata::UpdateBridgeItem(itemNumber); CloseTrapDoor(itemNumber); } void TrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item; item = &g_Level.Items[itemNumber]; if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd) ObjectCollision(itemNumber, l, coll); } void CeilingTrapDoorCollision(short itemNumber, ITEM_INFO* l, 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); if (TrInput & IN_ACTION && item->Status != ITEM_ACTIVE && l->ActiveState == LS_JUMP_UP && l->Airborne && Lara.Control.HandStatus == HandStatus::Free && itemIsAbove && (result || result2)) { AlignLaraPosition(&CeilingTrapDoorPos, item, l); if (result2) l->Position.yRot += ANGLE(180); 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; AddActiveItem(itemNumber); item->Status = ITEM_ACTIVE; item->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; } else { if (item->ActiveState == 1) UseForcedFixedCamera = 0; } if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd) ObjectCollision(itemNumber, l, coll); } void FloorTrapDoorCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item; 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 (TestLaraPosition(&FloorTrapDoorBounds, item, l)) { if (MoveLaraPosition(&FloorTrapDoorPos, item, l)) { 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; AddActiveItem(itemNumber); item->Status = ITEM_ACTIVE; item->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; } else { Lara.interactedItem =itemNumber; } } } else { if (item->ActiveState == 1) UseForcedFixedCamera = 0; } if (item->ActiveState == 1 && item->FrameNumber == g_Level.Anims[item->AnimNumber].frameEnd) ObjectCollision(itemNumber, l, coll); } void TrapDoorControl(short itemNumber) { ITEM_INFO* item; item = &g_Level.Items[itemNumber]; if (TriggerActive(item)) { 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; } } else { item->Status = ITEM_ACTIVE; if (item->ActiveState == 1) { item->TargetState = 0; } } AnimateItem(item); if (item->ActiveState == 1 && (item->ItemFlags[2] || JustLoaded)) { OpenTrapDoor(itemNumber); } else if (!item->ActiveState && !item->ItemFlags[2]) { CloseTrapDoor(itemNumber); } } void CloseTrapDoor(short itemNumber) { ITEM_INFO* item = &g_Level.Items[itemNumber]; item->ItemFlags[2] = 1; } void OpenTrapDoor(short itemNumber) { ITEM_INFO* item = &g_Level.Items[itemNumber]; item->ItemFlags[2] = 0; } int TrapDoorFloorBorder(short itemNumber) { return GetBridgeBorder(itemNumber, false); } int TrapDoorCeilingBorder(short itemNumber) { return GetBridgeBorder(itemNumber, true); } std::optional TrapDoorFloor(short itemNumber, int x, int y, int z) { ITEM_INFO* item = &g_Level.Items[itemNumber]; if (!item->MeshBits || item->ItemFlags[2] == 0) return std::nullopt; return GetBridgeItemIntersect(itemNumber, x, y, z, false); } std::optional TrapDoorCeiling(short itemNumber, int x, int y, int z) { ITEM_INFO* item = &g_Level.Items[itemNumber]; if (!item->MeshBits || item->ItemFlags[2] == 0) return std::nullopt; return GetBridgeItemIntersect(itemNumber, x, y, z, true); }