diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 50381e6fb..427498056 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -3,11 +3,11 @@ Version 1.0.3 * Add ledge jumps (Lara object must be updated with new animations to make it work). * Add FlipMap and PlayFlyBy script commands and node functions. +* Allow any object slot to be used as a meshswap. * Add FlyCheat option to gameflow script for disabling dozy mode. * Add SetNumberOfSecrets option to gameflow script to set overall amount of secrets. * Add OCB 1 for rollingball to make it silent. * Customize waterfall mist colour and OCB (XXYY, where XX is width, and YY is size). -* Backport SAS_DRAG_BLOKE from TR4. * Implement sprite instancing to speed up rendering. * Merge portals at runtime to speed up rendering. * Enable dynamic lights for swarm enemies (beetles, rats and bats). @@ -15,6 +15,8 @@ Version 1.0.3 * Increase amount of maximum secrets per level from 8 to 32. * Improve game and inventory input handling. * Adjust sprint jump timing. +* Fix going into inventory and load/save dialogs during fade-ins and fade-outs. +* Fix savegames not preserving save number and game timer. * Fix dodgy weapon lock angle constraints. * Fix wrong shotgun ammo pickup amount. * Fix shotgun using 6 units of ammo with each shot. @@ -28,6 +30,7 @@ Version 1.0.3 * Fix slow centaur projectile velocity. * Fix search animations - allow chest and shelf animations to play properly. * Fix sarcophagus and its item pickup. +* Fix SAS_DRAG_BLOKE object interaction. * Fix underwater door and double doors continuing to be interactable after opening. * Fix underwater door being interactable when underwater switch is on the same square. * Fix ability to turn when aligning to an object while standing. @@ -35,6 +38,7 @@ Version 1.0.3 * Fix potential crashes when exiting game. * Fix secret soundtrack (which filename number should be the last) not playing. * Fix distance fog not applying properly to additive and subtractive surfaces. +* Fix swarm enemies and projectiles occasionally drawn using incorrect meshes. * Fix single-hand weapons not having a sound on draw and undraw. * Fix waterfall mist - it can now be disabled with antitrigger. * Fix underwater lever pull animation playing after interacting with underwater ceiling switch. diff --git a/TombEngine/Game/Lara/lara_fire.cpp b/TombEngine/Game/Lara/lara_fire.cpp index d531cd984..c382355dd 100644 --- a/TombEngine/Game/Lara/lara_fire.cpp +++ b/TombEngine/Game/Lara/lara_fire.cpp @@ -641,7 +641,7 @@ void HandleWeapon(ItemInfo* laraItem) break; case HandStatus::WeaponUndraw: - lara->MeshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD; + laraItem->Model.MeshIndex[LM_HEAD] = laraItem->Model.BaseMesh + LM_HEAD; switch (lara->Control.Weapon.GunType) { @@ -672,9 +672,9 @@ void HandleWeapon(ItemInfo* laraItem) case HandStatus::WeaponReady: if (!(TrInput & IN_ACTION)) - lara->MeshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD; + laraItem->Model.MeshIndex[LM_HEAD] = laraItem->Model.BaseMesh + LM_HEAD; else - lara->MeshPtrs[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD; + laraItem->Model.MeshIndex[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD; if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy) @@ -747,7 +747,7 @@ void HandleWeapon(ItemInfo* laraItem) case HandStatus::Busy: if (lara->Control.Weapon.GunType == LaraWeaponType::Flare) { - if (lara->MeshPtrs[LM_LHAND] == Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND) + if (laraItem->Model.MeshIndex[LM_LHAND] == Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND) { lara->Flare.ControlLeft = (lara->Vehicle != NO_ITEM || TestState(laraItem->Animation.ActiveState, FlarePoseStates)); DoFlareInHand(laraItem, lara->Flare.Life); @@ -1148,10 +1148,10 @@ void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, i } } - if (!targetEntity->LuaCallbackOnHitName.empty()) + if (!targetEntity->Callbacks.OnHit.empty()) { - short index = g_GameScriptEntities->GetIndexByName(targetEntity->LuaName); - g_GameScript->ExecuteFunction(targetEntity->LuaCallbackOnHitName, index); + short index = g_GameScriptEntities->GetIndexByName(targetEntity->Name); + g_GameScript->ExecuteFunction(targetEntity->Callbacks.OnHit, index); } } diff --git a/TombEngine/Game/Lara/lara_flare.cpp b/TombEngine/Game/Lara/lara_flare.cpp index a96578c7b..2d0f1f1cc 100644 --- a/TombEngine/Game/Lara/lara_flare.cpp +++ b/TombEngine/Game/Lara/lara_flare.cpp @@ -100,14 +100,14 @@ void UndrawFlareMeshes(ItemInfo* laraItem) { auto* lara = GetLaraInfo(laraItem); - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; } void DrawFlareMeshes(ItemInfo* laraItem) { auto* lara = GetLaraInfo(laraItem); - lara->MeshPtrs[LM_LHAND] = Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND; } void UndrawFlare(ItemInfo* laraItem) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 0894d3ba5..296613933 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -99,12 +99,11 @@ void InitialiseLaraMeshes(ItemInfo* item) { auto* lara = GetLaraInfo(item); + // Override base mesh and mesh indices to Lara skin. + + item->Model.BaseMesh = Objects[ID_LARA_SKIN].meshIndex; for (int i = 0; i < NUM_LARA_MESHES; i++) - { - //Meshes[i] = Meshes[MESHES(ID_LARA_SKIN, i)]; - //LARA_MESHES(ID_LARA, MESHES(ID_LARA_SKIN, i)); - lara->MeshPtrs[i] = Objects[ID_LARA_SKIN].meshIndex + i; - } + item->Model.MeshIndex[i] = item->Model.BaseMesh + i; /* Hardcoded code */ diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index 01310a2f7..d3235e99d 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -430,14 +430,14 @@ void DrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType) auto* lara = GetLaraInfo(laraItem); lara->Control.Weapon.HolsterInfo.BackHolster = HolsterSlot::Empty; - lara->MeshPtrs[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND; } void UndrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType) { auto* lara = GetLaraInfo(laraItem); - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; if (lara->Weapons[(int)weaponType].Present) lara->Control.Weapon.HolsterInfo.BackHolster = GetWeaponHolsterSlot(weaponType); diff --git a/TombEngine/Game/Lara/lara_struct.h b/TombEngine/Game/Lara/lara_struct.h index 7c34c3b85..913e71d0f 100644 --- a/TombEngine/Game/Lara/lara_struct.h +++ b/TombEngine/Game/Lara/lara_struct.h @@ -1300,7 +1300,6 @@ struct LaraInfo bool BurnSmoke; byte Wet[NUM_LARA_MESHES]; - int MeshPtrs[NUM_LARA_MESHES]; signed char Location; signed char HighestLocation; signed char LocationPad; diff --git a/TombEngine/Game/Lara/lara_two_guns.cpp b/TombEngine/Game/Lara/lara_two_guns.cpp index a57bfc9ea..ed418027f 100644 --- a/TombEngine/Game/Lara/lara_two_guns.cpp +++ b/TombEngine/Game/Lara/lara_two_guns.cpp @@ -480,16 +480,16 @@ void DrawPistolMeshes(ItemInfo* laraItem, LaraWeaponType weaponType) lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty; - lara->MeshPtrs[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND; if (weaponType != LaraWeaponType::Revolver) - lara->MeshPtrs[LM_LHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_LHAND; } void UndrawPistolMeshRight(ItemInfo* laraItem, LaraWeaponType weaponType) { auto* lara = GetLaraInfo(laraItem); - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; if (lara->Weapons[(int)weaponType].Present) lara->Control.Weapon.HolsterInfo.RightHolster = GetWeaponHolsterSlot(weaponType); else @@ -502,7 +502,7 @@ void UndrawPistolMeshLeft(ItemInfo* laraItem, LaraWeaponType weaponType) if (weaponType != LaraWeaponType::Revolver) { - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; if (lara->Weapons[(int)weaponType].Present) lara->Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(weaponType); diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 6d82c4d24..77eb24f7a 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -115,8 +115,12 @@ void PerformAnimCommands(ItemInfo* item, bool isFrameBased) if (!isFrameBased) { TranslateItem(item, item->Pose.Orientation.y, commandPtr[2], commandPtr[1], commandPtr[0]); - auto bounds = GameBoundingBox(item); - UpdateItemRoom(item, -bounds.GetHeight() / 2, -commandPtr[0], -commandPtr[2]); + + if (item->IsLara()) + { + auto bounds = GameBoundingBox(item); + UpdateItemRoom(item, -bounds.GetHeight() / 2, -commandPtr[0], -commandPtr[2]); + } } commandPtr += 3; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e3f8f8502..0600fd176 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -135,7 +135,7 @@ GameStatus ControlPhase(int numFrames, bool demoMode) // which assumes 30 iterations per second. g_GameScript->OnControlPhase(DELTA_TIME); - if (CurrentLevel != 0) + if (CurrentLevel != 0 && !ScreenFading) { // Does the player want to enter inventory? if (IsClicked(In::Save) && LaraItem->HitPoints > 0 && @@ -161,7 +161,7 @@ GameStatus ControlPhase(int numFrames, bool demoMode) return GameStatus::LoadGame; } else if (IsClicked(In::Pause) && LaraItem->HitPoints > 0 && - g_Gui.GetInventoryMode() != InventoryMode::Pause) + g_Gui.GetInventoryMode() != InventoryMode::Pause) { StopAllSounds(); StopRumble(); diff --git a/TombEngine/Game/control/flipeffect.cpp b/TombEngine/Game/control/flipeffect.cpp index 2a1e860a0..23fa488f9 100644 --- a/TombEngine/Game/control/flipeffect.cpp +++ b/TombEngine/Game/control/flipeffect.cpp @@ -99,14 +99,14 @@ void MeshSwapToPour(ItemInfo* item) { auto* lara = GetLaraInfo(item); - lara->MeshPtrs[LM_LHAND] = Objects[item->ItemFlags[2]].meshIndex + LM_LHAND; + item->Model.MeshIndex[LM_LHAND] = Objects[item->ItemFlags[2]].meshIndex + LM_LHAND; } void MeshSwapFromPour(ItemInfo* item) { auto* lara = GetLaraInfo(item); - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + item->Model.MeshIndex[LM_LHAND] = item->Model.BaseMesh + LM_LHAND; } void Pickup(ItemInfo* item) @@ -153,14 +153,14 @@ void DrawLeftPistol(ItemInfo* item) { auto* lara = GetLaraInfo(item); - if (lara->MeshPtrs[LM_LHAND] == Objects[ID_LARA_SKIN].meshIndex + LM_LHAND) + if (item->Model.MeshIndex[LM_LHAND] == item->Model.BaseMesh + LM_LHAND) { - lara->MeshPtrs[LM_LHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_LHAND; + item->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_LHAND; lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty; } else { - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + item->Model.MeshIndex[LM_LHAND] = item->Model.BaseMesh + LM_LHAND; lara->Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); } } @@ -169,14 +169,14 @@ void DrawRightPistol(ItemInfo* item) { auto* lara = GetLaraInfo(item); - if (lara->MeshPtrs[LM_RHAND] == Objects[ID_LARA_SKIN].meshIndex + LM_RHAND) + if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND) { - lara->MeshPtrs[LM_RHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_RHAND; + item->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_RHAND; lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty; } else { - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + item->Model.MeshIndex[LM_RHAND] = item->Model.BaseMesh + LM_RHAND; lara->Control.Weapon.HolsterInfo.RightHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); } } @@ -263,10 +263,10 @@ void SwapCrowbar(ItemInfo* item) { auto* lara = GetLaraInfo(item); - if (lara->MeshPtrs[LM_RHAND] == Objects[ID_LARA_SKIN].meshIndex + LM_RHAND) - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_CROWBAR_ANIM].meshIndex + LM_RHAND; + if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND) + item->Model.MeshIndex[LM_RHAND] = Objects[ID_LARA_CROWBAR_ANIM].meshIndex + LM_RHAND; else - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + item->Model.MeshIndex[LM_RHAND] = item->Model.BaseMesh + LM_RHAND; } void ActivateKey(ItemInfo* item) diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index c964755e5..60db0cb41 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -191,10 +191,10 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo DoDamage(item, Weapons[(int)Lara.Control.Weapon.GunType].Damage); - if (!item->LuaCallbackOnHitName.empty()) + if (!item->Callbacks.OnHit.empty()) { - short index = g_GameScriptEntities->GetIndexByName(item->LuaName); - g_GameScript->ExecuteFunction(item->LuaCallbackOnHitName, index); + short index = g_GameScriptEntities->GetIndexByName(item->Name); + g_GameScript->ExecuteFunction(item->Callbacks.OnHit, index); } } } diff --git a/TombEngine/Game/control/volume.cpp b/TombEngine/Game/control/volume.cpp index dea98a9ff..2cf8e658d 100644 --- a/TombEngine/Game/control/volume.cpp +++ b/TombEngine/Game/control/volume.cpp @@ -154,7 +154,7 @@ namespace TEN::Control::Volumes else if (Objects[item->ObjectNumber].intelligent) TestVolumes(item->RoomNumber, bBox, TriggerVolumeActivators::NPC, itemNumber); else - TestVolumes(item->RoomNumber, bBox, TriggerVolumeActivators::Movable, itemNumber); + TestVolumes(item->RoomNumber, bBox, TriggerVolumeActivators::Moveable, itemNumber); } void InitialiseNodeScripts() diff --git a/TombEngine/Game/control/volume.h b/TombEngine/Game/control/volume.h index 5cabe9baf..079ba5327 100644 --- a/TombEngine/Game/control/volume.h +++ b/TombEngine/Game/control/volume.h @@ -29,7 +29,7 @@ enum TriggerVolumeActivators { Player = 1, NPC = 2, - Movable = 4, + Moveable = 4, Static = 8, Flyby = 16, PhysicalObject = 32 // Future-proofing for Bullet. @@ -38,7 +38,7 @@ enum TriggerVolumeActivators struct TriggerVolume { TriggerVolumeType Type; - std::string LuaName; + std::string Name = ""; int EventSetIndex; Vector3 Position; diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 518d416b3..5658d2c66 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -107,14 +107,14 @@ void HairControl(ItemInfo* item, int ponytail, AnimFrame* framePtr) frame = framePtr; // Get Lara's spheres in absolute coordinates for head, torso, hips, and upper arms. - auto* mesh = &g_Level.Meshes[lara->MeshPtrs[LM_HIPS]]; + auto* mesh = &g_Level.Meshes[item->Model.MeshIndex[LM_HIPS]]; auto pos = GetJointPosition(item, LM_HIPS, Vector3i(mesh->sphere.Center.x, mesh->sphere.Center.y, mesh->sphere.Center.z)); sphere[0].x = pos.x; sphere[0].y = pos.y; sphere[0].z = pos.z; sphere[0].r = (int)mesh->sphere.Radius; - mesh = &g_Level.Meshes[lara->MeshPtrs[LM_TORSO]]; + mesh = &g_Level.Meshes[item->Model.MeshIndex[LM_TORSO]]; pos = GetJointPosition(item, LM_TORSO, Vector3i(mesh->sphere.Center.x - 10, mesh->sphere.Center.y, mesh->sphere.Center.z + 25)); sphere[1].x = pos.x; sphere[1].y = pos.y; @@ -123,21 +123,21 @@ void HairControl(ItemInfo* item, int ponytail, AnimFrame* framePtr) if (youngLara) sphere[1].r = sphere[1].r - ((sphere[1].r >> 2) + (sphere[1].r >> 3)); - mesh = &g_Level.Meshes[lara->MeshPtrs[LM_HEAD]]; + mesh = &g_Level.Meshes[item->Model.MeshIndex[LM_HEAD]]; pos = GetJointPosition(item, LM_HEAD, Vector3i(mesh->sphere.Center.x - 2, mesh->sphere.Center.y, mesh->sphere.Center.z)); sphere[2].x = pos.x; sphere[2].y = pos.y; sphere[2].z = pos.z; sphere[2].r = (int)mesh->sphere.Radius; - mesh = &g_Level.Meshes[lara->MeshPtrs[LM_RINARM]]; + mesh = &g_Level.Meshes[item->Model.MeshIndex[LM_RINARM]]; pos = GetJointPosition(item, LM_RINARM, Vector3i(mesh->sphere.Center.x, mesh->sphere.Center.y, mesh->sphere.Center.z)); sphere[3].x = pos.x; sphere[3].y = pos.y; sphere[3].z = pos.z; sphere[3].r = int(4.0f * mesh->sphere.Radius / 3.0f); // Resizing sphere - from tomb5 - mesh = &g_Level.Meshes[lara->MeshPtrs[LM_LINARM]]; + mesh = &g_Level.Meshes[item->Model.MeshIndex[LM_LINARM]]; pos = GetJointPosition(item, LM_LINARM, Vector3i(mesh->sphere.Center.x, mesh->sphere.Center.y, mesh->sphere.Center.z)); sphere[4].x = pos.x; sphere[4].y = pos.y; diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 21794c34a..43eb3192c 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -48,6 +48,54 @@ void ItemInfo::SetFlags(short id, short value) ItemFlags[id] = value; } +bool ItemInfo::TestMeshSwapFlags(unsigned int flags) +{ + for (size_t i = 0; i < Model.MeshIndex.size(); i++) + { + if (flags & (1 << i)) + { + if (Model.MeshIndex[i] == Model.BaseMesh + i) + return false; + } + } + + return true; +} + +bool ItemInfo::TestMeshSwapFlags(const std::vector flags) +{ + BitField bits = {}; + bits.Set(flags); + return TestMeshSwapFlags(bits.ToPackedBits()); +} + +void ItemInfo::SetMeshSwapFlags(unsigned int flags, bool clear) +{ + bool meshSwapPresent = Objects[ObjectNumber].meshSwapSlot != -1 && + Objects[Objects[ObjectNumber].meshSwapSlot].loaded; + + + for (size_t i = 0; i < Model.MeshIndex.size(); i++) + { + if (meshSwapPresent && (flags & (1 << i))) + { + if (clear) + Model.MeshIndex[i] = Model.BaseMesh + i; + else + Model.MeshIndex[i] = Objects[Objects[ObjectNumber].meshSwapSlot].meshIndex + i; + } + else + Model.MeshIndex[i] = Model.BaseMesh + i; + } +} + +void ItemInfo::SetMeshSwapFlags(const std::vector flags, bool clear) +{ + BitField bits = {}; + bits.Set(flags); + SetMeshSwapFlags(bits.ToPackedBits(), clear); +} + bool ItemInfo::IsLara() { return this->Data.is(); @@ -133,14 +181,14 @@ void KillItem(short const itemNumber) g_GameScriptEntities->NotifyKilled(item); g_GameScriptEntities->TryRemoveColliding(itemNumber, true); - if (!item->LuaCallbackOnKilledName.empty()) - g_GameScript->ExecuteFunction(item->LuaCallbackOnKilledName, itemNumber); + if (!item->Callbacks.OnKilled.empty()) + g_GameScript->ExecuteFunction(item->Callbacks.OnKilled, itemNumber); - item->LuaName.clear(); - item->LuaCallbackOnKilledName.clear(); - item->LuaCallbackOnHitName.clear(); - item->LuaCallbackOnCollidedWithObjectName.clear(); - item->LuaCallbackOnCollidedWithRoomName.clear(); + item->Name.clear(); + item->Callbacks.OnKilled.clear(); + item->Callbacks.OnHit.clear(); + item->Callbacks.OnObjectCollided.clear(); + item->Callbacks.OnRoomCollided.clear(); if (itemNumber >= g_Level.NumItems) { @@ -385,9 +433,9 @@ void RemoveActiveItem(short itemNumber) } g_GameScriptEntities->NotifyKilled(&item); - if (!item.LuaCallbackOnKilledName.empty()) + if (!item.Callbacks.OnKilled.empty()) { - g_GameScript->ExecuteFunction(item.LuaCallbackOnKilledName, itemNumber); + g_GameScript->ExecuteFunction(item.Callbacks.OnKilled, itemNumber); } } } @@ -434,7 +482,6 @@ void InitialiseItem(short itemNumber) item->TouchBits = NO_JOINT_BITS; item->AfterDeath = 0; - item->MeshSwapBits = NO_JOINT_BITS; if (item->Flags & IFLAG_INVISIBLE) { @@ -463,14 +510,23 @@ void InitialiseItem(short itemNumber) if (Objects[item->ObjectNumber].nmeshes > 0) { - item->Animation.Mutator.resize(Objects[item->ObjectNumber].nmeshes); - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i] = {}; + item->Model.BaseMesh = Objects[item->ObjectNumber].meshIndex; + + item->Model.MeshIndex.resize(Objects[item->ObjectNumber].nmeshes); + for (int i = 0; i < item->Model.MeshIndex.size(); i++) + item->Model.MeshIndex[i] = item->Model.BaseMesh + i; + + item->Model.Mutator.resize(Objects[item->ObjectNumber].nmeshes); + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i] = {}; } else - item->Animation.Mutator.clear(); + { + item->Model.Mutator.clear(); + item->Model.MeshIndex.clear(); + } - if (Objects[item->ObjectNumber].initialise != NULL) + if (Objects[item->ObjectNumber].initialise != nullptr) Objects[item->ObjectNumber].initialise(itemNumber); } diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index a398a3183..52e285dac 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -66,13 +66,28 @@ struct EntityAnimationData bool IsAirborne = false; Vector3 Velocity = Vector3::Zero; // CONVENTION: +X = right, +Y = down, +Z = forward +}; + +struct EntityModelData +{ + int BaseMesh; + std::vector MeshIndex = {}; std::vector Mutator = {}; }; +struct EntityCallbackData +{ + std::string OnKilled; + std::string OnHit; + std::string OnObjectCollided; + std::string OnRoomCollided; +}; + //todo we need to find good "default states" for a lot of these - squidshire 25/05/2022 struct ItemInfo { GAME_OBJECT_ID ObjectNumber; + std::string Name; int Status; // ItemStatus enum. bool Active; @@ -83,6 +98,9 @@ struct ItemInfo ITEM_DATA Data; EntityAnimationData Animation; + EntityCallbackData Callbacks; + EntityModelData Model; + Pose StartPose; Pose Pose; ROOM_VECTOR Location; @@ -101,7 +119,6 @@ struct ItemInfo BitField TouchBits = BitField(); BitField MeshBits = BitField(); - BitField MeshSwapBits = BitField(); unsigned short Flags; // ItemFlags enum short ItemFlags[8]; @@ -112,13 +129,6 @@ struct ItemInfo short AfterDeath; short CarriedItem; - // Lua - std::string LuaName; - std::string LuaCallbackOnKilledName; - std::string LuaCallbackOnHitName; - std::string LuaCallbackOnCollidedWithObjectName; - std::string LuaCallbackOnCollidedWithRoomName; - bool TestOcb(short ocbFlags); void RemoveOcb(short ocbFlags); void ClearAllOcb(); @@ -126,6 +136,11 @@ struct ItemInfo bool TestFlags(short id, short value); void SetFlags(short id, short value); + bool TestMeshSwapFlags(unsigned int flags); + bool TestMeshSwapFlags(const std::vector flags); + void SetMeshSwapFlags(unsigned int flags, bool clear = false); + void SetMeshSwapFlags(const std::vector flags, bool clear = false); + bool IsLara(); bool IsCreature(); }; diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index d9aae3680..f672b0869 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -928,7 +928,7 @@ void InitialiseSearchObject(short itemNumber) auto* item = &g_Level.Items[itemNumber]; if (item->ObjectNumber == ID_SEARCH_OBJECT1) { - item->MeshSwapBits = ALL_JOINT_BITS; + item->SetMeshSwapFlags(ALL_JOINT_BITS); item->MeshBits = 7; } else if (item->ObjectNumber == ID_SEARCH_OBJECT2) @@ -1044,12 +1044,12 @@ void SearchObjectControl(short itemNumber) { if (frameNumber > 0) { - item->MeshSwapBits = NO_JOINT_BITS; + item->SetMeshSwapFlags(NO_JOINT_BITS); item->MeshBits = ALL_JOINT_BITS; } else { - item->MeshSwapBits = ALL_JOINT_BITS; + item->SetMeshSwapFlags(ALL_JOINT_BITS); item->MeshBits = 7; } } diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index f04c2b52c..e108587fb 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -228,11 +228,6 @@ bool SaveGame::Save(int slot) examinesCombo.push_back(Lara.Inventory.ExaminesCombo[i]); auto examinesComboOffset = fbb.CreateVector(examinesCombo); - std::vector meshPtrs; - for (int i = 0; i < 15; i++) - meshPtrs.push_back(Lara.MeshPtrs[i]); - auto meshPtrsOffset = fbb.CreateVector(meshPtrs); - std::vector wet; for (int i = 0; i < 15; i++) wet.push_back(Lara.Wet[i] == 1); @@ -440,7 +435,6 @@ bool SaveGame::Save(int slot) lara.add_left_arm(leftArmOffset); lara.add_location(Lara.Location); lara.add_location_pad(Lara.LocationPad); - lara.add_mesh_ptrs(meshPtrsOffset); lara.add_poison_potency(Lara.PoisonPotency); lara.add_projected_floor_height(Lara.ProjectedFloorHeight); lara.add_right_arm(rightArmOffset); @@ -462,16 +456,21 @@ bool SaveGame::Save(int slot) { ObjectInfo* obj = &Objects[itemToSerialize.ObjectNumber]; - auto luaNameOffset = fbb.CreateString(itemToSerialize.LuaName); - auto luaOnKilledNameOffset = fbb.CreateString(itemToSerialize.LuaCallbackOnKilledName); - auto luaOnHitNameOffset = fbb.CreateString(itemToSerialize.LuaCallbackOnHitName); - auto luaOnCollidedObjectNameOffset = fbb.CreateString(itemToSerialize.LuaCallbackOnCollidedWithObjectName); - auto luaOnCollidedRoomNameOffset = fbb.CreateString(itemToSerialize.LuaCallbackOnCollidedWithRoomName); + auto luaNameOffset = fbb.CreateString(itemToSerialize.Name); + auto luaOnKilledNameOffset = fbb.CreateString(itemToSerialize.Callbacks.OnKilled); + auto luaOnHitNameOffset = fbb.CreateString(itemToSerialize.Callbacks.OnHit); + auto luaOnCollidedObjectNameOffset = fbb.CreateString(itemToSerialize.Callbacks.OnObjectCollided); + auto luaOnCollidedRoomNameOffset = fbb.CreateString(itemToSerialize.Callbacks.OnRoomCollided); std::vector itemFlags; for (int i = 0; i < 7; i++) itemFlags.push_back(itemToSerialize.ItemFlags[i]); auto itemFlagsOffset = fbb.CreateVector(itemFlags); + + std::vector meshPointers; + for (auto p : itemToSerialize.Model.MeshIndex) + meshPointers.push_back(p); + auto meshPointerOffset = fbb.CreateVector(meshPointers); flatbuffers::Offset creatureOffset; flatbuffers::Offset quadOffset; @@ -628,6 +627,8 @@ bool SaveGame::Save(int slot) serializedItem.add_hit_points(itemToSerialize.HitPoints); serializedItem.add_item_flags(itemFlagsOffset); serializedItem.add_mesh_bits(itemToSerialize.MeshBits.ToPackedBits()); + serializedItem.add_mesh_pointers(meshPointerOffset); + serializedItem.add_base_mesh(itemToSerialize.Model.BaseMesh); serializedItem.add_object_id(itemToSerialize.ObjectNumber); serializedItem.add_pose(&FromPHD(itemToSerialize.Pose)); serializedItem.add_required_state(itemToSerialize.Animation.RequiredState); @@ -645,7 +646,6 @@ bool SaveGame::Save(int slot) serializedItem.add_ai_bits(itemToSerialize.AIBits); serializedItem.add_collidable(itemToSerialize.Collidable); serializedItem.add_looked_at(itemToSerialize.LookedAt); - serializedItem.add_swap_mesh_flags(itemToSerialize.MeshSwapBits.ToPackedBits()); if (Objects[itemToSerialize.ObjectNumber].intelligent && itemToSerialize.Data.is()) @@ -1195,6 +1195,9 @@ bool SaveGame::Load(int slot) const Save::SaveGame* s = Save::GetSaveGame(buffer.get()); // Statistics + LastSaveGame = s->header()->count(); + GameTimer = s->header()->timer(); + Statistics.Game.AmmoHits = s->game()->ammo_hits(); Statistics.Game.AmmoUsed = s->game()->ammo_used(); Statistics.Game.Distance = s->game()->distance(); @@ -1325,14 +1328,14 @@ bool SaveGame::Load(int slot) ObjectInfo* obj = &Objects[item->ObjectNumber]; - item->LuaName = savedItem->lua_name()->str(); - if (!item->LuaName.empty()) - g_GameScriptEntities->AddName(item->LuaName, i); + item->Name = savedItem->lua_name()->str(); + if (!item->Name.empty()) + g_GameScriptEntities->AddName(item->Name, i); - item->LuaCallbackOnKilledName = savedItem->lua_on_killed_name()->str(); - item->LuaCallbackOnHitName = savedItem->lua_on_hit_name()->str(); - item->LuaCallbackOnCollidedWithObjectName = savedItem->lua_on_collided_with_object_name()->str(); - item->LuaCallbackOnCollidedWithRoomName = savedItem->lua_on_collided_with_room_name()->str(); + item->Callbacks.OnKilled = savedItem->lua_on_killed_name()->str(); + item->Callbacks.OnHit = savedItem->lua_on_hit_name()->str(); + item->Callbacks.OnObjectCollided = savedItem->lua_on_collided_with_object_name()->str(); + item->Callbacks.OnRoomCollided = savedItem->lua_on_collided_with_room_name()->str(); g_GameScriptEntities->TryAddColliding(i); @@ -1388,7 +1391,10 @@ bool SaveGame::Load(int slot) // Mesh stuff item->MeshBits = savedItem->mesh_bits(); - item->MeshSwapBits = savedItem->swap_mesh_flags(); + + item->Model.BaseMesh = savedItem->base_mesh(); + for (int j = 0; j < savedItem->mesh_pointers()->size(); j++) + item->Model.MeshIndex[j] = savedItem->mesh_pointers()->Get(j); if (item->ObjectNumber >= ID_SMASH_OBJECT1 && item->ObjectNumber <= ID_SMASH_OBJECT8 && (item->Flags & ONESHOT)) @@ -1702,11 +1708,6 @@ bool SaveGame::Load(int slot) Lara.Inventory.ExaminesCombo[i] = s->lara()->inventory()->examines_combo()->Get(i); } - for (int i = 0; i < s->lara()->mesh_ptrs()->size(); i++) - { - Lara.MeshPtrs[i] = s->lara()->mesh_ptrs()->Get(i); - } - for (int i = 0; i < NUM_LARA_MESHES; i++) { Lara.Wet[i] = s->lara()->wet()->Get(i); diff --git a/TombEngine/Objects/Generic/Object/burning_torch.cpp b/TombEngine/Objects/Generic/Object/burning_torch.cpp index 9f17d3b0c..a823a6776 100644 --- a/TombEngine/Objects/Generic/Object/burning_torch.cpp +++ b/TombEngine/Objects/Generic/Object/burning_torch.cpp @@ -129,7 +129,7 @@ namespace TEN::Entities::Generic } else if (lara->LeftArm.FrameNumber == 12) { - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; CreateFlare(laraItem, ID_BURNING_TORCH_ITEM, true); } } @@ -149,7 +149,7 @@ namespace TEN::Entities::Generic } else if (lara->LeftArm.FrameNumber == 36) { - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; CreateFlare(laraItem, ID_BURNING_TORCH_ITEM, false); } } @@ -200,7 +200,7 @@ namespace TEN::Entities::Generic lara->LeftArm.FrameNumber = 0; lara->LeftArm.FrameBase = g_Level.Anims[lara->LeftArm.AnimNumber].FramePtr; - lara->MeshPtrs[LM_LHAND] = Objects[ID_LARA_TORCH_ANIM].meshIndex + LM_LHAND; + laraItem->Model.MeshIndex[LM_LHAND] = Objects[ID_LARA_TORCH_ANIM].meshIndex + LM_LHAND; } void TorchControl(short itemNumber) diff --git a/TombEngine/Objects/Generic/Traps/falling_block.cpp b/TombEngine/Objects/Generic/Traps/falling_block.cpp index 1df87068b..cb429654a 100644 --- a/TombEngine/Objects/Generic/Traps/falling_block.cpp +++ b/TombEngine/Objects/Generic/Traps/falling_block.cpp @@ -32,8 +32,8 @@ void InitialiseFallingBlock(short itemNumber) TEN::Floordata::UpdateBridgeItem(itemNumber); // Set mutators to 0 by default - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Rotation = Vector3::Zero; + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Rotation = Vector3::Zero; } void FallingBlockCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) @@ -70,23 +70,23 @@ void FallingBlockControl(short itemNumber) if (item->ItemFlags[0] < FALLINGBLOCK_DELAY) { // Subtly shake all meshes separately. - for (int i = 0; i < item->Animation.Mutator.size(); i++) + for (int i = 0; i < item->Model.Mutator.size(); i++) { - item->Animation.Mutator[i].Rotation.x = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); - item->Animation.Mutator[i].Rotation.y = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); - item->Animation.Mutator[i].Rotation.z = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); + item->Model.Mutator[i].Rotation.x = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); + item->Model.Mutator[i].Rotation.y = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); + item->Model.Mutator[i].Rotation.z = RADIAN * GenerateFloat(-FALLINGBLOCK_WIBBLE, FALLINGBLOCK_WIBBLE); } } else { // Make rotational falling movement with some random seed. - for (int i = 0; i < item->Animation.Mutator.size(); i++) + for (int i = 0; i < item->Model.Mutator.size(); i++) { auto rotSpeed = i % 2 ? FALLINGBLOCK_FALL_ROTATION_SPEED : -FALLINGBLOCK_FALL_ROTATION_SPEED; rotSpeed += i % 3 ? rotSpeed / 2 : rotSpeed; - item->Animation.Mutator[i].Rotation.x += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); - item->Animation.Mutator[i].Rotation.y += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); - item->Animation.Mutator[i].Rotation.z += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); + item->Model.Mutator[i].Rotation.x += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); + item->Model.Mutator[i].Rotation.y += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); + item->Model.Mutator[i].Rotation.z += RADIAN * rotSpeed + (RADIAN * GenerateFloat(-1, 1)); } if (item->ItemFlags[0] == FALLINGBLOCK_DELAY) diff --git a/TombEngine/Objects/Sink.h b/TombEngine/Objects/Sink.h index 638b46a0e..b3ea420ea 100644 --- a/TombEngine/Objects/Sink.h +++ b/TombEngine/Objects/Sink.h @@ -11,7 +11,7 @@ struct SinkInfo Vector3i Position = Vector3i::Zero; int Strength = 0; int BoxIndex = 0; - string LuaName = ""; + string Name = ""; SinkInfo() { diff --git a/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp b/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp index 410ddb389..7c668bb84 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_dragon.cpp @@ -213,7 +213,7 @@ namespace TEN::Entities::Creatures::TR2 Lara.Control.HandStatus = HandStatus::Busy; Lara.HitDirection = -1; - Lara.MeshPtrs[LM_RHAND] = Objects[ID_LARA_EXTRA_ANIMS].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_LARA_EXTRA_ANIMS].meshIndex + LM_RHAND; ((CreatureInfo*)g_Level.Items[(short)item->Data].Data)->Flags = -1; diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 016a298f3..5ff301cc7 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -1027,7 +1027,7 @@ namespace TEN::Entities::Vehicles !(kayak->Flags & 0x80)) { kayak->Flags |= 0x80; - lara->MeshPtrs[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND; laraItem->MeshBits.Clear(KayakLaraLegJoints); } @@ -1039,7 +1039,7 @@ namespace TEN::Entities::Vehicles kayak->Flags & 0x80) { kayak->Flags &= ~0x80; - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; laraItem->MeshBits.Set(KayakLaraLegJoints); } diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index 2b4571b16..e508b4338 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -741,7 +741,7 @@ namespace TEN::Entities::Vehicles if (laraItem->Animation.FrameNumber == GetFrameNumber(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME) && minecart->Flags & MINECART_FLAG_WRENCH_MESH) { - lara->MeshPtrs[LM_RHAND] = Objects[ID_LARA_SKIN].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH; } @@ -790,7 +790,7 @@ namespace TEN::Entities::Vehicles if (!(minecart->Flags & MINECART_FLAG_WRENCH_MESH) && laraItem->Animation.FrameNumber == GetFrameNumber(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME)) { - lara->MeshPtrs[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; + laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; minecart->Flags |= MINECART_FLAG_WRENCH_MESH; } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index 65c474e75..6bb3cd697 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -216,13 +216,13 @@ namespace TEN::Entities::TR4 if (item->ObjectNumber == ID_BADDY1) { - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_GUN; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN); item->MeshBits = 0xFF81FFFF; item->ItemFlags[2] = BADDY_USE_UZI; } else { - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_SWORD_NINJA; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_NINJA); item->MeshBits = ALL_JOINT_BITS; item->ItemFlags[2] = 0; } @@ -645,7 +645,7 @@ namespace TEN::Entities::TR4 break; } - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_SWORD_NINJA && + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_NINJA) && item == Lara.TargetEntity && laraAI.ahead && laraAI.distance > pow(682, 2)) @@ -656,13 +656,14 @@ namespace TEN::Entities::TR4 if (Targetable(item, &AI) && item->ItemFlags[2] > 0) { - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_GUN) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN)) { item->Animation.TargetState = BADDY_STATE_AIM; break; } - if (item->MeshSwapBits != MESHSWAPFLAGS_BADDY_SWORD_SIMPLE && item->MeshSwapBits != MESHSWAPFLAGS_BADDY_SWORD_NINJA) + if (!item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_SIMPLE) && + !item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_NINJA)) { item->Animation.TargetState = BADDY_STATE_DRAW_GUN; break; @@ -711,7 +712,7 @@ namespace TEN::Entities::TR4 } } - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_GUN && item->ItemFlags[2] < 1) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN) && item->ItemFlags[2] < 1) { item->Animation.TargetState = BADDY_STATE_HOLSTER_GUN; break; @@ -722,13 +723,13 @@ namespace TEN::Entities::TR4 probe = GetCollision(item); if (probe.Position.Ceiling == probe.Position.Floor - CLICK(6)) { - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_EMPTY) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_EMPTY)) { item->Animation.TargetState = BADDY_STATE_MONKEY_GRAB; break; } - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_GUN) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN)) { item->Animation.TargetState = BADDY_STATE_HOLSTER_GUN; break; @@ -754,7 +755,7 @@ namespace TEN::Entities::TR4 break; } - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_EMPTY) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_EMPTY)) { item->Animation.TargetState = BADDY_STATE_DRAW_SWORD; break; @@ -765,7 +766,7 @@ namespace TEN::Entities::TR4 AI.distance < pow(SECTOR(0.5f), 2) && AI.verticalDistance < SECTOR(1)) { - if (item->MeshSwapBits == MESHSWAPFLAGS_BADDY_GUN) + if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN)) item->Animation.TargetState = BADDY_STATE_HOLSTER_GUN; else if (AI.distance >= pow(SECTOR(0.5f), 2)) item->Animation.TargetState = BADDY_STATE_SWORD_HIT_FRONT; @@ -813,7 +814,8 @@ namespace TEN::Entities::TR4 if (item->ItemFlags[2] < 1) { - if (item->MeshSwapBits != MESHSWAPFLAGS_BADDY_SWORD_SIMPLE && item->MeshSwapBits != MESHSWAPFLAGS_BADDY_SWORD_NINJA) + if (!item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_SIMPLE) && + !item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_NINJA)) { item->Animation.TargetState = BADDY_STATE_IDLE; break; @@ -1170,19 +1172,19 @@ namespace TEN::Entities::TR4 case BADDY_STATE_HOLSTER_GUN: if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + FRAME_BADDY_HOLSTER_GUN) - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_EMPTY; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_EMPTY); break; case BADDY_STATE_DRAW_GUN: if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + FRAME_BADDY_DRAW_GUN) - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_GUN; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_GUN); break; case BADDY_STATE_HOLSTER_SWORD: if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + FRAME_BADDY_HOLSTER_SWORD) - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_EMPTY; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_EMPTY); break; @@ -1191,9 +1193,9 @@ namespace TEN::Entities::TR4 break; if (item->ObjectNumber == ID_BADDY1) - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_SWORD_SIMPLE; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_SIMPLE); else - item->MeshSwapBits = MESHSWAPFLAGS_BADDY_SWORD_NINJA; + item->SetMeshSwapFlags(MESHSWAPFLAGS_BADDY_SWORD_NINJA); break; diff --git a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp index d414ca67e..c5f540b35 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp @@ -100,7 +100,7 @@ namespace TEN::Entities::TR4 ClearItem(itemNumber); SetAnimation(item, GUIDE_ANIM_IDLE); - item->MeshSwapBits.Set(GuideRightHandSwapJoints); + item->SetMeshSwapFlags(GuideRightHandSwapJoints); } @@ -294,7 +294,7 @@ namespace TEN::Entities::TR4 { if (!creature->ReachedGoal || foundEnemy) { - if (item->MeshSwapBits == 0x40000) + if (item->TestMeshSwapFlags(0x40000)) item->Animation.TargetState = GUIDE_STATE_WALK_FORWARD_NO_TORCH; else if (foundEnemy && AI.distance < pow(SECTOR(1), 2)) { @@ -420,7 +420,7 @@ namespace TEN::Entities::TR4 { if (!foundEnemy || AI.distance >= pow(SECTOR(1.5f), 2) && - (item->MeshSwapBits.Test(GuideRightHandSwapJoints) || AI.distance >= pow(SECTOR(3), 2))) + (item->TestMeshSwapFlags(GuideRightHandSwapJoints) || AI.distance >= pow(SECTOR(3), 2))) { if (creature->Enemy->IsLara()) { @@ -476,7 +476,7 @@ namespace TEN::Entities::TR4 } else if (foundEnemy && (AI.distance < pow(SECTOR(1.5f), 2) || - !(item->MeshSwapBits.Test(GuideRightHandSwapJoints)) && + !(item->TestMeshSwapFlags(GuideRightHandSwapJoints)) && AI.distance < pow(SECTOR(3), 2))) { item->Animation.TargetState = GUIDE_STATE_IDLE; @@ -491,9 +491,9 @@ namespace TEN::Entities::TR4 random = GetRandomControl(); if (frameNumber == 32) - item->MeshSwapBits.Set(GuideLeftFingerSwapJoints); + item->SetMeshSwapFlags(GuideLeftFingerSwapJoints); else if (frameNumber == 216) - item->MeshSwapBits.Clear(GuideLeftFingerSwapJoints); + item->SetMeshSwapFlags(GuideLeftFingerSwapJoints, true); else if (frameNumber <= 79 || frameNumber >= 84) { if (frameNumber <= 83 || frameNumber >= 94) @@ -663,7 +663,7 @@ namespace TEN::Entities::TR4 } else if (item->Animation.FrameNumber == (g_Level.Anims[item->Animation.AnimNumber].frameBase + 35)) { - item->MeshSwapBits.Clear(GuideRightHandSwapJoints); + item->SetMeshSwapFlags(GuideRightHandSwapJoints, true); auto* room = &g_Level.Rooms[item->RoomNumber]; @@ -750,14 +750,14 @@ namespace TEN::Entities::TR4 flagScaryInscription) { item->Animation.RequiredState = GUIDE_STATE_RUN_FORWARD; - item->MeshSwapBits.Set(GuideHeadSwapJoints); + item->SetMeshSwapFlags(GuideHeadSwapJoints); SoundEffect(SFX_TR4_GUIDE_SCARE, &item->Pose); } if (item->Animation.FrameNumber == (g_Level.Anims[item->Animation.AnimNumber].frameBase + 185) && flagScaryInscription) { item->ItemFlags[2] &= ~(1 << 4); // Turn off 4th bit for flagScaryInscription. - item->MeshSwapBits.Clear(GuideHeadSwapJoints); + item->SetMeshSwapFlags(GuideHeadSwapJoints, true); } } else if ((enemy->Pose.Orientation.y - item->Pose.Orientation.y) <= ANGLE(2.0f)) diff --git a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp index fd5a18e48..612c6dcd3 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp @@ -5,6 +5,7 @@ #include "Game/collision/collide_item.h" #include "Game/control/box.h" #include "Game/control/control.h" +#include "Game/control/volume.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/itemdata/creature_info.h" @@ -21,18 +22,19 @@ using namespace TEN::Input; using namespace TEN::Math::Random; +using namespace TEN::Control::Volumes; namespace TEN::Entities::TR4 { - const auto SASGunBite = BiteInfo(Vector3(0.0f, 300.0f, 64.0f), 7); + const auto SasGunBite = BiteInfo(Vector3(0.0f, 300.0f, 64.0f), 7); - const auto SASDragBodyPosition = Vector3i(0, 0, -460); - const ObjectCollisionBounds SASDragBodyBounds = + const auto SasDragBodyPosition = Vector3i(0, 0, -460); + const auto SasDragBounds = ObjectCollisionBounds { GameBoundingBox( - -CLICK(1), CLICK(1), - -CLICK(0.25f), 100, - -200, -460 + -BLOCK(1.0f / 4), BLOCK(1.0f / 4), + -100, 100, + -BLOCK(1.0f / 2), -460 ), std::pair( EulerAngles(ANGLE(-10.0f), ANGLE(-30.0f), 0), @@ -40,7 +42,7 @@ namespace TEN::Entities::TR4 ) }; - enum SASState + enum SasState { SAS_STATE_NONE = 0, SAS_STATE_IDLE = 1, @@ -62,7 +64,7 @@ namespace TEN::Entities::TR4 SAS_STATE_BLIND = 17 }; - enum SASAnim + enum SasAnim { SAS_ANIM_WALK = 0, SAS_ANIM_RUN = 1, @@ -126,7 +128,7 @@ namespace TEN::Entities::TR4 // Handle SAS firing. if (creature->FiredWeapon) { - auto pos = GetJointPosition(item, SASGunBite.meshNum, Vector3i(SASGunBite.Position)); + auto pos = GetJointPosition(item, SasGunBite.meshNum, Vector3i(SasGunBite.Position)); TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 24, 16, 4); creature->FiredWeapon--; } @@ -346,7 +348,7 @@ namespace TEN::Entities::TR4 } else item->Animation.TargetState = SAS_STATE_IDLE; - + break; case SAS_STATE_RUN: @@ -511,7 +513,7 @@ namespace TEN::Entities::TR4 creature->Flags -= 1; else { - ShotLara(item, &AI, SASGunBite, joint0, 15); + ShotLara(item, &AI, SasGunBite, joint0, 15); creature->Flags = 5; creature->FiredWeapon = 3; } @@ -566,7 +568,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.meshNum, Vector3i(SasGunBite.Position)); grenadeItem->Pose.Position = pos; auto probe = GetCollision(pos.x, pos.y, pos.z, grenadeItem->RoomNumber); @@ -649,52 +651,49 @@ namespace TEN::Entities::TR4 void SasDragBlokeCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) { auto* item = &g_Level.Items[itemNumber]; + auto* lara = GetLaraInfo(laraItem); - if ((!(TrInput & IN_ACTION) || - laraItem->Animation.IsAirborne || - laraItem->Animation.ActiveState != LS_IDLE || - laraItem->Animation.AnimNumber != LA_STAND_IDLE || - Lara.Control.HandStatus != HandStatus::Free || - item->Flags & 0x3E00) && - (!(Lara.Control.IsMoving) || Lara.InteractedItem != itemNumber)) + if ((IsHeld(In::Action) && + laraItem->Animation.ActiveState == LS_IDLE && + laraItem->Animation.AnimNumber == LA_STAND_IDLE && + lara->Control.HandStatus == HandStatus::Free && + !laraItem->Animation.IsAirborne && + !(item->Flags & IFLAG_ACTIVATION_MASK)) || + lara->Control.IsMoving && lara->InteractedItem == itemNumber) { - if (item->Status == ITEM_ACTIVE) + if (TestLaraPosition(SasDragBounds, item, laraItem)) { - if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd) + if (MoveLaraPosition(SasDragBodyPosition, item, laraItem)) { - int x = laraItem->Pose.Position.x - 512 * phd_sin(laraItem->Pose.Orientation.y); - int y = laraItem->Pose.Position.y; - int z = laraItem->Pose.Position.z - 512 * phd_cos(laraItem->Pose.Orientation.y); + SetAnimation(laraItem, LA_DRAG_BODY); + ResetLaraFlex(laraItem); + laraItem->Pose.Orientation.y = item->Pose.Orientation.y; + lara->Control.HandStatus = HandStatus::Busy; + lara->Control.IsMoving = false; - TestTriggers(x, y, z, laraItem->RoomNumber, true); - - RemoveActiveItem(itemNumber); - item->Status = ITEM_NOT_ACTIVE; + AddActiveItem(itemNumber); + item->Flags |= IFLAG_ACTIVATION_MASK; + item->Status = ITEM_ACTIVE; } + else + lara->InteractedItem = itemNumber; } - - ObjectCollision(itemNumber, laraItem, coll); } else { - if (TestLaraPosition(SASDragBodyBounds, item, laraItem)) + if (item->Status != ITEM_ACTIVE) { - if (MoveLaraPosition(SASDragBodyPosition, item, laraItem)) - { - laraItem->Animation.AnimNumber = LA_DRAG_BODY; - laraItem->Animation.ActiveState = LS_MISC_CONTROL; - laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase; - laraItem->Pose.Orientation.y = item->Pose.Orientation.y; - ResetLaraFlex(laraItem); - Lara.Control.IsMoving = false; - Lara.Control.HandStatus = HandStatus::Busy; - item->Flags |= 0x3E00; - item->Status = ITEM_ACTIVE; - AddActiveItem(itemNumber); - } - else - Lara.InteractedItem = itemNumber; + ObjectCollision(itemNumber, laraItem, coll); + return; } + + if (!TestLastFrame(item)) + return; + + auto pos = GetJointPosition(item, 0); + TestTriggers(pos.x, pos.y, pos.z, item->RoomNumber, true); + RemoveActiveItem(itemNumber); + item->Status = ITEM_DEACTIVATED; } } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp index ed6052443..3fc86a4ef 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp @@ -142,7 +142,7 @@ namespace TEN::Entities::TR4 item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase; item->Animation.TargetState = VON_CROY_STATE_TOGGLE_KNIFE; item->Animation.ActiveState = VON_CROY_STATE_TOGGLE_KNIFE; - item->MeshSwapBits.Set(VonCroyKnifeSwapJoints); + item->SetMeshSwapFlags(VonCroyKnifeSwapJoints); memset(VonCroyPassedWaypoints, 0, 128); } @@ -427,7 +427,7 @@ namespace TEN::Entities::TR4 probe = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, probe.RoomNumber); if (probe.Position.Ceiling == (probe.Position.Floor - 1536)) { - if (item->MeshSwapBits.Test(VonCroyKnifeSwapJoints)) + if (item->TestMeshSwapFlags(VonCroyKnifeSwapJoints)) item->Animation.TargetState = VON_CROY_STATE_TOGGLE_KNIFE; else item->Animation.TargetState = VON_CROY_STATE_START_MONKEY; @@ -502,7 +502,7 @@ namespace TEN::Entities::TR4 if (Lara.Location >= item->ItemFlags[3]) { if (!foundTarget || AI.distance >= pow(SECTOR(1.5f), 2) && - (item->MeshSwapBits.Test(18) || AI.distance >= pow(SECTOR(3), 2))) + (item->TestMeshSwapFlags(18) || AI.distance >= pow(SECTOR(3), 2))) { if (creature->Enemy->IsLara()) { @@ -627,10 +627,7 @@ namespace TEN::Entities::TR4 case VON_CROY_STATE_TOGGLE_KNIFE: if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase) { - if (!item->MeshSwapBits.Test(VonCroyKnifeSwapJoints)) - item->MeshSwapBits.Set(VonCroyKnifeSwapJoints); - else - item->MeshSwapBits.Clear(VonCroyKnifeSwapJoints); + item->SetMeshSwapFlags(VonCroyKnifeSwapJoints, item->TestMeshSwapFlags(VonCroyKnifeSwapJoints)); } break; diff --git a/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.cpp b/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.cpp deleted file mode 100644 index ad39b64a6..000000000 --- a/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "framework.h" -#include "Objects/TR4/Object/tr4_sas_drag_bloke.h" - -#include "Game/collision/collide_item.h" -#include "Game/health.h" -#include "Game/items.h" -#include "Game/Lara/lara.h" -#include "Game/Lara/lara_helpers.h" -#include "Game/pickup/pickup.h" -#include "Math/Math.h" -#include "Specific/Input/Input.h" -#include "Specific/level.h" -#include "Specific/setup.h" - -using namespace TEN::Input; -using namespace TEN::Math; - -const auto DragSasPosition = Vector3i(0, 0, -460); -const auto DragSasBounds = ObjectCollisionBounds -{ - GameBoundingBox( - -BLOCK(1.0f / 4), BLOCK(1.0f / 4), - -100, 100, - -BLOCK(1.0f / 2), -460 - ), - std::pair( - EulerAngles(ANGLE(-10.0f), ANGLE(-30.0f), ANGLE(-10.0f)), - EulerAngles(ANGLE(10.0f), ANGLE(30.0f), ANGLE(10.0f)) - ) -}; - -void DragSasCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) -{ - auto* item = &g_Level.Items[itemNumber]; - auto* lara = GetLaraInfo(laraItem); - - if ((IsHeld(In::Action) && - laraItem->Animation.ActiveState == LS_IDLE && - laraItem->Animation.AnimNumber == LA_STAND_IDLE && - !laraItem->Animation.IsAirborne && - lara->Control.HandStatus == HandStatus::Free && - !(item->Flags & IFLAG_ACTIVATION_MASK)) || - (lara->Control.IsMoving && lara->InteractedItem == itemNumber)) - { - if (TestLaraPosition(DragSasBounds, item, laraItem)) - { - if (MoveLaraPosition(DragSasPosition, item, laraItem)) - { - AddActiveItem(itemNumber); - item->Pose.Orientation.y; - item->Flags |= IFLAG_ACTIVATION_MASK; - item->Status = ITEM_ACTIVE; - - SetAnimation(laraItem, LA_DRAG_BODY); - ResetLaraFlex(laraItem); - lara->Control.HandStatus = HandStatus::Busy; - lara->Control.IsMoving = false; - } - else - lara->InteractedItem = itemNumber; - } - } - else - { - if (item->Status != ITEM_ACTIVE) - { - ObjectCollision(itemNumber, laraItem, coll); - return; - } - - if (!TestLastFrame(item)) - return; - - auto pos = GetJointPosition(item, 0); - TestTriggers(pos.x, pos.y, pos.z, item->RoomNumber, true); - RemoveActiveItem(itemNumber); - item->Status = ITEM_DEACTIVATED; - } -} diff --git a/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.h b/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.h deleted file mode 100644 index f084d6da6..000000000 --- a/TombEngine/Objects/TR4/Object/tr4_sas_drag_bloke.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -struct CollisionInfo; -struct ItemInfo; - -void DragSasCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); diff --git a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp index d6b005e7f..ddbb31ba6 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp @@ -16,8 +16,8 @@ namespace TEN::Entities::TR4 auto* item = &g_Level.Items[itemNumber]; // Set bone mutators to 0 by default. - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Scale.y = 0.0f; + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Scale.y = 0.0f; item->Pose.Orientation.y = GetRandomControl() * 1024; item->ItemFlags[2] = GetRandomControl() & 1; @@ -81,8 +81,8 @@ namespace TEN::Entities::TR4 // Update bone mutators. if (item->ItemFlags[1]) { - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Scale = Vector3(1.0f, item->ItemFlags[1] / 4096.0f, 1.0f); + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Scale = Vector3(1.0f, item->ItemFlags[1] / 4096.0f, 1.0f); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 434b23fde..6d0a112c2 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -23,8 +23,8 @@ namespace TEN::Entities::TR4 auto* item = &g_Level.Items[itemNumber]; // Set mutators to 0 by default. - for (size_t i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Scale.y = 0.0f; + for (size_t i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Scale.y = 0.0f; item->Status = ITEM_INVISIBLE; item->ItemFlags[0] = 1024; @@ -210,13 +210,13 @@ namespace TEN::Entities::TR4 } // Update bone mutators. - for (size_t i = 0; i < item->Animation.Mutator.size(); i++) + for (size_t i = 0; i < item->Model.Mutator.size(); i++) { float scale = (float)item->ItemFlags[1] / 4096.0f; if (scale > 0.0f) - item->Animation.Mutator[i].Scale = Vector3(1.0f, scale, 1.0f); + item->Model.Mutator[i].Scale = Vector3(1.0f, scale, 1.0f); else - item->Animation.Mutator[i].Scale = Vector3::Zero; + item->Model.Mutator[i].Scale = Vector3::Zero; } } } diff --git a/TombEngine/Objects/TR4/tr4_objects.cpp b/TombEngine/Objects/TR4/tr4_objects.cpp index 61445b7e9..8fd8661d5 100644 --- a/TombEngine/Objects/TR4/tr4_objects.cpp +++ b/TombEngine/Objects/TR4/tr4_objects.cpp @@ -46,7 +46,6 @@ #include "tr4_hammer.h" // Objects -#include "tr4_sas_drag_bloke.h" #include "tr4_sarcophagus.h" #include "tr4_senet.h" #include "Objects/TR4/Object/tr4_clockwork_beetle.h" @@ -853,7 +852,7 @@ namespace TEN::Entities if (obj->loaded) { obj->control = AnimatingControl; - obj->collision = DragSasCollision; + obj->collision = SasDragBlokeCollision; obj->savePosition = true; obj->saveFlags = true; obj->saveAnim = true; diff --git a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp index 2aa85589e..bb8004419 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp @@ -239,7 +239,7 @@ namespace TEN::Entities::Creatures::TR5 { if (item->ItemFlags[0] < 11) { - item->MeshSwapBits |= 1 << HitmanJoints[item->ItemFlags[0]]; + item->SetMeshSwapFlags(1 << HitmanJoints[item->ItemFlags[0]]); item->ItemFlags[0]++; } } diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 6d13a6c30..6f3a66c00 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Creatures::TR5 SetAnimation(item, GLADIATOR_ANIM_IDLE); if (item->TriggerFlags == 1) - item->MeshSwapBits = ALL_JOINT_BITS; + item->SetMeshSwapFlags(ALL_JOINT_BITS); } void ControlGladiator(short itemNumber) diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index 100fcffb8..9f7a0c640 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -127,7 +127,7 @@ namespace TEN::Entities::Creatures::TR5 case 3: item->Animation.AnimNumber = anim + 28; item->Animation.TargetState = GUARD_STATE_SIT; - item->MeshSwapBits = 9216; + item->SetMeshSwapFlags(9216); roomItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; if (roomItemNumber != NO_ITEM) @@ -161,7 +161,7 @@ namespace TEN::Entities::Creatures::TR5 case 4: item->Animation.AnimNumber = anim + 30; item->Animation.TargetState = 17; - item->MeshSwapBits = 8192; + item->SetMeshSwapFlags(8192); break; case 5: @@ -708,7 +708,7 @@ namespace TEN::Entities::Creatures::TR5 if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + 44) { - item->MeshSwapBits = NO_JOINT_BITS; + item->SetMeshSwapFlags(NO_JOINT_BITS); short currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; if (currentItemNumber == NO_ITEM) @@ -803,7 +803,7 @@ namespace TEN::Entities::Creatures::TR5 item->Pose.Position.x = currentItem->Pose.Position.x - CLICK(1); item->Pose.Orientation.y = currentItem->Pose.Orientation.y; item->Pose.Position.z = currentItem->Pose.Position.z + CLICK(0.5f); - item->MeshSwapBits = 1024; + item->SetMeshSwapFlags(1024); } else { @@ -822,7 +822,7 @@ namespace TEN::Entities::Creatures::TR5 currentItem->MeshBits = 0x1FFF; TestTriggers(item, true); item->Animation.RequiredState = GUARD_STATE_WALK; - item->MeshSwapBits = NO_JOINT_BITS; + item->SetMeshSwapFlags(NO_JOINT_BITS); } } @@ -1085,7 +1085,7 @@ namespace TEN::Entities::Creatures::TR5 item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase; item->Animation.TargetState = GUARD_STATE_IDLE; item->Animation.ActiveState = GUARD_STATE_IDLE; - item->MeshSwapBits = 9216; + item->SetMeshSwapFlags(9216); } void Mafia2Control(short itemNumber) @@ -1210,13 +1210,13 @@ namespace TEN::Entities::Creatures::TR5 } if (laraAI.angle <= ANGLE(112.5f) && laraAI.angle >= -ANGLE(112.5f)) { - if (item->MeshSwapBits == 9216) + if (item->TestMeshSwapFlags(9216)) { item->Animation.TargetState = MAFIA2_STATE_UNDRAW_GUNS; break; } } - else if (item->MeshSwapBits == 9216) + else if (item->TestMeshSwapFlags(9216)) { item->Animation.TargetState = MAFIA2_STATE_TURN_180; break; @@ -1272,13 +1272,13 @@ namespace TEN::Entities::Creatures::TR5 item->Pose.Orientation.y += ANGLE(2.0f); if (item->Animation.FrameNumber != g_Level.Anims[item->Animation.AnimNumber].frameBase + 16 || - item->MeshSwapBits != 9216) + !item->TestMeshSwapFlags(9216)) { if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd) item->Pose.Orientation.y += -ANGLE(180.0f); } else - item->MeshSwapBits = 128; + item->SetMeshSwapFlags(128); break; @@ -1412,9 +1412,9 @@ namespace TEN::Entities::Creatures::TR5 item->Pose.Orientation.y -= ANGLE(2.0f); if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + 16 && - item->MeshSwapBits == 9216) + item->TestMeshSwapFlags(9216)) { - item->MeshSwapBits = 128; + item->SetMeshSwapFlags(128); } break; diff --git a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp index dba29eb5f..0c72b0a69 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp @@ -171,9 +171,9 @@ namespace TEN::Entities::Creatures::TR5 joint3 = AI.angle / 2; if (Wibble & 0x10) - item->MeshSwapBits = 1024; + item->SetMeshSwapFlags(1024); else - item->MeshSwapBits = NO_JOINT_BITS; + item->SetMeshSwapFlags(NO_JOINT_BITS); switch (item->Animation.ActiveState) { diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index c8393cb21..10ff46095 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -311,37 +311,37 @@ namespace TEN::Entities::Creatures::TR5 auto* item = &g_Level.Items[itemNumber]; auto* creature = GetCreatureInfo(item); - int prevMeshSwapBits = item->MeshSwapBits.ToPackedBits(); + auto prevMeshSwapBits = item->Model.MeshIndex; // At determined HP values, roman statues sheds material. - if (item->HitPoints < 1 && !(item->MeshSwapBits & 0x10000)) + if (item->HitPoints < 1 && !item->TestMeshSwapFlags(0x10000)) { ExplodeItemNode(item, 16, 0, 8); item->MeshBits |= 0x10000; - item->MeshSwapBits |= 0x10000; + item->SetMeshSwapFlags(0x10000); } - else if (item->HitPoints < 75 && !(item->MeshSwapBits & 0x100)) + else if (item->HitPoints < 75 && !item->TestMeshSwapFlags(0x100)) { ExplodeItemNode(item, 8, 0, 8); item->MeshBits |= 0x100; - item->MeshSwapBits |= 0x100; + item->SetMeshSwapFlags(0x100); } - else if (item->HitPoints < 150 && !(item->MeshSwapBits & 0x400)) + else if (item->HitPoints < 150 && !item->TestMeshSwapFlags(0x400)) { ExplodeItemNode(item, 10, 0, 32); ExplodeItemNode(item, 11, 0, 32); item->MeshBits |= 0x400u; - item->MeshSwapBits |= 0x400; + item->SetMeshSwapFlags(0x400); } - else if (item->HitPoints < 225 && !(item->MeshSwapBits & 0x10)) + else if (item->HitPoints < 225 && !item->TestMeshSwapFlags(0x10)) { ExplodeItemNode(item, 4, 0, 8); item->MeshBits |= 0x10; - item->MeshSwapBits |= 0x10; + item->SetMeshSwapFlags(0x10); } // Play hit animation. - if (prevMeshSwapBits != item->MeshSwapBits.ToPackedBits()) + if (prevMeshSwapBits != item->Model.MeshIndex) { item->Animation.TargetState = STATUE_STATE_HIT; item->Animation.ActiveState = STATUE_STATE_HIT; @@ -859,7 +859,7 @@ namespace TEN::Entities::Creatures::TR5 CreatureJoint(item, 1, joint1); CreatureJoint(item, 2, joint2); - if (item->MeshSwapBits & 0x400) + if (item->TestMeshSwapFlags(0x400)) { auto pos = Vector3i( (GetRandomControl() & 0x1F) - 16, @@ -869,7 +869,7 @@ namespace TEN::Entities::Creatures::TR5 RomanStatueHitEffect(item, &pos, 10); } - if (item->MeshSwapBits & 0x10) + if (item->TestMeshSwapFlags(0x10)) { auto pos = Vector3i( -40, @@ -879,7 +879,7 @@ namespace TEN::Entities::Creatures::TR5 RomanStatueHitEffect(item, &pos, 4); } - if (item->MeshSwapBits & 0x100) + if (item->TestMeshSwapFlags(0x100)) { auto pos = Vector3i( (GetRandomControl() & 0x3F) + 54, diff --git a/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp index d320b728c..f38622444 100644 --- a/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp @@ -290,9 +290,9 @@ void ExpandingPlatformUpdateMutators(short itemNumber) if (item->Pose.Orientation.y == ANGLE(180.0f)) zTranslate = -offset + width; if (item->Pose.Orientation.y == ANGLE(270.0f)) zTranslate = width - offset; - for (int i = 0; i < item->Animation.Mutator.size(); i++) + for (int i = 0; i < item->Model.Mutator.size(); i++) { - item->Animation.Mutator[i].Offset = Vector3(0, 0, zTranslate); - item->Animation.Mutator[i].Scale = Vector3(1.0f, 1.0f, item->ItemFlags[1] / 4096.0f); + item->Model.Mutator[i].Offset = Vector3(0, 0, zTranslate); + item->Model.Mutator[i].Scale = Vector3(1.0f, 1.0f, item->ItemFlags[1] / 4096.0f); } } diff --git a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp index 7dba1ca3c..8f3613678 100644 --- a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp @@ -24,8 +24,8 @@ void InitialiseRaisingBlock(short itemNumber) g_Level.Boxes[floor->Box].flags &= ~BLOCKED; // Set mutators to 0 by default - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Scale.y = 0; + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Scale.y = 0; if (item->TriggerFlags < 0) { @@ -144,8 +144,8 @@ void ControlRaisingBlock(short itemNumber) // Update bone mutators if (item->TriggerFlags > -1) { - for (int i = 0; i < item->Animation.Mutator.size(); i++) - item->Animation.Mutator[i].Scale = Vector3(1.0f, item->ItemFlags[1] / 4096.0f, 1.0f); + for (int i = 0; i < item->Model.Mutator.size(); i++) + item->Model.Mutator[i].Scale = Vector3(1.0f, item->ItemFlags[1] / 4096.0f, 1.0f); } } diff --git a/TombEngine/Renderer/Renderer11.h b/TombEngine/Renderer/Renderer11.h index 1f3a58f6b..05941bc30 100644 --- a/TombEngine/Renderer/Renderer11.h +++ b/TombEngine/Renderer/Renderer11.h @@ -108,19 +108,24 @@ namespace TEN::Renderer { int ItemNumber; int ObjectNumber; - bool DoneAnimations; + Vector3 Position; Matrix World; Matrix Translation; Matrix Rotation; Matrix Scale; Matrix AnimationTransforms[MAX_BONES]; + int RoomNumber = NO_ROOM; int PrevRoomNumber = NO_ROOM; Vector4 Color; Vector4 AmbientLight; std::vector LightsToDraw; float LightFade; + + std::vector MeshIndex; + + bool DoneAnimations; }; struct RendererMesh diff --git a/TombEngine/Renderer/Renderer11Compatibility.cpp b/TombEngine/Renderer/Renderer11Compatibility.cpp index 4ee2c3eab..fad49091c 100644 --- a/TombEngine/Renderer/Renderer11Compatibility.cpp +++ b/TombEngine/Renderer/Renderer11Compatibility.cpp @@ -395,6 +395,7 @@ namespace TEN::Renderer j, MoveablesIds[i] == ID_LARA_SKIN_JOINTS, MoveablesIds[i] == ID_HAIR, &lastVertex, &lastIndex); moveable.ObjectMeshes.push_back(mesh); + m_meshes.push_back(mesh); } if (objNum == ID_IMP_ROCK || objNum == ID_ENERGY_BUBBLES || objNum == ID_BUBBLES || objNum == ID_BODY_PART) @@ -678,6 +679,7 @@ namespace TEN::Renderer RendererMesh *mesh = GetRendererMeshFromTrMesh(&staticObject, &g_Level.Meshes[obj->meshNumber], 0, false, false, &lastVertex, &lastIndex); staticObject.ObjectMeshes.push_back(mesh); + m_meshes.push_back(mesh); m_staticObjects[StaticObjectsIds[i]] = staticObject; } @@ -857,8 +859,6 @@ namespace TEN::Renderer mesh->Buckets.push_back(bucket); } - m_meshes.push_back(mesh); - return mesh; } } diff --git a/TombEngine/Renderer/Renderer11Draw.cpp b/TombEngine/Renderer/Renderer11Draw.cpp index e0bacd7c8..6c8528b65 100644 --- a/TombEngine/Renderer/Renderer11Draw.cpp +++ b/TombEngine/Renderer/Renderer11Draw.cpp @@ -69,7 +69,7 @@ namespace TEN::Renderer if (!nativeItem.MeshBits.Test(sphereMeshes[i])) continue; - auto& mesh = g_Level.Meshes[Lara.MeshPtrs[sphereMeshes[i]]]; + auto& mesh = g_Level.Meshes[nativeItem.Model.MeshIndex[sphereMeshes[i]]]; auto offset = Vector3i(mesh.sphere.Center.x, mesh.sphere.Center.y, mesh.sphere.Center.z); // Push foot spheres a little lower. @@ -225,7 +225,7 @@ namespace TEN::Renderer for (int k = 0; k < skin.ObjectMeshes.size(); k++) { - auto* mesh = item->ObjectNumber == ID_LARA ? GetMesh(Lara.MeshPtrs[k]) : skin.ObjectMeshes[k]; + auto* mesh = GetMesh(item->MeshIndex[k]); for (auto& bucket : mesh->Buckets) { @@ -1711,7 +1711,6 @@ namespace TEN::Renderer ItemInfo* nativeItem = &g_Level.Items[item->ItemNumber]; RendererRoom* room = &m_rooms[item->RoomNumber]; RendererObject& moveableObj = *m_moveableObjects[item->ObjectNumber]; - ObjectInfo* obj = &Objects[item->ObjectNumber]; // Bind item main properties m_stItem.World = item->World; @@ -1733,17 +1732,7 @@ namespace TEN::Renderer if (!(nativeItem->MeshBits & (1 << k))) continue; - RendererMesh* mesh = moveableObj.ObjectMeshes[k]; - - // Do the swapmesh - if (obj->meshSwapSlot != -1 && m_moveableObjects[obj->meshSwapSlot].has_value() && ((nativeItem->MeshSwapBits.ToPackedBits() >> k) & 1)) - { - RendererObject& swapMeshObj = *m_moveableObjects[obj->meshSwapSlot]; - if (swapMeshObj.ObjectMeshes.size() > k) - mesh = swapMeshObj.ObjectMeshes[k]; - } - - DrawMoveableMesh(item, mesh, room, k, transparent); + DrawMoveableMesh(item, GetMesh(item->MeshIndex[k]), room, k, transparent); } } diff --git a/TombEngine/Renderer/Renderer11Enums.h b/TombEngine/Renderer/Renderer11Enums.h index c8b5be151..b5a0055bc 100644 --- a/TombEngine/Renderer/Renderer11Enums.h +++ b/TombEngine/Renderer/Renderer11Enums.h @@ -210,9 +210,6 @@ constexpr auto TEXTURE_PAGE = (TEXTURE_HEIGHT * TEXTURE_WIDTH); #define NUM_SPRITES_PER_BUCKET 4096 #define NUM_LINES_PER_BUCKET 4096 #define NUM_CAUSTICS_TEXTURES 16 -#define FADEMODE_NONE 0 -#define FADEMODE_FADEIN 1 -#define FADEMODE_FADEOUT 2 #define PRINTSTRING_CENTER 1 #define PRINTSTRING_BLINK 2 #define PRINTSTRING_OUTLINE 8 diff --git a/TombEngine/Renderer/Renderer11Helper.cpp b/TombEngine/Renderer/Renderer11Helper.cpp index 57171cd5f..9f095dbdf 100644 --- a/TombEngine/Renderer/Renderer11Helper.cpp +++ b/TombEngine/Renderer/Renderer11Helper.cpp @@ -120,11 +120,11 @@ namespace TEN::Renderer { auto* nativeItem = &g_Level.Items[item->ItemNumber]; - if (nativeItem->Animation.Mutator.size() == boneIndexList.size()) + if (nativeItem->Model.Mutator.size() == boneIndexList.size()) { for (int i : boneIndexList) { - auto mutator = nativeItem->Animation.Mutator[i]; + auto mutator = nativeItem->Model.Mutator[i]; if (mutator.IsEmpty()) continue; @@ -154,145 +154,147 @@ namespace TEN::Renderer if (!force && itemToDraw->DoneAnimations) return; + itemToDraw->DoneAnimations = true; + auto* obj = &Objects[nativeItem->ObjectNumber]; auto& moveableObj = *m_moveableObjects[nativeItem->ObjectNumber]; - // Update animation matrices - if (obj->animIndex != -1 /*&& item->objectNumber != ID_HARPOON*/) + // Copy meshswaps + itemToDraw->MeshIndex = nativeItem->Model.MeshIndex; + + if (obj->animIndex == -1) + return; + + // Apply extra rotations + int lastJoint = 0; + for (int j = 0; j < moveableObj.LinearizedBones.size(); j++) { - // Apply extra rotations - int lastJoint = 0; - for (int j = 0; j < moveableObj.LinearizedBones.size(); j++) - { - auto* currentBone = moveableObj.LinearizedBones[j]; + auto* currentBone = moveableObj.LinearizedBones[j]; - auto prevRotation = currentBone->ExtraRotation; - currentBone->ExtraRotation = Vector3(0.0f, 0.0f, 0.0f); + auto prevRotation = currentBone->ExtraRotation; + currentBone->ExtraRotation = Vector3(0.0f, 0.0f, 0.0f); - nativeItem->Data.apply( - [&j, ¤tBone](QuadBikeInfo& quadBike) + nativeItem->Data.apply( + [&j, ¤tBone](QuadBikeInfo& quadBike) + { + if (j == 3 || j == 4) + currentBone->ExtraRotation.x = TO_RAD(quadBike.RearRot); + else if (j == 6 || j == 7) { - if (j == 3 || j == 4) - currentBone->ExtraRotation.x = TO_RAD(quadBike.RearRot); - else if (j == 6 || j == 7) - { - currentBone->ExtraRotation.x = TO_RAD(quadBike.FrontRot); - currentBone->ExtraRotation.y = TO_RAD(quadBike.TurnRate * 2); - } - }, - [&j, ¤tBone](JeepInfo& jeep) + currentBone->ExtraRotation.x = TO_RAD(quadBike.FrontRot); + currentBone->ExtraRotation.y = TO_RAD(quadBike.TurnRate * 2); + } + }, + [&j, ¤tBone](JeepInfo& jeep) + { + switch(j) { - switch(j) - { - case 9: - currentBone->ExtraRotation.x = TO_RAD(jeep.FrontRightWheelRotation); - currentBone->ExtraRotation.y = TO_RAD(jeep.TurnRate * 4); - break; + case 9: + currentBone->ExtraRotation.x = TO_RAD(jeep.FrontRightWheelRotation); + currentBone->ExtraRotation.y = TO_RAD(jeep.TurnRate * 4); + break; - case 10: - currentBone->ExtraRotation.x = TO_RAD(jeep.FrontLeftWheelRotation); - currentBone->ExtraRotation.y = TO_RAD(jeep.TurnRate * 4); - break; + case 10: + currentBone->ExtraRotation.x = TO_RAD(jeep.FrontLeftWheelRotation); + currentBone->ExtraRotation.y = TO_RAD(jeep.TurnRate * 4); + break; - case 12: - currentBone->ExtraRotation.x = TO_RAD(jeep.BackRightWheelRotation); - break; + case 12: + currentBone->ExtraRotation.x = TO_RAD(jeep.BackRightWheelRotation); + break; - case 13: - currentBone->ExtraRotation.x = TO_RAD(jeep.BackLeftWheelRotation); - break; - } - }, - [&j, ¤tBone](MotorbikeInfo& bike) + case 13: + currentBone->ExtraRotation.x = TO_RAD(jeep.BackLeftWheelRotation); + break; + } + }, + [&j, ¤tBone](MotorbikeInfo& bike) + { + switch (j) { - switch (j) - { - case 2: - currentBone->ExtraRotation.x = TO_RAD(bike.RightWheelsRotation); - currentBone->ExtraRotation.y = TO_RAD(bike.TurnRate * 8); - break; + case 2: + currentBone->ExtraRotation.x = TO_RAD(bike.RightWheelsRotation); + currentBone->ExtraRotation.y = TO_RAD(bike.TurnRate * 8); + break; - case 4: - currentBone->ExtraRotation.x = TO_RAD(bike.RightWheelsRotation); - break; + case 4: + currentBone->ExtraRotation.x = TO_RAD(bike.RightWheelsRotation); + break; - case 8: - currentBone->ExtraRotation.x = TO_RAD(bike.LeftWheelRotation); - break; - } - }, - [&j, ¤tBone, &prevRotation](MinecartInfo& cart) + case 8: + currentBone->ExtraRotation.x = TO_RAD(bike.LeftWheelRotation); + break; + } + }, + [&j, ¤tBone, &prevRotation](MinecartInfo& cart) + { + switch (j) { - switch (j) - { - case 1: - case 2: - case 3: - case 4: - currentBone->ExtraRotation.z = TO_RAD((short)std::clamp(cart.Velocity, 0, (int)ANGLE(25.0f)) + FROM_RAD(prevRotation.z)); - break; - } - }, - [&j, ¤tBone](RubberBoatInfo& boat) + case 1: + case 2: + case 3: + case 4: + currentBone->ExtraRotation.z = TO_RAD((short)std::clamp(cart.Velocity, 0, (int)ANGLE(25.0f)) + FROM_RAD(prevRotation.z)); + break; + } + }, + [&j, ¤tBone](RubberBoatInfo& boat) + { + if (j == 2) + currentBone->ExtraRotation.z = TO_RAD(boat.PropellerRotation); + }, + [&j, ¤tBone](UPVInfo& upv) + { + switch (j) { - if (j == 2) - currentBone->ExtraRotation.z = TO_RAD(boat.PropellerRotation); - }, - [&j, ¤tBone](UPVInfo& upv) + case 1: + currentBone->ExtraRotation.x = TO_RAD(upv.LeftRudderRotation); + break; + + case 2: + currentBone->ExtraRotation.x = TO_RAD(upv.RightRudderRotation); + break; + + case 3: + currentBone->ExtraRotation.z = TO_RAD(upv.TurbineRotation); + break; + } + }, + [&j, ¤tBone](BigGunInfo& big_gun) + { + if (j == 2) + currentBone->ExtraRotation.z = big_gun.BarrelRotation; + }, + [&j, ¤tBone, &lastJoint](CreatureInfo& creature) + { + if (currentBone->ExtraRotationFlags & ROT_Y) { - switch (j) - { - case 1: - currentBone->ExtraRotation.x = TO_RAD(upv.LeftRudderRotation); - break; + currentBone->ExtraRotation.y = TO_RAD(creature.JointRotation[lastJoint]); + lastJoint++; + } - case 2: - currentBone->ExtraRotation.x = TO_RAD(upv.RightRudderRotation); - break; - - case 3: - currentBone->ExtraRotation.z = TO_RAD(upv.TurbineRotation); - break; - } - }, - [&j, ¤tBone](BigGunInfo& big_gun) + if (currentBone->ExtraRotationFlags & ROT_X) { - if (j == 2) - currentBone->ExtraRotation.z = big_gun.BarrelRotation; - }, - [&j, ¤tBone, &lastJoint](CreatureInfo& creature) + currentBone->ExtraRotation.x = TO_RAD(creature.JointRotation[lastJoint]); + lastJoint++; + } + + if (currentBone->ExtraRotationFlags & ROT_Z) { - if (currentBone->ExtraRotationFlags & ROT_Y) - { - currentBone->ExtraRotation.y = TO_RAD(creature.JointRotation[lastJoint]); - lastJoint++; - } - - if (currentBone->ExtraRotationFlags & ROT_X) - { - currentBone->ExtraRotation.x = TO_RAD(creature.JointRotation[lastJoint]); - lastJoint++; - } - - if (currentBone->ExtraRotationFlags & ROT_Z) - { - currentBone->ExtraRotation.z = TO_RAD(creature.JointRotation[lastJoint]); - lastJoint++; - } - }); - } - - AnimFrame* framePtr[2]; - int rate; - int frac = GetFrame(nativeItem, framePtr, rate); - - UpdateAnimation(itemToDraw, moveableObj, framePtr, frac, rate, UINT_MAX); - - for (int m = 0; m < obj->nmeshes; m++) - itemToDraw->AnimationTransforms[m] = itemToDraw->AnimationTransforms[m]; + currentBone->ExtraRotation.z = TO_RAD(creature.JointRotation[lastJoint]); + lastJoint++; + } + }); } - itemToDraw->DoneAnimations = true; + AnimFrame* framePtr[2]; + int rate; + int frac = GetFrame(nativeItem, framePtr, rate); + + UpdateAnimation(itemToDraw, moveableObj, framePtr, frac, rate, UINT_MAX); + + for (int m = 0; m < obj->nmeshes; m++) + itemToDraw->AnimationTransforms[m] = itemToDraw->AnimationTransforms[m]; } void Renderer11::UpdateItemAnimations(RenderView& view) diff --git a/TombEngine/Renderer/Renderer11Lara.cpp b/TombEngine/Renderer/Renderer11Lara.cpp index eb11b900a..045cd5883 100644 --- a/TombEngine/Renderer/Renderer11Lara.cpp +++ b/TombEngine/Renderer/Renderer11Lara.cpp @@ -244,7 +244,9 @@ void Renderer11::UpdateLaraAnimations(bool force) for (int m = 0; m < 15; m++) laraObj.AnimationTransforms[m] = item->AnimationTransforms[m]; - m_items[Lara.ItemNumber].DoneAnimations = true; + // Copy meshswap indices + item->MeshIndex = LaraItem->Model.MeshIndex; + item->DoneAnimations = true; } void TEN::Renderer::Renderer11::DrawLara(RenderView& view, bool transparent) @@ -287,7 +289,7 @@ void TEN::Renderer::Renderer11::DrawLara(RenderView& view, bool transparent) m_stItem.AmbientLight = item->AmbientLight; memcpy(m_stItem.BonesMatrices, laraObj.AnimationTransforms.data(), sizeof(Matrix) * MAX_BONES); for (int k = 0; k < laraSkin.ObjectMeshes.size(); k++) - m_stItem.BoneLightModes[k] = GetMesh(Lara.MeshPtrs[k])->LightMode; + m_stItem.BoneLightModes[k] = GetMesh(nativeItem->Model.MeshIndex[k])->LightMode; m_cbItem.updateData(m_stItem, m_context.Get()); BindConstantBufferVS(CB_ITEM, m_cbItem.get()); @@ -300,8 +302,7 @@ void TEN::Renderer::Renderer11::DrawLara(RenderView& view, bool transparent) if (!nativeItem->MeshBits.Test(k)) continue; - RendererMesh *mesh = GetMesh(Lara.MeshPtrs[k]); - DrawMoveableMesh(item, mesh, room, k, transparent); + DrawMoveableMesh(item, GetMesh(nativeItem->Model.MeshIndex[k]), room, k, transparent); } DrawLaraHolsters(transparent); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp index 052c23a67..f8738c92e 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp @@ -73,7 +73,7 @@ void Camera::SetPos(Vec3 const& pos) std::string Camera::GetName() const { - return m_camera.LuaName; + return m_camera.Name; } void Camera::SetName(std::string const & id) @@ -86,8 +86,8 @@ void Camera::SetName(std::string const & id) if (s_callbackSetName(id, m_camera)) { // remove the old name if we have one - s_callbackRemoveName(m_camera.LuaName); - m_camera.LuaName = id; + s_callbackRemoveName(m_camera.Name); + m_camera.Name = id; } else { diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index ddd11bc32..bbc336659 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -441,7 +441,7 @@ void Moveable::Init() { bool cond = IsPointInRoom(m_item->Pose.Position, m_item->RoomNumber); std::string err{ "Position of item \"{}\" does not match its room ID." }; - if (!ScriptAssertF(cond, err, m_item->LuaName)) + if (!ScriptAssertF(cond, err, m_item->Name)) { ScriptWarn("Resetting to the center of the room."); auto center = GetRoomCenter(m_item->RoomNumber); @@ -476,7 +476,7 @@ void SetLevelFuncCallback(TypeOrNil const & cb, std::string const & c } else { - ScriptAssert(false, "Tried giving " + mov.m_item->LuaName + ScriptAssert(false, "Tried giving " + mov.m_item->Name + " a non-LevelFunc object as an arg to " + callerName); } @@ -485,27 +485,27 @@ void SetLevelFuncCallback(TypeOrNil const & cb, std::string const & c void Moveable::SetOnHit(TypeOrNil const & cb) { - SetLevelFuncCallback(cb, ScriptReserved_SetOnHit, *this, m_item->LuaCallbackOnHitName); + SetLevelFuncCallback(cb, ScriptReserved_SetOnHit, *this, m_item->Callbacks.OnHit); } void Moveable::SetOnKilled(TypeOrNil const & cb) { - SetLevelFuncCallback(cb, ScriptReserved_SetOnKilled, *this, m_item->LuaCallbackOnKilledName); + SetLevelFuncCallback(cb, ScriptReserved_SetOnKilled, *this, m_item->Callbacks.OnKilled); } void Moveable::SetOnCollidedWithObject(TypeOrNil const & cb) { - SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithObject, *this, m_item->LuaCallbackOnCollidedWithObjectName); + SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithObject, *this, m_item->Callbacks.OnObjectCollided); } void Moveable::SetOnCollidedWithRoom(TypeOrNil const & cb) { - SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithRoom, *this, m_item->LuaCallbackOnCollidedWithRoomName); + SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithRoom, *this, m_item->Callbacks.OnRoomCollided); } std::string Moveable::GetName() const { - return m_item->LuaName; + return m_item->Name; } bool Moveable::SetName(std::string const & id) @@ -518,11 +518,11 @@ bool Moveable::SetName(std::string const & id) if (s_callbackSetName(id, m_num)) { // remove the old name if we have one - if (id != m_item->LuaName) + if (id != m_item->Name) { - if(!m_item->LuaName.empty()) - s_callbackRemoveName(m_item->LuaName); - m_item->LuaName = id; + if(!m_item->Name.empty()) + s_callbackRemoveName(m_item->Name); + m_item->Name = id; } } else @@ -814,7 +814,7 @@ bool Moveable::MeshIsSwapped(int meshId) const if (!MeshExists(meshId)) return false; - return m_item->MeshSwapBits.Test(meshId); + return m_item->Model.MeshIndex[meshId] == m_item->Model.BaseMesh + meshId; } void Moveable::SwapMesh(int meshId, int swapSlotId, sol::optional swapMeshIndex) @@ -825,32 +825,26 @@ void Moveable::SwapMesh(int meshId, int swapSlotId, sol::optional swapMeshI if (!swapMeshIndex.has_value()) swapMeshIndex = meshId; - // TODO: After beta, we should refactor whole meshswap workflow, - // because currently Lara and other objects use different convention -- Lwmte, 09.07.22 - if (m_item->IsLara()) + if (swapSlotId <= -1 || swapSlotId >= ID_NUMBER_OBJECTS) { - if (swapSlotId <= -1) - return; - - auto* lara = GetLaraInfo(m_item); - - if (swapSlotId >= ID_NUMBER_OBJECTS || !Objects[swapSlotId].loaded) - { - TENLog("Specified slot does not exist in level!", LogLevel::Error); - return; - } - - if (swapMeshIndex.value() >= Objects[swapSlotId].nmeshes) - { - TENLog("Specified meshswap index does not exist in meshswap slot!", LogLevel::Error); - return; - } - - lara->MeshPtrs[meshId] = Objects[swapSlotId].meshIndex + swapMeshIndex.value(); + TENLog("Specified meshswap slot ID is incorrect!", LogLevel::Error); + return; } - else - m_item->MeshSwapBits.Set(meshId); + + if (!Objects[swapSlotId].loaded) + { + TENLog("Object in specified meshswap slot doesn't exist in level!", LogLevel::Error); + return; + } + + if (swapMeshIndex.value() >= Objects[swapSlotId].nmeshes) + { + TENLog("Specified meshswap index does not exist in meshswap slot!", LogLevel::Error); + return; + } + + m_item->Model.MeshIndex[meshId] = Objects[swapSlotId].meshIndex + swapMeshIndex.value(); } void Moveable::UnswapMesh(int meshId) @@ -858,20 +852,7 @@ void Moveable::UnswapMesh(int meshId) if (!MeshExists(meshId)) return; - if (m_item->IsLara()) - { - auto* lara = GetLaraInfo(m_item); - - if (meshId >= NUM_LARA_MESHES) - { - TENLog("Specified mesh index does not exist!", LogLevel::Error); - return; - } - - lara->MeshPtrs[meshId] = Objects[ID_LARA_SKIN].meshIndex + meshId; - } - else - m_item->MeshSwapBits.Clear(meshId); + m_item->Model.MeshIndex[meshId] = m_item->Model.BaseMesh + meshId; } void Moveable::EnableItem() @@ -991,7 +972,7 @@ void Moveable::Destroy() if (m_num > NO_ITEM) { dynamic_cast(g_GameScriptEntities)->RemoveMoveableFromMap(m_item, this); - s_callbackRemoveName(m_item->LuaName); + s_callbackRemoveName(m_item->Name); KillItem(m_num); } @@ -1002,7 +983,7 @@ bool Moveable::MeshExists(int index) const { if (index < 0 || index >= Objects[m_item->ObjectNumber].nmeshes) { - ScriptAssertF(false, "Mesh index {} does not exist in moveable '{}'", index, m_item->LuaName); + ScriptAssertF(false, "Mesh index {} does not exist in moveable '{}'", index, m_item->Name); return false; } diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp index f1232f879..d30fdd816 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp @@ -125,7 +125,7 @@ void ObjectsHandler::TestCollidingObjects() for (const auto idOne : m_collidingItems) { auto item = &g_Level.Items[idOne]; - if (!item->LuaCallbackOnCollidedWithObjectName.empty()) + if (!item->Callbacks.OnObjectCollided.empty()) { //test against other moveables GetCollidedObjects(item, 0, true, CollidedItems, nullptr, 0); @@ -133,17 +133,17 @@ void ObjectsHandler::TestCollidingObjects() while (CollidedItems[i]) { short idTwo = CollidedItems[i] - &g_Level.Items[0]; - g_GameScript->ExecuteFunction(item->LuaCallbackOnCollidedWithObjectName, idOne, idTwo); + g_GameScript->ExecuteFunction(item->Callbacks.OnObjectCollided, idOne, idTwo); ++i; } } - if (!item->LuaCallbackOnCollidedWithRoomName.empty()) + if (!item->Callbacks.OnRoomCollided.empty()) { //test against room geometry if (TestItemRoomCollisionAABB(item)) { - g_GameScript->ExecuteFunction(item->LuaCallbackOnCollidedWithRoomName, idOne); + g_GameScript->ExecuteFunction(item->Callbacks.OnRoomCollided, idOne); } } } diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h index 1c1122e60..4eecd0d8c 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h @@ -20,8 +20,8 @@ public: bool TryAddColliding(short id) override { ItemInfo* item = &g_Level.Items[id]; - bool hasName = !(item->LuaCallbackOnCollidedWithObjectName.empty() && item->LuaCallbackOnCollidedWithRoomName.empty()); - if(hasName && item->Collidable && (item->Status != ITEM_INVISIBLE)) + bool hasName = !(item->Callbacks.OnObjectCollided.empty() && item->Callbacks.OnRoomCollided.empty()); + if (hasName && item->Collidable && (item->Status != ITEM_INVISIBLE)) return m_collidingItems.insert(id).second; return false; @@ -30,7 +30,7 @@ public: bool TryRemoveColliding(short id, bool force = false) override { ItemInfo* item = &g_Level.Items[id]; - bool hasName = !(item->LuaCallbackOnCollidedWithObjectName.empty() && item->LuaCallbackOnCollidedWithRoomName.empty()); + bool hasName = !(item->Callbacks.OnObjectCollided.empty() && item->Callbacks.OnRoomCollided.empty()); if(!force && hasName && item->Collidable && (item->Status != ITEM_INVISIBLE)) return false; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp index 8d8d756ed..7a31ffe30 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp @@ -73,7 +73,7 @@ void Sink::SetPos(Vec3 const& pos) std::string Sink::GetName() const { - return m_sink.LuaName; + return m_sink.Name; } void Sink::SetName(std::string const & id) @@ -86,8 +86,8 @@ void Sink::SetName(std::string const & id) if (s_callbackSetName(id, m_sink)) { // remove the old name if we have one - s_callbackRemoveName(m_sink.LuaName); - m_sink.LuaName = id; + s_callbackRemoveName(m_sink.Name); + m_sink.Name = id; } else { diff --git a/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp index c9b7f9b39..c76bf88eb 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp @@ -71,7 +71,7 @@ void SoundSource::SetPos(Vec3 const& pos) std::string SoundSource::GetName() const { - return m_soundSource.LuaName; + return m_soundSource.Name; } void SoundSource::SetName(std::string const& id) @@ -84,8 +84,8 @@ void SoundSource::SetName(std::string const& id) if (s_callbackSetName(id, m_soundSource)) { // remove the old name if we have one - s_callbackRemoveName(m_soundSource.LuaName); - m_soundSource.LuaName = id; + s_callbackRemoveName(m_soundSource.Name); + m_soundSource.Name = id; } else { diff --git a/TombEngine/Sound/sound.h b/TombEngine/Sound/sound.h index 68f199563..7ed3d58fd 100644 --- a/TombEngine/Sound/sound.h +++ b/TombEngine/Sound/sound.h @@ -115,7 +115,7 @@ struct SoundSourceInfo Vector3i Position = Vector3i::Zero; int SoundID = 0; int Flags = 0; - string LuaName = ""; + string Name = ""; SoundSourceInfo() { diff --git a/TombEngine/Specific/LevelCameraInfo.h b/TombEngine/Specific/LevelCameraInfo.h index ccb0d6b75..ea36fbb32 100644 --- a/TombEngine/Specific/LevelCameraInfo.h +++ b/TombEngine/Specific/LevelCameraInfo.h @@ -12,7 +12,7 @@ struct LevelCameraInfo int RoomNumber = 0; int Flags = 0; int Speed = 1; - string LuaName = ""; + string Name = ""; LevelCameraInfo() { diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index 04313ccb7..4fa46943a 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -184,9 +184,9 @@ void LoadItems() item->Color = ReadVector4(); item->TriggerFlags = ReadInt16(); item->Flags = ReadInt16(); - item->LuaName = ReadString(); + item->Name = ReadString(); - g_GameScriptEntities->AddName(item->LuaName, i); + g_GameScriptEntities->AddName(item->Name, i); g_GameScriptEntities->TryAddColliding(i); memcpy(&item->StartPose, &item->Pose, sizeof(Pose)); @@ -423,9 +423,9 @@ void LoadCameras() camera.RoomNumber = ReadInt32(); camera.Flags = ReadInt32(); camera.Speed = ReadInt32(); - camera.LuaName = ReadString(); + camera.Name = ReadString(); - g_GameScriptEntities->AddName(camera.LuaName, camera); + g_GameScriptEntities->AddName(camera.Name, camera); } NumberSpotcams = ReadInt32(); @@ -445,9 +445,9 @@ void LoadCameras() sink.Position.z = ReadInt32(); sink.Strength = ReadInt32(); sink.BoxIndex = ReadInt32(); - sink.LuaName = ReadString(); + sink.Name = ReadString(); - g_GameScriptEntities->AddName(sink.LuaName, sink); + g_GameScriptEntities->AddName(sink.Name, sink); } } @@ -795,7 +795,7 @@ void ReadRooms() volume.Scale.y = ReadFloat(); volume.Scale.z = ReadFloat(); - volume.LuaName = ReadString(); + volume.Name = ReadString(); volume.EventSetIndex = ReadInt32(); volume.Status = TriggerStatus::Outside; @@ -903,9 +903,9 @@ void LoadSoundSources() source.Position.z = ReadInt32(); source.SoundID = ReadInt32(); source.Flags = ReadInt32(); - source.LuaName = ReadString(); + source.Name = ReadString(); - g_GameScriptEntities->AddName(source.LuaName, source); + g_GameScriptEntities->AddName(source.Name, source); } } @@ -1428,96 +1428,12 @@ void LoadPortal(ROOM_INFO& room) door.normal.y = ReadInt32(); door.normal.z = ReadInt32(); - float minX1 = INFINITY; - float minY1 = INFINITY; - float minZ1 = INFINITY; - float maxX1 = -INFINITY; - float maxY1 = -INFINITY; - float maxZ1 = -INFINITY; - for (int k = 0; k < 4; k++) { door.vertices[k].x = ReadInt32(); door.vertices[k].y = ReadInt32(); door.vertices[k].z = ReadInt32(); - - minX1 = std::min(minX1, door.vertices[k].x); - minY1 = std::min(minY1, door.vertices[k].y); - minZ1 = std::min(minZ1, door.vertices[k].z); - - maxX1 = std::max(maxX1, door.vertices[k].x); - maxY1 = std::max(maxY1, door.vertices[k].y); - maxZ1 = std::max(maxZ1, door.vertices[k].z); } - bool found = false; - - float minX2 = INFINITY; - float minY2 = INFINITY; - float minZ2 = INFINITY; - float maxX2 = -INFINITY; - float maxY2 = -INFINITY; - float maxZ2 = -INFINITY; - - for (int k = 0; k < room.doors.size(); k++) - { - ROOM_DOOR* current = &room.doors[k]; - - if (current->room == door.room) - { - // Merge door - found = true; - - for (int n = 0; n < 4; n++) - { - minX2 = std::min(minX2, current->vertices[n].x); - minY2 = std::min(minY2, current->vertices[n].y); - minZ2 = std::min(minZ2, current->vertices[n].z); - - maxX2 = std::max(maxX2, current->vertices[n].x); - maxY2 = std::max(maxY2, current->vertices[n].y); - maxZ2 = std::max(maxZ2, current->vertices[n].z); - } - - minX1 = std::min(minX2, minX1); - minY1 = std::min(minY2, minY1); - minZ1 = std::min(minZ2, minZ1); - - maxX1 = std::max(maxX2, maxX1); - maxY1 = std::max(maxY2, maxY1); - maxZ1 = std::max(maxZ2, maxZ1); - - if (minY1 == maxY1) - { - current->vertices[0] = Vector3(minX1, minY1, minZ1); - current->vertices[1] = Vector3(minX1, minY1, maxZ1); - current->vertices[2] = Vector3(maxX1, minY1, maxZ1); - current->vertices[3] = Vector3(maxX1, minY1, minZ1); - } - else if (minX1 == maxX1) - { - current->vertices[0] = Vector3(minX1, minY1, minZ1); - current->vertices[1] = Vector3(minX1, maxY1, minZ1); - current->vertices[2] = Vector3(minX1, maxY1, maxZ1); - current->vertices[3] = Vector3(minX1, minY1, maxZ1); - } - else if (minZ1 == maxZ1) - { - current->vertices[0] = Vector3(minX1, minY1, minZ1); - current->vertices[1] = Vector3(minX1, maxY1, minZ1); - current->vertices[2] = Vector3(maxX1, maxY1, minZ1); - current->vertices[3] = Vector3(maxX1, minY1, minZ1); - } - else - { - current->vertices[0] = Vector3(minX1, minY1, minZ1); - current->vertices[1] = Vector3(minX1, maxY1, maxZ1); - current->vertices[2] = Vector3(maxX1, maxY1, maxZ1); - current->vertices[3] = Vector3(maxX1, minY1, minZ1); - } - } - } - - if (!found) - room.doors.push_back(door); + room.doors.push_back(door); } \ No newline at end of file diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index 14be600e6..80144bcdf 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -450,8 +450,9 @@ struct ItemT : public flatbuffers::NativeTable { bool collidable = false; bool looked_at = false; int32_t ai_bits = 0; - int32_t swap_mesh_flags = 0; TEN::Save::ItemDataUnion data{}; + int32_t base_mesh = 0; + std::vector mesh_pointers{}; std::string lua_name{}; std::string lua_on_killed_name{}; std::string lua_on_hit_name{}; @@ -495,14 +496,15 @@ struct Item FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_COLLIDABLE = 60, VT_LOOKED_AT = 62, VT_AI_BITS = 64, - VT_SWAP_MESH_FLAGS = 66, - VT_DATA_TYPE = 68, - VT_DATA = 70, - VT_LUA_NAME = 72, - VT_LUA_ON_KILLED_NAME = 74, - VT_LUA_ON_HIT_NAME = 76, - VT_LUA_ON_COLLIDED_WITH_OBJECT_NAME = 78, - VT_LUA_ON_COLLIDED_WITH_ROOM_NAME = 80 + VT_DATA_TYPE = 66, + VT_DATA = 68, + VT_BASE_MESH = 70, + VT_MESH_POINTERS = 72, + VT_LUA_NAME = 74, + VT_LUA_ON_KILLED_NAME = 76, + VT_LUA_ON_HIT_NAME = 78, + VT_LUA_ON_COLLIDED_WITH_OBJECT_NAME = 80, + VT_LUA_ON_COLLIDED_WITH_ROOM_NAME = 82 }; int32_t active_state() const { return GetField(VT_ACTIVE_STATE, 0); @@ -597,9 +599,6 @@ struct Item FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { int32_t ai_bits() const { return GetField(VT_AI_BITS, 0); } - int32_t swap_mesh_flags() const { - return GetField(VT_SWAP_MESH_FLAGS, 0); - } TEN::Save::ItemData data_type() const { return static_cast(GetField(VT_DATA_TYPE, 0)); } @@ -673,6 +672,12 @@ struct Item FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::Minecart *data_as_Minecart() const { return data_type() == TEN::Save::ItemData::Minecart ? static_cast(data()) : nullptr; } + int32_t base_mesh() const { + return GetField(VT_BASE_MESH, 0); + } + const flatbuffers::Vector *mesh_pointers() const { + return GetPointer *>(VT_MESH_POINTERS); + } const flatbuffers::String *lua_name() const { return GetPointer(VT_LUA_NAME); } @@ -722,10 +727,12 @@ struct Item FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_COLLIDABLE) && VerifyField(verifier, VT_LOOKED_AT) && VerifyField(verifier, VT_AI_BITS) && - VerifyField(verifier, VT_SWAP_MESH_FLAGS) && VerifyField(verifier, VT_DATA_TYPE) && VerifyOffset(verifier, VT_DATA) && VerifyItemData(verifier, data(), data_type()) && + VerifyField(verifier, VT_BASE_MESH) && + VerifyOffset(verifier, VT_MESH_POINTERS) && + verifier.VerifyVector(mesh_pointers()) && VerifyOffset(verifier, VT_LUA_NAME) && verifier.VerifyString(lua_name()) && VerifyOffset(verifier, VT_LUA_ON_KILLED_NAME) && @@ -928,15 +935,18 @@ struct ItemBuilder { void add_ai_bits(int32_t ai_bits) { fbb_.AddElement(Item::VT_AI_BITS, ai_bits, 0); } - void add_swap_mesh_flags(int32_t swap_mesh_flags) { - fbb_.AddElement(Item::VT_SWAP_MESH_FLAGS, swap_mesh_flags, 0); - } void add_data_type(TEN::Save::ItemData data_type) { fbb_.AddElement(Item::VT_DATA_TYPE, static_cast(data_type), 0); } void add_data(flatbuffers::Offset data) { fbb_.AddOffset(Item::VT_DATA, data); } + void add_base_mesh(int32_t base_mesh) { + fbb_.AddElement(Item::VT_BASE_MESH, base_mesh, 0); + } + void add_mesh_pointers(flatbuffers::Offset> mesh_pointers) { + fbb_.AddOffset(Item::VT_MESH_POINTERS, mesh_pointers); + } void add_lua_name(flatbuffers::Offset lua_name) { fbb_.AddOffset(Item::VT_LUA_NAME, lua_name); } @@ -996,9 +1006,10 @@ inline flatbuffers::Offset CreateItem( bool collidable = false, bool looked_at = false, int32_t ai_bits = 0, - int32_t swap_mesh_flags = 0, TEN::Save::ItemData data_type = TEN::Save::ItemData::NONE, flatbuffers::Offset data = 0, + int32_t base_mesh = 0, + flatbuffers::Offset> mesh_pointers = 0, flatbuffers::Offset lua_name = 0, flatbuffers::Offset lua_on_killed_name = 0, flatbuffers::Offset lua_on_hit_name = 0, @@ -1010,8 +1021,9 @@ inline flatbuffers::Offset CreateItem( builder_.add_lua_on_hit_name(lua_on_hit_name); builder_.add_lua_on_killed_name(lua_on_killed_name); builder_.add_lua_name(lua_name); + builder_.add_mesh_pointers(mesh_pointers); + builder_.add_base_mesh(base_mesh); builder_.add_data(data); - builder_.add_swap_mesh_flags(swap_mesh_flags); builder_.add_ai_bits(ai_bits); builder_.add_status(status); builder_.add_next_item_active(next_item_active); @@ -1085,15 +1097,17 @@ inline flatbuffers::Offset CreateItemDirect( bool collidable = false, bool looked_at = false, int32_t ai_bits = 0, - int32_t swap_mesh_flags = 0, TEN::Save::ItemData data_type = TEN::Save::ItemData::NONE, flatbuffers::Offset data = 0, + int32_t base_mesh = 0, + const std::vector *mesh_pointers = nullptr, const char *lua_name = nullptr, const char *lua_on_killed_name = nullptr, const char *lua_on_hit_name = nullptr, const char *lua_on_collided_with_object_name = nullptr, const char *lua_on_collided_with_room_name = nullptr) { auto item_flags__ = item_flags ? _fbb.CreateVector(*item_flags) : 0; + auto mesh_pointers__ = mesh_pointers ? _fbb.CreateVector(*mesh_pointers) : 0; auto lua_name__ = lua_name ? _fbb.CreateString(lua_name) : 0; auto lua_on_killed_name__ = lua_on_killed_name ? _fbb.CreateString(lua_on_killed_name) : 0; auto lua_on_hit_name__ = lua_on_hit_name ? _fbb.CreateString(lua_on_hit_name) : 0; @@ -1132,9 +1146,10 @@ inline flatbuffers::Offset CreateItemDirect( collidable, looked_at, ai_bits, - swap_mesh_flags, data_type, data, + base_mesh, + mesh_pointers__, lua_name__, lua_on_killed_name__, lua_on_hit_name__, @@ -3338,7 +3353,6 @@ struct LaraT : public flatbuffers::NativeTable { int32_t burn_blue = 0; bool burn_smoke = false; std::vector wet{}; - std::vector mesh_ptrs{}; int32_t location = 0; int32_t highest_location = 0; int32_t location_pad = 0; @@ -3381,10 +3395,9 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_BURN_BLUE = 62, VT_BURN_SMOKE = 64, VT_WET = 66, - VT_MESH_PTRS = 68, - VT_LOCATION = 70, - VT_HIGHEST_LOCATION = 72, - VT_LOCATION_PAD = 74 + VT_LOCATION = 68, + VT_HIGHEST_LOCATION = 70, + VT_LOCATION_PAD = 72 }; int32_t item_number() const { return GetField(VT_ITEM_NUMBER, 0); @@ -3482,9 +3495,6 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *wet() const { return GetPointer *>(VT_WET); } - const flatbuffers::Vector *mesh_ptrs() const { - return GetPointer *>(VT_MESH_PTRS); - } int32_t location() const { return GetField(VT_LOCATION, 0); } @@ -3538,8 +3548,6 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_BURN_SMOKE) && VerifyOffset(verifier, VT_WET) && verifier.VerifyVector(wet()) && - VerifyOffset(verifier, VT_MESH_PTRS) && - verifier.VerifyVector(mesh_ptrs()) && VerifyField(verifier, VT_LOCATION) && VerifyField(verifier, VT_HIGHEST_LOCATION) && VerifyField(verifier, VT_LOCATION_PAD) && @@ -3650,9 +3658,6 @@ struct LaraBuilder { void add_wet(flatbuffers::Offset> wet) { fbb_.AddOffset(Lara::VT_WET, wet); } - void add_mesh_ptrs(flatbuffers::Offset> mesh_ptrs) { - fbb_.AddOffset(Lara::VT_MESH_PTRS, mesh_ptrs); - } void add_location(int32_t location) { fbb_.AddElement(Lara::VT_LOCATION, location, 0); } @@ -3707,7 +3712,6 @@ inline flatbuffers::Offset CreateLara( int32_t burn_blue = 0, bool burn_smoke = false, flatbuffers::Offset> wet = 0, - flatbuffers::Offset> mesh_ptrs = 0, int32_t location = 0, int32_t highest_location = 0, int32_t location_pad = 0) { @@ -3715,7 +3719,6 @@ inline flatbuffers::Offset CreateLara( builder_.add_location_pad(location_pad); builder_.add_highest_location(highest_location); builder_.add_location(location); - builder_.add_mesh_ptrs(mesh_ptrs); builder_.add_wet(wet); builder_.add_burn_blue(burn_blue); builder_.add_burn_count(burn_count); @@ -3790,14 +3793,12 @@ inline flatbuffers::Offset CreateLaraDirect( int32_t burn_blue = 0, bool burn_smoke = false, const std::vector *wet = nullptr, - const std::vector *mesh_ptrs = nullptr, int32_t location = 0, int32_t highest_location = 0, int32_t location_pad = 0) { auto weapons__ = weapons ? _fbb.CreateVector>(*weapons) : 0; auto target_arm_angles__ = target_arm_angles ? _fbb.CreateVector(*target_arm_angles) : 0; auto wet__ = wet ? _fbb.CreateVector(*wet) : 0; - auto mesh_ptrs__ = mesh_ptrs ? _fbb.CreateVector(*mesh_ptrs) : 0; return TEN::Save::CreateLara( _fbb, item_number, @@ -3832,7 +3833,6 @@ inline flatbuffers::Offset CreateLaraDirect( burn_blue, burn_smoke, wet__, - mesh_ptrs__, location, highest_location, location_pad); @@ -6652,9 +6652,10 @@ inline void Item::UnPackTo(ItemT *_o, const flatbuffers::resolver_function_t *_r { auto _e = collidable(); _o->collidable = _e; } { auto _e = looked_at(); _o->looked_at = _e; } { auto _e = ai_bits(); _o->ai_bits = _e; } - { auto _e = swap_mesh_flags(); _o->swap_mesh_flags = _e; } { auto _e = data_type(); _o->data.type = _e; } { auto _e = data(); if (_e) _o->data.value = TEN::Save::ItemDataUnion::UnPack(_e, data_type(), _resolver); } + { auto _e = base_mesh(); _o->base_mesh = _e; } + { auto _e = mesh_pointers(); if (_e) { _o->mesh_pointers.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->mesh_pointers[_i] = _e->Get(_i); } } } { auto _e = lua_name(); if (_e) _o->lua_name = _e->str(); } { auto _e = lua_on_killed_name(); if (_e) _o->lua_on_killed_name = _e->str(); } { auto _e = lua_on_hit_name(); if (_e) _o->lua_on_hit_name = _e->str(); } @@ -6701,9 +6702,10 @@ inline flatbuffers::Offset CreateItem(flatbuffers::FlatBufferBuilder &_fbb auto _collidable = _o->collidable; auto _looked_at = _o->looked_at; auto _ai_bits = _o->ai_bits; - auto _swap_mesh_flags = _o->swap_mesh_flags; auto _data_type = _o->data.type; auto _data = _o->data.Pack(_fbb); + auto _base_mesh = _o->base_mesh; + auto _mesh_pointers = _fbb.CreateVector(_o->mesh_pointers); auto _lua_name = _o->lua_name.empty() ? _fbb.CreateSharedString("") : _fbb.CreateString(_o->lua_name); auto _lua_on_killed_name = _o->lua_on_killed_name.empty() ? _fbb.CreateSharedString("") : _fbb.CreateString(_o->lua_on_killed_name); auto _lua_on_hit_name = _o->lua_on_hit_name.empty() ? _fbb.CreateSharedString("") : _fbb.CreateString(_o->lua_on_hit_name); @@ -6742,9 +6744,10 @@ inline flatbuffers::Offset CreateItem(flatbuffers::FlatBufferBuilder &_fbb _collidable, _looked_at, _ai_bits, - _swap_mesh_flags, _data_type, _data, + _base_mesh, + _mesh_pointers, _lua_name, _lua_on_killed_name, _lua_on_hit_name, @@ -7504,7 +7507,6 @@ inline void Lara::UnPackTo(LaraT *_o, const flatbuffers::resolver_function_t *_r { auto _e = burn_blue(); _o->burn_blue = _e; } { auto _e = burn_smoke(); _o->burn_smoke = _e; } { auto _e = wet(); if (_e) { _o->wet.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->wet[_i] = _e->Get(_i) != 0; } } } - { auto _e = mesh_ptrs(); if (_e) { _o->mesh_ptrs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->mesh_ptrs[_i] = _e->Get(_i); } } } { auto _e = location(); _o->location = _e; } { auto _e = highest_location(); _o->highest_location = _e; } { auto _e = location_pad(); _o->location_pad = _e; } @@ -7550,7 +7552,6 @@ inline flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb auto _burn_blue = _o->burn_blue; auto _burn_smoke = _o->burn_smoke; auto _wet = _fbb.CreateVector(_o->wet); - auto _mesh_ptrs = _fbb.CreateVector(_o->mesh_ptrs); auto _location = _o->location; auto _highest_location = _o->highest_location; auto _location_pad = _o->location_pad; @@ -7588,7 +7589,6 @@ inline flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb _burn_blue, _burn_smoke, _wet, - _mesh_ptrs, _location, _highest_location, _location_pad); diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index d734b53f2..d56d0afda 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -39,8 +39,11 @@ table Item { collidable: bool; looked_at: bool; ai_bits: int32; - swap_mesh_flags: int32; data: TEN.Save.ItemData; + + base_mesh: int32; + mesh_pointers: [int32]; + lua_name: string; lua_on_killed_name: string; lua_on_hit_name: string; @@ -255,7 +258,6 @@ table Lara { burn_blue: int32; burn_smoke: bool; wet: [bool]; - mesh_ptrs: [int32]; location: int32; highest_location: int32; location_pad: int32; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 32e205e7b..bf7ebb046 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -166,7 +166,6 @@ CALL gen.bat - @@ -630,7 +629,6 @@ CALL gen.bat -