From 6d9c03ea36183ade97f3e327006670eaef2b1db4 Mon Sep 17 00:00:00 2001 From: Joey Quint Date: Mon, 24 Apr 2023 21:31:42 +0200 Subject: [PATCH 01/16] Fix crash if ID_LITTLE_BEETLE exists and ID_BATS_EMITTER does not Copy-paste error --- TombEngine/Renderer/Renderer11Draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/Renderer11Draw.cpp b/TombEngine/Renderer/Renderer11Draw.cpp index 8f1ba951c..dccbcfcfe 100644 --- a/TombEngine/Renderer/Renderer11Draw.cpp +++ b/TombEngine/Renderer/Renderer11Draw.cpp @@ -541,7 +541,7 @@ namespace TEN::Renderer void Renderer11::DrawBats(RenderView& view) { - if (!Objects[ID_LITTLE_BEETLE].loaded) + if (!Objects[ID_BATS_EMITTER].loaded) { return; } From aa9a7a394a94972a173fa9eb372c7ac8ec50d600 Mon Sep 17 00:00:00 2001 From: Kubsy Date: Mon, 24 Apr 2023 20:35:05 +0100 Subject: [PATCH 02/16] Update Changes.txt --- Documentation/Changes.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index b11c8902d..7dfe5f9a1 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -10,7 +10,8 @@ Version 1.0.9 - Fix Cold bar triggered when room is dry (only trigger if and only if the room is water). - Fix spiky wall speed value. - Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]). -- Fix spiky wall being too slow when triggered. +- Fix crash if little beetle does not exist in wad to load bats emitter. + Lua API changes: * Add function String::SetTranslated() From 2b417e574564010ac6fb86c18f505e0acf1e799c Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 25 Apr 2023 14:35:16 +1000 Subject: [PATCH 03/16] Init bar values correctly --- TombEngine/Game/Hud/StatusBars.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/Hud/StatusBars.cpp b/TombEngine/Game/Hud/StatusBars.cpp index 19ae359c7..1e3c00983 100644 --- a/TombEngine/Game/Hud/StatusBars.cpp +++ b/TombEngine/Game/Hud/StatusBars.cpp @@ -21,7 +21,8 @@ namespace TEN::Hud { void StatusBar::Initialize(float value) { - Value = std::clamp(value, 0.0f, 1.0f); + Value = + TargetValue = std::clamp(value, 0.0f, 1.0f); } void StatusBar::Update(float value) From b7e2aaf18beeb83d075c7a245a503d937b0e8c95 Mon Sep 17 00:00:00 2001 From: Nemoel-Tomo Date: Tue, 25 Apr 2023 21:48:09 +0200 Subject: [PATCH 04/16] multiusable keyholes (#1082) * multi useable keyholes * removed hardcoded keycard slots, key anim number = ocb number * changed enum name * fixed a compile error --- TombEngine/Game/control/trigger.cpp | 31 +++++++++++ TombEngine/Objects/Generic/puzzles_keys.cpp | 61 ++++++++------------- TombEngine/Objects/Generic/puzzles_keys.h | 7 +++ 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 25eba5ac4..b50124eb8 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -17,6 +17,7 @@ #include "Game/savegame.h" #include "Game/spotcam.h" #include "Objects/Generic/Switches/generic_switch.h" +#include "Objects/Generic/puzzles_keys.h" #include "Objects/objectslist.h" #include "Objects/TR3/Vehicles/kayak.h" #include "Sound/sound.h" @@ -122,6 +123,7 @@ int SwitchTrigger(short itemNumber, short timer) { auto& item = g_Level.Items[itemNumber]; + //Stuff for multi useable puzzleholes. if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) && item.ItemFlags[1]) { item.Flags |= IFLAG_ACTIVATION_MASK; @@ -144,6 +146,35 @@ int SwitchTrigger(short itemNumber, short timer) (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16)) return 0; + //Stuff for multi useable keyholes. + if ((item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16) && + item.ItemFlags[1] && + (item.ItemFlags[5] == ReusableType::Hole || item.ItemFlags[5] == ReusableType::None)&& + (Lara.Control.HandStatus != HandStatus::Busy)) + { + item.Flags |= IFLAG_ACTIVATION_MASK; + item.Status = ITEM_ACTIVE; + item.ItemFlags[5] = ReusableType::Done; + item.ItemFlags[1] = false; + return 1; + } + + if ((item.ObjectNumber >= ID_KEY_HOLE1 && + item.ObjectNumber <= ID_KEY_HOLE16) && + item.ItemFlags[1] && item.ItemFlags[5] == ReusableType::Done && + (Lara.Control.HandStatus != HandStatus::Busy)) + { + item.Flags |= IFLAG_ACTIVATION_MASK; + item.Status = ITEM_DEACTIVATED; + item.ItemFlags[5] = ReusableType::Hole; + item.ItemFlags[1] = false; + return 1; + } + + if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16) + return 0; + + //Stuff for switches. if (item.Status == ITEM_DEACTIVATED) { if ((!item.Animation.ActiveState && item.ObjectNumber != ID_JUMP_SWITCH || item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH) && diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index 0c8bb55ce..be5a7ae34 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -33,13 +33,6 @@ enum class PuzzleType AnimAfter }; -enum PuzzleHoleType -{ - None = 0, - Done = 1, - Hole = 2 -}; - ObjectCollisionBounds PuzzleBounds = { GameBoundingBox( @@ -67,7 +60,7 @@ const ObjectCollisionBounds KeyHoleBounds = void InitializePuzzleHole(short itemNumber) { auto& receptacleItem = g_Level.Items[itemNumber]; - receptacleItem.ItemFlags[5] = PuzzleHoleType::Hole; + receptacleItem.ItemFlags[5] = ReusableType::Hole; } void InitializePuzzleDone(short itemNumber) @@ -84,7 +77,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co auto& player = GetLaraInfo(*laraItem); //Start level with the right object when loading the game. - if (receptacleItem.ItemFlags[5] == PuzzleHoleType::Done) + if (receptacleItem.ItemFlags[5] == ReusableType::Done) { receptacleItem.ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; SetAnimation(receptacleItem, 0); @@ -245,7 +238,7 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co AnimateItem(&receptacleItem); //Start level with the right object when loading the game. - if (receptacleItem.ItemFlags[5] == PuzzleHoleType::Hole) + if (receptacleItem.ItemFlags[5] == ReusableType::Hole) { receptacleItem.ObjectNumber = GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); SetAnimation(receptacleItem, 0); @@ -254,11 +247,11 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co } //Activate triggers when startig the level for the first time - if (receptacleItem.ItemFlags[5] == PuzzleHoleType::None) + if (receptacleItem.ItemFlags[5] == ReusableType::None) { receptacleItem.ItemFlags[1] = true; TestTriggers(receptacleItem.Pose.Position.x, receptacleItem.Pose.Position.y, receptacleItem.Pose.Position.z, receptacleItem.RoomNumber, false, 0); - receptacleItem.ItemFlags[5] = PuzzleHoleType::Done; + receptacleItem.ItemFlags[5] = ReusableType::Done; } auto puzzleType = PuzzleType::Normal; @@ -341,7 +334,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; - item->ItemFlags[5] = PuzzleHoleType::Done; + item->ItemFlags[5] = ReusableType::Done; SetAnimation(item, 0); item->ResetModelToDefault(); } @@ -371,7 +364,7 @@ void PuzzleHole(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber = GAME_OBJECT_ID(item->ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); - item->ItemFlags[5] = PuzzleHoleType::Hole; + item->ItemFlags[5] = ReusableType::Hole; SetAnimation(item, 0); item->ResetModelToDefault(); } @@ -444,16 +437,8 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) auto* laraInfo = GetLaraInfo(laraItem); auto* keyHoleItem = &g_Level.Items[itemNumber]; - if (g_Level.Items[itemNumber].TriggerFlags == 1 && - keyHoleItem->ObjectNumber == ID_KEY_HOLE8) - { - if (keyHoleItem->ItemFlags[3]) - { - keyHoleItem->ItemFlags[3]--; - if (!keyHoleItem->ItemFlags[3]) - keyHoleItem->MeshBits = 2; - } - } + auto triggerIndex = GetTriggerIndex(keyHoleItem); + short triggerType = (*(triggerIndex++) >> 8) & 0x3F; bool actionReady = (TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM); @@ -469,7 +454,7 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) { if (!laraInfo->Control.IsMoving) //TROYE INVENTORY FIX ME { - if (keyHoleItem->Status != ITEM_NOT_ACTIVE) + if (keyHoleItem->Status != ITEM_NOT_ACTIVE && triggerType != TRIGGER_TYPES::SWITCH) return; if (g_Gui.GetInventoryItemChosen() == NO_ITEM) @@ -491,13 +476,18 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) if (MoveLaraPosition(KeyHolePosition, keyHoleItem, laraItem)) { - if (keyHoleItem->ObjectNumber == ID_KEY_HOLE8) - laraItem->Animation.AnimNumber = LA_KEYCARD_USE; - else - { - RemoveObjectFromInventory(static_cast(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1); - laraItem->Animation.AnimNumber = LA_USE_KEY; - } + + if (triggerType != TRIGGER_TYPES::SWITCH) + { + RemoveObjectFromInventory(static_cast(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1); + } + else + { + keyHoleItem->ItemFlags[1] = true; + } + + laraItem->Animation.AnimNumber = keyHoleItem->TriggerFlags; + laraItem->Animation.ActiveState = LS_INSERT_KEY; laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase; @@ -506,13 +496,6 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) laraInfo->Control.HandStatus = HandStatus::Busy; keyHoleItem->Flags |= TRIGGERED; keyHoleItem->Status = ITEM_ACTIVE; - - if (keyHoleItem->TriggerFlags == 1 && keyHoleItem->ObjectNumber == ID_KEY_HOLE8) - { - keyHoleItem->ItemFlags[3] = 92; - g_Gui.SetInventoryItemChosen(NO_ITEM); - return; - } } g_Gui.SetInventoryItemChosen(NO_ITEM); diff --git a/TombEngine/Objects/Generic/puzzles_keys.h b/TombEngine/Objects/Generic/puzzles_keys.h index 65749aebd..0f40ac68f 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.h +++ b/TombEngine/Objects/Generic/puzzles_keys.h @@ -3,6 +3,13 @@ struct CollisionInfo; struct ItemInfo; +enum ReusableType +{ + None = 0, + Done = 1, + Hole = 2 +}; + // Puzzles void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); From 1ee85ce26ba0e6905a5e824e20ea1e2b7f13b295 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 26 Apr 2023 14:03:18 +1000 Subject: [PATCH 05/16] Formatting --- TombEngine/Game/control/trigger.cpp | 92 ++++++++++++--------- TombEngine/Game/control/trigger.h | 8 +- TombEngine/Objects/Generic/puzzles_keys.cpp | 74 ++++++++--------- TombEngine/Objects/Generic/puzzles_keys.h | 4 +- 4 files changed, 93 insertions(+), 85 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index b50124eb8..583324c56 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -83,7 +83,8 @@ bool GetKeyTrigger(ItemInfo* item) return true; } -int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch) +// NOTE: attatchedToSwitch parameter unused. +int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch) { auto triggerIndex = GetTriggerIndex(item); @@ -96,14 +97,14 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch) return 0; trigger += 2; - short* current = itemNos; + short* currentPtr = itemNumbersPtr; int k = 0; do { if (TRIG_BITS(*trigger) == TO_OBJECT && item != &g_Level.Items[*trigger & VALUE_BITS]) { - current[k] = *trigger & VALUE_BITS; + currentPtr[k] = *trigger & VALUE_BITS; ++k; } @@ -122,9 +123,11 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch) int SwitchTrigger(short itemNumber, short timer) { auto& item = g_Level.Items[itemNumber]; + const auto& player = Lara; - //Stuff for multi useable puzzleholes. - if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) && item.ItemFlags[1]) + // Handle reusable receptacles. + if (item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16 && + item.ItemFlags[1] != 0) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_ACTIVE; @@ -133,51 +136,54 @@ int SwitchTrigger(short itemNumber, short timer) return 1; } - if ((item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16) && item.ItemFlags[1]) + if (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16 && + item.ItemFlags[1] != 0) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_DEACTIVATED; item.ItemFlags[1] = false; - return 1; + return 1; } if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) || (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16)) + { return 0; + } - //Stuff for multi useable keyholes. - if ((item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16) && - item.ItemFlags[1] && - (item.ItemFlags[5] == ReusableType::Hole || item.ItemFlags[5] == ReusableType::None)&& - (Lara.Control.HandStatus != HandStatus::Busy)) + // Handle reusable receptacles. + if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 && + item.ItemFlags[1] != 0 && + (item.ItemFlags[5] == (int)ReusableReceptacleType::Empty || item.ItemFlags[5] == (int)ReusableReceptacleType::None) && + player.Control.HandStatus != HandStatus::Busy) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_ACTIVE; - item.ItemFlags[5] = ReusableType::Done; + item.ItemFlags[5] = (int)ReusableReceptacleType::Done; item.ItemFlags[1] = false; return 1; } - if ((item.ObjectNumber >= ID_KEY_HOLE1 && - item.ObjectNumber <= ID_KEY_HOLE16) && - item.ItemFlags[1] && item.ItemFlags[5] == ReusableType::Done && - (Lara.Control.HandStatus != HandStatus::Busy)) + if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 && + item.ItemFlags[1] != 0 && item.ItemFlags[5] == (int)ReusableReceptacleType::Done && + player.Control.HandStatus != HandStatus::Busy) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_DEACTIVATED; - item.ItemFlags[5] = ReusableType::Hole; + item.ItemFlags[5] = (int)ReusableReceptacleType::Empty; item.ItemFlags[1] = false; - return 1; + return 1; } if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16) return 0; - //Stuff for switches. + // Handle switches. if (item.Status == ITEM_DEACTIVATED) { - if ((!item.Animation.ActiveState && item.ObjectNumber != ID_JUMP_SWITCH || item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH) && + if (((item.Animation.ActiveState == 0 && item.ObjectNumber != ID_JUMP_SWITCH) || + (item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH)) && timer > 0) { item.Timer = timer; @@ -188,24 +194,24 @@ int SwitchTrigger(short itemNumber, short timer) return 1; } - - if (item.TriggerFlags >= 0 || item.Animation.ActiveState) + + if (item.TriggerFlags >= 0 || item.Animation.ActiveState != 0) { RemoveActiveItem(itemNumber); item.Status = ITEM_NOT_ACTIVE; if (!item.ItemFlags[0] == 0) item.Flags |= ONESHOT; + return 1; } - else //if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) && item.ItemFlags[1] == 0 || - //(item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16) && item.ItemFlags[1] == 0) + else { item.Status = ITEM_ACTIVE; return 1; } } - else if (item.Status) + else if (item.Status != 0) { if (item.ObjectNumber == ID_AIRLOCK_SWITCH && item.Animation.AnimNumber == GetAnimIndex(item, 2) && @@ -224,15 +230,18 @@ int SwitchTrigger(short itemNumber, short timer) return 0; } -int KeyTrigger(short itemNum) +int KeyTrigger(short itemNumber) { - ItemInfo* item = &g_Level.Items[itemNum]; - int oldkey; + auto* item = &g_Level.Items[itemNumber]; + const auto& player = Lara; - if ((item->Status != ITEM_ACTIVE || Lara.Control.HandStatus == HandStatus::Busy) && (!KeyTriggerActive || Lara.Control.HandStatus != HandStatus::Busy)) + if ((item->Status != ITEM_ACTIVE || player.Control.HandStatus == HandStatus::Busy) && + (!KeyTriggerActive || player.Control.HandStatus != HandStatus::Busy)) + { return -1; + } - oldkey = KeyTriggerActive; + int oldkey = KeyTriggerActive; if (!oldkey) item->Status = ITEM_DEACTIVATED; @@ -242,9 +251,9 @@ int KeyTrigger(short itemNum) return oldkey; } -bool PickupTrigger(short itemNum) +bool PickupTrigger(short itemNumber) { - ItemInfo* item = &g_Level.Items[itemNum]; + auto* item = &g_Level.Items[itemNumber]; if (((item->Flags & IFLAG_CLEAR_BODY) && (item->Flags & IFLAG_KILLED)) || item->Status != ITEM_INVISIBLE || @@ -254,7 +263,7 @@ bool PickupTrigger(short itemNum) return false; } - KillItem(itemNum); + KillItem(itemNumber); item->Flags |= IFLAG_CLEAR_BODY; return true; @@ -291,6 +300,7 @@ void RefreshCamera(short type, short* data) } else targetOk = 0; + break; case TO_TARGET: @@ -304,7 +314,7 @@ void RefreshCamera(short type, short* data) if (Camera.item) if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem)) - Camera.item = NULL; + Camera.item = nullptr; if (Camera.number == -1 && Camera.timer > 0) Camera.timer = -1; @@ -552,8 +562,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat short targetType = 0; short trigger = 0; - ItemInfo* item = NULL; - ItemInfo* cameraItem = NULL; + ItemInfo* item = nullptr; + ItemInfo* cameraItem = nullptr; do { @@ -815,12 +825,12 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat FlipEffect = newEffect; } -void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags) +void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags) { - auto roomNum = item->RoomNumber; - auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNum); + auto roomNumber = item->RoomNumber; + auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); - TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, heavy, heavyFlags); + TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, isHeavy, heavyFlags); } void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags) diff --git a/TombEngine/Game/control/trigger.h b/TombEngine/Game/control/trigger.h index 4ad5f02da..ebb3690e8 100644 --- a/TombEngine/Game/control/trigger.h +++ b/TombEngine/Game/control/trigger.h @@ -67,16 +67,16 @@ extern int TriggerTimer; extern int KeyTriggerActive; bool GetKeyTrigger(ItemInfo* item); -int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch); +int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch); int SwitchTrigger(short itemNumber, short timer); -int KeyTrigger(short itemNum); -bool PickupTrigger(short itemNum); +int KeyTrigger(short itemNumber); +bool PickupTrigger(short itemNumber); void RefreshCamera(short type, short* data); int TriggerActive(ItemInfo* item); short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z); short* GetTriggerIndex(ItemInfo* item); void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags = 0); -void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags = 0); +void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags = 0); void ProcessSectorFlags(ItemInfo* item); void Antitrigger(short const value, short const flags = 0); diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index be5a7ae34..bc86a52ec 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -60,7 +60,7 @@ const ObjectCollisionBounds KeyHoleBounds = void InitializePuzzleHole(short itemNumber) { auto& receptacleItem = g_Level.Items[itemNumber]; - receptacleItem.ItemFlags[5] = ReusableType::Hole; + receptacleItem.ItemFlags[5] = (int)ReusableReceptacleType::Empty; } void InitializePuzzleDone(short itemNumber) @@ -76,8 +76,8 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co auto& receptacleItem = g_Level.Items[itemNumber]; auto& player = GetLaraInfo(*laraItem); - //Start level with the right object when loading the game. - if (receptacleItem.ItemFlags[5] == ReusableType::Done) + // Start level with correct object when loading game. + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::Done) { receptacleItem.ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; SetAnimation(receptacleItem, 0); @@ -237,8 +237,8 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co return; AnimateItem(&receptacleItem); - //Start level with the right object when loading the game. - if (receptacleItem.ItemFlags[5] == ReusableType::Hole) + // Start level with correct object when loading game. + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::Empty) { receptacleItem.ObjectNumber = GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); SetAnimation(receptacleItem, 0); @@ -246,12 +246,12 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co return; } - //Activate triggers when startig the level for the first time - if (receptacleItem.ItemFlags[5] == ReusableType::None) + // Activate triggers when startig level for first time. + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::None) { receptacleItem.ItemFlags[1] = true; TestTriggers(receptacleItem.Pose.Position.x, receptacleItem.Pose.Position.y, receptacleItem.Pose.Position.z, receptacleItem.RoomNumber, false, 0); - receptacleItem.ItemFlags[5] = ReusableType::Done; + receptacleItem.ItemFlags[5] = (int)ReusableReceptacleType::Done; } auto puzzleType = PuzzleType::Normal; @@ -334,7 +334,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; - item->ItemFlags[5] = ReusableType::Done; + item->ItemFlags[5] = (int)ReusableReceptacleType::Done; SetAnimation(item, 0); item->ResetModelToDefault(); } @@ -364,7 +364,7 @@ void PuzzleHole(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber = GAME_OBJECT_ID(item->ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); - item->ItemFlags[5] = ReusableType::Hole; + item->ItemFlags[5] = (int)ReusableReceptacleType::Empty; SetAnimation(item, 0); item->ResetModelToDefault(); } @@ -434,25 +434,25 @@ void DoPuzzle() // Keys void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) { - auto* laraInfo = GetLaraInfo(laraItem); auto* keyHoleItem = &g_Level.Items[itemNumber]; + auto* player = GetLaraInfo(laraItem); - auto triggerIndex = GetTriggerIndex(keyHoleItem); - short triggerType = (*(triggerIndex++) >> 8) & 0x3F; + short* triggerIndexPtr = GetTriggerIndex(keyHoleItem); + short triggerType = (*(triggerIndexPtr++) >> 8) & 0x3F; - bool actionReady = (TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM); + bool isActionReady = (IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_ITEM); - bool laraAvailable = !BinocularRange && - laraItem->Animation.ActiveState == LS_IDLE && - laraItem->Animation.AnimNumber == LA_STAND_IDLE; + bool isPlayerAvailable = !BinocularRange && + laraItem->Animation.ActiveState == LS_IDLE && + laraItem->Animation.AnimNumber == LA_STAND_IDLE; - bool actionActive = laraInfo->Control.IsMoving && laraInfo->Context.InteractedItem == itemNumber; + bool actionActive = player->Control.IsMoving && player->Context.InteractedItem == itemNumber; - if (actionActive || (actionReady && laraAvailable)) + if (actionActive || (isActionReady && isPlayerAvailable)) { if (TestLaraPosition(KeyHoleBounds, keyHoleItem, laraItem)) { - if (!laraInfo->Control.IsMoving) //TROYE INVENTORY FIX ME + if (!player->Control.IsMoving) { if (keyHoleItem->Status != ITEM_NOT_ACTIVE && triggerType != TRIGGER_TYPES::SWITCH) return; @@ -468,32 +468,30 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) if (g_Gui.GetInventoryItemChosen() != keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)) return; - laraInfo->Context.InteractedItem = itemNumber; + player->Context.InteractedItem = itemNumber; } - if (laraInfo->Context.InteractedItem != itemNumber) + if (player->Context.InteractedItem != itemNumber) return; if (MoveLaraPosition(KeyHolePosition, keyHoleItem, laraItem)) { - - if (triggerType != TRIGGER_TYPES::SWITCH) - { - RemoveObjectFromInventory(static_cast(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1); - } - else - { - keyHoleItem->ItemFlags[1] = true; - } + if (triggerType != TRIGGER_TYPES::SWITCH) + { + RemoveObjectFromInventory(GAME_OBJECT_ID(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1); + } + else + { + keyHoleItem->ItemFlags[1] = true; + } - laraItem->Animation.AnimNumber = keyHoleItem->TriggerFlags; + laraItem->Animation.AnimNumber = keyHoleItem->TriggerFlags; - laraItem->Animation.ActiveState = LS_INSERT_KEY; laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase; - laraInfo->Control.IsMoving = false; + player->Control.IsMoving = false; ResetPlayerFlex(laraItem); - laraInfo->Control.HandStatus = HandStatus::Busy; + player->Control.HandStatus = HandStatus::Busy; keyHoleItem->Flags |= TRIGGERED; keyHoleItem->Status = ITEM_ACTIVE; } @@ -502,10 +500,10 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) return; } - if (laraInfo->Control.IsMoving && laraInfo->Context.InteractedItem == itemNumber) + if (player->Control.IsMoving && player->Context.InteractedItem == itemNumber) { - laraInfo->Control.IsMoving = false; - laraInfo->Control.HandStatus = HandStatus::Free; + player->Control.IsMoving = false; + player->Control.HandStatus = HandStatus::Free; } } else diff --git a/TombEngine/Objects/Generic/puzzles_keys.h b/TombEngine/Objects/Generic/puzzles_keys.h index 0f40ac68f..9c3300bbb 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.h +++ b/TombEngine/Objects/Generic/puzzles_keys.h @@ -3,11 +3,11 @@ struct CollisionInfo; struct ItemInfo; -enum ReusableType +enum class ReusableReceptacleType { None = 0, Done = 1, - Hole = 2 + Empty = 2 }; // Puzzles From 79add2d62de379bded4dced61fe23da7c0a92d6d Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 26 Apr 2023 14:05:04 +1000 Subject: [PATCH 06/16] Clarify enum name --- TombEngine/Game/control/trigger.cpp | 8 ++++---- TombEngine/Objects/Generic/puzzles_keys.cpp | 14 +++++++------- TombEngine/Objects/Generic/puzzles_keys.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 583324c56..af46c8809 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -155,23 +155,23 @@ int SwitchTrigger(short itemNumber, short timer) // Handle reusable receptacles. if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 && item.ItemFlags[1] != 0 && - (item.ItemFlags[5] == (int)ReusableReceptacleType::Empty || item.ItemFlags[5] == (int)ReusableReceptacleType::None) && + (item.ItemFlags[5] == (int)ReusableReceptacleState::Empty || item.ItemFlags[5] == (int)ReusableReceptacleState::None) && player.Control.HandStatus != HandStatus::Busy) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_ACTIVE; - item.ItemFlags[5] = (int)ReusableReceptacleType::Done; + item.ItemFlags[5] = (int)ReusableReceptacleState::Done; item.ItemFlags[1] = false; return 1; } if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 && - item.ItemFlags[1] != 0 && item.ItemFlags[5] == (int)ReusableReceptacleType::Done && + item.ItemFlags[1] != 0 && item.ItemFlags[5] == (int)ReusableReceptacleState::Done && player.Control.HandStatus != HandStatus::Busy) { item.Flags |= IFLAG_ACTIVATION_MASK; item.Status = ITEM_DEACTIVATED; - item.ItemFlags[5] = (int)ReusableReceptacleType::Empty; + item.ItemFlags[5] = (int)ReusableReceptacleState::Empty; item.ItemFlags[1] = false; return 1; } diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index bc86a52ec..27725ea81 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -60,7 +60,7 @@ const ObjectCollisionBounds KeyHoleBounds = void InitializePuzzleHole(short itemNumber) { auto& receptacleItem = g_Level.Items[itemNumber]; - receptacleItem.ItemFlags[5] = (int)ReusableReceptacleType::Empty; + receptacleItem.ItemFlags[5] = (int)ReusableReceptacleState::Empty; } void InitializePuzzleDone(short itemNumber) @@ -77,7 +77,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co auto& player = GetLaraInfo(*laraItem); // Start level with correct object when loading game. - if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::Done) + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::Done) { receptacleItem.ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; SetAnimation(receptacleItem, 0); @@ -238,7 +238,7 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co AnimateItem(&receptacleItem); // Start level with correct object when loading game. - if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::Empty) + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::Empty) { receptacleItem.ObjectNumber = GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); SetAnimation(receptacleItem, 0); @@ -247,11 +247,11 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co } // Activate triggers when startig level for first time. - if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleType::None) + if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::None) { receptacleItem.ItemFlags[1] = true; TestTriggers(receptacleItem.Pose.Position.x, receptacleItem.Pose.Position.y, receptacleItem.Pose.Position.z, receptacleItem.RoomNumber, false, 0); - receptacleItem.ItemFlags[5] = (int)ReusableReceptacleType::Done; + receptacleItem.ItemFlags[5] = (int)ReusableReceptacleState::Done; } auto puzzleType = PuzzleType::Normal; @@ -334,7 +334,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; - item->ItemFlags[5] = (int)ReusableReceptacleType::Done; + item->ItemFlags[5] = (int)ReusableReceptacleState::Done; SetAnimation(item, 0); item->ResetModelToDefault(); } @@ -364,7 +364,7 @@ void PuzzleHole(ItemInfo* item, short itemNumber) item->ItemFlags[1] = true; item->ObjectNumber = GAME_OBJECT_ID(item->ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1)); - item->ItemFlags[5] = (int)ReusableReceptacleType::Empty; + item->ItemFlags[5] = (int)ReusableReceptacleState::Empty; SetAnimation(item, 0); item->ResetModelToDefault(); } diff --git a/TombEngine/Objects/Generic/puzzles_keys.h b/TombEngine/Objects/Generic/puzzles_keys.h index 9c3300bbb..913c77a51 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.h +++ b/TombEngine/Objects/Generic/puzzles_keys.h @@ -3,7 +3,7 @@ struct CollisionInfo; struct ItemInfo; -enum class ReusableReceptacleType +enum class ReusableReceptacleState { None = 0, Done = 1, From 875a44d0d51e33ec63aae9fe3575744fa59d8f0b Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 26 Apr 2023 14:06:42 +1000 Subject: [PATCH 07/16] Use C-style cast --- TombEngine/Objects/Generic/puzzles_keys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index 27725ea81..08c67de4d 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -156,7 +156,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co } } - RemoveObjectFromInventory(static_cast(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1); + RemoveObjectFromInventory(GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1); if (puzzleType == PuzzleType::Specfic) { From e7c01add784f9c46fde512e718cf563002e10f4b Mon Sep 17 00:00:00 2001 From: Kubsy Date: Wed, 26 Apr 2023 11:58:42 +0100 Subject: [PATCH 08/16] Update Changes.txt --- Documentation/Changes.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 7dfe5f9a1..737240c94 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -1,16 +1,20 @@ Version 1.0.9 ============= -- Add TR1 Cowboy. -- Add TR3 Wall mounted blade. -- Add TR3 Claw mutant. -- Add removable puzzles from puzzle holes and puzzle dones. - - employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done. - - Can be mixed with puzzle done and puzzle holes of the same or different type. - Fix Cold bar triggered when room is dry (only trigger if and only if the room is water). - Fix spiky wall speed value. - Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]). - Fix crash if little beetle does not exist in wad to load bats emitter. +- Add TR1 Cowboy. +- Add TR3 Wall mounted blade. +- Add TR3 Claw mutant. +- Add removable puzzles from puzzle holes and puzzle dones. + - Employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done. + - Can be mixed with puzzle done and puzzle holes of the same or different type. +- Add reusable keys for key holes + - Employed by setting the trigger type as "Switch" for key hole. +- Allow Animation to be played by setting OCB to keyholes. + - +ve OCB will play the animation according to the OCB number. Lua API changes: From e24a1d1fd0bff91799c8a34cc7132c64b5842835 Mon Sep 17 00:00:00 2001 From: hispidence Date: Thu, 27 Apr 2023 14:48:24 +0100 Subject: [PATCH 09/16] Fix doc comment. --- Scripts/Engine/Timer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/Engine/Timer.lua b/Scripts/Engine/Timer.lua index a3edc3682..df05d13b0 100644 --- a/Scripts/Engine/Timer.lua +++ b/Scripts/Engine/Timer.lua @@ -277,7 +277,7 @@ Timer = { --- Get the total time for a timer. -- This is the amount of time the timer will start with, as well as when starting a new loop - -- @function myTimer:GetRemainingTime + -- @function myTimer:GetTotalTime -- @treturn float the timer's total time GetTotalTime = function(t) return LevelVars.Engine.Timer.timers[t.name].totalTime From 8bf82ab0b35a0a22f48b7e9e3cfb6c737ca32b58 Mon Sep 17 00:00:00 2001 From: davidmarr <116632612+davidmarr@users.noreply.github.com> Date: Fri, 28 Apr 2023 09:22:50 +0200 Subject: [PATCH 10/16] Check levels in Gameflow.lua (#1087) * Check levels in Gameflow.lua Check if there is the title and at least one playable level to avoid crashing the game * code review * code review * code review * revisione codice * code review use of TENLog() instead of TENScriptException() * code review * Update FlowHandler.cpp * Update FlowHandler.cpp * Update FlowHandler.cpp --------- Co-authored-by: Sezz --- TombEngine/Game/control/control.cpp | 1 - .../Internal/TEN/Flow/FlowHandler.cpp | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e770ca776..08c1cc214 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -271,7 +271,6 @@ unsigned CALLBACK GameMain(void *) else g_Renderer.RenderTitleImage(); - // Execute the Lua gameflow and play the game. g_GameFlow->DoFlow(); diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index 1d47050e6..cd04a2cc9 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -263,14 +263,28 @@ void FlowHandler::LoadFlowScript() m_handler.ExecuteScript("Scripts/Settings.lua"); SetScriptErrorMode(GetSettings()->ErrorMode); + + // Check if levels exist in Gameflow.lua. + if (Levels.empty()) + { + throw TENScriptException("No levels found. Check Gameflow.lua file integrity."); + } + else + { + TENLog("Level count: " + std::to_string(Levels.size()), LogLevel::Info); + } } char const * FlowHandler::GetString(const char* id) const { if (!ScriptAssert(m_translationsMap.find(id) != m_translationsMap.end(), std::string{ "Couldn't find string " } + id)) + { return "String not found."; + } else + { return m_translationsMap.at(string(id)).at(0).c_str(); + } } Settings* FlowHandler::GetSettings() @@ -404,6 +418,13 @@ bool FlowHandler::DoFlow() while (DoTheGame) { + // Check if called level exists in script. + if (CurrentLevel >= Levels.size()) + { + TENLog("Level not found. Check Gameflow.lua file integrity.", LogLevel::Error, LogConfig::All); + CurrentLevel = 0; + } + // First we need to fill some legacy variables in PCTomb5.exe Level* level = Levels[CurrentLevel]; From 0a7fe249946d783ab1b7ddab8be7935bee1307b1 Mon Sep 17 00:00:00 2001 From: Kubsy Date: Fri, 28 Apr 2023 09:46:01 +0100 Subject: [PATCH 11/16] Update Changes.txt --- Documentation/Changes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 737240c94..b7951f878 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -15,7 +15,7 @@ Version 1.0.9 - Employed by setting the trigger type as "Switch" for key hole. - Allow Animation to be played by setting OCB to keyholes. - +ve OCB will play the animation according to the OCB number. - +- Add log reports if title level or other levels don't exist. Lua API changes: * Add function String::SetTranslated() From e220c649e5e17cabe69c747610bbb26f4557c283 Mon Sep 17 00:00:00 2001 From: Kubsy Date: Fri, 28 Apr 2023 11:05:50 +0100 Subject: [PATCH 12/16] Fix blade damaging player when initially disabled. --- TombEngine/Objects/TR3/Trap/WallMountedBlade.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Objects/TR3/Trap/WallMountedBlade.cpp b/TombEngine/Objects/TR3/Trap/WallMountedBlade.cpp index c234cd3d9..8e9e65cc5 100644 --- a/TombEngine/Objects/TR3/Trap/WallMountedBlade.cpp +++ b/TombEngine/Objects/TR3/Trap/WallMountedBlade.cpp @@ -32,8 +32,8 @@ namespace TEN::Entities::Traps SetAnimation(item, WALL_MOUNTED_BLADE_ANIM_IDLE); // Used for GenericSphereBoxCollision. - item.ItemFlags[0] = WALL_MOUNTED_BLADE_JOINT; - item.ItemFlags[3] = WALL_MOUNTED_BLADE_HARM_DAMAGE; + item.ItemFlags[0] = WALL_MOUNTED_BLADE_JOINT; // Damaging mesh joint. + item.ItemFlags[3] = 0; // Set the Damage initially to 0 to avoid player being damaged when the blade is disabled. item.ItemFlags[4] = 1; // NOTE: avoid the blade pushing lara in GenericSphereBoxCollision() ! } From 2ba8257468389fc8ee2cc6657a63b0eff563be34 Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Fri, 28 Apr 2023 17:52:35 +0200 Subject: [PATCH 13/16] Enemy firing system refactor (#1069) * Refactored gunflash. - Fixed rendering of gunflash. - Improved gen.bat with some comment. - Now entity can shoot with 2 weapon (left and right) like lara. * Fix compiling error * Move muzzleFlash to creature struct - Removed BiteInfo and remplaced it by CreatureBiteInfo. - Fixed Mafia2 and Cybord muzzleflash pos. - Added dynamic light and smoke when entity shoot. (only for weapon) * Able to switch GUN_FLASH mesh. * Improve CreatureEffect/Effect2 Pass bite directly instead. * Fixed TR5 and TR4 biteInfo * Finished implementing gunflash for creatures. - Fix snowmobile gun crash. - Fix knifethrower not throwing knife. * Removed traps cpp/h. * Update Changes.txt * Update Changes.txt * Update effects.cpp * Fixed build error * Update setup.cpp - Removed old ObjectObjects() and TrapObjects() and move the code to TR5 objects. * Fix mpgun gunflash not playing when dead. * Fixed snowmobile gun not appearing correctly - Fixed crash if ID_GUN_FLASH2 not exist and creature like snomobile driver shoot. - Fix the snowmobile driver AI that where commented (was disabled to test the gunflash). * Improved AssignObjectAnimations * Added new lot for snowmobile gun - Allow the snowmobile to drop from 4 block ! * Fixed savegame crash * Change what @Lwmte reviewed. * Added todo for snowmobile gun. - reverted NO_JOINT in CreatureBiteInfo causing error when compiling. * Fix compile error caused by the develop merge * Minor formatting * Update people.cpp --------- Co-authored-by: Sezz Co-authored-by: Kubsy <80340234+Kubsy@users.noreply.github.com> --- Documentation/Changes.txt | 5 + TombEngine/Game/Lara/lara_fire.cpp | 3 +- TombEngine/Game/animation.cpp | 10 + TombEngine/Game/animation.h | 4 + TombEngine/Game/control/box.cpp | 32 +- TombEngine/Game/control/box.h | 79 +---- TombEngine/Game/control/lot.cpp | 6 + TombEngine/Game/effects/effects.cpp | 2 +- TombEngine/Game/effects/smoke.cpp | 11 +- TombEngine/Game/effects/smoke.h | 1 + TombEngine/Game/effects/tomb4fx.cpp | 11 +- TombEngine/Game/effects/tomb4fx.h | 3 + TombEngine/Game/itemdata/creature_info.cpp | 9 + TombEngine/Game/itemdata/creature_info.h | 60 +++- TombEngine/Game/missile.cpp | 2 +- TombEngine/Game/people.cpp | 5 +- TombEngine/Game/people.h | 3 +- TombEngine/Game/savegame.cpp | 11 +- .../Objects/Effects/tr5_electricity.cpp | 1 - TombEngine/Objects/Generic/Traps/traps.cpp | 299 ------------------ TombEngine/Objects/Generic/Traps/traps.h | 9 - TombEngine/Objects/TR1/Entity/tr1_ape.cpp | 2 +- TombEngine/Objects/TR1/Entity/tr1_bear.cpp | 2 +- TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp | 12 +- TombEngine/Objects/TR1/Entity/tr1_centaur.cpp | 4 +- TombEngine/Objects/TR1/Entity/tr1_natla.cpp | 2 +- .../Objects/TR1/Entity/tr1_winged_mutant.cpp | 6 +- TombEngine/Objects/TR1/Entity/tr1_wolf.cpp | 4 +- TombEngine/Objects/TR1/tr1_objects.cpp | 5 +- .../Objects/TR2/Entity/tr2_barracuda.cpp | 2 +- .../Objects/TR2/Entity/tr2_bird_monster.cpp | 4 +- TombEngine/Objects/TR2/Entity/tr2_dragon.cpp | 2 +- .../Objects/TR2/Entity/tr2_eagle_or_crow.cpp | 4 +- .../Objects/TR2/Entity/tr2_knife_thrower.cpp | 75 ++--- .../Objects/TR2/Entity/tr2_knife_thrower.h | 1 - .../Objects/TR2/Entity/tr2_mercenary.cpp | 41 ++- TombEngine/Objects/TR2/Entity/tr2_monk.cpp | 2 +- TombEngine/Objects/TR2/Entity/tr2_rat.cpp | 4 +- TombEngine/Objects/TR2/Entity/tr2_shark.cpp | 2 +- .../Objects/TR2/Entity/tr2_silencer.cpp | 16 +- TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 212 ++++++++----- .../Objects/TR2/Entity/tr2_spear_guardian.cpp | 8 +- TombEngine/Objects/TR2/Entity/tr2_spider.cpp | 4 +- .../Objects/TR2/Entity/tr2_sword_guardian.cpp | 4 +- .../TR2/Entity/tr2_worker_dualrevolver.cpp | 23 +- .../TR2/Entity/tr2_worker_flamethrower.cpp | 9 +- .../TR2/Entity/tr2_worker_machinegun.cpp | 59 +++- .../Objects/TR2/Entity/tr2_worker_shotgun.cpp | 22 +- TombEngine/Objects/TR2/Entity/tr2_yeti.cpp | 4 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 24 +- TombEngine/Objects/TR2/tr2_objects.cpp | 15 +- .../Objects/TR3/Entity/Compsognathus.cpp | 2 +- TombEngine/Objects/TR3/Entity/Lizard.cpp | 13 +- TombEngine/Objects/TR3/Entity/PunaBoss.cpp | 10 +- TombEngine/Objects/TR3/Entity/Shiva.cpp | 4 +- TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp | 10 +- TombEngine/Objects/TR3/Entity/WaspMutant.cpp | 8 +- TombEngine/Objects/TR3/Entity/tr3_civvy.cpp | 6 +- .../Objects/TR3/Entity/tr3_claw_mutant.cpp | 12 +- TombEngine/Objects/TR3/Entity/tr3_cobra.cpp | 2 +- .../Objects/TR3/Entity/tr3_flamethrower.cpp | 16 +- TombEngine/Objects/TR3/Entity/tr3_monkey.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 33 +- .../Objects/TR3/Entity/tr3_mp_stick.cpp | 4 +- TombEngine/Objects/TR3/Entity/tr3_raptor.cpp | 2 +- .../Objects/TR3/Entity/tr3_scuba_diver.cpp | 3 +- TombEngine/Objects/TR3/Entity/tr3_tiger.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_tony.cpp | 10 +- .../Objects/TR3/Entity/tr3_tribesman.cpp | 10 +- TombEngine/Objects/TR3/Vehicles/big_gun.cpp | 4 +- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 17 +- TombEngine/Objects/TR3/Vehicles/upv.cpp | 19 +- TombEngine/Objects/TR3/tr3_objects.cpp | 1 - TombEngine/Objects/TR4/Entity/Wraith.cpp | 1 - TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp | 6 +- TombEngine/Objects/TR4/Entity/tr4_baboon.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_baddy.cpp | 21 +- TombEngine/Objects/TR4/Entity/tr4_bat.cpp | 2 +- .../Objects/TR4/Entity/tr4_big_beetle.cpp | 2 +- .../Objects/TR4/Entity/tr4_big_scorpion.cpp | 19 +- .../Objects/TR4/Entity/tr4_crocodile.cpp | 30 +- TombEngine/Objects/TR4/Entity/tr4_dog.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_guide.cpp | 8 +- .../Objects/TR4/Entity/tr4_hammerhead.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_harpy.cpp | 18 +- .../Objects/TR4/Entity/tr4_horseman.cpp | 13 +- .../Objects/TR4/Entity/tr4_knight_templar.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_mummy.cpp | 4 +- TombEngine/Objects/TR4/Entity/tr4_mutant.cpp | 20 +- TombEngine/Objects/TR4/Entity/tr4_sas.cpp | 21 +- .../Objects/TR4/Entity/tr4_sentry_gun.cpp | 4 +- TombEngine/Objects/TR4/Entity/tr4_setha.cpp | 25 +- .../Objects/TR4/Entity/tr4_skeleton.cpp | 2 +- .../Objects/TR4/Entity/tr4_small_scorpion.cpp | 6 +- TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_troops.cpp | 21 +- .../Objects/TR4/Entity/tr4_von_croy.cpp | 2 +- .../Objects/TR4/Entity/tr4_wild_boar.cpp | 2 +- TombEngine/Objects/TR4/tr4_objects.cpp | 4 - TombEngine/Objects/TR5/Entity/HeavyGuard.cpp | 2 +- .../Objects/TR5/Entity/tr5_brownbeast.cpp | 4 +- TombEngine/Objects/TR5/Entity/tr5_chef.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp | 17 +- .../Objects/TR5/Entity/tr5_doberman.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_dog.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_ghost.cpp | 2 +- .../Objects/TR5/Entity/tr5_gladiator.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_guard.cpp | 114 ++++--- TombEngine/Objects/TR5/Entity/tr5_hydra.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_imp.cpp | 12 +- .../Objects/TR5/Entity/tr5_lagoon_witch.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_larson.cpp | 33 +- TombEngine/Objects/TR5/Entity/tr5_lion.cpp | 4 +- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 2 +- TombEngine/Objects/TR5/Trap/tr5_explosion.cpp | 1 - TombEngine/Objects/TR5/tr5_objects.cpp | 22 +- TombEngine/Objects/Utils/object_helper.cpp | 11 +- TombEngine/Renderer/Renderer11.h | 1 + TombEngine/Renderer/Renderer11DrawEffect.cpp | 109 +++---- .../flatbuffers/ten_itemdata_generated.h | 62 ++-- .../Specific/savegame/schema/ten_itemdata.fbs | 3 +- TombEngine/Specific/setup.cpp | 252 --------------- TombEngine/Specific/setup.h | 6 +- TombEngine/TombEngine.vcxproj | 1 + TombEngine/TombEngine_vs2022.vcxproj | 1 + 125 files changed, 883 insertions(+), 1359 deletions(-) create mode 100644 TombEngine/Game/itemdata/creature_info.cpp delete mode 100644 TombEngine/Objects/Generic/Traps/traps.cpp delete mode 100644 TombEngine/Objects/Generic/Traps/traps.h diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index b7951f878..7715a2e1c 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -5,12 +5,17 @@ Version 1.0.9 - Fix spiky wall speed value. - Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]). - Fix crash if little beetle does not exist in wad to load bats emitter. +- Fix gunflash rendering for entities. +- Fix all entities gunflash position. +- Fix snowmobile driver crashing the game. +- Fix knifethrower not throwing knife. - Add TR1 Cowboy. - Add TR3 Wall mounted blade. - Add TR3 Claw mutant. - Add removable puzzles from puzzle holes and puzzle dones. - Employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done. - Can be mixed with puzzle done and puzzle holes of the same or different type. +- Add missing gunflash for some entities, also include dynamic light and smoke to all gunflashes. - Add reusable keys for key holes - Employed by setting the trigger type as "Switch" for key hole. - Allow Animation to be played by setting OCB to keyholes. diff --git a/TombEngine/Game/Lara/lara_fire.cpp b/TombEngine/Game/Lara/lara_fire.cpp index 8f2309344..618db38d4 100644 --- a/TombEngine/Game/Lara/lara_fire.cpp +++ b/TombEngine/Game/Lara/lara_fire.cpp @@ -280,7 +280,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] = BLOCK(8), 3, 0, - 0, + 2, 0, SFX_TR4_UZI_FIRE, 0 @@ -781,6 +781,7 @@ void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo) arm.Orientation.InterpolateConstant(targetArmOrient, weaponInfo.AimSpeed); } +// TODO: include snowmobile gun in GetAmmo(), else it won't be able to shoot if lara control it. TokyoSU: 21/04/2023 FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient) { auto& player = *GetLaraInfo(&laraItem); diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 58c444e35..0619a03bd 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -664,6 +664,16 @@ Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOff return GetJointPosition(*item, jointIndex, relOffset); } +Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite) +{ + return GetJointPosition(item, bite.BoneID, bite.Position); +} + +Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite) +{ + return GetJointPosition(item, bite.BoneID, bite.Position); +} + Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex) { const auto& object = Objects[objectID]; diff --git a/TombEngine/Game/animation.h b/TombEngine/Game/animation.h index 5569010b6..da5cec222 100644 --- a/TombEngine/Game/animation.h +++ b/TombEngine/Game/animation.h @@ -10,6 +10,7 @@ class Pose; class Vector3i; struct ItemInfo; struct ObjectInfo; +struct CreatureBiteInfo; // NOTES: // animNumber: Relative animation number. @@ -145,6 +146,9 @@ void DrawAnimatingItem(ItemInfo* item); Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero); Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero); +Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite); +Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite); + Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex); Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex); float GetBoneLength(GAME_OBJECT_ID objectID, int boneIndex); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 6c645d735..b8eae1135 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -7,6 +7,7 @@ #include "Game/collision/collide_room.h" #include "Game/control/control.h" #include "Game/control/lot.h" +#include "Game/effects/smoke.h" #include "Game/effects/tomb4fx.h" #include "Game/itemdata/creature_info.h" #include "Game/Lara/lara.h" @@ -21,6 +22,8 @@ #include "Objects/TR5/Object/tr5_pushableblock.h" #include "Renderer/Renderer11.h" +using namespace TEN::Effects::Smoke; + constexpr auto ESCAPE_DIST = SECTOR(5); constexpr auto STALK_DIST = SECTOR(3); constexpr auto REACHED_GOAL_RADIUS = 640; @@ -32,6 +35,7 @@ constexpr auto FEELER_DISTANCE = CLICK(2); constexpr auto FEELER_ANGLE = ANGLE(45.0f); constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f); constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f); +constexpr auto GUN_EFFECT_CREATURE_YSHIFT = 75; #ifdef CREATURE_AI_PRIORITY_OPTIMIZATION constexpr int HIGH_PRIO_RANGE = 8; @@ -577,15 +581,15 @@ void CreatureKill(ItemInfo* creatureItem, int creatureAnimNumber, int playerAnim Camera.targetElevation = -ANGLE(25.0f); } -short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function func) +short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function func) { - auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position)); + auto pos = GetJointPosition(item, bite); return func(pos.x, pos.y, pos.z, velocity, angle, item->RoomNumber); } -short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function func) +short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function func) { - auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position)); + auto pos = GetJointPosition(item, bite); return func(pos.x, pos.y, pos.z, item->Animation.Velocity.z, item->Pose.Orientation.y, item->RoomNumber); } @@ -722,12 +726,30 @@ short CreatureTurn(ItemInfo* item, short maxTurn) return angle; } +static void PlayGunEffectForCreature(ItemInfo* item, const CreatureMuzzleflashInfo& muzzleFlash) +{ + if (muzzleFlash.Delay == 0) return; + auto muzzleNewpos = muzzleFlash.Bite; + auto pos = GetJointPosition(item, muzzleNewpos); + TriggerDynamicLight(pos.x, pos.y, pos.z, 15, 128, 64, 16); + if (muzzleFlash.UseSmoke) + { + // NOTE: Fix the smoke position, + // avoiding creating new variable in CreatureMuzzleflashInfo for a smoke biteInfo + muzzleNewpos.Position.y -= GUN_EFFECT_CREATURE_YSHIFT; + auto smokePos = GetJointPosition(item, muzzleNewpos); + TriggerGunSmokeParticles(smokePos.x, smokePos.y, smokePos.z, 0, 0, 0, 1, LaraWeaponType::Pistol, 12, item->RoomNumber); + } +} + bool CreatureAnimation(short itemNumber, short angle, short tilt) { auto* item = &g_Level.Items[itemNumber]; - if (!item->IsCreature()) return false; + auto* creature = GetCreatureInfo(item); + PlayGunEffectForCreature(item, creature->MuzzleFlash[0]); + PlayGunEffectForCreature(item, creature->MuzzleFlash[1]); auto prevPos = item->Pose.Position; diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 2ad6b3080..d1a735f05 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -2,10 +2,10 @@ #include "Specific/level.h" #include "Math/Math.h" -struct BiteInfo; struct CreatureInfo; struct ItemInfo; struct LOTInfo; +struct CreatureBiteInfo; enum class JumpDistance { @@ -20,55 +20,6 @@ enum TARGET_TYPE SECONDARY_TARGET }; -struct OBJECT_BONES -{ - short bone0; - short bone1; - short bone2; - short bone3; - - OBJECT_BONES() - { - this->bone0 = 0; - this->bone1 = 0; - this->bone2 = 0; - this->bone3 = 0; - } - - OBJECT_BONES(short all) - { - this->bone0 = all; - this->bone1 = all; - this->bone2 = all; - this->bone3 = all; - } - - OBJECT_BONES(short angleY, short angleX) - { - this->bone0 = angleY; - this->bone1 = angleX; - this->bone2 = angleY; - this->bone3 = angleX; - } - - OBJECT_BONES(short angleY, short angleX, bool total) - { - this->bone0 = angleY; - this->bone1 = angleX; - - if (total) - { - this->bone2 = angleY; - this->bone3 = angleX; - } - else - { - this->bone2 = 0; - this->bone3 = 0; - } - } -}; - struct AI_INFO { int zoneNumber; @@ -99,30 +50,6 @@ struct OVERLAP int flags; }; -struct BiteInfo -{ - Vector3 Position = Vector3::Zero; - int meshNum = 0; - - BiteInfo() - { - this->Position = Vector3::Zero; - this->meshNum = 0; - } - - BiteInfo(const Vector3& pos, int meshNumber) - { - this->Position = pos; - this->meshNum = meshNumber; - } - - BiteInfo(float xPos, float yPos, float zPos, int meshNumber) - { - this->Position = Vector3(xPos, yPos, zPos); - this->meshNum = meshNumber; - } -}; - #define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber) constexpr auto BOX_BLOCKED = (1 << 14); // unpassable for other enemies, always set for movable blocks & closed doors @@ -164,8 +91,8 @@ short AIGuard(CreatureInfo* creature); void AlertNearbyGuards(ItemInfo* item); void AlertAllGuards(short itemNumber); void CreatureKill(ItemInfo* item, int entityKillAnim, int laraExtraKillAnim, int entityKillState, int laraKillState); -short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function func); -short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function func); +short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function func); +short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function func); void CreatureUnderwater(ItemInfo* item, int depth); void CreatureFloat(short itemNumber); void CreatureJoint(ItemInfo* item, short joint, short required, short maxAngle = ANGLE(70.0f)); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 73c094f07..87a2fb1d6 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -146,6 +146,12 @@ void InitializeSlot(short itemNumber, bool makeTarget) break; + case LotType::SnowmobileGun: + creature->LOT.Step = CLICK(1); + creature->LOT.Drop = -BLOCK(1); + creature->LOT.Zone = ZoneType::Human; + break; + // Can climb. case LotType::Human: creature->LOT.Step = BLOCK(1); diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 13f6de93d..ef6b0936a 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -52,7 +52,7 @@ int SplashCount = 0; Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax]; NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] = { - { -16, 40, 160, -LM_LHAND, false }, // TR5 offset 0, TODO: This mesh is invalid as it can't be negative. -- TokyoSU 23.02.20 + { -16, 40, 160, 13, false }, // TR5 offset 0 { -16, -8, 160, 0, false }, // TR5 offset 1 { 0, 0, 256, 8, false }, // TR5 offset 2 { 0, 0, 256, 17, false }, // TR5 offset 3 diff --git a/TombEngine/Game/effects/smoke.cpp b/TombEngine/Game/effects/smoke.cpp index 3c45e6ddd..938055312 100644 --- a/TombEngine/Game/effects/smoke.cpp +++ b/TombEngine/Game/effects/smoke.cpp @@ -113,6 +113,11 @@ namespace TEN::Effects::Smoke //TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke. //TODO: Refactor different weapon types out of it void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count) + { + TriggerGunSmokeParticles(x, y, z, xv, yv, zv, initial, weaponType, count, LaraItem->RoomNumber); + } + + void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count, short roomNumber) { auto& s = GetFreeSmokeParticle(); s = {}; @@ -124,7 +129,7 @@ namespace TEN::Effects::Smoke s.velocity = direction; s.gravity = -.1f; - s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, LaraItem); + s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, x, y, z, roomNumber); s.sourceColor = Vector4(.4f, .4f, .4f, 1); s.destinationColor = Vector4(0, 0, 0, 0); @@ -135,7 +140,7 @@ namespace TEN::Effects::Smoke float size = Random::GenerateFloat(48, 80); s.sourceSize = size * 2; s.destinationSize = size * 8; - s.sourceColor = {0.75,0.75,1,1}; + s.sourceColor = { 0.75,0.75,1,1 }; s.terminalVelocity = 0; s.friction = 0.82f; s.life = Random::GenerateFloat(60, 90); @@ -188,7 +193,7 @@ namespace TEN::Effects::Smoke s.position += Vector3(Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8)); s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4); s.angularDrag = 0.95f; - s.room = LaraItem->RoomNumber; + s.room = roomNumber; } void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving) diff --git a/TombEngine/Game/effects/smoke.h b/TombEngine/Game/effects/smoke.h index 0cc7196f4..fa5fbd187 100644 --- a/TombEngine/Game/effects/smoke.h +++ b/TombEngine/Game/effects/smoke.h @@ -34,6 +34,7 @@ namespace TEN::Effects::Smoke void DisableSmokeParticles(); void TriggerFlareSmoke(const Vector3& pos, const Vector3& direction, int life, int room); void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count); + void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count, short roomNumber); void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving); void TriggerRocketSmoke(int x, int y, int z); void TriggerBreathSmoke(long x, long y, long z, short angle); diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 30eaa3719..075035a03 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -335,6 +335,11 @@ void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed) } } +void ThrowFire(int itemNum, const CreatureBiteInfo& bite, Vector3i speed) +{ + ThrowFire(itemNum, bite.BoneID, bite.Position, speed); +} + void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color) { auto* item = &g_Level.Items[itemNum]; @@ -343,11 +348,15 @@ void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Ve { auto* spark = SetupPoisonSpark(color); AttachAndCreateSpark(spark, item, meshIndex, offset, speed); - spark->flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; } } +void ThrowPoison(int itemNum, const CreatureBiteInfo& bite, Vector3i speed, Vector3 color) +{ + ThrowPoison(itemNum, bite.BoneID, bite.Position, speed, color); +} + void UpdateFireProgress() { TriggerGlobalStaticFlame(); diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index 5cb3374ff..7c91464b2 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -6,6 +6,7 @@ enum class LaraWeaponType; struct ItemInfo; +struct CreatureBiteInfo; enum BodyPartFlags { @@ -234,7 +235,9 @@ void TriggerGlobalFireSmoke(); void TriggerGlobalFireFlame(); void TriggerPilotFlame(int itemNum, int nodeIndex); void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed); +void ThrowFire(int itemNum, const CreatureBiteInfo& bite, Vector3i speed); void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color); +void ThrowPoison(int itemNum, const CreatureBiteInfo& bite, Vector3i speed, Vector3 color); void UpdateFireProgress(); void ClearFires(); void AddFire(int x, int y, int z, short roomNum, float size, short fade); diff --git a/TombEngine/Game/itemdata/creature_info.cpp b/TombEngine/Game/itemdata/creature_info.cpp new file mode 100644 index 000000000..a2150b899 --- /dev/null +++ b/TombEngine/Game/itemdata/creature_info.cpp @@ -0,0 +1,9 @@ +#include "framework.h" +#include "Game/itemdata/creature_info.h" + +#include "Game/items.h" + +bool CreatureInfo::IsTargetAlive() +{ + return ((Enemy != nullptr) && (Enemy->HitPoints > 0)); +} diff --git a/TombEngine/Game/itemdata/creature_info.h b/TombEngine/Game/itemdata/creature_info.h index 15ea209f9..9ef9fd52c 100644 --- a/TombEngine/Game/itemdata/creature_info.h +++ b/TombEngine/Game/itemdata/creature_info.h @@ -71,6 +71,62 @@ struct LOTInfo bool CanMonkey = false; }; +struct CreatureBiteInfo +{ + Vector3i Position = Vector3i::Zero; + int BoneID = -1; + + CreatureBiteInfo() {} + + CreatureBiteInfo(const Vector3i& pos, int boneID) + { + Position = pos; + BoneID = boneID; + } + + CreatureBiteInfo(int x, int y, int z, int boneID) + { + Position = Vector3i(x, y, z); + BoneID = boneID; + } +}; + +struct CreatureMuzzleflashInfo +{ + CreatureBiteInfo Bite = {}; + + int Delay = 0; + bool SwitchToMuzzle2 = false; // Changes muzzle object to ID_GUNFLASH2. + bool ApplyXRotation = true; // Applies X axis rotation for muzzleflash (required for creatures). + bool ApplyZRotation = true; // Applies Y axis rotation for muzzleflash (required for creatures). + bool UseSmoke = true; // Determines if CreatureAnimation calls TriggerGunSmokeParticles(). + + CreatureMuzzleflashInfo() {} + + CreatureMuzzleflashInfo(const Vector3i& pos, int boneID, int delay, bool changeToMuzzle2 = false) + { + Bite = CreatureBiteInfo(pos, boneID); + Delay = delay; + SwitchToMuzzle2 = changeToMuzzle2; + } + + CreatureMuzzleflashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false) + { + Bite = bite; + Delay = delay; + SwitchToMuzzle2 = changeToMuzzle2; + } + + CreatureMuzzleflashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false, bool applyXRot = true, bool applyZRot = true) + { + Bite = bite; + Delay = delay; + SwitchToMuzzle2 = changeToMuzzle2; + ApplyXRotation = applyXRot; + ApplyZRotation = applyZRot; + } +}; + struct CreatureInfo { int ItemNumber = -1; @@ -96,11 +152,13 @@ struct CreatureInfo bool MonkeySwingAhead = false; bool ReachedGoal = false; - short FiredWeapon = 0; + CreatureMuzzleflashInfo MuzzleFlash[2]; short Tosspad = 0; short LocationAI = 0; short Flags = 0; + bool IsTargetAlive(); + #ifdef CREATURE_AI_PRIORITY_OPTIMIZATION CreatureAIPriority Priority = CreatureAIPriority::None; size_t FramesSinceLOTUpdate = 0; diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index cc28e9284..8d4bcf403 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -115,7 +115,7 @@ void ControlMissile(short fxNumber) EffectNewRoom(fxNumber, pointColl.RoomNumber); if (fx.objectNumber == ID_KNIFETHROWER_KNIFE) - fx.pos.Orientation.z += ANGLE(3.0f); // Update knife rotation over time. + fx.pos.Orientation.z += ANGLE(30.0f); // Update knife rotation over time. switch (fx.objectNumber) { diff --git a/TombEngine/Game/people.cpp b/TombEngine/Game/people.cpp index 1e5d3f6cf..c2252f32c 100644 --- a/TombEngine/Game/people.cpp +++ b/TombEngine/Game/people.cpp @@ -12,7 +12,7 @@ #include "Game/misc.h" #include "Sound/sound.h" -bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage) +bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage) { auto* creature = GetCreatureInfo(item); auto* enemy = creature->Enemy; @@ -79,9 +79,10 @@ bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, in short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber) { + // TODO: Remove the -128 and fix the Ricochet effect going on the floor ! TokyoSU: 28/04/2023 auto pos = GameVector( LaraItem->Pose.Position.x + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF, - LaraItem->Floor, + LaraItem->Floor - 128, LaraItem->Pose.Position.z + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF, LaraItem->RoomNumber); diff --git a/TombEngine/Game/people.h b/TombEngine/Game/people.h index 9e6321657..318f779e7 100644 --- a/TombEngine/Game/people.h +++ b/TombEngine/Game/people.h @@ -1,9 +1,10 @@ #pragma once #include "Game/control/box.h" +struct CreatureBiteInfo; constexpr auto MAX_VISIBILITY_DISTANCE = SECTOR(8); -bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage); +bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage); short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber); short GunHit(int x, int y, int z, short velocity, short yRot, short roomNumber); short GunShot(int x, int y, int z, short velocity, short yRot, short roomNumber); diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index f76bcca4a..7f51f17c5 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -20,7 +20,6 @@ #include "Game/room.h" #include "Objects/Generic/Object/rope.h" #include "Objects/Generic/Switches/fullblock_switch.h" -#include "Objects/Generic/Traps/traps.h" #include "Objects/Generic/puzzles_keys.h" #include "Objects/Sink.h" #include "Objects/TR4/Entity/tr4_beetle_swarm.h" @@ -527,8 +526,7 @@ bool SaveGame::Save(int slot) flatbuffers::Offset shortOffset; flatbuffers::Offset intOffset; - if (Objects[itemToSerialize.ObjectNumber].intelligent - && itemToSerialize.Data.is()) + if (Objects[itemToSerialize.ObjectNumber].intelligent && itemToSerialize.IsCreature()) { auto creature = GetCreatureInfo(&itemToSerialize); @@ -538,12 +536,10 @@ bool SaveGame::Save(int slot) auto jointRotationsOffset = fbb.CreateVector(jointRotations); Save::CreatureBuilder creatureBuilder{ fbb }; - creatureBuilder.add_alerted(creature->Alerted); creatureBuilder.add_can_jump(creature->LOT.CanJump); creatureBuilder.add_can_monkey(creature->LOT.CanMonkey); creatureBuilder.add_enemy(creature->Enemy - g_Level.Items.data()); - creatureBuilder.add_fired_weapon(creature->FiredWeapon); creatureBuilder.add_flags(creature->Flags); creatureBuilder.add_friendly(creature->Friendly); creatureBuilder.add_head_left(creature->HeadLeft); @@ -555,6 +551,8 @@ bool SaveGame::Save(int slot) creatureBuilder.add_joint_rotation(jointRotationsOffset); creatureBuilder.add_jump_ahead(creature->JumpAhead); creatureBuilder.add_location_ai(creature->LocationAI); + creatureBuilder.add_weapon_delay1(creature->MuzzleFlash[0].Delay); + creatureBuilder.add_weapon_delay2(creature->MuzzleFlash[1].Delay); creatureBuilder.add_maximum_turn(creature->MaxTurn); creatureBuilder.add_monkey_swing_ahead(creature->MonkeySwingAhead); creatureBuilder.add_mood((int)creature->Mood); @@ -1545,13 +1543,14 @@ bool SaveGame::Load(int slot) creature->LOT.CanMonkey = savedCreature->can_monkey(); if (savedCreature->enemy() >= 0) creature->Enemy = &g_Level.Items[savedCreature->enemy()]; - creature->FiredWeapon = savedCreature->fired_weapon(); creature->Flags = savedCreature->flags(); creature->Friendly = savedCreature->friendly(); creature->HeadLeft = savedCreature->head_left(); creature->HeadRight = savedCreature->head_right(); creature->HurtByLara = savedCreature->hurt_by_lara(); creature->LocationAI = savedCreature->location_ai(); + creature->MuzzleFlash[0].Delay = savedCreature->weapon_delay1(); + creature->MuzzleFlash[1].Delay = savedCreature->weapon_delay2(); creature->LOT.IsAmphibious = savedCreature->is_amphibious(); creature->LOT.IsJumping = savedCreature->is_jumping(); creature->LOT.IsMonkeying = savedCreature->is_monkeying(); diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 44aee9952..ecb994f6a 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -12,7 +12,6 @@ #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_collide.h" -#include "Objects/Generic/Traps/traps.h" #include "Sound/sound.h" #include "Specific/clock.h" #include "Specific/level.h" diff --git a/TombEngine/Objects/Generic/Traps/traps.cpp b/TombEngine/Objects/Generic/Traps/traps.cpp deleted file mode 100644 index b217b2799..000000000 --- a/TombEngine/Objects/Generic/Traps/traps.cpp +++ /dev/null @@ -1,299 +0,0 @@ -#include "framework.h" -#include "traps.h" -#include "Game/items.h" -#include "Game/effects/effects.h" -#include "Game/effects/tomb4fx.h" -#include "Game/effects/weather.h" -#include "Game/Lara/lara.h" -#include "Game/collision/collide_room.h" -#include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" -#include "Game/camera.h" -#include "tr5_light.h" -#include "Game/animation.h" -#include "Specific/level.h" -#include "Specific/Input/Input.h" -#include "Game/room.h" -#include "Sound/sound.h" - -using namespace TEN::Effects::Environment; - -static short WreckingBallData[2] = {0, 0}; - -void InitialiseWreckingBall(short itemNumber) -{ - ItemInfo* item; - short room; - - item = &g_Level.Items[itemNumber]; - item->ItemFlags[3] = FindAllItems(ID_ANIMATING16)[0]; - room = item->RoomNumber; - item->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z) + 1644; - GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room); - if (room != item->RoomNumber) - ItemNewRoom(itemNumber, room); -} - -void WreckingBallCollision(short itemNumber, ItemInfo* l, CollisionInfo* coll) -{ - ItemInfo* item; - int x, y, z, test; - short damage; - - item = &g_Level.Items[itemNumber]; - if (TestBoundsCollide(item, l, coll->Setup.Radius)) - { - x = l->Pose.Position.x; - y = l->Pose.Position.y; - z = l->Pose.Position.z; - test = (x & 1023) > 256 && (x & 1023) < 768 && (z & 1023) > 256 && (z & 1023) < 768; - damage = item->Animation.Velocity.y > 0 ? 96 : 0; - if (ItemPushItem(item, l, coll, coll->Setup.EnableSpasm, 1)) - { - if (test) - DoDamage(l, INT_MAX); - else - DoDamage(l, damage); - - x -= l->Pose.Position.x; - y -= l->Pose.Position.y; - z -= l->Pose.Position.z; - if (damage) - { - for (int i = 14 + (GetRandomControl() & 3); i > 0; --i) - { - TriggerBlood(l->Pose.Position.x + (GetRandomControl() & 63) - 32, l->Pose.Position.y - (GetRandomControl() & 511) - 256, - l->Pose.Position.z + (GetRandomControl() & 63) - 32, -1, 1); - } - } - if (!coll->Setup.EnableObjectPush || test) - { - l->Pose.Position.x += x; - l->Pose.Position.y += y; - l->Pose.Position.z += z; - } - } - } -} - -void WreckingBallControl(short itemNumber) -{ - ItemInfo* item, *item2; - int test, x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz; - short room; - - item = &g_Level.Items[itemNumber]; - test = 1; - item2 = &g_Level.Items[item->ItemFlags[3]]; - if (LaraItem->Pose.Position.x >= 45056 && LaraItem->Pose.Position.x <= 57344 && LaraItem->Pose.Position.z >= 26624 && LaraItem->Pose.Position.z <= 43008 - || item->ItemFlags[2] < 900) - { - if (item->ItemFlags[2] < 900) - { - if (!item->ItemFlags[2] || !(GlobalCounter & 0x3F)) - { - WreckingBallData[0] = GetRandomControl() % 7 - 3; - WreckingBallData[1] = GetRandomControl() % 7 - 3; - } - x = (WreckingBallData[0] << 10) + 51712; - z = (WreckingBallData[1] << 10) + 34304; - test = 0; - } - else - { - x = LaraItem->Pose.Position.x; - z = LaraItem->Pose.Position.z; - } - } - else - { - x = 51200; - z = 33792; - test = 0; - } - if (item->ItemFlags[2] < 900) - ++item->ItemFlags[2]; - - if (item->ItemFlags[1] <= 0) - { - oldX = item->Pose.Position.x; - oldZ = item->Pose.Position.z; - x = x & 0xFFFFFE00 | 0x200; - z = z & 0xFFFFFE00 | 0x200; - dx = x - item->Pose.Position.x; - dz = z - item->Pose.Position.z; - wx = 0; - if (dx < 0) - wx = -1024; - else if (dx > 0) - wx = 1024; - wz = 0; - if (dz < 0) - wz = -1024; - else if (dz > 0) - wz = 1024; - room = item->RoomNumber; - ceilingX = GetCeiling(GetFloor(item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z); - room = item->RoomNumber; - ceilingZ = GetCeiling(GetFloor(item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz, &room), item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz); - if (ceilingX <= item2->Pose.Position.y && ceilingX != NO_HEIGHT) - flagX = 1; - else - flagX = 0; - if (ceilingZ <= item2->Pose.Position.y && ceilingZ != NO_HEIGHT) - flagZ = 1; - else - flagZ = 0; - if (!item->ItemFlags[0]) - { - if (flagX && dx && (abs(dx) > abs(dz) || !flagZ || GetRandomControl() & 1)) - { - item->ItemFlags[0] = 1; - } - else if (flagZ && dz) - { - item->ItemFlags[0] = 2; - } - } - if (item->ItemFlags[0] == 1) - { - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose); - adx = abs(dx); - if (adx >= 32) - adx = 32; - if (dx > 0) - { - item->Pose.Position.x += adx; - } - else if (dx < 0) - { - item->Pose.Position.x -= adx; - } - else - { - item->ItemFlags[0] = 0; - } - } - if (item->ItemFlags[0] == 2) - { - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose); - adz = abs(dz); - if (adz >= 32) - adz = 32; - if (dz > 0) - { - item->Pose.Position.z += adz; - } - else if (dz < 0) - { - item->Pose.Position.z -= adz; - } - else - { - item->ItemFlags[0] = 0; - } - } - if (item->ItemFlags[1] == -1 && (oldX != item->Pose.Position.x || oldZ != item->Pose.Position.z)) - { - item->ItemFlags[1] = 0; - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_A, &item->Pose); - } - if ((item->Pose.Position.x & 0x3FF) == 512 && (item->Pose.Position.z & 0x3FF) == 512) - item->ItemFlags[0] = 0; - if (x == item->Pose.Position.x && z == item->Pose.Position.z && test) - { - if (item->ItemFlags[1] != -1) - { - StopSoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP); - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_C, &item->Pose); - } - item->ItemFlags[1] = 1; - item->TriggerFlags = 30; - } - } - else if (item->ItemFlags[1] == 1) - { - if (!item->TriggerFlags) - { - --item->TriggerFlags; - } - else if (!item->Animation.ActiveState) - { - item->Animation.TargetState = 1; - } - else if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd) - { - SoundEffect(SFX_TR5_BASE_CLAW_DROP, &item->Pose); - ++item->ItemFlags[1]; - item->Animation.Velocity.y = 6; - item->Pose.Position.y += item->Animation.Velocity.y; - } - } - else if (item->ItemFlags[1] == 2) - { - item->Animation.Velocity.y += 24; - item->Pose.Position.y += item->Animation.Velocity.y; - room = item->RoomNumber; - height = GetFloorHeight(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - if (height < item->Pose.Position.y) - { - item->Pose.Position.y = height; - if (item->Animation.Velocity.y > 48) - { - BounceCamera(item, 64, 8192); - item->Animation.Velocity.y = -item->Animation.Velocity.y / 8; - } - else - { - ++item->ItemFlags[1]; - item->Animation.Velocity.y = 0; - } - } - else if (height - item->Pose.Position.y < 1536 && item->Animation.ActiveState) - { - item->Animation.TargetState = 0; - } - } - else if (item->ItemFlags[1] == 3) - { - item->Animation.Velocity.y -= 3; - item->Pose.Position.y += item->Animation.Velocity.y; - if (item->Pose.Position.y < item2->Pose.Position.y + 1644) - { - StopSoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP); - item->ItemFlags[0] = 1; - item->Pose.Position.y = item2->Pose.Position.y + 1644; - if (item->Animation.Velocity.y < -32) - { - SoundEffect(SFX_TR5_BASE_CLAW_TOP_IMPACT, &item->Pose, SoundEnvironment::Land, 1.0f, 0.5f); - item->Animation.Velocity.y = -item->Animation.Velocity.y / 8; - BounceCamera(item, 16, 8192); - } - else - { - item->ItemFlags[1] = -1; - item->Animation.Velocity.y = 0; - item->ItemFlags[0] = 0; - } - } - else if (!item->ItemFlags[0]) - { - SoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP, &item->Pose); - } - } - item2->Pose.Position.x = item->Pose.Position.x; - item2->Pose.Position.z = item->Pose.Position.z; - room = item->RoomNumber; - item2->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - GetFloor(item2->Pose.Position.x, item2->Pose.Position.y, item2->Pose.Position.z, &room); - if (room != item2->RoomNumber) - ItemNewRoom(item->ItemFlags[3], room); - TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter & 0x3F), item2->RoomNumber, 24); - TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter - 32) & 0xFFF, item2->RoomNumber, 24); - room = item->RoomNumber; - GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room); - if (room != item->RoomNumber) - ItemNewRoom(itemNumber, room); - AnimateItem(item); -} - diff --git a/TombEngine/Objects/Generic/Traps/traps.h b/TombEngine/Objects/Generic/Traps/traps.h deleted file mode 100644 index bdb8f7faf..000000000 --- a/TombEngine/Objects/Generic/Traps/traps.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -struct CollisionInfo; -struct ItemInfo; - -void InitializeFallingBlock(short itemNumber); -void InitializeWreckingBall(short itemNumber); -void WreckingBallCollision(short itemNumber, ItemInfo* l, CollisionInfo* coll); -void WreckingBallControl(short itemNumber); \ No newline at end of file diff --git a/TombEngine/Objects/TR1/Entity/tr1_ape.cpp b/TombEngine/Objects/TR1/Entity/tr1_ape.cpp index 9627c3c7c..4aaa155a2 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_ape.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_ape.cpp @@ -35,7 +35,7 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto APE_RUN_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto APE_DISPLAY_ANGLE = ANGLE(45.0f); - const auto ApeBite = BiteInfo(Vector3(0.0f, -19.0f, 75.0f), 15); + const auto ApeBite = CreatureBiteInfo(Vector3i(0, -19, 75), 15); const auto ApeAttackJoints = std::vector{ 8, 9, 10, 11, 12, 13, 14, 15 }; enum ApeState diff --git a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp index 80f832dd7..d45192a46 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp @@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto BEAR_WALK_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto BEAR_RUN_TURN_RATE_MAX = ANGLE(5.0f); - const auto BearBite = BiteInfo(Vector3(0.0f, 96.0f, 335.0f), 14); + const auto BearBite = CreatureBiteInfo(Vector3i(0, 96, 335), 14); const auto BearAttackJoints = std::vector{ 2, 3, 5, 6, 14, 17 }; enum BearState diff --git a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp index ddc0ee53f..cb430d269 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp @@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto BIG_RAT_RUN_TURN_RATE_MAX = ANGLE(6.0f); constexpr auto BIG_RAT_SWIM_TURN_RATE_MAX = ANGLE(3.0f); - const auto BigRatBite = BiteInfo(Vector3(0.0f, -11.0f, 108.0f), 3); + const auto BigRatBite = CreatureBiteInfo(Vector3i(0, -11, 108), 3); enum BigRatState { @@ -163,7 +163,7 @@ namespace TEN::Entities::Creatures::TR1 break; } - if (ai.ahead && item->TouchBits.Test(BigRatBite.meshNum)) + if (ai.ahead && item->TouchBits.Test(BigRatBite.BoneID)) { item->Animation.TargetState = BIG_RAT_STATE_IDLE; } @@ -181,7 +181,7 @@ namespace TEN::Entities::Creatures::TR1 case BIG_RAT_STATE_LAND_BITE_ATTACK: if (item->Animation.RequiredState == NO_STATE && ai.ahead && - item->TouchBits.Test(BigRatBite.meshNum)) + item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE); CreatureEffect(item, BigRatBite, DoBloodSplat); @@ -192,7 +192,7 @@ namespace TEN::Entities::Creatures::TR1 case BIG_RAT_STATE_POUNCE_ATTACK: if (item->Animation.RequiredState == NO_STATE && ai.ahead && - item->TouchBits.Test(BigRatBite.meshNum)) + item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_POUNCE_ATTACK_DAMAGE); CreatureEffect(item, BigRatBite, DoBloodSplat); @@ -216,14 +216,14 @@ namespace TEN::Entities::Creatures::TR1 break; } - if (ai.ahead && item->TouchBits.Test(BigRatBite.meshNum)) + if (ai.ahead && item->TouchBits.Test(BigRatBite.BoneID)) item->Animation.TargetState = BIG_RAT_STATE_SWIM_BITE_ATTACK; break; case BIG_RAT_STATE_SWIM_BITE_ATTACK: if (item->Animation.RequiredState == NO_STATE && ai.ahead && - item->TouchBits.Test(BigRatBite.meshNum)) + item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE); CreatureEffect(item, BigRatBite, DoBloodSplat); diff --git a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp b/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp index c9a37fc45..2b320c0e0 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp @@ -29,8 +29,8 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto CENTAUR_TURN_RATE_MAX = ANGLE(4.0f); - const auto CentaurRocketBite = BiteInfo(Vector3(11.0f, 415.0f, 41.0f), 13); - const auto CentaurRearBite = BiteInfo(Vector3(50.0f, 30.0f, 0.0f), 5); + const auto CentaurRocketBite = CreatureBiteInfo(Vector3(11, 415, 41), 13); + const auto CentaurRearBite = CreatureBiteInfo(Vector3(50, 30, 0), 5); const auto CentaurAttackJoints = std::vector{ 0, 3, 4, 7, 8, 16, 17 }; enum CentaurState diff --git a/TombEngine/Objects/TR1/Entity/tr1_natla.cpp b/TombEngine/Objects/TR1/Entity/tr1_natla.cpp index 949be1bc4..e0bf98e6f 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_natla.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_natla.cpp @@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto NATLA_FLY_ANGLE_SPEED = ANGLE(5.0f); constexpr auto NATLA_SHOOT_ANGLE = ANGLE(30.0f); - const auto NatlaGunBite = BiteInfo(Vector3(5.0f, 220.0f, 7.0f), 4); + const auto NatlaGunBite = CreatureBiteInfo(Vector3i(5, 220, 7), 4); enum NatlaState { diff --git a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp b/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp index 6cb8cfb3a..8e626ce08 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp @@ -39,9 +39,9 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto WINGED_MUTANT_WALK_FORWARD_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto WINGED_MUTANT_RUN_FORWARD_TURN_RATE_MAX = ANGLE(6.0f); - const auto WingedMutantBite = BiteInfo(Vector3(-27.0f, 98.0f, 0.0f), 10); - const auto WingedMutantRocketBite = BiteInfo(Vector3(51.0f, 213.0f, 0.0f), 14); - const auto WingedMutantShardBite = BiteInfo(Vector3(-35.0f, 269.0f, 0.0f), 9); + const auto WingedMutantBite = CreatureBiteInfo(Vector3i(-27, 98, 0), 10); + const auto WingedMutantRocketBite = CreatureBiteInfo(Vector3i(51, 213, 0), 14); + const auto WingedMutantShardBite = CreatureBiteInfo(Vector3i(-35, 269, 0), 9); const auto WingedMutantJoints = std::vector{ 9, 10, 14 }; enum WingedMutantState diff --git a/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp b/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp index 38ff58573..b8a14c177 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp @@ -31,8 +31,8 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto WOLF_WALK_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto WOLF_RUN_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto WOLF_STALK_TURN_RATE_MAX = ANGLE(2.0f); - - const auto WolfBite = BiteInfo(Vector3(0.0f, -14.0f, 174.0f), 6); + + const auto WolfBite = CreatureBiteInfo(Vector3i(0, -14, 174), 6); const auto WolfAttackJoints = std::vector{ 0, 1, 2, 3, 6, 8, 9, 10, 12, 13, 14 }; enum WolfState diff --git a/TombEngine/Objects/TR1/tr1_objects.cpp b/TombEngine/Objects/TR1/tr1_objects.cpp index ba29cea62..bf35bc6fd 100644 --- a/TombEngine/Objects/TR1/tr1_objects.cpp +++ b/TombEngine/Objects/TR1/tr1_objects.cpp @@ -17,8 +17,8 @@ #include "Objects/TR1/Entity/tr1_giant_mutant.h" // OK #include "Objects/TR1/Entity/tr1_wolf.h" // OK #include "Objects/TR1/Entity/tr1_big_rat.h" // OK -#include "Objects/TR1/Entity/tr1_centaur.h" -#include "Objects/TR1/Entity/tr1_winged_mutant.h" +#include "Objects/TR1/Entity/tr1_centaur.h" // OK +#include "Objects/TR1/Entity/tr1_winged_mutant.h" // OK #include "Objects/Utils/object_helper.h" // Traps @@ -157,7 +157,6 @@ static void StartEntity(ObjectInfo* obj) obj->control = WingedMutantControl; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->hitEffect = HitEffect::Blood; obj->pivotLength = 150; obj->radius = BLOCK(1 / 3.0f); obj->HitPoints = 50; diff --git a/TombEngine/Objects/TR2/Entity/tr2_barracuda.cpp b/TombEngine/Objects/TR2/Entity/tr2_barracuda.cpp index fb637c77f..0fd03155a 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_barracuda.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_barracuda.cpp @@ -16,7 +16,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto BARRACUDA_IDLE_ATTACK_RANGE = SQUARE(BLOCK(0.67f)); constexpr auto BARRACUDA_SWIM_FAST_ATTACK_RANGE = SQUARE(BLOCK(0.34f)); - const auto BarracudaBite = BiteInfo(Vector3(2.0f, -60.0f, 121.0f), 7); + const auto BarracudaBite = CreatureBiteInfo(Vector3i(2, -60, 121), 7); const auto BarracudaAttackJoints = std::vector{ 5, 6, 7 }; enum BarracudaState diff --git a/TombEngine/Objects/TR2/Entity/tr2_bird_monster.cpp b/TombEngine/Objects/TR2/Entity/tr2_bird_monster.cpp index 34609bac1..ccdae731c 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_bird_monster.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_bird_monster.cpp @@ -21,8 +21,8 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto BIRD_MONSTER_WALK_TURN_RATE_MAX = ANGLE(4.0f); - const auto BirdMonsterBiteLeft = BiteInfo(Vector3(0.0f, 224.0f, 0.0f), 19); - const auto BirdMonsterBiteRight = BiteInfo(Vector3(0.0f, 224.0f, 0.0f), 22); + const auto BirdMonsterBiteLeft = CreatureBiteInfo(Vector3i(0, 224, 0), 19); + const auto BirdMonsterBiteRight = CreatureBiteInfo(Vector3i(0, 224, 0), 22); const auto BirdMonsterAttackLeftJoints = std::vector{ 18, 19 }; const auto BirdMonsterAttackRightJoints = std::vector{ 21, 22 }; diff --git a/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp b/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp index ca9127202..f4129f57b 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp @@ -24,7 +24,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto DRAGON_SWIPE_ATTACK_DAMAGE = 250; constexpr auto DRAGON_CONTACT_DAMAGE = 10; - const auto DragonMouthBite = BiteInfo(Vector3(35.0f, 171.0f, 1168.0f), 12); + const auto DragonMouthBite = CreatureBiteInfo(Vector3i(35, 171, 1168), 12); const auto DragonSwipeAttackJointsLeft = std::vector{ 24, 25, 26, 27, 28, 29, 30 }; const auto DragonSwipeAttackJointsRight = std::vector{ 1, 2, 3, 4, 5, 6, 7 }; diff --git a/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp b/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp index b55716925..1a2b70a25 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp @@ -13,8 +13,8 @@ namespace TEN::Entities::Creatures::TR2 { - const auto EagleBite = BiteInfo(Vector3(15.0f, 46.0f, 21.0f), 6); - const auto CrowBite = BiteInfo(Vector3(2.0f, 10.0f, 60.0f), 14); + const auto EagleBite = CreatureBiteInfo(Vector3i(15, 46, 21), 6); + const auto CrowBite = CreatureBiteInfo(Vector3i(2, 10, 60), 14); enum EagleOrCrowState { diff --git a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp index 61416e1a0..16b7710a6 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp @@ -11,6 +11,7 @@ #include "Game/Lara/lara.h" #include "Game/misc.h" #include "Game/people.h" +#include "Game/missile.h" #include "Math/Math.h" #include "Sound/sound.h" #include "Specific/level.h" @@ -24,8 +25,8 @@ namespace TEN::Entities::Creatures::TR2 // TODO: Ranges. - const auto KnifeBiteLeft = BiteInfo(Vector3::Zero, 5); - const auto KnifeBiteRight = BiteInfo(Vector3::Zero, 8); + const auto KnifeBiteLeft = CreatureBiteInfo(Vector3i::Zero, 5); + const auto KnifeBiteRight = CreatureBiteInfo(Vector3i::Zero, 8); enum KnifeThrowerState { @@ -70,55 +71,23 @@ namespace TEN::Entities::Creatures::TR2 KTHROWER_ANIM_DEATH = 23 }; - void KnifeControl(short fxNumber) - { - auto* fx = &EffectList[fxNumber]; - - if (fx->counter <= 0) - { - KillEffect(fxNumber); - return; - } - else - fx->counter--; - - int speed = fx->speed * phd_cos(fx->pos.Orientation.x); - fx->pos.Position.z += speed * phd_cos(fx->pos.Orientation.y); - fx->pos.Position.x += speed * phd_sin(fx->pos.Orientation.y); - fx->pos.Position.y += fx->speed * phd_sin(-fx->pos.Orientation.x); - - auto probe = GetCollision(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, fx->roomNumber); - - if (fx->pos.Position.y >= probe.Position.Floor || - fx->pos.Position.y <= probe.Position.Ceiling) - { - KillEffect(fxNumber); - return; - } - - if (probe.RoomNumber != fx->roomNumber) - EffectNewRoom(fxNumber, probe.RoomNumber); - - fx->pos.Orientation.z += ANGLE(30.0f); - - if (ItemNearLara(fx->pos.Position, 200)) - { - DoDamage(LaraItem, KNIFE_PROJECTILE_DAMAGE); - - fx->pos.Orientation.y = LaraItem->Pose.Orientation.y; - fx->speed = LaraItem->Animation.Velocity.z; - fx->frameNumber = fx->counter = 0; - - DoBloodSplat(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, 80, fx->pos.Orientation.y, fx->roomNumber); - SoundEffect(SFX_TR2_CRUNCH2, &fx->pos); - KillEffect(fxNumber); - } - } - short ThrowKnife(int x, int y, int z, short velocity, short yRot, short roomNumber) { - short fxNumber = 0; - // TODO: add fx parameters + short fxNumber = CreateNewEffect(roomNumber); + if (fxNumber != NO_ITEM) + { + auto* fx = &EffectList[fxNumber]; + fx->objectNumber = ID_KNIFETHROWER_KNIFE; + fx->pos.Position.x = x; + fx->pos.Position.y = y; + fx->pos.Position.z = z; + fx->speed = velocity; + fx->pos.Orientation.y = yRot; + fx->fallspeed = 0; + fx->flag2 = KNIFE_PROJECTILE_DAMAGE; + fx->color = Vector4::One; + ShootAtLara(*fx); + } return fxNumber; } @@ -264,7 +233,7 @@ namespace TEN::Entities::Creatures::TR2 if (!creature->Flags) { - CreatureEffect(item, KnifeBiteLeft, ThrowKnife); + CreatureEffect2(item, KnifeBiteLeft, 100, torso, ThrowKnife); creature->Flags = 1; } @@ -276,7 +245,7 @@ namespace TEN::Entities::Creatures::TR2 if (!creature->Flags) { - CreatureEffect(item, KnifeBiteRight, ThrowKnife); + CreatureEffect2(item, KnifeBiteRight, 100, torso, ThrowKnife); creature->Flags = 1; } @@ -288,8 +257,8 @@ namespace TEN::Entities::Creatures::TR2 if (!creature->Flags) { - CreatureEffect(item, KnifeBiteLeft, ThrowKnife); - CreatureEffect(item, KnifeBiteRight, ThrowKnife); + CreatureEffect2(item, KnifeBiteLeft, 100, torso, ThrowKnife); + CreatureEffect2(item, KnifeBiteRight, 100, torso, ThrowKnife); creature->Flags = 1; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.h b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.h index 2204a999c..ba72b2e7e 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.h +++ b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.h @@ -2,6 +2,5 @@ namespace TEN::Entities::Creatures::TR2 { - void KnifeControl(short fxNumber); void KnifeThrowerControl(short itemNumber); } diff --git a/TombEngine/Objects/TR2/Entity/tr2_mercenary.cpp b/TombEngine/Objects/TR2/Entity/tr2_mercenary.cpp index 49ab0548a..10e13ff0f 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_mercenary.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_mercenary.cpp @@ -13,8 +13,8 @@ namespace TEN::Entities::Creatures::TR2 { - const auto MercenaryUziBite = BiteInfo(Vector3(0.0f, 150.0f, 19.0f), 17); - const auto MercenaryAutoPistolBite = BiteInfo(Vector3(0.0f, 230.0f, 9.0f), 17); + const auto MercenaryUziBite = CreatureBiteInfo(Vector3i(0, 200, 19), 17); + const auto MercenaryAutoPistolBite = CreatureBiteInfo(Vector3i(0, 230, 9), 17); // TODO enum MercenaryState @@ -41,6 +41,9 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (item->HitPoints <= 0) { if (item->Animation.ActiveState != 13) @@ -163,8 +166,13 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8)) - item->Animation.TargetState = 1; + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) + { + if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8)) + item->Animation.TargetState = 1; + creature->MuzzleFlash[0].Bite = MercenaryUziBite; + creature->MuzzleFlash[0].Delay = 2; + } if (AI.distance < pow(SECTOR(2), 2)) item->Animation.TargetState = 1; @@ -179,8 +187,13 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8)) - item->Animation.TargetState = 1; + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) + { + if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8)) + item->Animation.TargetState = 1; + creature->MuzzleFlash[0].Bite = MercenaryUziBite; + creature->MuzzleFlash[0].Delay = 2; + } if (AI.distance < pow(SECTOR(2), 2)) item->Animation.TargetState = 2; @@ -210,6 +223,9 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (item->HitPoints <= 0) { if (item->Animation.ActiveState != 11) @@ -330,12 +346,13 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.x = AI.xAngle; extraTorsoRot.y = AI.angle; - if (!creature->Flags) + if (creature->Flags == 0) { if (GetRandomControl() < 0x2000) item->Animation.TargetState = 2; - ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50); + creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } } @@ -353,11 +370,12 @@ namespace TEN::Entities::Creatures::TR2 if (AI.distance < pow(SECTOR(2), 2)) item->Animation.TargetState = 3; - if (creature->Flags != 1) + if (creature->Flags == 0) { if (!ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50)) item->Animation.TargetState = 3; - + creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } } @@ -395,7 +413,8 @@ namespace TEN::Entities::Creatures::TR2 { if (!ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50)) item->Animation.TargetState = 3; - + creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 2; } } diff --git a/TombEngine/Objects/TR2/Entity/tr2_monk.cpp b/TombEngine/Objects/TR2/Entity/tr2_monk.cpp index 0fd0b766f..08ea3d767 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_monk.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_monk.cpp @@ -13,7 +13,7 @@ namespace TEN::Entities::Creatures::TR2 { - const auto MonkBite = BiteInfo(Vector3(-23.0f, 16.0f, 265.0f), 14); + const auto MonkBite = CreatureBiteInfo(Vector3i(-23, 16, 265), 14); bool MonksAttackLara; diff --git a/TombEngine/Objects/TR2/Entity/tr2_rat.cpp b/TombEngine/Objects/TR2/Entity/tr2_rat.cpp index 97566873d..b626ae3c7 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_rat.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_rat.cpp @@ -25,7 +25,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto RAT_TURN_RATE_MAX = ANGLE(6.0f); - const auto RatBite = BiteInfo(Vector3(0.0f, 0.0f, 57.0f), 2); + const auto RatBite = CreatureBiteInfo(Vector3i(0, 0, 57), 2); enum RatState { @@ -131,7 +131,7 @@ namespace TEN::Entities::Creatures::TR2 case RAT_STATE_POUNCE_ATTACK: if (item->Animation.RequiredState == NO_STATE && - item->TouchBits.Test(RatBite.meshNum)) + item->TouchBits.Test(RatBite.BoneID)) { item->Animation.RequiredState = RAT_STATE_IDLE; DoDamage(creature->Enemy, RAT_ATTACK_DAMAGE); diff --git a/TombEngine/Objects/TR2/Entity/tr2_shark.cpp b/TombEngine/Objects/TR2/Entity/tr2_shark.cpp index eebf398f9..ce71873ea 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_shark.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_shark.cpp @@ -15,7 +15,7 @@ namespace TEN::Entities::Creatures::TR2 { constexpr auto SHARK_BITE_ATTACK_DAMAGE = 400; - const auto SharkBite = BiteInfo(Vector3(17.0f, -22.0f, 344.0f), 12); + const auto SharkBite = CreatureBiteInfo(Vector3i(17, -22, 344), 12); const auto SharkBiteAttackJoints = std::vector{ 10, 12, 13 }; void SharkControl(short itemNumber) diff --git a/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp b/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp index 8140df6ec..ed6db3896 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp @@ -21,7 +21,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto SILENCER_WALK_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto SILENCER_RUN_TURN_RATE_MAX = ANGLE(5.0f); - const auto SilencerGunBite = BiteInfo(Vector3(3.0f, 331.0f, 56.0f), 10); + const auto SilencerGunBite = CreatureBiteInfo(Vector3(-10, 360, 60), 10); enum SilencerState { @@ -87,6 +87,9 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (item->HitPoints <= 0) { if (item->Animation.ActiveState != SILENCER_STATE_DEATH_1 && @@ -279,9 +282,11 @@ namespace TEN::Entities::Creatures::TR2 else extraHeadRot.y = AI.angle; - if (!creature->Flags) + if (creature->Flags == 0 && item->Animation.FrameNumber == GetFrameIndex(item, 0)) { ShotLara(item, &AI, SilencerGunBite, extraTorsoRot.y, SILENCER_SHOOT_ATTACK_DAMAGE); + creature->MuzzleFlash[0].Bite = SilencerGunBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } @@ -298,11 +303,14 @@ namespace TEN::Entities::Creatures::TR2 else extraHeadRot.y = AI.angle; - if (item->Animation.RequiredState == NO_STATE) + if (item->Animation.RequiredState == NO_STATE && + (item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_LEFT) && item->Animation.FrameNumber == GetFrameIndex(item, 1) || + item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_RIGHT) && item->Animation.FrameNumber == GetFrameIndex(item, 3))) { if (!ShotLara(item, &AI, SilencerGunBite, extraTorsoRot.y, SILENCER_SHOOT_ATTACK_DAMAGE)) item->Animation.TargetState = SILENCER_STATE_RUN_FORWARD; - + creature->MuzzleFlash[0].Bite = SilencerGunBite; + creature->MuzzleFlash[0].Delay = 2; item->Animation.RequiredState = SILENCER_STATE_RUN_SHOOT; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index bc388f409..e3aac2692 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -7,8 +7,10 @@ #include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/control/lot.h" +#include "Game/effects/smoke.h" #include "Game/itemdata/creature_info.h" #include "Game/Lara/lara.h" +#include "Game/Lara/lara_helpers.h" #include "Game/misc.h" #include "Game/people.h" #include "Objects/TR2/Vehicles/skidoo.h" @@ -17,15 +19,19 @@ #include "Specific/level.h" #include "Specific/setup.h" +using namespace TEN::Effects::Smoke; + namespace TEN::Entities::Creatures::TR2 { constexpr auto SMAN_WAIT_RANGE = SQUARE(BLOCK(4)); - const auto SkidooBiteLeft = BiteInfo(Vector3(240.0f, -190.0f, 540.0f), 0); - const auto SkidooBiteRight = BiteInfo(Vector3(-240.0f, -190.0f, 540.0f), 0); + const auto SkidooBiteLeft = CreatureBiteInfo(Vector3i(240, -80, 540), 0); + const auto SkidooBiteRight = CreatureBiteInfo(Vector3i(-240, -80, 540), 0); + const auto SkidooBiteSmokeLeft = CreatureBiteInfo(Vector3i(240, -80, 450), 0); + const auto SkidooBiteSmokeRight = CreatureBiteInfo(Vector3i(-240, -80, 450), 0); constexpr auto SMAN_MIN_TURN = ANGLE(2.0f); - constexpr auto SMAN_TARGET_ANGLE = ANGLE(15.0f); + constexpr auto SMAN_TARGET_ANGLE = ANGLE(30.0f); enum SnowmobileManState { @@ -45,30 +51,34 @@ namespace TEN::Entities::Creatures::TR2 SMAN_ANIM_DEATH = 10 }; - void InitializeSkidooMan(short itemNumber) + static void CreateSnowmobileGun(ItemInfo* driver) { - short skidooItemNumber = CreateItem(); - if (skidooItemNumber != NO_ITEM) + short snowmobileNumber = CreateItem(); + if (snowmobileNumber != NO_ITEM) { - auto* riderItem = &g_Level.Items[itemNumber]; - auto* skidooItem = &g_Level.Items[skidooItemNumber]; - - skidooItem->ObjectNumber = ID_SNOWMOBILE_GUN; - skidooItem->Pose.Position = riderItem->Pose.Position; - skidooItem->Pose.Orientation.y = riderItem->Pose.Orientation.y; - skidooItem->RoomNumber = riderItem->RoomNumber; - skidooItem->Flags = ITEM_INVISIBLE; - skidooItem->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f); - - InitializeItem(skidooItemNumber); - - // The rider remembers his skidoo. - riderItem->Data = skidooItemNumber; - - g_Level.NumItems++; + auto* snowmobileGunItem = &g_Level.Items[snowmobileNumber]; + snowmobileGunItem->Pose.Position = driver->Pose.Position; + snowmobileGunItem->Pose.Orientation.y = driver->Pose.Orientation.y; + snowmobileGunItem->RoomNumber = driver->RoomNumber; + snowmobileGunItem->ObjectNumber = ID_SNOWMOBILE_GUN; + snowmobileGunItem->Model.Color = driver->Model.Color; + snowmobileGunItem->Flags = IFLAG_ACTIVATION_MASK; + InitializeItem(snowmobileNumber); g_Level.NumItems++; + driver->Data = snowmobileNumber; // Register the snowmobile gun for the driver to control it. } else - TENLog("Can't create skidoo for rider!", LogLevel::Error); + { + TENLog("Failed to create the ID_SNOWMOBILE_GUN from ID_SNOWMOBILE_DRIVER.", LogLevel::Warning); + } + } + + void InitializeSkidooMan(short itemNumber) + { + auto* item = &g_Level.Items[itemNumber]; + if (item->Flags & IFLAG_REVERSE) + item->Status &= ~ITEM_INVISIBLE; + else + item->Status = ITEM_INVISIBLE; } void SkidooManCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) @@ -95,60 +105,67 @@ namespace TEN::Entities::Creatures::TR2 void SkidooManControl(short riderItemNumber) { - auto* riderItem = &g_Level.Items[riderItemNumber]; - if (!riderItem->Data) + auto* rider = &g_Level.Items[riderItemNumber]; + if (!rider->Data) { - TENLog("Rider data does not contain the skidoo itemNumber!", LogLevel::Error); + // Create the snowmobile. + CreateSnowmobileGun(rider); + if (!rider->Data) + TENLog("Rider data does not contain the skidoo itemNumber !", LogLevel::Error); return; } - short itemNumber = (short)riderItem->Data; - auto* item = &g_Level.Items[itemNumber]; + short itemNumber = (short)rider->Data; + auto* skidoo = &g_Level.Items[itemNumber]; - if (!item->Data) + if (!skidoo->Data) { EnableEntityAI(itemNumber, true); - item->Status = ITEM_ACTIVE; + skidoo->Status = ITEM_ACTIVE; } - auto* creatureInfo = GetCreatureInfo(item); + auto* creatureInfo = GetCreatureInfo(skidoo); short angle = 0; - int damage; + + if (creatureInfo->MuzzleFlash[0].Delay != 0) + creatureInfo->MuzzleFlash[0].Delay--; + if (creatureInfo->MuzzleFlash[1].Delay != 0) + creatureInfo->MuzzleFlash[1].Delay--; AI_INFO AI; - if (item->HitPoints <= 0) + if (skidoo->HitPoints <= 0) { - if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH) + if (rider->Animation.ActiveState != SMAN_STATE_DEATH) { - riderItem->Pose.Position = item->Pose.Position; - riderItem->Pose.Orientation.y = item->Pose.Orientation.y; - riderItem->RoomNumber = item->RoomNumber; + rider->Pose.Position = skidoo->Pose.Position; + rider->Pose.Orientation.y = skidoo->Pose.Orientation.y; + rider->RoomNumber = skidoo->RoomNumber; - riderItem->Animation.AnimNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_ANIM_DEATH; - riderItem->Animation.FrameNumber = g_Level.Anims[riderItem->Animation.AnimNumber].frameBase; - riderItem->Animation.ActiveState = SMAN_STATE_DEATH; + rider->Animation.AnimNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_ANIM_DEATH; + rider->Animation.FrameNumber = g_Level.Anims[rider->Animation.AnimNumber].frameBase; + rider->Animation.ActiveState = SMAN_STATE_DEATH; - if (Lara.TargetEntity == item) + if (Lara.TargetEntity == skidoo) Lara.TargetEntity = nullptr; } else - AnimateItem(riderItem); + AnimateItem(rider); - if (item->Animation.ActiveState == SMAN_STATE_MOVING || item->Animation.ActiveState == SMAN_STATE_WAIT) - item->Animation.TargetState = SMAN_STATE_WAIT; + if (skidoo->Animation.ActiveState == SMAN_STATE_MOVING || skidoo->Animation.ActiveState == SMAN_STATE_WAIT) + skidoo->Animation.TargetState = SMAN_STATE_WAIT; else - item->Animation.TargetState = SMAN_STATE_MOVING; + skidoo->Animation.TargetState = SMAN_STATE_MOVING; } else { - CreatureAIInfo(item, &AI); + CreatureAIInfo(skidoo, &AI); - GetCreatureMood(item, &AI, true); - CreatureMood(item, &AI, true); + GetCreatureMood(skidoo, &AI, true); + CreatureMood(skidoo, &AI, true); - angle = CreatureTurn(item, ANGLE(3.0f)); + angle = CreatureTurn(skidoo, ANGLE(3.0f)); - switch (item->Animation.ActiveState) + switch (skidoo->Animation.ActiveState) { case SMAN_STATE_WAIT: if (creatureInfo->Mood == MoodType::Bored) @@ -156,98 +173,119 @@ namespace TEN::Entities::Creatures::TR2 else if (abs(AI.angle) < SMAN_TARGET_ANGLE && AI.distance < SMAN_WAIT_RANGE) break; - item->Animation.TargetState = SMAN_STATE_MOVING; + skidoo->Animation.TargetState = SMAN_STATE_MOVING; break; case SMAN_STATE_MOVING: if (creatureInfo->Mood == MoodType::Bored) - item->Animation.TargetState = SMAN_STATE_WAIT; + skidoo->Animation.TargetState = SMAN_STATE_WAIT; else if (abs(AI.angle) < SMAN_TARGET_ANGLE && AI.distance < SMAN_WAIT_RANGE) - item->Animation.TargetState = SMAN_STATE_WAIT; + skidoo->Animation.TargetState = SMAN_STATE_WAIT; else if (angle < -SMAN_MIN_TURN) - item->Animation.TargetState = SMAN_STATE_START_LEFT; + skidoo->Animation.TargetState = SMAN_STATE_START_LEFT; else if (angle > SMAN_MIN_TURN) - item->Animation.TargetState = SMAN_STATE_START_RIGHT; + skidoo->Animation.TargetState = SMAN_STATE_START_RIGHT; break; case SMAN_STATE_START_LEFT: case SMAN_STATE_LEFT: if (angle < -SMAN_MIN_TURN) - item->Animation.TargetState = SMAN_STATE_LEFT; + skidoo->Animation.TargetState = SMAN_STATE_LEFT; else - item->Animation.TargetState = SMAN_STATE_MOVING; + skidoo->Animation.TargetState = SMAN_STATE_MOVING; break; case SMAN_STATE_START_RIGHT: case SMAN_STATE_RIGHT: if (angle < -SMAN_MIN_TURN) - item->Animation.TargetState = SMAN_STATE_LEFT; + skidoo->Animation.TargetState = SMAN_STATE_LEFT; else - item->Animation.TargetState = SMAN_STATE_MOVING; + skidoo->Animation.TargetState = SMAN_STATE_MOVING; break; } } - if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH) + if (rider->Animation.ActiveState != SMAN_STATE_DEATH) { - if (!creatureInfo->Flags && abs(AI.angle) < SMAN_TARGET_ANGLE && LaraItem->HitPoints > 0) + if (creatureInfo->Flags == 0 && abs(AI.angle) < SMAN_TARGET_ANGLE && creatureInfo->Enemy->HitPoints > 0) { - damage = (Lara.Context.Vehicle != NO_ITEM) ? 10 : 50; + int damage = (creatureInfo->Enemy->IsLara() && GetLaraInfo(creatureInfo->Enemy)->Context.Vehicle != NO_ITEM) ? 10 : 50; + + ShotLara(skidoo, &AI, SkidooBiteLeft, 0, damage); + auto jointPos = GetJointPosition(skidoo, SkidooBiteSmokeLeft); + TriggerGunSmokeParticles(jointPos.x, jointPos.y, jointPos.z, 0, 0, 0, 1, LaraWeaponType::Snowmobile, 16, skidoo->RoomNumber); + creatureInfo->MuzzleFlash[0].Bite = SkidooBiteLeft; + creatureInfo->MuzzleFlash[0].Delay = 1; + creatureInfo->MuzzleFlash[0].SwitchToMuzzle2 = true; + creatureInfo->MuzzleFlash[0].ApplyXRotation = false; + creatureInfo->MuzzleFlash[0].UseSmoke = false; - if (ShotLara(item, &AI, SkidooBiteLeft, 0, damage) + ShotLara(item, &AI, SkidooBiteRight, 0, damage)) - creatureInfo->Flags = 5; + ShotLara(skidoo, &AI, SkidooBiteRight, 0, damage); + jointPos = GetJointPosition(skidoo, SkidooBiteSmokeRight); + TriggerGunSmokeParticles(jointPos.x, jointPos.y, jointPos.z, 0, 0, 0, 1, LaraWeaponType::Snowmobile, 16, skidoo->RoomNumber); + creatureInfo->MuzzleFlash[1].Bite = SkidooBiteRight; + creatureInfo->MuzzleFlash[1].Delay = 1; + creatureInfo->MuzzleFlash[1].SwitchToMuzzle2 = true; + creatureInfo->MuzzleFlash[1].ApplyXRotation = false; + creatureInfo->MuzzleFlash[1].UseSmoke = false; + + creatureInfo->Flags = 4; } - if (creatureInfo->Flags) + if (creatureInfo->Flags != 0) { - SoundEffect(SFX_TR4_BADDY_UZI, &item->Pose); + SoundEffect(SFX_TR4_BADDY_UZI, &skidoo->Pose); creatureInfo->Flags--; } } - if (item->Animation.ActiveState == SMAN_STATE_WAIT) + if (skidoo->Animation.ActiveState == SMAN_STATE_WAIT) { - SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &item->Pose); + SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &skidoo->Pose); creatureInfo->JointRotation[0] = 0; } else { creatureInfo->JointRotation[0] = (creatureInfo->JointRotation[0] == 1) ? 2 : 1; - DoSnowEffect(item); - SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &item->Pose, SoundEnvironment::Land, 0.5f + item->Animation.Velocity.z / 100.0f); // SKIDOO_MAX_VELOCITY. TODO: Check actual sound! + DoSnowEffect(skidoo); + SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &skidoo->Pose, SoundEnvironment::Land, 0.5f + skidoo->Animation.Velocity.z / 100.0f); // SKIDOO_MAX_VELOCITY. TODO: Check actual sound! } CreatureAnimation(itemNumber, angle, 0); - if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH) + if (rider->Animation.ActiveState != SMAN_STATE_DEATH) { - riderItem->Pose.Position = item->Pose.Position; - riderItem->Pose.Orientation.y = item->Pose.Orientation.y; + rider->Pose.Position = skidoo->Pose.Position; + rider->Pose.Orientation.y = skidoo->Pose.Orientation.y; - if (item->RoomNumber != riderItem->RoomNumber) - ItemNewRoom(riderItemNumber, item->RoomNumber); + if (skidoo->RoomNumber != rider->RoomNumber) + ItemNewRoom(riderItemNumber, skidoo->RoomNumber); - riderItem->Animation.AnimNumber = item->Animation.AnimNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex); - riderItem->Animation.FrameNumber = item->Animation.FrameNumber + (g_Level.Anims[riderItem->Animation.AnimNumber].frameBase - g_Level.Anims[item->Animation.AnimNumber].frameBase); + rider->Animation.AnimNumber = skidoo->Animation.AnimNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex); + rider->Animation.FrameNumber = skidoo->Animation.FrameNumber + (g_Level.Anims[rider->Animation.AnimNumber].frameBase - g_Level.Anims[skidoo->Animation.AnimNumber].frameBase); } - else if (riderItem->Status == ITEM_DEACTIVATED && - item->Animation.Velocity.z == 0 && - item->Animation.Velocity.y == 0) + else if (rider->Status == ITEM_DEACTIVATED && + skidoo->Animation.Velocity.z == 0 && + skidoo->Animation.Velocity.y == 0) { RemoveActiveItem(riderItemNumber); - riderItem->Collidable = false; - riderItem->HitPoints = NOT_TARGETABLE; - riderItem->Flags |= IFLAG_INVISIBLE; + rider->Collidable = false; + rider->HitPoints = NOT_TARGETABLE; + rider->Flags |= IFLAG_INVISIBLE; DisableEntityAI(itemNumber); - item->ObjectNumber = ID_SNOWMOBILE; - item->Status = ITEM_DEACTIVATED; - InitializeSkidoo(itemNumber); + skidoo->ObjectNumber = ID_SNOWMOBILE; + skidoo->Status = ITEM_DEACTIVATED; - ((SkidooInfo*)item->Data)->Armed = true; + InitializeSkidoo(itemNumber); + if (skidoo->Data.is()) + { + auto* skidooData = (SkidooInfo*)skidoo->Data; + skidooData->Armed = true; + } } } } diff --git a/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp b/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp index 9c1bc221d..9ebf6bd85 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp @@ -34,8 +34,8 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto SPEAR_GUARDIAN_SWAPMESH_TIME = 3; - const auto SpearGuardianBiteLeft = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 11); - const auto SpearGuardianBiteRight = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 18); + const auto SpearGuardianBiteLeft = CreatureBiteInfo(Vector3i(0, 0, 920), 11); + const auto SpearGuardianBiteRight = CreatureBiteInfo(Vector3i(0, 0, 920), 18); enum SpearGuardianState { @@ -108,7 +108,7 @@ namespace TEN::Entities::Creatures::TR2 { auto& creature = *GetCreatureInfo(&item); - if (!(creature.Flags & 1) && item.TouchBits.Test(SpearGuardianBiteRight.meshNum)) + if (!(creature.Flags & 1) && item.TouchBits.Test(SpearGuardianBiteRight.BoneID)) { DoDamage(creature.Enemy, damage); CreatureEffect(&item, SpearGuardianBiteRight, DoBloodSplat); @@ -116,7 +116,7 @@ namespace TEN::Entities::Creatures::TR2 SoundEffect(SFX_TR2_CRUNCH2, &item.Pose); } - if (!(creature.Flags & 2) && item.TouchBits.Test(SpearGuardianBiteLeft.meshNum)) + if (!(creature.Flags & 2) && item.TouchBits.Test(SpearGuardianBiteLeft.BoneID)) { DoDamage(creature.Enemy, damage); CreatureEffect(&item, SpearGuardianBiteLeft, DoBloodSplat); diff --git a/TombEngine/Objects/TR2/Entity/tr2_spider.cpp b/TombEngine/Objects/TR2/Entity/tr2_spider.cpp index 7216d1c26..720fd07de 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_spider.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_spider.cpp @@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto SMALL_SPIDER_TURN_RATE_MAX = ANGLE(8.0f); constexpr auto BIG_SPIDER_TURN_RATE_MAX = ANGLE(4.0f); - const auto SpiderBite = BiteInfo(Vector3(0.0f, 0.0f, 41.0f), 1); + const auto SpiderBite = CreatureBiteInfo(Vector3i(0, 0, 41), 1); enum SpiderState { @@ -72,7 +72,7 @@ namespace TEN::Entities::Creatures::TR2 void DoSpiderBloodEffect(ItemInfo& item) { - auto pos = GetJointPosition(&item, SpiderBite.meshNum, SpiderBite.Position); + auto pos = GetJointPosition(&item, SpiderBite); DoBloodSplat(pos.x, pos.y, pos.z, 10, item.Pose.Position.y, item.RoomNumber); } diff --git a/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp b/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp index 511ed29af..e21dbb47c 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp @@ -29,7 +29,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto SWORD_GUARDIAN_MESH_SWAP_TIME = 3; - const auto SwordBite = BiteInfo(Vector3(0.0f, 37.0f, 550.0f), 15); + const auto SwordBite = CreatureBiteInfo(Vector3i(0, 37, 550), 15); enum SwordGuardianState { @@ -352,7 +352,7 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = ai.angle; } - if (!creature->Flags && item->TouchBits.Test(SwordBite.meshNum)) + if (!creature->Flags && item->TouchBits.Test(SwordBite.BoneID)) { DoDamage(creature->Enemy, SWORD_GUARDIAN_ATTACK_DAMAGE); CreatureEffect(item, SwordBite, DoBloodSplat); diff --git a/TombEngine/Objects/TR2/Entity/tr2_worker_dualrevolver.cpp b/TombEngine/Objects/TR2/Entity/tr2_worker_dualrevolver.cpp index 9abe5e8ef..938e144ce 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_worker_dualrevolver.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_worker_dualrevolver.cpp @@ -12,8 +12,8 @@ namespace TEN::Entities::Creatures::TR2 { - const auto WorkerDualGunBiteLeft = BiteInfo(Vector3(-2.0f, 275.0f, 23.0f), 6); - const auto WorkerDualGunBiteRight = BiteInfo(Vector3(2.0f, 275.0f, 23.0f), 10); + const auto WorkerDualGunBiteLeft = CreatureBiteInfo(Vector3i(-2, 340, 23), 6); + const auto WorkerDualGunBiteRight = CreatureBiteInfo(Vector3i(2, 340, 23), 10); // TODO enum WorkerDualGunState @@ -40,6 +40,11 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (creature->MuzzleFlash[1].Delay != 0) + creature->MuzzleFlash[1].Delay--; + if (item->HitPoints <= 0) { if (item->Animation.ActiveState != 11) @@ -223,9 +228,11 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!creature->Flags) + if (creature->Flags == 0 && TestAnimFrame(*item, 0)) { ShotLara(item, &AI, WorkerDualGunBiteLeft, extraTorsoRot.y, 50); + creature->MuzzleFlash[0].Bite = WorkerDualGunBiteLeft; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } @@ -238,9 +245,11 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!creature->Flags) + if (creature->Flags == 0 && TestAnimFrame(*item, 0)) { ShotLara(item, &AI, WorkerDualGunBiteRight, extraTorsoRot.y, 50); + creature->MuzzleFlash[0].Bite = WorkerDualGunBiteRight; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } @@ -269,10 +278,14 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!creature->Flags) + if (creature->Flags == 0 && item->Animation.FrameNumber == GetFrameIndex(item, 0)) { ShotLara(item, &AI, WorkerDualGunBiteLeft, extraTorsoRot.y, 50); ShotLara(item, &AI, WorkerDualGunBiteRight, extraTorsoRot.y, 50); + creature->MuzzleFlash[0].Bite = WorkerDualGunBiteLeft; + creature->MuzzleFlash[0].Delay = 1; + creature->MuzzleFlash[1].Bite = WorkerDualGunBiteRight; + creature->MuzzleFlash[1].Delay = 1; creature->Flags = 1; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_worker_flamethrower.cpp b/TombEngine/Objects/TR2/Entity/tr2_worker_flamethrower.cpp index c358ecb30..15836441f 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_worker_flamethrower.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_worker_flamethrower.cpp @@ -26,7 +26,7 @@ namespace TEN::Entities::Creatures::TR2 constexpr auto WORKER_FLAME_RUN_TURN_RATE_MAX = ANGLE(10.0f); const auto WorkerFlamethrowerOffset = Vector3i(0, 140, 0); - const auto WorkerFlamethrowerBite = BiteInfo(Vector3(0.0f, 250.0f, 32.0f), 9); + const auto WorkerFlamethrowerBite = CreatureBiteInfo(Vector3(0.0f, 250.0f, 32.0f), 9); enum WorkerFlamethrowerState { @@ -70,8 +70,7 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; - auto pos = GetJointPosition(item, WorkerFlamethrowerBite.meshNum, Vector3i(WorkerFlamethrowerBite.Position)); - + auto pos = GetJointPosition(item, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerBite.Position); if (item->HitPoints <= 0) { if (item->Animation.ActiveState != WORKER_FLAME_STATE_DEATH) @@ -82,12 +81,12 @@ namespace TEN::Entities::Creatures::TR2 if (item->Animation.ActiveState != WORKER_FLAME_STATE_ATTACK && item->Animation.ActiveState != WORKER_FLAME_STATE_WALK_FORWARD_ATTACK) { TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 10, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7); - TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.meshNum); + TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.BoneID); } else { TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 14, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7); - ThrowFire(itemNumber, WorkerFlamethrowerBite.meshNum, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset); + ThrowFire(itemNumber, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset); } AI_INFO AI; diff --git a/TombEngine/Objects/TR2/Entity/tr2_worker_machinegun.cpp b/TombEngine/Objects/TR2/Entity/tr2_worker_machinegun.cpp index 4d2ad0f7b..f0f0d0bf4 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_worker_machinegun.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_worker_machinegun.cpp @@ -13,16 +13,34 @@ namespace TEN::Entities::Creatures::TR2 { - const auto WorkerMachineGunBite = BiteInfo(Vector3(0.0f, 308.0f, 32.0f), 9); + const auto WorkerMachineGunBite = CreatureBiteInfo(Vector3i(0, 380, 37), 9); + + // TODO + enum WorkerMachineGunState + { + + }; + + // TODO + enum WorkerMachineGunAnim + { + + }; void InitializeWorkerMachineGun(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; - InitializeCreature(itemNumber); SetAnimation(item, 12); } + static void Shoot(ItemInfo* item, CreatureInfo* creature, AI_INFO* ai, const EulerAngles& extraTorsoRot) + { + ShotLara(item, ai, WorkerMachineGunBite, extraTorsoRot.y, 30); + creature->MuzzleFlash[0].Bite = WorkerMachineGunBite; + creature->MuzzleFlash[0].Delay = 2; + } + void WorkerMachineGunControl(short itemNumber) { if (!CreatureActive(itemNumber)) @@ -36,6 +54,9 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (item->HitPoints <= 0) { if (item->Animation.ActiveState != 7) @@ -191,13 +212,19 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (creature->Flags) - creature->Flags--; - else + if (item->Animation.AnimNumber == GetAnimIndex(*item, 2)) { - ShotLara(item, &AI, WorkerMachineGunBite, extraTorsoRot.y, 30); - creature->FiredWeapon = 1; - creature->Flags = 5; + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) + Shoot(item, creature, &AI, extraTorsoRot); + else if (item->Animation.FrameNumber == GetFrameIndex(item, 6)) + Shoot(item, creature, &AI, extraTorsoRot); + else if (item->Animation.FrameNumber == GetFrameIndex(item, 12)) + Shoot(item, creature, &AI, extraTorsoRot); + } + else if (item->Animation.AnimNumber == GetAnimIndex(*item, 21) && + item->Animation.FrameNumber == GetFrameIndex(item, 0)) + { + Shoot(item, creature, &AI, extraTorsoRot); } if (item->Animation.TargetState != 1 && @@ -215,14 +242,14 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (creature->Flags) - creature->Flags--; - else - { - ShotLara(item, &AI, WorkerMachineGunBite, extraTorsoRot.y, 30); - creature->FiredWeapon = 1; - creature->Flags = 5; - } + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) + Shoot(item, creature, &AI, extraTorsoRot); + else if (item->Animation.FrameNumber == GetFrameIndex(item, 2)) + Shoot(item, creature, &AI, extraTorsoRot); + else if (item->Animation.FrameNumber == GetFrameIndex(item, 6)) + Shoot(item, creature, &AI, extraTorsoRot); + else if (item->Animation.FrameNumber == GetFrameIndex(item, 12)) + Shoot(item, creature, &AI, extraTorsoRot); break; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp b/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp index c423b5901..ba3c0ed39 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp @@ -16,7 +16,7 @@ namespace TEN::Entities::Creatures::TR2 { constexpr auto WORKER_SHOTGUN_NUM_SHOTS = 6; - const auto WorkerShotgunBite = BiteInfo(Vector3(0.0f, 281.0f, 40.0f), 9); + const auto WorkerShotgunBite = CreatureBiteInfo(Vector3i(0, 350, 40), 9); // TODO enum ShotgunWorkerState @@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR2 }; - void ShotLaraWithShotgun(ItemInfo* item, AI_INFO* info, BiteInfo bite, short angleY, int damage) + void ShotLaraWithShotgun(ItemInfo* item, AI_INFO* info, const CreatureBiteInfo& bite, short angleY, int damage) { for (int i = 0; i < WORKER_SHOTGUN_NUM_SHOTS; i++) ShotLara(item, info, bite, angleY, damage); @@ -57,12 +57,8 @@ namespace TEN::Entities::Creatures::TR2 auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, WorkerShotgunBite.meshNum, Vector3i(WorkerShotgunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, (creature->FiredWeapon * 2) + 4, 24, 16, 4); - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; if (item->HitPoints <= 0) { @@ -202,10 +198,11 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!creature->Flags) + if (creature->Flags == 0) { ShotLaraWithShotgun(item, &AI, WorkerShotgunBite, extraTorsoRot.y, 25); - creature->FiredWeapon = 2; + creature->MuzzleFlash[0].Bite = WorkerShotgunBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } @@ -224,10 +221,11 @@ namespace TEN::Entities::Creatures::TR2 extraTorsoRot.y = AI.angle; } - if (!creature->Flags) + if (creature->Flags == 0) { + creature->MuzzleFlash[0].Bite = WorkerShotgunBite; + creature->MuzzleFlash[0].Delay = 1; ShotLaraWithShotgun(item, &AI, WorkerShotgunBite, extraTorsoRot.y, 25); - creature->FiredWeapon = 2; creature->Flags = 1; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp b/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp index a013c4412..d02e760d4 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp @@ -16,8 +16,8 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR2 { - const auto YetiBiteLeft = BiteInfo(Vector3(12.0f, 101.0f, 19.0f), 13); - const auto YetiBiteRight = BiteInfo(Vector3(12.0f, 101.0f, 19.0f), 10); + const auto YetiBiteLeft = CreatureBiteInfo(Vector3i(12, 101, 19), 13); + const auto YetiBiteRight = CreatureBiteInfo(Vector3i(12, 101, 19), 10); const auto YetiAttackJoints1 = std::vector{ 10, 12 }; // TODO: Rename. const auto YetiAttackJoints2 = std::vector{ 8, 9, 10 }; diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index a98523703..28043b5ed 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -129,9 +129,6 @@ namespace TEN::Entities::Vehicles skidooItem->Status = ITEM_ACTIVE; } - if (skidooItem->ObjectNumber == ID_SNOWMOBILE_GUN) - skidoo->Armed = true; - skidoo->MomentumAngle = skidooItem->Pose.Orientation.y; } @@ -204,6 +201,7 @@ namespace TEN::Entities::Vehicles bool TestSkidooDismount(ItemInfo* skidooItem, ItemInfo* laraItem) { auto* lara = GetLaraInfo(laraItem); + auto* skidoo = GetSkidooInfo(skidooItem); if (lara->Context.Vehicle != NO_ITEM) { @@ -220,6 +218,8 @@ namespace TEN::Entities::Vehicles laraItem->Pose.Orientation.x = 0; laraItem->Pose.Orientation.z = 0; lara->Control.HandStatus = HandStatus::Free; + if (skidoo->Armed) + lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType; SetLaraVehicle(laraItem, nullptr); } else if (laraItem->Animation.ActiveState == SKIDOO_STATE_JUMP_OFF && @@ -248,6 +248,9 @@ namespace TEN::Entities::Vehicles laraItem->Animation.IsAirborne = true; lara->Control.MoveAngle = skidooItem->Pose.Orientation.y; lara->Control.HandStatus = HandStatus::Free; + lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType; + if (skidoo->Armed) + lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType; skidooItem->Collidable = false; skidooItem->Flags |= IFLAG_INVISIBLE; @@ -663,7 +666,7 @@ namespace TEN::Entities::Vehicles FindNewTarget(*laraItem, weapon); AimWeapon(*laraItem, lara->RightArm, weapon); - if (TrInput & VEHICLE_IN_FIRE && !skidooItem->ItemFlags[0]) + if (IsHeld(In::DrawWeapon) && !skidooItem->ItemFlags[0]) { auto angles = EulerAngles( lara->RightArm.Orientation.x, @@ -671,13 +674,12 @@ namespace TEN::Entities::Vehicles 0 ); - if ((int)FireWeapon(LaraWeaponType::Pistol, *lara->TargetEntity, *laraItem, angles) + - (int)FireWeapon(LaraWeaponType::Pistol, *lara->TargetEntity, *laraItem, angles)) - { - skidoo->FlashTimer = 2; - SoundEffect(weapon.SampleNum, &laraItem->Pose); - skidooItem->ItemFlags[0] = 4; - } + FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles); + FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles); + //lara->LeftArm.GunFlash = 1; + //lara->RightArm.GunFlash = 1; + SoundEffect(weapon.SampleNum, &laraItem->Pose); + skidooItem->ItemFlags[0] = 4; } if (skidooItem->ItemFlags[0]) diff --git a/TombEngine/Objects/TR2/tr2_objects.cpp b/TombEngine/Objects/TR2/tr2_objects.cpp index 25debcd7b..360d99180 100644 --- a/TombEngine/Objects/TR2/tr2_objects.cpp +++ b/TombEngine/Objects/TR2/tr2_objects.cpp @@ -8,6 +8,8 @@ #include "Specific/level.h" #include "Specific/setup.h" +#include "Game/missile.h" + // Creatures #include "Objects/TR2/Entity/tr2_barracuda.h" // OK #include "Objects/TR2/Entity/tr2_bird_monster.h" // OK @@ -145,7 +147,6 @@ static void StartEntity(ObjectInfo* obj) obj->control = SilencerControl; obj->shadowType = ShadowMode::All; obj->HitPoints = 25; - obj->biteOffset = 0; obj->radius = 102; obj->pivotLength = 50; obj->intelligent = true; @@ -163,7 +164,6 @@ static void StartEntity(ObjectInfo* obj) obj->control = SilencerControl; obj->shadowType = ShadowMode::All; obj->HitPoints = 25; - obj->biteOffset = 0; obj->radius = 102; obj->pivotLength = 50; obj->intelligent = true; @@ -181,7 +181,6 @@ static void StartEntity(ObjectInfo* obj) obj->control = SilencerControl; obj->shadowType = ShadowMode::All; obj->HitPoints = 25; - obj->biteOffset = 0; obj->radius = 102; obj->pivotLength = 50; obj->intelligent = true; @@ -197,7 +196,6 @@ static void StartEntity(ObjectInfo* obj) obj->collision = CreatureCollision; obj->control = WorkerShotgunControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 25; obj->pivotLength = 50; obj->radius = 102; @@ -315,10 +313,6 @@ static void StartEntity(ObjectInfo* obj) obj->SetupHitEffect(); } - obj = &Objects[ID_KNIFETHROWER_KNIFE]; - if (obj->loaded) - obj->control = KnifeControl; - obj = &Objects[ID_MERCENARY_UZI]; if (obj->loaded) { @@ -478,22 +472,23 @@ static void StartEntity(ObjectInfo* obj) obj->pivotLength = 0; obj->radius = 256; obj->intelligent = true; + obj->LotType = LotType::SnowmobileGun; obj->SetupHitEffect(); } obj = &Objects[ID_SNOWMOBILE_DRIVER]; if (obj->loaded) { + CheckIfSlotExists(ID_SNOWMOBILE_GUN, "ID_SNOWMOBILE_DRIVER", "ID_SNOWMOBILE_GUN"); obj->Initialize = InitializeSkidooMan; obj->control = SkidooManControl; - obj->HitPoints = 1; obj->SetupHitEffect(true); } } static void StartObject(ObjectInfo* obj) { - + InitProjectile(obj, ControlMissile, ID_KNIFETHROWER_KNIFE); } static void StartTrap(ObjectInfo* obj) diff --git a/TombEngine/Objects/TR3/Entity/Compsognathus.cpp b/TombEngine/Objects/TR3/Entity/Compsognathus.cpp index 86739d20e..fb5520437 100644 --- a/TombEngine/Objects/TR3/Entity/Compsognathus.cpp +++ b/TombEngine/Objects/TR3/Entity/Compsognathus.cpp @@ -35,7 +35,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto COMPY_PLAYER_ALERT_VELOCITY = 15; constexpr auto COMPY_HIT_FLAG = 1; - const auto CompyBite = BiteInfo(Vector3::Zero, 2); + const auto CompyBite = CreatureBiteInfo(Vector3i::Zero, 2); const auto CompyAttackJoints = std::vector{ 1, 2 }; enum CompyState diff --git a/TombEngine/Objects/TR3/Entity/Lizard.cpp b/TombEngine/Objects/TR3/Entity/Lizard.cpp index da605bf00..2ad22caac 100644 --- a/TombEngine/Objects/TR3/Entity/Lizard.cpp +++ b/TombEngine/Objects/TR3/Entity/Lizard.cpp @@ -27,9 +27,9 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto LIZARD_VAULT_SHIFT = 260; - const auto LizardBiteAttackBite = BiteInfo(Vector3(0.0f, -120.0f, 120.0f), 10); - const auto LizardSwipeAttackBite = BiteInfo(Vector3::Zero, 5); - const auto LizardGasBite = BiteInfo(Vector3(0.0f, -64.0f, 56.0f), 9); + const auto LizardBiteAttackBite = CreatureBiteInfo(Vector3i(0, -120, 120), 10); + const auto LizardSwipeAttackBite = CreatureBiteInfo(Vector3i::Zero, 5); + const auto LizardGasBite = CreatureBiteInfo(Vector3i(0, -64, 56), 9); const auto LizardSwipeAttackJoints = std::vector{ 5 }; const auto LizardBiteAttackJoints = std::vector{ 10 }; @@ -72,14 +72,13 @@ namespace TEN::Entities::Creatures::TR3 (g_Level.Boxes[creature.Enemy->BoxNumber].flags & BLOCKABLE)); } - static void SpawnLizardGas(int itemNumber, const BiteInfo& bite, int speed) + static void SpawnLizardGas(int itemNumber, const CreatureBiteInfo& bite, int speed) { static constexpr auto numPoisonThrows = 2; for (int i = 0; i < numPoisonThrows; i++) - ThrowPoison(itemNumber, bite.meshNum, Vector3i(bite.Position), Vector3i(0.0f, -100.0f, speed << 2), Vector3(0.0f, 1.0f, 0.0f)); - - ThrowPoison(itemNumber, bite.meshNum, Vector3i(bite.Position), Vector3i(0.0f, -100.0f, speed << 1), Vector3(0.0f, 1.0f, 0.0f)); + ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 2), Vector3(0.0f, 1.0f, 0.0f)); + ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 1), Vector3(0.0f, 1.0f, 0.0f)); } void LizardControl(short itemNumber) diff --git a/TombEngine/Objects/TR3/Entity/PunaBoss.cpp b/TombEngine/Objects/TR3/Entity/PunaBoss.cpp index 5fc248f11..79e48de3d 100644 --- a/TombEngine/Objects/TR3/Entity/PunaBoss.cpp +++ b/TombEngine/Objects/TR3/Entity/PunaBoss.cpp @@ -36,8 +36,8 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto PUNA_EXPLOSION_MAIN_COLOR = Vector4(0.0f, 0.7f, 0.3f, 0.5f); constexpr auto PUNA_EXPLOSION_SECOND_COLOR = Vector4(0.1f, 0.3f, 0.7f, 0.5f); - const auto PunaBossHeadBite = BiteInfo(Vector3::Zero, 8); - const auto PunaBossHandBite = BiteInfo(Vector3::Zero, 14); + const auto PunaBossHeadBite = CreatureBiteInfo(Vector3i::Zero, 8); + const auto PunaBossHandBite = CreatureBiteInfo(Vector3i::Zero, 14); enum PunaState { @@ -68,7 +68,7 @@ namespace TEN::Entities::Creatures::TR3 if (!item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard)) return NO_ITEM; - auto pos = GetJointPosition(&item, PunaBossHeadBite.meshNum).ToVector3(); + auto pos = GetJointPosition(&item, PunaBossHeadBite).ToVector3(); auto orient = Geometry::GetOrientToPoint(pos, target); return (orient.y - item.Pose.Orientation.y); } @@ -213,11 +213,11 @@ namespace TEN::Entities::Creatures::TR3 } } - static void SpawnPunaLightning(ItemInfo& item, const Vector3& pos, const BiteInfo& bite, bool isSummon) + static void SpawnPunaLightning(ItemInfo& item, const Vector3& pos, const CreatureBiteInfo& bite, bool isSummon) { const auto& creature = *GetCreatureInfo(&item); - auto origin = GameVector(GetJointPosition(&item, bite.meshNum, bite.Position), item.RoomNumber); + auto origin = GameVector(GetJointPosition(&item, bite), item.RoomNumber); if (isSummon) { diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index 6f3bba219..dabf6bcf8 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -33,8 +33,8 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto SHIVA_SWAPMESH_TIME = 3; constexpr auto PLAYER_ANIM_SHIVA_DEATH = 7; // TODO: Move to LaraExtraAnims enum. - const auto ShivaBiteLeft = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 13); - const auto ShivaBiteRight = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 22); + const auto ShivaBiteLeft = CreatureBiteInfo(Vector3i(0, 0, 920), 13); + const auto ShivaBiteRight = CreatureBiteInfo(Vector3i(0, 0, 920), 22); const auto ShivaAttackLeftJoints = std::vector{ 10, 13 }; const auto ShivaAttackRightJoints = std::vector{ 22, 25 }; diff --git a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp index 6b14985f0..d1102b200 100644 --- a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp +++ b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp @@ -63,9 +63,9 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto SOPHIALEIGH_VAULT_SHIFT = 96; - const auto SophiaLeighStaffBite = BiteInfo(Vector3(-28.0f, 56.0f, 356.0f), 10); - const auto SophiaLeighLeftBite = BiteInfo(Vector3(-72.0f, 48.0f, 356.0f), 10); - const auto SophiaLeighRightBite = BiteInfo(Vector3(16.0f, 48.0f, 304.0f), 10); + const auto SophiaLeighStaffBite = CreatureBiteInfo(Vector3i(-28, 56, 356), 10); + const auto SophiaLeighLeftBite = CreatureBiteInfo(Vector3i(-72, 48, 356), 10); + const auto SophiaLeighRightBite = CreatureBiteInfo(Vector3i(16, 48, 304), 10); struct SophiaData { @@ -243,7 +243,7 @@ namespace TEN::Entities::Creatures::TR3 } } - static void SpawnSophiaLeighProjectileBolt(ItemInfo& item, ItemInfo* enemy, const BiteInfo& bite, SophiaData* data, bool isBoltLarge, short angleAdd) + static void SpawnSophiaLeighProjectileBolt(ItemInfo& item, ItemInfo* enemy, const CreatureBiteInfo& bite, SophiaData* data, bool isBoltLarge, short angleAdd) { int fxNumber = CreateNewEffect(item.RoomNumber); if (fxNumber == NO_ITEM) @@ -253,7 +253,7 @@ namespace TEN::Entities::Creatures::TR3 auto boltType = isBoltLarge ? (short)MissileType::SophiaLeighLarge : (short)MissileType::SophiaLeighNormal; - fx.pos.Position = GetJointPosition(&item, bite.meshNum, bite.Position); + fx.pos.Position = GetJointPosition(&item, bite); fx.pos.Orientation.x = item.Pose.Orientation.x + data->torsoXAngle; if (enemy->IsLara()) diff --git a/TombEngine/Objects/TR3/Entity/WaspMutant.cpp b/TombEngine/Objects/TR3/Entity/WaspMutant.cpp index e8c5e290b..048c14b51 100644 --- a/TombEngine/Objects/TR3/Entity/WaspMutant.cpp +++ b/TombEngine/Objects/TR3/Entity/WaspMutant.cpp @@ -28,8 +28,8 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto WaspVenomSackLightColor = Vector4(0.0f, 0.35f, 0.0f, 1.0f); - const auto WaspBite = BiteInfo(Vector3(0.0f, 0.0f, -260.0f), 12); - const auto WaspVenomSackBite = BiteInfo(Vector3::Zero, 10); + const auto WaspBite = CreatureBiteInfo(Vector3i(0, 0, -260), 12); + const auto WaspVenomSackBite = CreatureBiteInfo(Vector3i::Zero, 10); enum WaspMutantState { @@ -112,7 +112,7 @@ namespace TEN::Entities::Creatures::TR3 item.ItemFlags[0] = 0; // Spawn light. - auto pos = GetJointPosition(&item, WaspVenomSackBite.meshNum, WaspVenomSackBite.Position); + auto pos = GetJointPosition(&item, WaspVenomSackBite); TriggerDynamicLight( pos.x, pos.y, pos.z, item.ItemFlags[0], @@ -276,7 +276,7 @@ namespace TEN::Entities::Creatures::TR3 item.Animation.RequiredState = WASP_STATE_FLY_FORWARD; } - if (!creature.Flags && item.TouchBits.Test(WaspBite.meshNum)) + if (!creature.Flags && item.TouchBits.Test(WaspBite.BoneID)) { DoDamage(creature.Enemy, WASP_DAMAGE); CreatureEffect2(&item, WaspBite, 10, item.Pose.Orientation.y, DoBloodSplat); diff --git a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp index c7ee5cba4..33586c7f3 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp @@ -36,9 +36,9 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto CIVVY_TARGET_ALERT_VELOCITY = 10.0f; constexpr auto CIVVY_VAULT_SHIFT = 260; - const auto CivvyBiteRight = BiteInfo(Vector3::Zero, 13); - const auto CivvyBiteLeft = BiteInfo(Vector3::Zero, 10); - const auto CivvyAttackJoints = std::vector{ (unsigned int)CivvyBiteLeft.meshNum, (unsigned int)CivvyBiteRight.meshNum }; + const auto CivvyBiteLeft = CreatureBiteInfo(Vector3i::Zero, 10); + const auto CivvyBiteRight = CreatureBiteInfo(Vector3i::Zero, 13); + const auto CivvyAttackJoints = std::vector{ 10, 13 }; const auto CivvyExcludedTargets = std::vector { diff --git a/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp b/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp index b4b612098..ef32139b3 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp @@ -35,9 +35,9 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto CLAW_MUTANT_WALK_TURN_RATE_MAX = ANGLE(3.0f); constexpr auto CLAW_MUTANT_RUN_TURN_RATE_MAX = ANGLE(4.0f); - const auto ClawMutantLeftBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 7); - const auto ClawMutantRightBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 4); - const auto ClawMutantTailBite = BiteInfo(Vector3(-32.0f, -16.0f, -119.0f), 13); + const auto ClawMutantLeftBite = CreatureBiteInfo(Vector3i(19, -13, 3), 7); + const auto ClawMutantRightBite = CreatureBiteInfo(Vector3i(19, -13, 3), 4); + const auto ClawMutantTailBite = CreatureBiteInfo(Vector3i(-32, -16, -119), 13); enum ClawMutantState { @@ -164,7 +164,7 @@ namespace TEN::Entities::Creatures::TR3 auto& fx = EffectList[plasmaBall]; - auto jointPos = GetJointPosition(item, ClawMutantTailBite.meshNum, ClawMutantTailBite.Position); + auto jointPos = GetJointPosition(item, ClawMutantTailBite.BoneID, ClawMutantTailBite.Position); auto orient = Geometry::GetOrientToPoint(jointPos.ToVector3(), enemyPos.ToVector3()); fx.pos.Position = jointPos; @@ -207,14 +207,14 @@ namespace TEN::Entities::Creatures::TR3 static void DamageTargetWithClaw(ItemInfo& source, ItemInfo& target) { - if (source.ItemFlags[5] == 0 && source.TouchBits.Test(ClawMutantLeftBite.meshNum)) + if (source.ItemFlags[5] == 0 && source.TouchBits.Test(ClawMutantLeftBite.BoneID)) { DoDamage(&target, CLAW_MUTANT_CLAW_ATTACK_DAMAGE / 2); CreatureEffect2(&source, ClawMutantLeftBite, 10, source.Pose.Orientation.y, DoBloodSplat); source.ItemFlags[5] = 1; } - if (source.ItemFlags[6] == 0 && source.TouchBits.Test(ClawMutantRightBite.meshNum)) + if (source.ItemFlags[6] == 0 && source.TouchBits.Test(ClawMutantRightBite.BoneID)) { DoDamage(&target, CLAW_MUTANT_CLAW_ATTACK_DAMAGE / 2); CreatureEffect2(&source, ClawMutantRightBite, 10, source.Pose.Orientation.y, DoBloodSplat); diff --git a/TombEngine/Objects/TR3/Entity/tr3_cobra.cpp b/TombEngine/Objects/TR3/Entity/tr3_cobra.cpp index decaeab2a..72c9062b0 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_cobra.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_cobra.cpp @@ -24,7 +24,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto COBRA_DISTURBANCE_VELOCITY = 15.0f; constexpr auto COBRA_SLEEP_FRAME = 45; - const auto CobraBite = BiteInfo(Vector3::Zero, 13); + const auto CobraBite = CreatureBiteInfo(Vector3i::Zero, 13); const auto CobraAttackJoints = std::vector{ 13 }; enum CobraState diff --git a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp index 83f4607ff..041eec042 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp @@ -27,8 +27,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto FLAMETHROWER_WALK_TURN_RATE_MAX = ANGLE(5.0f); - const auto FlamethrowerOffset = Vector3i(0, 340, 0); - const auto FlamethrowerBite = BiteInfo(Vector3(0.0f, 340.0f, 64.0f), 7); + const auto FlamethrowerBite = CreatureBiteInfo(Vector3i(0, 340, 64), 7); // TODO enum FlamethrowerState @@ -64,10 +63,9 @@ namespace TEN::Entities::Creatures::TR3 short tilt = 0; auto extraHeadRot = EulerAngles::Zero; auto extraTorsoRot = EulerAngles::Zero; - - auto pos = GetJointPosition(item, FlamethrowerBite.meshNum, Vector3i(FlamethrowerBite.Position)); - + auto pos = GetJointPosition(item, FlamethrowerBite); int randomInt = GetRandomControl(); + if (item->Animation.ActiveState != 6 && item->Animation.ActiveState != 11) { TriggerDynamicLight(pos.x, pos.y, pos.z, (randomInt & 3) + 6, 24 - ((randomInt / 16) & 3), 16 - ((randomInt / 64) & 3), randomInt & 3); @@ -308,10 +306,10 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.TargetState = FLAMETHROWER_STATE_IDLE; if (creature->Flags < 40) - ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, creature->Flags * 1.5f, 0)); + ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, creature->Flags * 1.5f, 0)); else { - ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, (Random::GenerateInt() & 63) + 12, 0)); + ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (Random::GenerateInt() & 63) + 12, 0)); if (realEnemy) { /*code*/ @@ -342,10 +340,10 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.TargetState = FLAMETHROWER_STATE_WALK_FORWARD; if (creature->Flags < 40) - ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, creature->Flags * 1.5f, 0)); + ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, creature->Flags * 1.5f, 0)); else { - ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, (GetRandomControl() & 63) + 12, 0)); + ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (GetRandomControl() & 63) + 12, 0)); if (realEnemy) { /*code*/ diff --git a/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp b/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp index ed97442e5..e35ed14fd 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp @@ -23,7 +23,7 @@ namespace TEN::Entities::Creatures::TR3 // TODO: Range constants. - const auto MonkeyBite = BiteInfo(Vector3(10.0f, 10.0f, 11.0f), 13); + const auto MonkeyBite = CreatureBiteInfo(Vector3i(10, 10, 11), 13); const auto MonkeyAttackJoints = std::vector{ 10, 13 }; enum MonkeyState diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index e8c958008..f4c72a7ef 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -21,7 +21,7 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 { - const auto MPGunBite = BiteInfo(Vector3(0.0f, 160.0f, 40.0f), 13); + const auto MPGunBite = CreatureBiteInfo(Vector3i(0, 225, 50), 13); enum MPGunState { @@ -67,13 +67,8 @@ namespace TEN::Entities::Creatures::TR3 short head = 0; auto extraTorsoRot = EulerAngles::Zero; - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, MPGunBite.meshNum, Vector3i(MPGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, (creature->FiredWeapon * 2) + 4, 24, 16, 4); - - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; if (item->BoxNumber != NO_BOX && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) { @@ -98,14 +93,14 @@ namespace TEN::Entities::Creatures::TR3 if (Targetable(item, &AI)) { - if (AI.angle > -ANGLE(45.0f) && - AI.angle < ANGLE(45.0f)) + if (AI.angle > -ANGLE(45.0f) && AI.angle < ANGLE(45.0f)) { head = AI.angle; extraTorsoRot.y = AI.angle; ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32); + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; SoundEffect(SFX_TR3_OIL_SMG_FIRE, &item->Pose, SoundEnvironment::Land, 1.0f, 0.7f); - creature->FiredWeapon = 1; } } } @@ -330,6 +325,12 @@ namespace TEN::Entities::Creatures::TR3 extraTorsoRot.y = AI.angle; } + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) + { + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 1; + } + if (item->Animation.RequiredState == MPGUN_STATE_WAIT) item->Animation.TargetState = MPGUN_STATE_WAIT; @@ -346,6 +347,8 @@ namespace TEN::Entities::Creatures::TR3 { if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32)) item->Animation.TargetState = MPGUN_STATE_WAIT; + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; } else if (item->HitStatus && Random::TestProbability(0.25f) && cover) { @@ -368,6 +371,8 @@ namespace TEN::Entities::Creatures::TR3 { if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32)) item->Animation.TargetState = MPGUN_STATE_WAIT; + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; } else if (item->HitStatus && Random::TestProbability(0.25f) && cover) { @@ -391,6 +396,8 @@ namespace TEN::Entities::Creatures::TR3 { if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32)) item->Animation.RequiredState = MPGUN_STATE_WALK; + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; } else if (item->HitStatus && Random::TestProbability(0.25f) && cover) { @@ -418,6 +425,8 @@ namespace TEN::Entities::Creatures::TR3 { if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32)) item->Animation.TargetState = MPGUN_STATE_WALK; + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; } if (AI.distance < pow(SECTOR(1.5f), 2)) @@ -461,6 +470,8 @@ namespace TEN::Entities::Creatures::TR3 { if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32) || Random::TestProbability(1 / 8.0f)) item->Animation.TargetState = MPGUN_STATE_CROUCHED; + creature->MuzzleFlash[0].Bite = MPGunBite; + creature->MuzzleFlash[0].Delay = 2; } break; diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp index 7a138ee5d..fbb423526 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp @@ -18,8 +18,8 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 { - const auto MPStickBite1 = BiteInfo(Vector3(247.0f, 10.0f, 11.0f), 13); - const auto MPStickBite2 = BiteInfo(Vector3(0.0f, 0.0f, 100.0f), 6); + const auto MPStickBite1 = CreatureBiteInfo(Vector3i(247, 10, 11), 13); + const auto MPStickBite2 = CreatureBiteInfo(Vector3i(0, 0, 100), 6); const auto MPStickPunchAttackJoints = std::vector{ 10, 13 }; const auto MPStickKickAttackJoints = std::vector{ 5, 6 }; diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp index 66a12c5e0..57c6b4319 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp @@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto RAPTOR_RUN_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto RAPTOR_ATTACK_TURN_RATE_MAX = ANGLE(2.0f); - const auto RaptorBite = BiteInfo(Vector3(0.0f, 66.0f, 318.0f), 22); + const auto RaptorBite = CreatureBiteInfo(Vector3i(0, 66, 318), 22); const auto RaptorAttackJoints = std::vector{ 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23 }; enum RaptorState diff --git a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp index 2c5a582fe..0191ea486 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp @@ -16,10 +16,9 @@ namespace TEN::Entities::Creatures::TR3 { constexpr auto SCUBA_DIVER_ATTACK_DAMAGE = 50; - constexpr auto SCUBA_DIVER_SWIM_TURN_RATE_MAX = ANGLE(3.0f); - const auto ScubaGunBite = BiteInfo(Vector3(17.0f, 164.0f, 44.0f), 18); + const auto ScubaGunBite = CreatureBiteInfo(Vector3i(17, 164, 44), 18); enum ScubaDiverState { diff --git a/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp b/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp index 82cc7ca99..aa5511ce7 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp @@ -34,7 +34,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto TIGER_PLAYER_ALERT_VELOCITY = 10.0f; - const auto TigerBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 26); + const auto TigerBite = CreatureBiteInfo(Vector3i(19, -13, 3), 26); const auto TigerSwipeAttackJoints = std::vector{ 14, 15, 16 }; const auto TigerBiteAttackJoints = std::vector{ 22, 25, 26 }; diff --git a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp index b7659a77b..391f4aa99 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp @@ -27,10 +27,10 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto TONY_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto TONY_EXPLOSION_COUNT_MAX = 60; - constexpr auto TONY_EFFECT_COLOR = Vector4(0.8f, 0.4f, 0.0f, 0.5f); + constexpr auto TONY_EFFECT_COLOR = Vector4(0.8f, 0.4f, 0.0f, 0.5f); - const auto TonyLeftHandBite = BiteInfo(Vector3::Zero, 10); - const auto TonyRightHandBite = BiteInfo(Vector3::Zero, 13); + const auto TonyLeftHandBite = CreatureBiteInfo(Vector3i::Zero, 10); + const auto TonyRightHandBite = CreatureBiteInfo(Vector3i::Zero, 13); // I can't set it to the TonyFlame struct since the control of the // flame use fxNumber as argument or that FX_INFO have no void* to hold custom data. @@ -654,14 +654,14 @@ namespace TEN::Entities::Creatures::TR3 g = (g * bright) / 16; b = (b * bright) / 16; - auto handPos = GetJointPosition(item, TonyLeftHandBite.meshNum); + auto handPos = GetJointPosition(item, TonyLeftHandBite); TriggerTonyFlame(itemNumber, 13); TriggerDynamicLight(handPos.x, handPos.y, handPos.z, 12, r, g, b); if (item->Animation.ActiveState == TONY_STATE_SHOOT_CEILING || item->Animation.ActiveState == TONY_STATE_FLIPMAP) { - handPos = GetJointPosition(item, TonyRightHandBite.meshNum); + handPos = GetJointPosition(item, TonyRightHandBite); TriggerTonyFlame(itemNumber, 14); TriggerDynamicLight(handPos.x, handPos.y, handPos.z, 12, r, g, b); } diff --git a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp index 138ee48a3..5043dcaab 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp @@ -24,9 +24,9 @@ namespace TEN::Entities::Creatures::TR3 { constexpr auto TRIBESMAN_DART_DAMAGE = -25; // NOTE: Negative value gives poison. - const auto TribesmanAxeBite = BiteInfo(Vector3(0.0f, 56.0f, 265.0f), 13); - const auto TribesmanDartBite1 = BiteInfo(Vector3(0.0f, 0.0f, -200.0f), 13); - const auto TribesmanDartBite2 = BiteInfo(Vector3(8.0f, 40.0f, -248.0f), 13); + const auto TribesmanAxeBite = CreatureBiteInfo(Vector3i(0, 56, 265), 13); + const auto TribesmanDartBite1 = CreatureBiteInfo(Vector3i(0, 0, -200), 13); + const auto TribesmanDartBite2 = CreatureBiteInfo(Vector3i(8, 40, -248), 13); const auto TribesmanAxeAttackJoints = std::vector{ 13 }; const auto TribesmanDartAttackJoints = std::vector{ 10, 13 }; // TODO: Check. @@ -371,7 +371,7 @@ namespace TEN::Entities::Creatures::TR3 dartItem->ObjectNumber = ID_DARTS; dartItem->RoomNumber = item->RoomNumber; - auto pos1 = GetJointPosition(item, TribesmanDartBite1.meshNum, Vector3i(TribesmanDartBite1.Position)); + auto pos1 = GetJointPosition(item, TribesmanDartBite1); auto pos2 = GetJointPosition(LaraItem, LM_TORSO); auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos2.ToVector3()); @@ -389,7 +389,7 @@ namespace TEN::Entities::Creatures::TR3 pos1 = Vector3i(TribesmanDartBite2.Position); pos1.z += 96; - pos1 = GetJointPosition(item, TribesmanDartBite2.meshNum, pos1); + pos1 = GetJointPosition(item, TribesmanDartBite2.BoneID, pos1); TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true); TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true); diff --git a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp index 0fb89de91..425f4b785 100644 --- a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp +++ b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp @@ -47,7 +47,7 @@ namespace TEN::Entities::Vehicles VehicleMountType::Back }; - const auto BigGunBite = BiteInfo(Vector3(0, 0, BGUN_ROCKET_SPAWN_DISTANCE), 2); + const auto BigGunBite = CreatureBiteInfo(Vector3i(0, 0, BGUN_ROCKET_SPAWN_DISTANCE), 2); enum BigGunState { @@ -125,7 +125,7 @@ namespace TEN::Entities::Vehicles auto* projectileItem = &g_Level.Items[itemNumber]; projectileItem->ObjectNumber = ID_ROCKET; - auto pos = GetJointPosition(bigGunItem, BigGunBite.meshNum, BigGunBite.Position); + auto pos = GetJointPosition(bigGunItem, BigGunBite); auto probe = GetCollision(pos.x, pos.y, pos.z, bigGunItem->RoomNumber); projectileItem->RoomNumber = probe.RoomNumber; projectileItem->Pose.Position = pos; diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 8e8135752..d5d6be2d6 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -27,14 +27,14 @@ using namespace TEN::Math; namespace TEN::Entities::Vehicles { - BiteInfo QuadBikeEffectsPositions[6] = + const CreatureBiteInfo QuadBikeEffectsPositions[6] = { - { -56, -32, -380, 0 }, - { 56, -32, -380, 0 }, - { -8, 180, -48, 3 }, - { 8, 180, -48, 4 }, - { 90, 180, -32, 6 }, - { -90, 180, -32, 7 } + CreatureBiteInfo(Vector3i(-56, -32, -380), 0), + CreatureBiteInfo(Vector3i(56, -32, -380), 0), + CreatureBiteInfo(Vector3i(-8, 180, -48), 3), + CreatureBiteInfo(Vector3i(8, 180, -48), 4), + CreatureBiteInfo(Vector3i(90, 180, -32), 6), + CreatureBiteInfo(Vector3i(-90, 180, -32), 7) }; const vector QuadBikeMountTypes = { @@ -1207,8 +1207,7 @@ namespace TEN::Entities::Vehicles for (int i = 0; i < 2; i++) { - auto pos = GetJointPosition(quadBikeItem, QuadBikeEffectsPositions[i].meshNum, Vector3i(QuadBikeEffectsPositions[i].Position)); - + auto pos = GetJointPosition(quadBikeItem, QuadBikeEffectsPositions[i]); angle = quadBikeItem->Pose.Orientation.y + ((i == 0) ? 0x9000 : 0x7000); if (quadBikeItem->Animation.Velocity.z > 32) { diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index 893b0aa10..1bcbbb943 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -84,15 +84,16 @@ namespace TEN::Entities::Vehicles #define UPV_LEAN_RATE ANGLE(0.6f) #define UPV_LEAN_MAX ANGLE(10.0f) - BiteInfo UPVBites[6] = + const CreatureBiteInfo UPVBites[6] = { - { 0, 0, 0, 3 }, - { 0, 96, 256, 0 }, - { -128, 0, 64, 1 }, - { 0, 0, -64, 1 }, - { 128, 0, 64, 2 }, - { 0, 0, -64, 2 } + CreatureBiteInfo(Vector3i(0, 0, 0), 3), + CreatureBiteInfo(Vector3i(0, 96, 256), 0), + CreatureBiteInfo(Vector3i(-128, 0, 64), 1), + CreatureBiteInfo(Vector3i(0, 0, -64), 1), + CreatureBiteInfo(Vector3i(128, 0, 64), 2), + CreatureBiteInfo(Vector3i(0, 0, -64), 2) }; + const std::vector UPVMountTypes = { VehicleMountType::LevelStart, @@ -304,7 +305,7 @@ namespace TEN::Entities::Vehicles if (UPV->Velocity) { - auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_TURBINE].meshNum, Vector3i(UPVBites[UPV_BITE_TURBINE].Position)).ToVector3(); + auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_TURBINE]).ToVector3(); TriggerUPVMist(pos.x, pos.y + UPV_SHIFT, pos.z, abs(UPV->Velocity) / VEHICLE_VELOCITY_SCALE, UPVItem->Pose.Orientation.y + ANGLE(180.0f)); auto sphere = BoundingSphere(pos, BLOCK(1 / 32.0f)); @@ -322,7 +323,7 @@ namespace TEN::Entities::Vehicles for (int lp = 0; lp < 2; lp++) { int random = 31 - (GetRandomControl() & 3); - auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_FRONT_LIGHT].meshNum, Vector3i( + auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_FRONT_LIGHT].BoneID, Vector3i( UPVBites[UPV_BITE_FRONT_LIGHT].Position.x, UPVBites[UPV_BITE_FRONT_LIGHT].Position.y, (int)UPVBites[UPV_BITE_FRONT_LIGHT].Position.z << (lp * 6) diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index ddca7ff56..d4c1c1291 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -242,7 +242,6 @@ static void StartEntity(ObjectInfo* obj) obj->radius = 102; obj->intelligent = true; obj->pivotLength = 0; - obj->biteOffset = 0; obj->SetBoneRotationFlags(6, ROT_X | ROT_Y); obj->SetBoneRotationFlags(13, ROT_Y); obj->SetupHitEffect(); diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index 4273bf55d..5089ed39a 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -13,7 +13,6 @@ #include "Game/people.h" #include "Game/room.h" #include "Math/Math.h" -#include "Objects/Generic/Traps/traps.h" #include "Objects/TR4/Entity/WraithInfo.h" #include "Objects/objectslist.h" #include "Sound/sound.h" diff --git a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp index 035f79e24..3f60a39cd 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp @@ -35,9 +35,9 @@ namespace TEN::Entities::TR4 constexpr auto AHMET_VIEW_ANGLE = ANGLE(45.0f); constexpr auto AHMET_ENEMY_ANGLE = ANGLE(90.0f); - const auto AhmetBiteLeft = BiteInfo(Vector3::Zero, 16); - const auto AhmetBiteRight = BiteInfo(Vector3::Zero, 22); - const auto AhmetBiteJaw = BiteInfo(Vector3::Zero, 11); + const auto AhmetBiteLeft = CreatureBiteInfo(Vector3i::Zero, 16); + const auto AhmetBiteRight = CreatureBiteInfo(Vector3i::Zero, 22); + const auto AhmetBiteJaw = CreatureBiteInfo(Vector3i::Zero, 11); const auto AhmetSwipeAttackLeftJoints = std::vector{ 14, 15, 16, 17 }; const auto AhmetSwipeAttackRightJoints = std::vector{ 20, 21, 22, 23 }; diff --git a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp index e674110d3..7dd13ff8f 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp @@ -39,7 +39,7 @@ namespace TEN::Entities::TR4 constexpr auto NO_BABOON_COUNT = -2; constexpr auto NO_CROWBAR_SWITCH_FOUND = -1; - const auto BaboonBite = BiteInfo(Vector3(10.0f, 10.0f, 11.0f), 4); + const auto BaboonBite = CreatureBiteInfo(Vector3i(10, 10, 11), 4); const auto BaboonAttackJoints = std::vector{ 11, 12 }; const auto BaboonAttackRightJoints = std::vector{ 1, 2, 3, 5, 8, 9 }; const auto BaboonJumpAttackJoints = std::vector{ 3, 4, 8 }; diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index 4cb2d7c90..24f6018d2 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -54,8 +54,8 @@ namespace TEN::Entities::TR4 { constexpr auto BADDY_UZI_AMMO = 24; - const auto BaddyGunBite = BiteInfo(Vector3(0.0f, -16.0f, 200.0f), 11); - const auto BaddySwordBite = BiteInfo(Vector3::Zero, 15); + const auto BaddyGunBite = CreatureBiteInfo(Vector3i(-5, 200, 50), 11); + const auto BaddySwordBite = CreatureBiteInfo(Vector3i::Zero, 15); const auto BaddySwordAttackJoints = std::vector{ 14, 15, 16 }; enum BaddyState @@ -330,6 +330,9 @@ namespace TEN::Entities::TR4 // TODO: better add a second control routine for baddy 2 instead of mixing them? short objectNumber = (Objects[ID_BADDY2].loaded ? ID_BADDY2 : ID_BADDY1); + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + bool roll = false; bool jump = false; @@ -419,14 +422,6 @@ namespace TEN::Entities::TR4 item->ItemFlags[1] = item->RoomNumber; - // Handle baddy firing. - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, BaddyGunBite.meshNum, Vector3i(BaddyGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * creature->FiredWeapon + 8, 24, 16, 4); - creature->FiredWeapon--; - } - CollisionResult probe; if (item->HitPoints <= 0) @@ -1158,13 +1153,13 @@ namespace TEN::Entities::TR4 break; } - creature->FiredWeapon = 1; - if (!item->HitStatus) item->ItemFlags[2]--; - + if (!ShotLara(item, &AI, BaddyGunBite, joint1, 15)) item->Animation.TargetState = BADDY_STATE_IDLE; + creature->MuzzleFlash[0].Bite = BaddyGunBite; + creature->MuzzleFlash[0].Delay = 2; break; diff --git a/TombEngine/Objects/TR4/Entity/tr4_bat.cpp b/TombEngine/Objects/TR4/Entity/tr4_bat.cpp index aa737ee14..90db66b7d 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_bat.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_bat.cpp @@ -24,7 +24,7 @@ namespace TEN::Entities::TR4 constexpr auto BAT_ANGLE = ANGLE(20.0f); - const auto BatBite = BiteInfo(Vector3(0.0f, 16.0f, 45.0f), 4); + const auto BatBite = CreatureBiteInfo(Vector3i(0, 16, 45), 4); enum BatState { diff --git a/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp b/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp index f2a589668..04b302c70 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp @@ -21,7 +21,7 @@ namespace TEN::Entities::TR4 constexpr auto BIG_BEETLE_ATTACK_RANGE = SQUARE(CLICK(1)); constexpr auto BIG_BEETLE_AWARE_RANGE = SQUARE(CLICK(12)); - const auto BigBeetleBite = BiteInfo(Vector3::Zero, 12); + const auto BigBeetleBite = CreatureBiteInfo(Vector3i::Zero, 12); const auto BigBeetleAttackJoints = std::vector{ 5, 6 }; enum BigBeetleState diff --git a/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp b/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp index 43fddd468..6652bcb5c 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp @@ -26,12 +26,10 @@ namespace TEN::Entities::TR4 constexpr auto BIG_SCORPION_ATTACK_RANGE = SQUARE(BLOCK(1.35)); constexpr auto BIG_SCORPION_RUN_RANGE = SQUARE(BLOCK(2)); - const auto BigScorpionBite1 = BiteInfo(Vector3::Zero, 8); - const auto BigScorpionBite2 = BiteInfo(Vector3::Zero, 23); + const auto BigScorpionBite1 = CreatureBiteInfo(Vector3i::Zero, 8); + const auto BigScorpionBite2 = CreatureBiteInfo(Vector3i::Zero, 23); const auto BigScorpionAttackJoints = std::vector{ 8, 20, 21, 23, 24 }; - int CutSeqNum; - enum BigScorpionState { // No state 0. @@ -87,7 +85,6 @@ namespace TEN::Entities::TR4 { if (item->TriggerFlags > 0 && item->TriggerFlags < 7) { - CutSeqNum = 4; SetAnimation(item, BSCORPION_ANIM_DEATH); item->Status = ITEM_INVISIBLE; creature->MaxTurn = 0; @@ -114,11 +111,6 @@ namespace TEN::Entities::TR4 SetAnimation(item, BSCORPION_ANIM_DEATH); } } - else if (CutSeqNum == 4) - { - item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameEnd - 1; - item->Status = ITEM_INVISIBLE; - } else if (item->Animation.ActiveState == BSCORPION_STATE_DEATH && item->Status == ITEM_INVISIBLE) item->Status = ITEM_ACTIVE; } @@ -287,10 +279,7 @@ namespace TEN::Entities::TR4 } } - if (!CutSeqNum) - CreatureAnimation(itemNumber, angle, 0); - - auto radius = Vector2(object->radius, object->radius * 1.33f); - AlignEntityToSurface(item, radius); + CreatureAnimation(itemNumber, angle, 0); + AlignEntityToSurface(item, Vector2(object->radius, object->radius * 1.33f)); } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp index 25c6eda8c..a2f4b34af 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp @@ -33,7 +33,7 @@ namespace TEN::Entities::TR4 constexpr auto CROC_STATE_RUN_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto CROC_STATE_SWIM_TURN_RATE_MAX = ANGLE(3.0f); - const auto CrocodileBite = BiteInfo(Vector3(0.0f, -100.0f, 500.0f), 9); + const auto CrocodileBite = CreatureBiteInfo(Vector3i(0, -100, 500), 9); const auto CrocodileBiteAttackJoints = std::vector{ 8, 9 }; enum CrocodileState @@ -115,7 +115,7 @@ namespace TEN::Entities::TR4 auto* item = &g_Level.Items[itemNumber]; auto* object = &Objects[item->ObjectNumber]; auto* creature = GetCreatureInfo(item); - + auto head = EulerAngles::Zero, torso = EulerAngles::Zero; short angle = 0; short boneAngle = 0; AI_INFO AI; @@ -298,28 +298,26 @@ namespace TEN::Entities::TR4 } } - OBJECT_BONES boneRot; if (item->Animation.ActiveState == CROC_STATE_IDLE || item->Animation.ActiveState == CROC_STATE_BITE_ATTACK || item->Animation.ActiveState == CROC_STATE_WATER_BITE_ATTACK) { - boneRot.bone0 = AI.angle / 3; - boneRot.bone1 = AI.angle / 2; - boneRot.bone2 = 0; - boneRot.bone3 = 0; + head.y = AI.angle / 3; + head.x = AI.angle / 2; + torso.y = 0; + torso.x = 0; } else { - boneRot.bone0 = boneAngle; - boneRot.bone1 = boneAngle; - boneRot.bone2 = -boneAngle; - boneRot.bone3 = -boneAngle; + head.y = boneAngle; + head.x = boneAngle; + torso.y = -boneAngle; + torso.x = -boneAngle; } CreatureTilt(item, 0); - CreatureJoint(item, 0, boneRot.bone0); - CreatureJoint(item, 1, boneRot.bone1); - CreatureJoint(item, 2, boneRot.bone2); - CreatureJoint(item, 3, boneRot.bone3); - + CreatureJoint(item, 0, head.y); + CreatureJoint(item, 1, head.x); + CreatureJoint(item, 2, torso.y); + CreatureJoint(item, 3, torso.x); CreatureAnimation(itemNumber, angle, 0); if (item->Animation.ActiveState < CROC_STATE_SWIM_FORWARD) diff --git a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp index 7c3f8f205..fd7c4c5fe 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp @@ -22,7 +22,7 @@ namespace TEN::Entities::TR4 constexpr auto DOG_BITE_ATTACK_RANGE = SQUARE(BLOCK(0.55)); constexpr auto DOG_JUMP_ATTACK_RANGE = SQUARE(BLOCK(1)); - const auto DogBite = BiteInfo(Vector3(0.0f, 0.0f, 100.0f), 3.0f); + const auto DogBite = CreatureBiteInfo(Vector3i(0, 0, 100), 3); const auto DogJumpAttackJoints = std::vector{ 3, 6, 9, 10, 13, 14 }; const auto DogBiteAttackJoints = std::vector{ 3, 6 }; diff --git a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp index f4a760409..e05b49872 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp @@ -18,8 +18,8 @@ namespace TEN::Entities::TR4 { constexpr auto GUIDE_ATTACK_DAMAGE = 20; - const auto GuideBite1 = BiteInfo(Vector3(0.0f, 20.0f, 180.0f), 18); - const auto GuideBite2 = BiteInfo(Vector3(30.0f, 80.0f, 50.0f), 15); + const auto GuideBite1 = CreatureBiteInfo(Vector3i(0, 20, 180), 18); + const auto GuideBite2 = CreatureBiteInfo(Vector3i(30, 80, 50), 15); const auto GuideLeftFingerSwapJoints = std::vector{ 15 }; const auto GuideRightHandSwapJoints = std::vector{ 18 }; const auto GuideHeadSwapJoints = std::vector{ 21 }; @@ -119,7 +119,7 @@ namespace TEN::Entities::TR4 // Ignite torch. if (item->ItemFlags[1] == 2) { - auto pos = GetJointPosition(item, GuideBite1.meshNum, Vector3i(GuideBite1.Position)); + auto pos = GetJointPosition(item, GuideBite1); TriggerFireFlame(pos.x, pos.y - 20, pos.z, FlameType::Trail); SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose); @@ -479,7 +479,7 @@ namespace TEN::Entities::TR4 break; case GUIDE_STATE_IGNITE_TORCH: - pos1 = GetJointPosition(item, GuideBite2.meshNum, Vector3i(GuideBite2.Position)); + pos1 = GetJointPosition(item, GuideBite2); frameNumber = item->Animation.FrameNumber - g_Level.Anims[item->Animation.AnimNumber].frameBase; random = GetRandomControl(); diff --git a/TombEngine/Objects/TR4/Entity/tr4_hammerhead.cpp b/TombEngine/Objects/TR4/Entity/tr4_hammerhead.cpp index ed0edf399..b5fc0330a 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_hammerhead.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_hammerhead.cpp @@ -16,7 +16,7 @@ namespace TEN::Entities::TR4 constexpr auto HAMMERHEAD_BITE_ATTACK_DAMAGE = 120; constexpr auto HAMMERHEAD_ATTACK_RANGE = SQUARE(BLOCK(0.66f)); - const auto HammerheadBite = BiteInfo(Vector3::Zero, 12); + const auto HammerheadBite = CreatureBiteInfo(Vector3i::Zero, 12); const auto HammerheadBiteAttackJoints = std::vector{ 10, 12, 13 }; enum HammerheadState diff --git a/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp b/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp index 7c05d05e5..43692164b 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp @@ -30,11 +30,11 @@ namespace TEN::Entities::TR4 constexpr auto HARPY_SWOOP_ATTACK_DAMAGE = 10; constexpr auto HARPY_STINGER_POISON_POTENCY = 8; - const auto HarpyBite1 = BiteInfo(Vector3::Zero, 4); - const auto HarpyBite2 = BiteInfo(Vector3::Zero, 2); - const auto HarpyBite3 = BiteInfo(Vector3::Zero, 15); - const auto HarpyAttack1 = BiteInfo(Vector3(0.0f, 128.0f, 0.0f), 2); - const auto HarpyAttack2 = BiteInfo(Vector3(0.0f, 128.0f, 0.0f), 4); + const auto HarpyBite1 = CreatureBiteInfo(Vector3i::Zero, 4); + const auto HarpyBite2 = CreatureBiteInfo(Vector3i::Zero, 2); + const auto HarpyBite3 = CreatureBiteInfo(Vector3i::Zero, 15); + const auto HarpyAttack1 = CreatureBiteInfo(Vector3i(0, 128, 0), 2); + const auto HarpyAttack2 = CreatureBiteInfo(Vector3i(0, 128, 0), 4); const auto HarpySwoopAttackJoints = std::vector{ 2, 4, 15 }; const auto HarpyStingerAttackJoints = std::vector{ 2, 4 }; @@ -105,8 +105,8 @@ namespace TEN::Entities::TR4 { item->ItemFlags[0]++; - auto rh = GetJointPosition(item, HarpyAttack1.meshNum, Vector3i(HarpyAttack1.Position)); - auto lr = GetJointPosition(item, HarpyAttack2.meshNum, Vector3i(HarpyAttack2.Position)); + auto rh = GetJointPosition(item, HarpyAttack1); + auto lr = GetJointPosition(item, HarpyAttack2); int sG = (GetRandomControl() & 0x7F) + 32; int sR = sG; @@ -149,7 +149,7 @@ namespace TEN::Entities::TR4 { if (item->ItemFlags[0] <= 65 && GlobalCounter & 1) { - auto pos3 = GetJointPosition(item, HarpyAttack1.meshNum, Vector3i(HarpyAttack1.Position.x, HarpyAttack1.Position.y * 2, HarpyAttack1.Position.z)); + auto pos3 = GetJointPosition(item, HarpyAttack1.BoneID, Vector3i(HarpyAttack1.Position.x, HarpyAttack1.Position.y * 2, HarpyAttack1.Position.z)); auto orient = Geometry::GetOrientToPoint(lr.ToVector3(), rh.ToVector3()); auto pose = Pose(rh, orient); TriggerHarpyMissile(&pose, item->RoomNumber, 2); @@ -157,7 +157,7 @@ namespace TEN::Entities::TR4 if (item->ItemFlags[0] >= 61 && item->ItemFlags[0] <= 65 && !(GlobalCounter & 1)) { - auto pos3 = GetJointPosition(item, HarpyAttack2.meshNum, Vector3i(HarpyAttack2.Position.x, HarpyAttack2.Position.y * 2, HarpyAttack2.Position.z)); + auto pos3 = GetJointPosition(item, HarpyAttack2.BoneID, Vector3i(HarpyAttack2.Position.x, HarpyAttack2.Position.y * 2, HarpyAttack2.Position.z)); auto orient = Geometry::GetOrientToPoint(lr.ToVector3(), rh.ToVector3()); auto pose = Pose(rh, orient); TriggerHarpyMissile(&pose, item->RoomNumber, 2); diff --git a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp index 6db0ae90d..b1cc24c23 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp @@ -20,17 +20,16 @@ using namespace TEN::Math; namespace TEN::Entities::TR4 { - const auto HorsemanBite1 = BiteInfo(Vector3::Zero, 6); - const auto HorsemanBite2 = BiteInfo(Vector3::Zero, 14); - const auto HorsemanBite3 = BiteInfo(Vector3::Zero, 10); + const auto HorsemanBite1 = CreatureBiteInfo(Vector3i::Zero, 6); + const auto HorsemanBite2 = CreatureBiteInfo(Vector3i::Zero, 14); + const auto HorsemanBite3 = CreatureBiteInfo(Vector3i::Zero, 10); const auto HorsemanAxeAttackJoints = std::vector{ 5, 6 }; const auto HorsemanKickAttackJoints = std::vector{ 14 }; const auto HorsemanMountedAttackJoints = std::vector{ 5, 6, 10 }; const auto HorsemanShieldAttackJoints = std::vector{ 10 }; - - const auto HorseBite1 = BiteInfo(Vector3::Zero, 13); - const auto HorseBite2 = BiteInfo(Vector3::Zero, 17); - const auto HorseBite3 = BiteInfo(Vector3::Zero, 19); + const auto HorseBite1 = CreatureBiteInfo(Vector3i::Zero, 13); + const auto HorseBite2 = CreatureBiteInfo(Vector3i::Zero, 17); + const auto HorseBite3 = CreatureBiteInfo(Vector3i::Zero, 19); enum HorsemanState { diff --git a/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp b/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp index 37faf704c..ccf0a28d5 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp @@ -24,7 +24,7 @@ namespace TEN::Entities::TR4 constexpr auto KTEMPLAR_IDLE_TURN_RATE_MAX = ANGLE(2.0f); constexpr auto KTEMPLAR_WALK_TURN_RATE_MAX = ANGLE(7.0f); - const auto KnightTemplarBite = BiteInfo(Vector3::Zero, 11); + const auto KnightTemplarBite = CreatureBiteInfo(Vector3i::Zero, 11); const auto KnightTemplarSwordAttackJoints = std::vector{ 10, 11 }; enum KnightTemplarState diff --git a/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp b/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp index 47ac49811..85ed9f36e 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp @@ -28,8 +28,8 @@ namespace TEN::Entities::TR4 constexpr auto MUMMY_WALK_TURN_RATE_MAX = ANGLE(7.0f); constexpr auto MUMMY_ATTACK_TURN_RATE_MAX = ANGLE(7.0f); - const auto MummyBite1 = BiteInfo(Vector3::Zero, 11); - const auto MummyBite2 = BiteInfo(Vector3::Zero, 14); + const auto MummyBite1 = CreatureBiteInfo(Vector3i::Zero, 11); + const auto MummyBite2 = CreatureBiteInfo(Vector3i::Zero, 14); const auto MummySwipeAttackJoints = std::vector{ 11, 14 }; enum MummyState diff --git a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp index 08cc94adf..d9ef60d57 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp @@ -271,7 +271,7 @@ namespace TEN::Entities::TR4 auto* item = &g_Level.Items[itemNumber]; auto* creature = GetCreatureInfo(item); - OBJECT_BONES mutantJoint; + auto head = EulerAngles::Zero, torso = EulerAngles::Zero; int frameNumber; short angle = 0; short headY = 0; @@ -286,7 +286,7 @@ namespace TEN::Entities::TR4 AI_INFO AI; MutantAIFix(item, &AI); - RotateHeadToTarget(item, creature, 9, headY); + RotateHeadToTarget(item, creature, 9, head.y); GetCreatureMood(item, &AI, true); CreatureMood(item, &AI, true); @@ -350,14 +350,16 @@ namespace TEN::Entities::TR4 } if (item->Animation.ActiveState != MUTANT_STATE_LOCUST_ATTACK_1) - mutantJoint = OBJECT_BONES(headY, AI.xAngle, true); - else - mutantJoint = OBJECT_BONES(0); + { + head.x = AI.xAngle; + torso.x = AI.xAngle; + torso.y = AI.angle; + } - CreatureJoint(item, 0, mutantJoint.bone0); - CreatureJoint(item, 1, mutantJoint.bone1); - CreatureJoint(item, 2, mutantJoint.bone2); - CreatureJoint(item, 3, mutantJoint.bone3); + CreatureJoint(item, 0, head.y); + CreatureJoint(item, 1, head.x); + CreatureJoint(item, 2, torso.y); + CreatureJoint(item, 3, torso.x); CreatureAnimation(itemNumber, angle, 0); } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp index f8e13c13a..12a0360fe 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp @@ -34,7 +34,7 @@ namespace TEN::Entities::TR4 constexpr auto SAS_WALK_RANGE = SQUARE(BLOCK(2)); constexpr auto SAS_SHOOT_RANGE = SQUARE(BLOCK(3)); - const auto SasGunBite = BiteInfo(Vector3(0.0f, 550.0f, 84.0f), 7); + const auto SasGunBite = CreatureBiteInfo(Vector3i(0, 420, 80), 7); const auto SasDragBodyPosition = Vector3i(0, 0, -460); const auto SasDragBounds = ObjectCollisionBounds @@ -145,13 +145,8 @@ namespace TEN::Entities::TR4 short joint1 = 0; short joint2 = 0; - // Handle SAS firing. - if (creature.FiredWeapon) - { - auto pos = GetJointPosition(&item, SasGunBite.meshNum, Vector3i(SasGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 24, 16, 4); - creature.FiredWeapon--; - } + if (creature.MuzzleFlash[0].Delay != 0) + creature.MuzzleFlash[0].Delay--; if (item.HitPoints > 0) { @@ -522,14 +517,15 @@ namespace TEN::Entities::TR4 joint1 = AI.xAngle; } - if (creature.Flags) + if (creature.Flags != 0) { creature.Flags -= 1; } else { ShotLara(&item, &AI, SasGunBite, joint0, SAS_SHOT_DAMAGE); - creature.FiredWeapon = 3; + creature.MuzzleFlash[0].Bite = SasGunBite; + creature.MuzzleFlash[0].Delay = 2; creature.Flags = 5; } @@ -540,9 +536,6 @@ namespace TEN::Entities::TR4 item.Animation.TargetState = SAS_STATE_WAIT; break; - - default: - break; } if (FlashGrenadeAftershockTimer > 100 && @@ -659,7 +652,7 @@ namespace TEN::Entities::TR4 grenadeItem->ObjectNumber = ID_GRENADE; grenadeItem->RoomNumber = item.RoomNumber; - auto pos = GetJointPosition(&item, SasGunBite.meshNum, Vector3i(SasGunBite.Position)); + auto pos = GetJointPosition(&item, SasGunBite); grenadeItem->Pose.Position = pos; auto floorHeight = GetCollision(pos.x, pos.y, pos.z, grenadeItem->RoomNumber).Position.Floor; diff --git a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp index cb7a83628..722746e05 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp @@ -21,7 +21,7 @@ using namespace TEN::Gui; namespace TEN::Entities::TR4 { const auto SentryGunFlameOffset = Vector3i(-140, 0, 0); - const auto SentryGunBite = BiteInfo(Vector3::Zero, 8); + const auto SentryGunBite = CreatureBiteInfo(Vector3i::Zero, 8); void InitializeSentryGun(short itemNumber) { @@ -51,7 +51,7 @@ namespace TEN::Entities::TR4 { if (item->ItemFlags[0]) { - auto pos = GetJointPosition(item, SentryGunBite.meshNum, Vector3i(SentryGunBite.Position)); + auto pos = GetJointPosition(item, SentryGunBite); TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->ItemFlags[0] + 12, 24, 16, 4); item->ItemFlags[0]--; } diff --git a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp index 4a1493a1e..a7f1cb453 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp @@ -44,10 +44,10 @@ namespace TEN::Entities::TR4 constexpr auto SETH_WALK_TURN_RATE_MAX = ANGLE(7.0f); constexpr auto SETH_RUN_TURN_RATE_MAX = ANGLE(11.0f); - const auto SethBite1 = BiteInfo(Vector3(0.0f, 220.0f, 50.0f), 17); - const auto SethBite2 = BiteInfo(Vector3(0.0f, 220.0f, 50.0f), 13); - const auto SethAttack1 = BiteInfo(Vector3(-16.0f, 200.0f, 32.0f), 13); - const auto SethAttack2 = BiteInfo(Vector3(16.0f, 200.0f, 32.0f), 17); + const auto SethBite1 = CreatureBiteInfo(Vector3i(0, 220, 50), 17); + const auto SethBite2 = CreatureBiteInfo(Vector3i(0, 220, 50), 13); + const auto SethAttack1 = CreatureBiteInfo(Vector3i(-16, 200, 32), 13); + const auto SethAttack2 = CreatureBiteInfo(Vector3i(16, 200, 32), 17); const auto SethPounceAttackJoints1 = std::vector{ 13, 14, 15 }; const auto SethPounceAttackJoints2 = std::vector{ 16, 17, 18 }; @@ -493,8 +493,8 @@ namespace TEN::Entities::TR4 item->ItemFlags[0]++; - auto pos1 = GetJointPosition(item, SethAttack1.meshNum, Vector3i(SethAttack1.Position)); - auto pos2 = GetJointPosition(item, SethAttack2.meshNum, Vector3i(SethAttack2.Position)); + auto pos1 = GetJointPosition(item, SethAttack1); + auto pos2 = GetJointPosition(item, SethAttack2); int sparkR = 64; int sparkG = Random::GenerateInt(64, 192); @@ -542,13 +542,13 @@ namespace TEN::Entities::TR4 if (item->ItemFlags[0] >= 96 && item->ItemFlags[0] <= 99) { - auto pos = GetJointPosition(item, SethAttack1.meshNum, Vector3i(SethAttack1.Position.x, SethAttack1.Position.y * 2, SethAttack1.Position.z)); + auto pos = GetJointPosition(item, SethAttack1.BoneID, Vector3i(SethAttack1.Position.x, SethAttack1.Position.y * 2, SethAttack1.Position.z)); auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos.ToVector3()); SethProjectileAttack(Pose(pos1, orient), item->RoomNumber, 0); } else if (item->ItemFlags[0] >= 122 && item->ItemFlags[0] <= 125) { - auto pos = GetJointPosition(item, SethAttack2.meshNum, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); + auto pos = GetJointPosition(item, SethAttack2.BoneID, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); auto orient = Geometry::GetOrientToPoint(pos2.ToVector3(), pos.ToVector3()); SethProjectileAttack(Pose(pos2, orient), item->RoomNumber, 0); } @@ -579,11 +579,11 @@ namespace TEN::Entities::TR4 { if (Wibble & 4) { - auto pos = GetJointPosition(item, SethAttack1.meshNum, Vector3i(SethAttack1.Position.x, SethAttack1.Position.y * 2, SethAttack1.Position.z)); + auto pos = GetJointPosition(item, SethAttack1.BoneID, Vector3i(SethAttack1.Position.x, SethAttack1.Position.y * 2, SethAttack1.Position.z)); auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos.ToVector3()); SethProjectileAttack(Pose(pos1, orient), item->RoomNumber, 0); - pos = GetJointPosition(item, SethAttack2.meshNum, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); + pos = GetJointPosition(item, SethAttack2.BoneID, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); orient = Geometry::GetOrientToPoint(pos2.ToVector3(), pos.ToVector3()); SethProjectileAttack(Pose(pos2, orient), item->RoomNumber, 0); } @@ -624,15 +624,12 @@ namespace TEN::Entities::TR4 if (item->ItemFlags[0] == 102) { - auto pos = GetJointPosition(item, SethAttack1.meshNum, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); + auto pos = GetJointPosition(item, SethAttack1.BoneID, Vector3i(SethAttack2.Position.x, SethAttack2.Position.y * 2, SethAttack2.Position.z)); auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos.ToVector3()); SethProjectileAttack(Pose(pos1, orient), item->RoomNumber, 1); } break; - - default: - break; } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp index f5db80f58..b22f85966 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp @@ -26,7 +26,7 @@ namespace TEN::Entities::TR4 { constexpr auto SKELETON_ATTACK_DAMAGE = 80; - const auto SkeletonBite = BiteInfo(Vector3(0.0f, -16.0f, 200.0f), 11); + const auto SkeletonBite = CreatureBiteInfo(Vector3i(0, -16, 200), 11); const auto SkeletonSwordAttackJoints = std::vector{ 15, 16 }; enum SkeletonState diff --git a/TombEngine/Objects/TR4/Entity/tr4_small_scorpion.cpp b/TombEngine/Objects/TR4/Entity/tr4_small_scorpion.cpp index 8a4fa6b8a..920fe8cb3 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_small_scorpion.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_small_scorpion.cpp @@ -23,8 +23,8 @@ namespace TEN::Entities::TR4 constexpr auto SMALL_SCORPION_ATTACK_RANGE = SQUARE(BLOCK(0.31)); - const auto SmallScorpionBite1 = BiteInfo(Vector3::Zero, 0); - const auto SmallScorpionBite2 = BiteInfo(Vector3::Zero, 23); + const auto SmallScorpionBite1 = CreatureBiteInfo(Vector3i::Zero, 0); + const auto SmallScorpionBite2 = CreatureBiteInfo(Vector3i::Zero, 23); const auto SmallScorpionAttackJoints = std::vector{ 8, 22, 23, 25, 26 }; enum SmallScorionState @@ -163,7 +163,7 @@ namespace TEN::Entities::TR4 item->Animation.FrameNumber < g_Level.Anims[item->Animation.AnimNumber].frameBase + 32) { short rotation; - BiteInfo biteInfo; + CreatureBiteInfo biteInfo; // Pincer attack if (item->Animation.ActiveState == SSCORPION_STATE_ATTACK_1) diff --git a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp index 2d8cfd6f9..7c9ff699c 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp @@ -20,7 +20,7 @@ namespace TEN::Entities::TR4 constexpr auto SPHINX_WALK_TURN_ANGLE = ANGLE(3.0f); constexpr auto SPHINX_RUN_TURN_ANGLE = ANGLE(0.33f); - const auto SphinxBite = BiteInfo(Vector3::Zero, 6); + const auto SphinxBite = CreatureBiteInfo(Vector3i::Zero, 6); const auto SphinxAttackJoints = std::vector{ 6 }; enum SphinxState diff --git a/TombEngine/Objects/TR4/Entity/tr4_troops.cpp b/TombEngine/Objects/TR4/Entity/tr4_troops.cpp index 16f6906ba..56fa19675 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_troops.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_troops.cpp @@ -20,7 +20,7 @@ using namespace TEN::Math; namespace TEN::Entities::TR4 { - const auto TroopsBite1 = BiteInfo(Vector3(0.0f, 300.0f, 64.0f), 7); + const auto TroopsBite1 = CreatureBiteInfo(Vector3i(0, 270, 40), 7); enum TroopState { @@ -87,13 +87,8 @@ namespace TEN::Entities::TR4 int dy = 0; int dz = 0; - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, TroopsBite1.meshNum, Vector3i(TroopsBite1.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * creature->FiredWeapon + 8, 24, 16, 4); - - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; if (item->HitPoints <= 0) { @@ -369,11 +364,14 @@ namespace TEN::Entities::TR4 } if (creature->Flags) + { creature->Flags--; + } else { - creature->FiredWeapon = 1; ShotLara(item, &AI, TroopsBite1, joint0, 23); + creature->MuzzleFlash[0].Bite = TroopsBite1; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 5; } @@ -428,11 +426,14 @@ namespace TEN::Entities::TR4 } if (creature->Flags) + { creature->Flags--; + } else { - creature->FiredWeapon = 1; ShotLara(item, &AI, TroopsBite1, joint0, 23); + creature->MuzzleFlash[0].Bite = TroopsBite1; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 5; } diff --git a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp index 10ebb0239..fabfd74a3 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp @@ -22,7 +22,7 @@ namespace TEN::Entities::TR4 { constexpr auto VON_CROY_FLAG_JUMP = 6; - const auto VonCroyBite = BiteInfo(Vector3(0.0f, 35.0f, 130.0f), 18); + const auto VonCroyBite = CreatureBiteInfo(Vector3i(0, 35, 130), 18); const auto VonCroyKnifeSwapJoints = std::vector{ 7, 18 }; bool VonCroyPassedWaypoints[128]; diff --git a/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp b/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp index e4b663de0..99b688f13 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp @@ -20,7 +20,7 @@ namespace TEN::Entities::TR4 constexpr auto WILD_BOAR_ATTACK_DAMAGE = 30; constexpr auto WILD_BOAR_ATTACK_RANGE = SQUARE(CLICK(1)); - const auto WildBoarBite = BiteInfo(Vector3::Zero, 14); + const auto WildBoarBite = CreatureBiteInfo(Vector3i::Zero, 14); enum WildBoarState { diff --git a/TombEngine/Objects/TR4/tr4_objects.cpp b/TombEngine/Objects/TR4/tr4_objects.cpp index b5570957f..7883dacf0 100644 --- a/TombEngine/Objects/TR4/tr4_objects.cpp +++ b/TombEngine/Objects/TR4/tr4_objects.cpp @@ -204,7 +204,6 @@ namespace TEN::Entities obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; obj->HitPoints = 25; - obj->biteOffset = 9; obj->pivotLength = 50; obj->radius = 102; obj->intelligent = true; @@ -226,7 +225,6 @@ namespace TEN::Entities obj->shadowType = ShadowMode::All; obj->HitPoints = 25; obj->pivotLength = 50; - obj->biteOffset = 9; obj->radius = 102; obj->intelligent = true; obj->meshSwapSlot = ID_MESHSWAP_BADDY2; @@ -243,7 +241,6 @@ namespace TEN::Entities obj->control = SasControl; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->biteOffset = 10; obj->HitPoints = 40; obj->pivotLength = 50; obj->radius = 102; @@ -400,7 +397,6 @@ namespace TEN::Entities obj->control = TroopsControl; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->biteOffset = 11; obj->HitPoints = 40; obj->pivotLength = 50; obj->radius = 102; diff --git a/TombEngine/Objects/TR5/Entity/HeavyGuard.cpp b/TombEngine/Objects/TR5/Entity/HeavyGuard.cpp index 5eeeaa415..847ae09f6 100644 --- a/TombEngine/Objects/TR5/Entity/HeavyGuard.cpp +++ b/TombEngine/Objects/TR5/Entity/HeavyGuard.cpp @@ -50,7 +50,7 @@ namespace TEN::Entities::Creatures::TR5 Vector3(8.0f, 230.0f, 40.0f), }; - const auto HeavyGuardHeadBite = BiteInfo(Vector3(0.0f, -200.0f, 0.0f), 2); + const auto HeavyGuardHeadBite = CreatureBiteInfo(Vector3(0, -200, 0), 2); enum HeavyGuardState { diff --git a/TombEngine/Objects/TR5/Entity/tr5_brownbeast.cpp b/TombEngine/Objects/TR5/Entity/tr5_brownbeast.cpp index 029e0a753..f7f470baf 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_brownbeast.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_brownbeast.cpp @@ -19,8 +19,8 @@ namespace TEN::Entities::Creatures::TR5 { constexpr auto BROWN_BEAST_ATTACK_DAMAGE = 150; - const auto BrownBeastBite1 = BiteInfo(Vector3::Zero, 16); - const auto BrownBeastBite2 = BiteInfo(Vector3::Zero, 22); + const auto BrownBeastBite1 = CreatureBiteInfo(Vector3i::Zero, 16); + const auto BrownBeastBite2 = CreatureBiteInfo(Vector3i::Zero, 22); const auto BrownBeastAttackJoints1 = std::vector{ 14, 15, 16, 17 }; const auto BrownBeastAttackJoints2 = std::vector{ 20, 21, 22, 23 }; diff --git a/TombEngine/Objects/TR5/Entity/tr5_chef.cpp b/TombEngine/Objects/TR5/Entity/tr5_chef.cpp index dea6b5324..4107e280c 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_chef.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_chef.cpp @@ -15,7 +15,7 @@ namespace TEN::Entities::Creatures::TR5 { - const auto ChefBite = BiteInfo(Vector3(0.0f, 200.0f, 0.0f), 13); + const auto ChefBite = CreatureBiteInfo(Vector3i(0, 200, 0), 13); // TODO enum ChefState diff --git a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp index 42b3d8727..0a9e4711f 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp @@ -36,7 +36,7 @@ namespace TEN::Entities::Creatures::TR5 constexpr auto CYBORG_DISTURBANCE_VELOCITY = 20.0f; - const auto CyborgGunBite = BiteInfo(Vector3(0.0f, 300.0f, 64.0f), 7); + const auto CyborgGunBite = CreatureBiteInfo(Vector3i(-32, 240, 50), 18); const auto CyborgJoints = std::vector{ 15, 14, 13, 6, 5, 12, 7, 4, 10, 11, 19 }; enum CyborgState @@ -175,13 +175,8 @@ namespace TEN::Entities::Creatures::TR5 canJump2blocks = false; } - // Fire weapon. - if (creature.FiredWeapon) - { - auto pos = GetJointPosition(&item, CyborgGunBite.meshNum, Vector3i(CyborgGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * creature.FiredWeapon + 10, 192, 128, 32); - creature.FiredWeapon--; - } + if (creature.MuzzleFlash[0].Delay != 0) + creature.MuzzleFlash[0].Delay--; if (item.AIBits) GetAITarget(&creature); @@ -577,14 +572,12 @@ namespace TEN::Entities::Creatures::TR5 item.Animation.FrameNumber < g_Level.Anims[item.Animation.AnimNumber].frameBase + 16 && ((byte)item.Animation.FrameNumber - (byte)g_Level.Anims[item.Animation.AnimNumber].frameBase) & 1) { - creature.FiredWeapon = 1; ShotLara(&item, &AI, CyborgGunBite, joint0, CYBORG_GUN_ATTACK_DAMAGE); + creature.MuzzleFlash[0].Bite = CyborgGunBite; + creature.MuzzleFlash[0].Delay = 1; } break; - - default: - break; } } else if (item.Animation.ActiveState == CYBORG_STATE_DEATH && LaraItem->Effect.Type == EffectType::None) diff --git a/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp b/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp index 7ea8547ba..d0dfc3e49 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp @@ -16,7 +16,7 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 { - const auto DobermanBite = BiteInfo(Vector3(0.0f, 30.0f, 141.0f), 20); + const auto DobermanBite = CreatureBiteInfo(Vector3i(0, 30, 141), 20); enum DobermanState { diff --git a/TombEngine/Objects/TR5/Entity/tr5_dog.cpp b/TombEngine/Objects/TR5/Entity/tr5_dog.cpp index 1231c92e7..492e87d23 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_dog.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_dog.cpp @@ -14,7 +14,7 @@ namespace TEN::Entities::Creatures::TR5 { - const auto DogBite = BiteInfo(Vector3(0.0f, 0.0f, 100.0f), 3); + const auto DogBite = CreatureBiteInfo(Vector3i(0, 0, 100), 3); static BYTE DogAnims[] = { 20, 21, 22, 20 }; void InitializeTr5Dog(short itemNumber) diff --git a/TombEngine/Objects/TR5/Entity/tr5_ghost.cpp b/TombEngine/Objects/TR5/Entity/tr5_ghost.cpp index df5de7e99..f78c7528d 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_ghost.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_ghost.cpp @@ -13,7 +13,7 @@ namespace TEN::Entities::Creatures::TR5 { - const auto InvisibleGhostBite = BiteInfo(Vector3::Zero, 17); + const auto InvisibleGhostBite = CreatureBiteInfo(Vector3i::Zero, 17); void InitializeInvisibleGhost(short itemNumber) { diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 7cf55ea3c..3e8a9f923 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -23,7 +23,7 @@ namespace TEN::Entities::Creatures::TR5 // TODO: Ranges. - const auto GladiatorBite = BiteInfo(Vector3::Zero, 16); + const auto GladiatorBite = CreatureBiteInfo(Vector3i::Zero, 16); const auto GladiatorAttackJoints = std::vector{ 13, 14 }; enum GladiatorState diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index 619e8793e..a37f4f8cb 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -24,19 +24,17 @@ namespace TEN::Entities::Creatures::TR5 constexpr auto GUARD_ALERT_RANGE = SQUARE(BLOCK(1)); constexpr auto GUARD_WALK_RANGE = SQUARE(BLOCK(3)); constexpr auto GUARD_ATTACK_RANGE = SQUARE(BLOCK(4)); - constexpr auto GUARD_WALK_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto GUARD_RUN_TURN_RATE_MAX = ANGLE(10.0f); - constexpr auto GUARD_LARA_ANGLE_FOR_DEATH2 = ANGLE(67.5f); - constexpr auto GUARD_NO_WEAPON_ON_HAND_SWAPFLAG = 0x2000; - constexpr auto GUARD_HEAD_MESH = 14; - const auto SwatGunBite = BiteInfo(Vector3(80.0f, 200.0f, 13.0f), 0); - const auto SniperGunBite = BiteInfo(Vector3(0.0f, 480.0f, 110.0f), 13); - const auto ArmedMafia2GunBite = BiteInfo(Vector3(-50.0f, 220.0f, 60.0f), 13); + const auto SwatGunBite = CreatureBiteInfo(Vector3i(16, 240, 90), 13); + const auto MafiaGunBite = CreatureBiteInfo(Vector3i(16, 270, 90), 13); + const auto SniperGunBite = CreatureBiteInfo(Vector3i(0, 480, 110), 13); + const auto ArmedMafia2GunLeftBite = CreatureBiteInfo(Vector3i(-16, 200, 60), 10); + const auto ArmedMafia2GunRightBite = CreatureBiteInfo(Vector3i(16, 200, 60), 13); // TODO: Revise names of enum elements. @@ -327,18 +325,14 @@ namespace TEN::Entities::Creatures::TR5 bool canJump1block = CanCreatureJump(*item, JumpDistance::Block1); bool canJump2blocks = !canJump1block && CanCreatureJump(*item, JumpDistance::Block2); - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, SwatGunBite.meshNum, Vector3i(SwatGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * creature->FiredWeapon + 10, 192, 128, 32); - creature->FiredWeapon--; - } - if (item->AIBits) GetAITarget(creature); else creature->Enemy = LaraItem; + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + AI_INFO AI; CreatureAIInfo(item, &AI); @@ -578,23 +572,28 @@ namespace TEN::Entities::Creatures::TR5 } } - if (!creature->Flags) + if (creature->Flags == 0) { - creature->FiredWeapon = 2; - creature->Flags = 1; - - if (item->Animation.ActiveState == GUARD_STATE_SINGLE_FIRE_ATTACK) - ShotLara(item, &AI, SwatGunBite, torsoX, 30); + if (item->ObjectNumber == ID_MAFIA) + { + if (item->Animation.ActiveState == GUARD_STATE_SINGLE_FIRE_ATTACK) + ShotLara(item, &AI, MafiaGunBite, torsoX, 30); + else + ShotLara(item, &AI, MafiaGunBite, torsoX, 10); + creature->MuzzleFlash[0].Bite = MafiaGunBite; + creature->MuzzleFlash[0].Delay = 2; + } else - ShotLara(item, &AI, SwatGunBite, torsoX, 10); - - // TODO: just for testing energy arcs - /*pos1.x = SwatGunBite.x; - pos1.y = SwatGunBite.y; - pos1.z = SwatGunBite.z; - GetJointPosition(item, &pos1, SwatGunBite.meshNum); - TriggerEnergyArc(&pos1, (Vector3i*)& LaraItem->pos, 192, 128, 192, 256, 150, 256, 0, ENERGY_ARC_STRAIGHT_LINE);*/ - + { + if (item->Animation.ActiveState == GUARD_STATE_SINGLE_FIRE_ATTACK) + ShotLara(item, &AI, SwatGunBite, torsoX, 30); + else + ShotLara(item, &AI, SwatGunBite, torsoX, 10); + creature->MuzzleFlash[0].Bite = SwatGunBite; + creature->MuzzleFlash[0].Delay = 2; + } + + creature->Flags = 1; } break; @@ -1018,12 +1017,8 @@ namespace TEN::Entities::Creatures::TR5 short joint1 = 0; short joint2 = 0; - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, SniperGunBite.meshNum, Vector3i(SniperGunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * creature->FiredWeapon + 10, 192, 128, 32); - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; if (item->HitPoints > 0) { @@ -1079,14 +1074,12 @@ namespace TEN::Entities::Creatures::TR5 if (!creature->Flags) { ShotLara(item, &AI, SniperGunBite, joint0, 100); - creature->FiredWeapon = 2; + creature->MuzzleFlash[0].Bite = SniperGunBite; + creature->MuzzleFlash[0].Delay = 2; creature->Flags = 1; } break; - - default: - break; } } else @@ -1171,25 +1164,21 @@ namespace TEN::Entities::Creatures::TR5 canJump2Sectors = false; } - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, ArmedMafia2GunBite.meshNum, Vector3i(ArmedMafia2GunBite.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * creature->FiredWeapon + 8, 24, 16, 4); - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (creature->MuzzleFlash[1].Delay != 0) + creature->MuzzleFlash[1].Delay--; + + if (item->AIBits) + GetAITarget(creature); + else + creature->Enemy = LaraItem; AI_INFO AI; - ZeroMemory(&AI, sizeof(AI_INFO)); + CreatureAIInfo(item, &AI); if (item->HitPoints > 0) { - if (item->AIBits) - GetAITarget(creature); - else - creature->Enemy = LaraItem; - - CreatureAIInfo(item, &AI); - AI_INFO laraAI; if (creature->Enemy == LaraItem) { @@ -1329,11 +1318,19 @@ namespace TEN::Entities::Creatures::TR5 else item->Pose.Orientation.y += AI.angle; - if (!creature->Flags) + if (!(creature->Flags & 1) && item->Animation.FrameNumber == GetFrameIndex(item, 2)) { - ShotLara(item, &AI, ArmedMafia2GunBite, laraAI.angle / 2, 35); - creature->Flags = 1; - creature->FiredWeapon = 2; + ShotLara(item, &AI, ArmedMafia2GunRightBite, laraAI.angle / 2, 25); + creature->MuzzleFlash[1].Bite = ArmedMafia2GunRightBite; + creature->MuzzleFlash[1].Delay = 2; + creature->Flags |= 1; + } + if (!(creature->Flags & 2) && item->Animation.FrameNumber == GetFrameIndex(item, 6)) + { + ShotLara(item, &AI, ArmedMafia2GunLeftBite, laraAI.angle / 2, 25); + creature->MuzzleFlash[0].Bite = ArmedMafia2GunLeftBite; + creature->MuzzleFlash[0].Delay = 2; + creature->Flags |= 2; } break; @@ -1528,9 +1525,6 @@ namespace TEN::Entities::Creatures::TR5 item->Animation.ActiveState = 22; creature->MaxTurn = 0; break; - - default: - return; } } } diff --git a/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp b/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp index 77247c684..31bba36f2 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp @@ -19,7 +19,7 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 { - const auto HydraBite = BiteInfo(Vector3::Zero, 11); + const auto HydraBite = CreatureBiteInfo(Vector3i::Zero, 11); enum HydraState { diff --git a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp index d722c8b92..17668df93 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp @@ -33,8 +33,8 @@ namespace TEN::Entities::Creatures::TR5 constexpr auto IMP_HEAD_MESH_SWAP_INTERVAL = 16; - const auto ImpLeftHandBite = BiteInfo(Vector3(0.0f, 100.0f, 0.0f), 7); - const auto ImpRightHandBite = BiteInfo(Vector3(0.0f, 100.0f, 0.0f), 9); + const auto ImpLeftHandBite = CreatureBiteInfo(Vector3i(0, 100, 0), 7); + const auto ImpRightHandBite = CreatureBiteInfo(Vector3i(0, 100, 0), 9); const auto ImpHeadMeshSwapJoints = std::vector{ 10 }; enum ImpState @@ -98,7 +98,7 @@ namespace TEN::Entities::Creatures::TR5 static void DoImpStoneAttack(ItemInfo* item) { - auto pos1 = GetJointPosition(item, ImpRightHandBite.meshNum); + auto pos1 = GetJointPosition(item, ImpRightHandBite); auto pos2 = GetJointPosition(LaraItem, LM_HEAD); auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos2.ToVector3()); @@ -344,7 +344,7 @@ namespace TEN::Entities::Creatures::TR5 case IMP_STATE_ATTACK_1: creature->MaxTurn = 0; - if (!(creature->Flags & 1) && item->TouchBits.Test(ImpRightHandBite.meshNum)) + if (!(creature->Flags & 1) && item->TouchBits.Test(ImpRightHandBite.BoneID)) { DoDamage(creature->Enemy, IMP_ATTACK_DAMAGE); CreatureEffect2(item, ImpRightHandBite, 10, item->Pose.Orientation.y, DoBloodSplat); @@ -356,14 +356,14 @@ namespace TEN::Entities::Creatures::TR5 case IMP_STATE_JUMP_ATTACK: RotateTowardTarget(*item, ai, IMP_ATTACK_TURN_RATE_MAX); - if (!(creature->Flags & 1) && item->TouchBits.Test(ImpRightHandBite.meshNum)) + if (!(creature->Flags & 1) && item->TouchBits.Test(ImpRightHandBite.BoneID)) { DoDamage(creature->Enemy, IMP_ATTACK_DAMAGE); CreatureEffect(item, ImpRightHandBite, DoBloodSplat); creature->Flags |= 1; } - if (!(creature->Flags & 2) && item->TouchBits.Test(ImpLeftHandBite.meshNum)) + if (!(creature->Flags & 2) && item->TouchBits.Test(ImpLeftHandBite.BoneID)) { DoDamage(creature->Enemy, IMP_ATTACK_DAMAGE); CreatureEffect(item, ImpLeftHandBite, DoBloodSplat); diff --git a/TombEngine/Objects/TR5/Entity/tr5_lagoon_witch.cpp b/TombEngine/Objects/TR5/Entity/tr5_lagoon_witch.cpp index c77e3f30d..da71caf0e 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_lagoon_witch.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_lagoon_witch.cpp @@ -18,7 +18,7 @@ namespace TEN::Entities::Creatures::TR5 { constexpr auto LAGOON_WITCH_ATTACK_DAMAGE = 100; - const auto LagoonWitchBite = BiteInfo(Vector3::Zero, 7); + const auto LagoonWitchBite = CreatureBiteInfo(Vector3i::Zero, 7); const auto LagoonWitchAttackJoints = std::vector{ 6, 7, 8, 9, 14, 15, 16, 17 }; enum LagoonWitchState diff --git a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp index d42154bdf..3cd31ce4f 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp @@ -31,9 +31,9 @@ namespace TEN::Entities::Creatures::TR5 #define TR5_LARSON_MIN_HP 40 - const auto LarsonGun = BiteInfo(Vector3(-55.0f, 200.0f, 5.0f), 14); - const auto PierreGun1 = BiteInfo(Vector3(60.0f, 200.0f, 0.0f), 11); - const auto PierreGun2 = BiteInfo(Vector3(-57.0f, 200.0f, 0.0f), 14); + const auto LarsonGun = CreatureBiteInfo(Vector3i(-55, 200, 5), 14); + const auto PierreGunLeft = CreatureBiteInfo(Vector3i(45, 200, 0), 11); + const auto PierreGunRight = CreatureBiteInfo(Vector3i(-40, 200, 0), 14); void InitializeLarson(short itemNumber) { @@ -79,13 +79,10 @@ namespace TEN::Entities::Creatures::TR5 creature->flags++; }*/ - // Fire weapon effects. - if (creature->FiredWeapon) - { - auto pos = GetJointPosition(item, LarsonGun.meshNum, Vector3i(LarsonGun.Position)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * creature->FiredWeapon + 10, 192, 128, 32); - creature->FiredWeapon--; - } + if (creature->MuzzleFlash[0].Delay != 0) + creature->MuzzleFlash[0].Delay--; + if (creature->MuzzleFlash[1].Delay != 0) + creature->MuzzleFlash[1].Delay--; if (item->TriggerFlags) { @@ -323,17 +320,23 @@ namespace TEN::Entities::Creatures::TR5 else item->Pose.Orientation.y += AI.angle; - if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase) + if (item->Animation.FrameNumber == GetFrameIndex(item, 0)) { if (item->ObjectNumber == ID_PIERRE) { - ShotLara(item, &AI, PierreGun1, joint0, 20); - ShotLara(item, &AI, PierreGun2, joint0, 20); + ShotLara(item, &AI, PierreGunLeft, joint0, 20); + ShotLara(item, &AI, PierreGunRight, joint0, 20); + creature->MuzzleFlash[0].Bite = PierreGunLeft; + creature->MuzzleFlash[0].Delay = 2; + creature->MuzzleFlash[1].Bite = PierreGunRight; + creature->MuzzleFlash[1].Delay = 2; } else + { ShotLara(item, &AI, LarsonGun, joint0, 20); - - creature->FiredWeapon = 2; + creature->MuzzleFlash[0].Bite = LarsonGun; + creature->MuzzleFlash[0].Delay = 2; + } } if (creature->Mood == MoodType::Escape && Random::TestProbability(0.75f)) diff --git a/TombEngine/Objects/TR5/Entity/tr5_lion.cpp b/TombEngine/Objects/TR5/Entity/tr5_lion.cpp index c0800a0ed..540fa33f4 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_lion.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_lion.cpp @@ -34,8 +34,8 @@ namespace TEN::Entities::Creatures::TR5 constexpr auto LION_RUN_TURN_RATE_MAX = ANGLE(5.0f); constexpr auto LION_ATTACK_TURN_RATE_MAX = ANGLE(1.0f); - const auto LionBite1 = BiteInfo(Vector3(2.0f, -10.0f, 250.0f), 21); - const auto LionBite2 = BiteInfo(Vector3(-2.0f, -10.0f, 132.0f), 21); + const auto LionBite1 = CreatureBiteInfo(Vector3i(2, -10, 250), 21); + const auto LionBite2 = CreatureBiteInfo(Vector3i(-2, -10, 132), 21); const auto LionAttackJoints = std::vector{ 3, 6, 21 }; enum LionState diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index e4dc28b0d..d4ff85fba 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -29,7 +29,7 @@ namespace TEN::Entities::Creatures::TR5 constexpr auto ROMAN_STATUE_GRENADE_SUPER_AMMO_LIMITER = 2.0f; constexpr auto ROMAN_STATUE_EXPLOSIVE_DAMAGE_COEFF = 2.0f; - const auto RomanStatueBite = BiteInfo(Vector3::Zero, 15); + const auto RomanStatueBite = CreatureBiteInfo(Vector3i::Zero, 15); struct RomanStatueInfo { diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp index 484d4063c..52f2551de 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp @@ -15,7 +15,6 @@ #include "Game/Lara/lara_one_gun.h" #include "Game/Lara/lara_fire.h" #include "Objects/Generic/Switches/generic_switch.h" -#include "Objects/Generic/Traps/traps.h" #include "Objects/TR5/Shatter/tr5_smashobject.h" #include "Sound/sound.h" #include "Specific/level.h" diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp index 5613631ad..9b630d003 100644 --- a/TombEngine/Objects/TR5/tr5_objects.cpp +++ b/TombEngine/Objects/TR5/tr5_objects.cpp @@ -109,7 +109,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = GuardControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 102; @@ -129,7 +128,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = GuardControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 4; obj->HitPoints = 24; obj->radius = 102; obj->pivotLength = 50; @@ -151,7 +149,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = GuardControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 102; @@ -172,7 +169,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = GuardControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 102; @@ -215,7 +211,6 @@ static void StartEntity(ObjectInfo *obj) obj->control = GuardControl; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->biteOffset = 4; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 102; @@ -237,7 +232,6 @@ static void StartEntity(ObjectInfo *obj) obj->control = GuardControl; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->biteOffset = 4; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 102; @@ -277,7 +271,6 @@ static void StartEntity(ObjectInfo *obj) obj->HitPoints = 35; obj->pivotLength = 50; obj->radius = 102; - obj->biteOffset = 0; obj->intelligent = true; obj->LotType = LotType::Human; obj->SetBoneRotationFlags(6, ROT_X | ROT_Y); @@ -354,7 +347,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = Mafia2Control; obj->shadowType = ShadowMode::All; - obj->biteOffset = 7; obj->HitPoints = 26; obj->pivotLength = 50; obj->radius = 102; @@ -374,7 +366,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = LarsonControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 1; obj->HitPoints = 60; obj->pivotLength = 50; obj->radius = 102; @@ -392,7 +383,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = LarsonControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 3; obj->HitPoints = 60; obj->pivotLength = 50; obj->radius = 102; @@ -410,7 +400,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = CyborgControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 5; obj->HitPoints = 50; obj->pivotLength = 50; obj->radius = 102; @@ -430,7 +419,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = SniperControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 6; obj->HitPoints = 35; obj->pivotLength = 50; obj->radius = 102; @@ -447,9 +435,8 @@ static void StartEntity(ObjectInfo *obj) obj->Initialize = InitializeHeavyGuard; obj->collision = CreatureCollision; obj->control = HeavyGuardControl; - obj->shadowType = ShadowMode::All; obj->HitRoutine = HeavyGuardHit; - obj->biteOffset = 0; + obj->shadowType = ShadowMode::All; obj->HitPoints = 24; obj->pivotLength = 50; obj->radius = 128; @@ -470,7 +457,6 @@ static void StartEntity(ObjectInfo *obj) obj->HitPoints = 30; obj->pivotLength = 50; obj->radius = 102; - obj->biteOffset = 1024; obj->intelligent = true; obj->undead = true; obj->SetBoneRotationFlags(0, ROT_X | ROT_Y); @@ -502,7 +488,6 @@ static void StartEntity(ObjectInfo *obj) //obj->control = ControlLightingGuide; obj->drawRoutine = nullptr; obj->shadowType = ShadowMode::All; - obj->biteOffset = 256; obj->radius = 256; obj->HitPoints = NOT_TARGETABLE; obj->pivotLength = 20; @@ -520,7 +505,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = ControlBrowsBeast; obj->shadowType = ShadowMode::All; - obj->biteOffset = 256; obj->HitPoints = 100; obj->pivotLength = 20; obj->radius = 341; @@ -537,7 +521,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = LagoonWitchControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 256; obj->HitPoints = 100; obj->pivotLength = 20; obj->radius = 256; @@ -556,7 +539,6 @@ static void StartEntity(ObjectInfo *obj) obj->collision = CreatureCollision; obj->control = InvisibleGhostControl; obj->shadowType = ShadowMode::All; - obj->biteOffset = 256; obj->HitPoints = NOT_TARGETABLE; obj->pivotLength = 20; obj->radius = 256; @@ -601,7 +583,6 @@ static void StartEntity(ObjectInfo *obj) obj->control = ControlGladiator; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 20; obj->pivotLength = 50; obj->radius = 102; @@ -621,7 +602,6 @@ static void StartEntity(ObjectInfo *obj) obj->control = RomanStatueControl; obj->HitRoutine = RomanStatueHit; obj->shadowType = ShadowMode::All; - obj->biteOffset = 0; obj->HitPoints = 300; obj->pivotLength = 50; obj->radius = 256; diff --git a/TombEngine/Objects/Utils/object_helper.cpp b/TombEngine/Objects/Utils/object_helper.cpp index 622b94daf..5576f33c3 100644 --- a/TombEngine/Objects/Utils/object_helper.cpp +++ b/TombEngine/Objects/Utils/object_helper.cpp @@ -20,19 +20,20 @@ void AssignObjectMeshSwap(ObjectInfo& object, int requiredMeshSwap, const std::s bool AssignObjectAnimations(ObjectInfo& object, int requiredObject, const std::string& baseName, const std::string& requiredName) { // Check if the object has at least 1 animation with more than 1 frame. - const auto& anim = g_Level.Anims[object.animIndex]; + const auto& anim = GetAnimData(object.animIndex); if ((anim.frameEnd - anim.frameBase) > 1) return true; // Use slot if loaded. - if (Objects[requiredObject].loaded) + const auto& requiredObj = Objects[requiredObject]; + if (requiredObj.loaded) { // Check if the required object has at least 1 animation with more than 1 frame. - const auto& anim = g_Level.Anims[Objects[requiredObject].animIndex]; + const auto& anim = GetAnimData(requiredObj.animIndex); if ((anim.frameEnd - anim.frameBase) > 1) { - object.animIndex = Objects[requiredObject].animIndex; - object.frameBase = Objects[requiredObject].frameBase; + object.animIndex = requiredObj.animIndex; + object.frameBase = requiredObj.frameBase; return true; } else diff --git a/TombEngine/Renderer/Renderer11.h b/TombEngine/Renderer/Renderer11.h index 381dbcab1..2c7fe2f69 100644 --- a/TombEngine/Renderer/Renderer11.h +++ b/TombEngine/Renderer/Renderer11.h @@ -5,6 +5,7 @@ #include #include +#include "Game/control/box.h" #include "Game/items.h" #include "Game/animation.h" #include "Game/Gui.h" diff --git a/TombEngine/Renderer/Renderer11DrawEffect.cpp b/TombEngine/Renderer/Renderer11DrawEffect.cpp index 917480c9c..e43765b84 100644 --- a/TombEngine/Renderer/Renderer11DrawEffect.cpp +++ b/TombEngine/Renderer/Renderer11DrawEffect.cpp @@ -50,24 +50,6 @@ extern GUNFLASH_STRUCT Gunflashes[MAX_GUNFLASH]; // offset 0xA31D8 extern Particle Particles[MAX_PARTICLES]; extern SPLASH_STRUCT Splashes[MAX_SPLASHES]; -// TODO: EnemyBites must be eradicated and kept directly in object structs or passed to gunflash functions. - -BiteInfo EnemyBites[12] = -{ - { 20, -95, 240, 13 }, - { 48, 0, 180, -11 }, - { -48, 0, 180, 14 }, - { -48, 5, 225, 14 }, - { 15, -60, 195, 13 }, - { -30, -65, 250, 18 }, - { 0, -110, 480, 13 }, - { -20, -80, 190, -10 }, - { 10, -60, 200, 13 }, - { 10, -60, 200, 11 }, // Baddy 2 - { 20, -60, 400, 7 }, // SAS - { 0, -64, 250, 7 } // Troops -}; - namespace TEN::Renderer { constexpr auto ELECTRICITY_RANGE_MAX = BLOCK(24); @@ -840,7 +822,6 @@ namespace TEN::Renderer zOffset = 92; rotationX = -14560; break; - default: case LaraWeaponType::Pistol: length = 180; @@ -925,74 +906,87 @@ namespace TEN::Renderer m_context->IASetInputLayout(m_inputLayout.Get()); m_context->IASetIndexBuffer(m_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); - for (auto room : view.roomsToDraw) + for (auto* room : view.roomsToDraw) { - for (auto item : room->ItemsToDraw) + for (auto* item : room->ItemsToDraw) { // Does the item need gunflash? - ItemInfo* nativeItem = &g_Level.Items[item->ItemNumber]; - ObjectInfo* obj = &Objects[nativeItem->ObjectNumber]; + auto* nativeItem = &g_Level.Items[item->ItemNumber]; + auto* obj = &Objects[nativeItem->ObjectNumber]; - if (obj->biteOffset == -1) + if (!nativeItem->IsCreature()) continue; - - if (nativeItem->Data.is()) - { - auto* creature = GetCreatureInfo(nativeItem); - if (!creature->FiredWeapon) - continue; - } - else - continue; - - RendererRoom const& room = m_rooms[nativeItem->RoomNumber]; - RendererObject& flashMoveable = *m_moveableObjects[ID_GUN_FLASH]; + auto* creature = GetCreatureInfo(nativeItem); + auto const& room_item = m_rooms[nativeItem->RoomNumber]; m_stStatic.Color = Vector4::One; - m_stStatic.AmbientLight = room.AmbientLight; + m_stStatic.AmbientLight = room_item.AmbientLight; m_stStatic.LightMode = LIGHT_MODES::LIGHT_MODE_STATIC; + BindStaticLights(item->LightsToDraw); // FIXME: Is it really needed for gunflashes? -- Lwmte, 15.07.22 - SetBlendMode(BLENDMODE_ADDITIVE); - SetAlphaTest(ALPHA_TEST_GREATER_THAN, ALPHA_TEST_THRESHOLD); - BiteInfo* bites[2] = { - &EnemyBites[obj->biteOffset], - &EnemyBites[obj->biteOffset + 1] - }; - - int numBites = (bites[0]->meshNum < 0) + 1; - - for (int k = 0; k < numBites; k++) + if (creature->MuzzleFlash[0].Delay != 0 && creature->MuzzleFlash[0].Bite.BoneID != -1) { - int joint = abs(bites[k]->meshNum); - - RendererMesh* flashMesh = flashMoveable.ObjectMeshes[0]; - - for (auto& flashBucket : flashMesh->Buckets) + GAME_OBJECT_ID flashObjID = creature->MuzzleFlash[0].SwitchToMuzzle2 ? m_moveableObjects[ID_GUN_FLASH2].has_value() ? ID_GUN_FLASH2 : ID_GUN_FLASH : ID_GUN_FLASH; + auto* flashMoveable = m_moveableObjects[flashObjID]->ObjectMeshes.at(0); + for (RendererBucket& flashBucket : flashMoveable->Buckets) { if (flashBucket.BlendMode == BLENDMODE_OPAQUE) continue; - if (flashBucket.Polygons.size() == 0) continue; BindTexture(TEXTURE_COLOR_MAP, &std::get<0>(m_moveablesTextures[flashBucket.Texture]), SAMPLER_ANISOTROPIC_CLAMP); - Matrix offset = Matrix::CreateTranslation(bites[k]->Position); + Matrix offset = Matrix::CreateTranslation(creature->MuzzleFlash[0].Bite.Position.ToVector3()); Matrix rotationX = Matrix::CreateRotationX(TO_RAD(ANGLE(270.0f))); Matrix rotationZ = Matrix::CreateRotationZ(TO_RAD(2 * GetRandomControl())); - Matrix world = item->AnimationTransforms[joint] * item->World; - world = rotationX * world; + Matrix world = item->AnimationTransforms[creature->MuzzleFlash[0].Bite.BoneID] * item->World; world = offset * world; - world = rotationZ * world; + if (creature->MuzzleFlash[0].ApplyXRotation) + world = rotationX * world; + if (creature->MuzzleFlash[0].ApplyZRotation) + world = rotationZ * world; m_stStatic.World = world; m_cbStatic.updateData(m_stStatic, m_context.Get()); BindConstantBufferVS(CB_STATIC, m_cbStatic.get()); + BindConstantBufferPS(CB_STATIC, m_cbStatic.get()); + DrawIndexedTriangles(flashBucket.NumIndices, flashBucket.StartIndex, 0); + } + } + if (creature->MuzzleFlash[1].Delay != 0 && creature->MuzzleFlash[1].Bite.BoneID != -1) + { + GAME_OBJECT_ID flashObjID = creature->MuzzleFlash[1].SwitchToMuzzle2 ? m_moveableObjects[ID_GUN_FLASH2].has_value() ? ID_GUN_FLASH2 : ID_GUN_FLASH : ID_GUN_FLASH; + auto* flashMoveable = m_moveableObjects[flashObjID]->ObjectMeshes.at(0); + for (RendererBucket& flashBucket : flashMoveable->Buckets) + { + if (flashBucket.BlendMode == BLENDMODE_OPAQUE) + continue; + if (flashBucket.Polygons.size() == 0) + continue; + + BindTexture(TEXTURE_COLOR_MAP, &std::get<0>(m_moveablesTextures[flashBucket.Texture]), SAMPLER_ANISOTROPIC_CLAMP); + + Matrix offset = Matrix::CreateTranslation(creature->MuzzleFlash[1].Bite.Position.ToVector3()); + Matrix rotationX = Matrix::CreateRotationX(TO_RAD(ANGLE(270.0f))); + Matrix rotationZ = Matrix::CreateRotationZ(TO_RAD(2 * GetRandomControl())); + + Matrix world = item->AnimationTransforms[creature->MuzzleFlash[1].Bite.BoneID] * item->World; + world = offset * world; + if (creature->MuzzleFlash[1].ApplyXRotation) + world = rotationX * world; + if (creature->MuzzleFlash[1].ApplyZRotation) + world = rotationZ * world; + + m_stStatic.World = world; + m_cbStatic.updateData(m_stStatic, m_context.Get()); + BindConstantBufferVS(CB_STATIC, m_cbStatic.get()); + BindConstantBufferPS(CB_STATIC, m_cbStatic.get()); DrawIndexedTriangles(flashBucket.NumIndices, flashBucket.StartIndex, 0); } } @@ -1000,7 +994,6 @@ namespace TEN::Renderer } SetBlendMode(BLENDMODE_OPAQUE); - } Texture2D Renderer11::CreateDefaultNormalTexture() diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h index 7f70b79cf..75f611817 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h @@ -760,7 +760,8 @@ struct CreatureT : public flatbuffers::NativeTable { bool hurt_by_lara = false; int32_t tosspad = 0; int32_t location_ai = 0; - int32_t fired_weapon = 0; + int32_t weapon_delay1 = 0; + int32_t weapon_delay2 = 0; int32_t mood = 0; int32_t enemy = 0; int32_t ai_target_number = 0; @@ -791,16 +792,17 @@ struct Creature FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_HURT_BY_LARA = 26, VT_TOSSPAD = 28, VT_LOCATION_AI = 30, - VT_FIRED_WEAPON = 32, - VT_MOOD = 34, - VT_ENEMY = 36, - VT_AI_TARGET_NUMBER = 38, - VT_FLAGS = 40, - VT_CAN_JUMP = 42, - VT_CAN_MONKEY = 44, - VT_IS_AMPHIBIOUS = 46, - VT_IS_JUMPING = 48, - VT_IS_MONKEYING = 50 + VT_WEAPON_DELAY1 = 32, + VT_WEAPON_DELAY2 = 34, + VT_MOOD = 36, + VT_ENEMY = 38, + VT_AI_TARGET_NUMBER = 40, + VT_FLAGS = 42, + VT_CAN_JUMP = 44, + VT_CAN_MONKEY = 46, + VT_IS_AMPHIBIOUS = 48, + VT_IS_JUMPING = 50, + VT_IS_MONKEYING = 52 }; int32_t maximum_turn() const { return GetField(VT_MAXIMUM_TURN, 0); @@ -844,8 +846,11 @@ struct Creature FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { int32_t location_ai() const { return GetField(VT_LOCATION_AI, 0); } - int32_t fired_weapon() const { - return GetField(VT_FIRED_WEAPON, 0); + int32_t weapon_delay1() const { + return GetField(VT_WEAPON_DELAY1, 0); + } + int32_t weapon_delay2() const { + return GetField(VT_WEAPON_DELAY2, 0); } int32_t mood() const { return GetField(VT_MOOD, 0); @@ -891,7 +896,8 @@ struct Creature FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_HURT_BY_LARA) && VerifyField(verifier, VT_TOSSPAD) && VerifyField(verifier, VT_LOCATION_AI) && - VerifyField(verifier, VT_FIRED_WEAPON) && + VerifyField(verifier, VT_WEAPON_DELAY1) && + VerifyField(verifier, VT_WEAPON_DELAY2) && VerifyField(verifier, VT_MOOD) && VerifyField(verifier, VT_ENEMY) && VerifyField(verifier, VT_AI_TARGET_NUMBER) && @@ -954,8 +960,11 @@ struct CreatureBuilder { void add_location_ai(int32_t location_ai) { fbb_.AddElement(Creature::VT_LOCATION_AI, location_ai, 0); } - void add_fired_weapon(int32_t fired_weapon) { - fbb_.AddElement(Creature::VT_FIRED_WEAPON, fired_weapon, 0); + void add_weapon_delay1(int32_t weapon_delay1) { + fbb_.AddElement(Creature::VT_WEAPON_DELAY1, weapon_delay1, 0); + } + void add_weapon_delay2(int32_t weapon_delay2) { + fbb_.AddElement(Creature::VT_WEAPON_DELAY2, weapon_delay2, 0); } void add_mood(int32_t mood) { fbb_.AddElement(Creature::VT_MOOD, mood, 0); @@ -1011,7 +1020,8 @@ inline flatbuffers::Offset CreateCreature( bool hurt_by_lara = false, int32_t tosspad = 0, int32_t location_ai = 0, - int32_t fired_weapon = 0, + int32_t weapon_delay1 = 0, + int32_t weapon_delay2 = 0, int32_t mood = 0, int32_t enemy = 0, int32_t ai_target_number = 0, @@ -1026,7 +1036,8 @@ inline flatbuffers::Offset CreateCreature( builder_.add_ai_target_number(ai_target_number); builder_.add_enemy(enemy); builder_.add_mood(mood); - builder_.add_fired_weapon(fired_weapon); + builder_.add_weapon_delay2(weapon_delay2); + builder_.add_weapon_delay1(weapon_delay1); builder_.add_location_ai(location_ai); builder_.add_tosspad(tosspad); builder_.add_joint_rotation(joint_rotation); @@ -1070,7 +1081,8 @@ inline flatbuffers::Offset CreateCreatureDirect( bool hurt_by_lara = false, int32_t tosspad = 0, int32_t location_ai = 0, - int32_t fired_weapon = 0, + int32_t weapon_delay1 = 0, + int32_t weapon_delay2 = 0, int32_t mood = 0, int32_t enemy = 0, int32_t ai_target_number = 0, @@ -1097,7 +1109,8 @@ inline flatbuffers::Offset CreateCreatureDirect( hurt_by_lara, tosspad, location_ai, - fired_weapon, + weapon_delay1, + weapon_delay2, mood, enemy, ai_target_number, @@ -2709,7 +2722,8 @@ inline void Creature::UnPackTo(CreatureT *_o, const flatbuffers::resolver_functi { auto _e = hurt_by_lara(); _o->hurt_by_lara = _e; } { auto _e = tosspad(); _o->tosspad = _e; } { auto _e = location_ai(); _o->location_ai = _e; } - { auto _e = fired_weapon(); _o->fired_weapon = _e; } + { auto _e = weapon_delay1(); _o->weapon_delay1 = _e; } + { auto _e = weapon_delay2(); _o->weapon_delay2 = _e; } { auto _e = mood(); _o->mood = _e; } { auto _e = enemy(); _o->enemy = _e; } { auto _e = ai_target_number(); _o->ai_target_number = _e; } @@ -2743,7 +2757,8 @@ inline flatbuffers::Offset CreateCreature(flatbuffers::FlatBufferBuild auto _hurt_by_lara = _o->hurt_by_lara; auto _tosspad = _o->tosspad; auto _location_ai = _o->location_ai; - auto _fired_weapon = _o->fired_weapon; + auto _weapon_delay1 = _o->weapon_delay1; + auto _weapon_delay2 = _o->weapon_delay2; auto _mood = _o->mood; auto _enemy = _o->enemy; auto _ai_target_number = _o->ai_target_number; @@ -2769,7 +2784,8 @@ inline flatbuffers::Offset CreateCreature(flatbuffers::FlatBufferBuild _hurt_by_lara, _tosspad, _location_ai, - _fired_weapon, + _weapon_delay1, + _weapon_delay2, _mood, _enemy, _ai_target_number, diff --git a/TombEngine/Specific/savegame/schema/ten_itemdata.fbs b/TombEngine/Specific/savegame/schema/ten_itemdata.fbs index 4b3dccbf9..de9fba931 100644 --- a/TombEngine/Specific/savegame/schema/ten_itemdata.fbs +++ b/TombEngine/Specific/savegame/schema/ten_itemdata.fbs @@ -33,7 +33,8 @@ table Creature { hurt_by_lara: bool; tosspad: int32; location_ai: int32; - fired_weapon: int32; + weapon_delay1: int32; + weapon_delay2: int32; mood: int32; enemy: int32; ai_target_number: int32; diff --git a/TombEngine/Specific/setup.cpp b/TombEngine/Specific/setup.cpp index b4fe14fdb..9d16d6609 100644 --- a/TombEngine/Specific/setup.cpp +++ b/TombEngine/Specific/setup.cpp @@ -17,7 +17,6 @@ #include "Objects/Generic/Object/rope.h" #include "Objects/Generic/Switches/fullblock_switch.h" #include "Objects/Generic/Switches/switch.h" -#include "Objects/Generic/Traps/traps.h" #include "Objects/Generic/Traps/falling_block.h" #include "Objects/TR1/tr1_objects.h" #include "Objects/TR2/tr2_objects.h" @@ -45,254 +44,6 @@ void InitializeGameFlags() Camera.underwater = false; } -void ObjectObjects() -{ - ObjectInfo* obj; - - obj = &Objects[ID_CAMERA_TARGET]; - if (obj->loaded) - { - obj->drawRoutine = nullptr; - obj->usingDrawAnimatingItem = false; - } - - obj = &Objects[ID_SMASH_OBJECT1]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT2]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT3]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT4]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT5]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT6]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT7]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_SMASH_OBJECT8]; - if (obj->loaded) - { - obj->Initialize = InitializeSmashObject; - obj->collision = ObjectCollision; - obj->control = SmashObjectControl; - } - - obj = &Objects[ID_CRUMBLING_FLOOR]; - if (obj->loaded) - { - obj->Initialize = InitializeFallingBlock; - obj->collision = FallingBlockCollision; - obj->control = FallingBlockControl; - } - - for (int objNum = ID_KEY_HOLE1; objNum <= ID_KEY_HOLE16; objNum++) - { - InitKeyHole(obj, objNum); - } - - for (int objNum = ID_PUZZLE_HOLE1; objNum <= ID_PUZZLE_HOLE16; objNum++) - { - InitPuzzleHole(obj, objNum); - } - - for (int objNum = ID_PUZZLE_DONE1; objNum <= ID_PUZZLE_DONE16; objNum++) - { - InitPuzzleDone(obj, objNum); - } - - for (int objNum = ID_ANIMATING1; objNum <= ID_ANIMATING128; objNum++) - { - InitAnimating(obj, objNum); - } - - InitAnimating(obj, ID_LASERHEAD_BASE); - InitAnimating(obj, ID_LASERHEAD_TENTACLE); - - obj = &Objects[ID_TIGHT_ROPE]; - if (obj->loaded) - { - obj->Initialize = InitializeTightrope; - obj->collision = TightropeCollision; - obj->drawRoutine = nullptr; - - obj->usingDrawAnimatingItem = false; - } - - obj = &Objects[ID_PARALLEL_BARS]; - if (obj->loaded) - { - obj->collision = HorizontalBarCollision; - } - - obj = &Objects[ID_EARTHQUAKE]; - if (obj->loaded) - { - obj->drawRoutine = nullptr; - } - - obj = &Objects[ID_HIGH_OBJECT2]; - if (obj->loaded) - { - obj->drawRoutine = nullptr; - obj->control = HighObject2Control; - } - - obj = &Objects[ID_LENS_FLARE]; - if (obj->loaded) - { - //obj->drawRoutine = DrawLensFlare; - - } - - obj = &Objects[ID_WATERFALLMIST]; - if (obj->loaded) - { - obj->control = ControlWaterfallMist; - obj->drawRoutine = nullptr; - } - - for (int objNum = ID_WATERFALL1; objNum <= ID_WATERFALL6; objNum++) - { - obj = &Objects[objNum]; - if (obj->loaded) - { - obj->control = nullptr; - } - } - - obj = &Objects[ID_WATERFALLSS1]; - if (obj->loaded) - { - obj->control = nullptr; - } - - obj = &Objects[ID_WATERFALLSS2]; - if (obj->loaded) - { - obj->control = nullptr; - } - - for (int objNum = ID_SHOOT_SWITCH1; objNum <= ID_SHOOT_SWITCH4; objNum++) - { - obj = &Objects[objNum]; - if (obj->loaded) - { - obj->Initialize = InitializeShootSwitch; - obj->control = ControlAnimatingSlots; - obj->collision = ShootSwitchCollision; - } - } -} - -void TrapObjects() -{ - ObjectInfo* obj; - obj = &Objects[ID_KILL_ALL_TRIGGERS]; - if (obj->loaded) - { - obj->control = KillAllCurrentItems; - obj->drawRoutine = nullptr; - obj->HitPoints = 0; - obj->usingDrawAnimatingItem = false; - } - - obj = &Objects[ID_FALLING_BLOCK]; - if (obj->loaded) - { - obj->Initialize = InitializeFallingBlock; - obj->collision = FallingBlockCollision; - obj->control = FallingBlockControl; - obj->floor = FallingBlockFloor; - obj->ceiling = FallingBlockCeiling; - obj->floorBorder = FallingBlockFloorBorder; - obj->ceilingBorder = FallingBlockCeilingBorder; - } - - obj = &Objects[ID_FALLING_BLOCK2]; - if (obj->loaded) - { - obj->Initialize = InitializeFallingBlock; - obj->collision = FallingBlockCollision; - obj->control = FallingBlockControl; - obj->floor = FallingBlockFloor; - obj->ceiling = FallingBlockCeiling; - obj->floorBorder = FallingBlockFloorBorder; - obj->ceilingBorder = FallingBlockCeilingBorder; - } - - obj = &Objects[ID_GEN_SLOT2]; - if (obj->loaded) - { - /*obj->Initialize = InitializeGenSlot2; - obj->control = GenSlot2Control; - obj->drawRoutine = DrawGenSlot2;*/ - obj->usingDrawAnimatingItem = false; - } - - obj = &Objects[ID_PORTAL]; - if (obj->loaded) - { - //obj->Initialize = InitializePortal; - //obj->control = PortalControl; // TODO: found the control procedure ! - obj->drawRoutine = nullptr; // go to nullsub_44() ! - - obj->usingDrawAnimatingItem = false; - } - - obj = &Objects[ID_TRIGGER_TRIGGERER]; - if (obj->loaded) - { - obj->control = ControlTriggerTriggerer; - obj->drawRoutine = nullptr; - - obj->usingDrawAnimatingItem = false; - } - -} - void InitializeSpecialEffects() { memset(&FireSparks, 0, MAX_SPARKS_FIRE * sizeof(FIRE_SPARKS)); @@ -352,7 +103,6 @@ void InitializeObjects() obj->usingDrawAnimatingItem = true; obj->undead = false; obj->LotType = LotType::Basic; - obj->biteOffset = -1; obj->meshSwapSlot = NO_ITEM; obj->isPickup = false; obj->isPuzzleHole = false; @@ -365,8 +115,6 @@ void InitializeObjects() InitializeTR3Objects(); // Standard TR3 objects InitializeTR4Objects(); // Standard TR4 objects InitializeTR5Objects(); // Standard TR5 objects - ObjectObjects(); - TrapObjects(); // User defined objects CustomObjects(); diff --git a/TombEngine/Specific/setup.h b/TombEngine/Specific/setup.h index 77d7f1689..f6c59b984 100644 --- a/TombEngine/Specific/setup.h +++ b/TombEngine/Specific/setup.h @@ -1,10 +1,10 @@ #pragma once #include "Objects/objectslist.h" +#include "Game/control/box.h" #include "Math/Math.h" #include "Renderer/Renderer11Enums.h" #include "Specific/level.h" -enum class ZoneType; struct CollisionInfo; struct ItemInfo; @@ -23,7 +23,8 @@ enum class LotType Flyer, Blockable, // For large creatures such as trex and shiva. Spider, // Only 2 block vault allowed. - Ape // Only 2 block vault allowed. + Ape, // Only 2 block vault allowed. + SnowmobileGun // Only 1 block vault allowed and 4 block drop max. }; enum JointRotationFlags @@ -67,7 +68,6 @@ struct ObjectInfo int meshSwapSlot; int pivotLength; int radius; - int biteOffset; int HitPoints; bool intelligent; // IsIntelligent diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index b229fd0e1..689563b9d 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -635,6 +635,7 @@ CALL gen.bat + diff --git a/TombEngine/TombEngine_vs2022.vcxproj b/TombEngine/TombEngine_vs2022.vcxproj index bb92b1988..1a91755d1 100644 --- a/TombEngine/TombEngine_vs2022.vcxproj +++ b/TombEngine/TombEngine_vs2022.vcxproj @@ -634,6 +634,7 @@ CALL gen.bat + From e3e7b65b107f54022010a94005628b5f3cdb6e02 Mon Sep 17 00:00:00 2001 From: Kubsy Date: Fri, 28 Apr 2023 17:03:33 +0100 Subject: [PATCH 14/16] Update Changes.txt --- Documentation/Changes.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 7715a2e1c..ebce37511 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -18,8 +18,9 @@ Version 1.0.9 - Add missing gunflash for some entities, also include dynamic light and smoke to all gunflashes. - Add reusable keys for key holes - Employed by setting the trigger type as "Switch" for key hole. -- Allow Animation to be played by setting OCB to keyholes. - - +ve OCB will play the animation according to the OCB number. +- Allow key hole Animation to be played via OCB number. + - Default 0 OCB will play Lara use key animation. + - Any positive OCB number will play the animation according to the OCB number. - Add log reports if title level or other levels don't exist. Lua API changes: From 4d1a689e99db7f5d9397469eabec5bfd5559441f Mon Sep 17 00:00:00 2001 From: Kubsy Date: Fri, 28 Apr 2023 17:04:59 +0100 Subject: [PATCH 15/16] Update Changes.txt --- Documentation/Changes.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index ebce37511..2ec6bf579 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -5,8 +5,7 @@ Version 1.0.9 - Fix spiky wall speed value. - Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]). - Fix crash if little beetle does not exist in wad to load bats emitter. -- Fix gunflash rendering for entities. -- Fix all entities gunflash position. +- Fix gunflash rendering and position for entities. - Fix snowmobile driver crashing the game. - Fix knifethrower not throwing knife. - Add TR1 Cowboy. From 8305f79cf0443a5683a39bbfd901a5a537b2a2e5 Mon Sep 17 00:00:00 2001 From: Kubsy Date: Fri, 28 Apr 2023 22:12:44 +0100 Subject: [PATCH 16/16] Fix merge error --- TombEngine/Objects/TR1/Entity/Cowboy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Objects/TR1/Entity/Cowboy.cpp b/TombEngine/Objects/TR1/Entity/Cowboy.cpp index 1dd69fc15..003a8d474 100644 --- a/TombEngine/Objects/TR1/Entity/Cowboy.cpp +++ b/TombEngine/Objects/TR1/Entity/Cowboy.cpp @@ -18,8 +18,8 @@ namespace TEN::Entities::Creatures::TR1 constexpr auto COWBOY_WALK_TURN_RATE_MAX = ANGLE(3.0f); constexpr auto COWBOY_RUN_TURN_RATE_MAX = ANGLE(6.0f); - const auto CowboyGunLeft = BiteInfo(Vector3(1.0f, 200.0f, 40.0f), 5); - const auto CowboyGunRight = BiteInfo(Vector3(-1.0f, 200.0f, 40.0f), 8); + const auto CowboyGunLeft = CreatureBiteInfo(Vector3(1.0f, 200.0f, 40.0f), 5); + const auto CowboyGunRight = CreatureBiteInfo(Vector3(-1.0f, 200.0f, 40.0f), 8); enum CowboyState {