Merge branch 'develop' into develop_60fps

This commit is contained in:
Lwmte 2024-10-05 00:28:40 +02:00
commit cb0e8fb23e
23 changed files with 141 additions and 65 deletions

View file

@ -11,6 +11,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Bug fixes ### Bug fixes
* Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions.
* Fixed leveljump vehicle transfer. * Fixed leveljump vehicle transfer.
* Fixed sarcophagus pick-ups.
* Fixed several binocular bugs.
* Fixed incorrect diving animation when swandiving from a high place. * Fixed incorrect diving animation when swandiving from a high place.
* Fixed camera rotating with the player's hips when climbing out of water. * Fixed camera rotating with the player's hips when climbing out of water.
* Fixed AI for TR2 skidoo driver and worker with shotgun. * Fixed AI for TR2 skidoo driver and worker with shotgun.
@ -56,14 +58,14 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Lua API changes ### Lua API changes
* Added Flow.EnableHomeLevel() * Added Flow.EnableHomeLevel() function.
* Added Flow.LensFlare() * Added Flow.IsStringPresent() function.
* Added Flow.Starfield()
* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions.
* Added Input.KeyClearAll() * Added Flow.LensFlare() and Flow.Starfield() classes.
* Added Room:GetRoomNumber() * Added Input.KeyClearAll() function.
* Added Room:GetRoomNumber() function.
* Removed anims.monkeyAutoJump. It is now a player menu configuration. * Removed anims.monkeyAutoJump. It is now a player menu configuration.
* Fixed Volume:GetActive() method * Fixed Volume:GetActive() method.
## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21

View file

@ -13,8 +13,12 @@
#include "Game/Lara/PlayerStateMachine.h" #include "Game/Lara/PlayerStateMachine.h"
#include "Game/Setup.h" #include "Game/Setup.h"
#include "Objects/TR2/Vehicles/skidoo.h" #include "Objects/TR2/Vehicles/skidoo.h"
#include "Objects/TR2/Vehicles/speedboat.h"
#include "Objects/TR3/Vehicles/kayak.h" #include "Objects/TR3/Vehicles/kayak.h"
#include "Objects/TR3/Vehicles/minecart.h"
#include "Objects/TR3/Vehicles/quad_bike.h" #include "Objects/TR3/Vehicles/quad_bike.h"
#include "Objects/TR3/Vehicles/rubber_boat.h"
#include "Objects/TR3/Vehicles/upv.h"
#include "Objects/TR4/Vehicles/jeep.h" #include "Objects/TR4/Vehicles/jeep.h"
#include "Objects/TR4/Vehicles/motorbike.h" #include "Objects/TR4/Vehicles/motorbike.h"
#include "Specific/level.h" #include "Specific/level.h"
@ -200,7 +204,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem)
{ {
case GAME_OBJECT_ID::ID_KAYAK: case GAME_OBJECT_ID::ID_KAYAK:
InitializeKayak(vehicle->Index); InitializeKayak(vehicle->Index);
KayakPaddleTake(&playerItem); KayakPaddleTake(GetKayakInfo(&g_Level.Items[vehicle->Index]), &playerItem);
break; break;
case GAME_OBJECT_ID::ID_MOTORBIKE: case GAME_OBJECT_ID::ID_MOTORBIKE:
@ -220,12 +224,37 @@ static void InitializePlayerVehicle(ItemInfo& playerItem)
break; break;
case GAME_OBJECT_ID::ID_MINECART: case GAME_OBJECT_ID::ID_MINECART:
playerItem.Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; MinecartWrenchTake(GetMinecartInfo(&g_Level.Items[vehicle->Index]), &playerItem);
break;
case GAME_OBJECT_ID::ID_SPEEDBOAT:
InitializeSpeedboat(vehicle->Index);
DoSpeedboatMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart);
break;
case GAME_OBJECT_ID::ID_RUBBER_BOAT:
InitializeRubberBoat(vehicle->Index);
DoRubberBoatMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart);
break;
case GAME_OBJECT_ID::ID_UPV:
DoUPVMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart);
GetUPVInfo(&g_Level.Items[vehicle->Index])->Flags = UPVFlags::UPV_FLAG_CONTROL;
break; break;
default: default:
break; break;
} }
// HACK: Reset activity status because boats need to be on active item linked list.
if (vehicle->ObjectNumber == GAME_OBJECT_ID::ID_RUBBER_BOAT ||
vehicle->ObjectNumber == GAME_OBJECT_ID::ID_SPEEDBOAT)
{
g_Level.Items[vehicle->Index].Active = false;
AddActiveItem(vehicle->Index);
g_Level.Items[vehicle->Index].Status = ITEM_ACTIVE;
}
} }
void InitializeLaraLevelJump(ItemInfo* item, LaraInfo* playerBackup) void InitializeLaraLevelJump(ItemInfo* item, LaraInfo* playerBackup)

View file

@ -952,6 +952,7 @@ void BinocularCamera(ItemInfo* item)
player.Inventory.IsBusy = false; player.Inventory.IsBusy = false;
Camera.type = BinocularOldCamera; Camera.type = BinocularOldCamera;
Camera.target = LastTarget;
AlterFOV(LastFOV); AlterFOV(LastFOV);
return; return;
} }
@ -1025,6 +1026,8 @@ void BinocularCamera(ItemInfo* item)
if (IsHeld(In::Action)) if (IsHeld(In::Action))
{ {
ClearAction(In::Action);
auto origin = Camera.pos.ToVector3i(); auto origin = Camera.pos.ToVector3i();
auto target = Camera.target.ToVector3i(); auto target = Camera.target.ToVector3i();
LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192); LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192);
@ -1519,6 +1522,21 @@ void ItemsCollideCamera()
staticList.clear(); staticList.clear();
} }
void UpdateCamera()
{
if (UseSpotCam)
{
// Draw flyby cameras.
CalculateSpotCameras();
}
else
{
// Do the standard camera.
TrackCameraInit = false;
CalculateCamera(LaraCollision);
}
}
void UpdateMikePos(const ItemInfo& item) void UpdateMikePos(const ItemInfo& item)
{ {
if (Camera.mikeAtLara) if (Camera.mikeAtLara)

View file

@ -105,16 +105,18 @@ void RumbleScreen();
bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius); bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius);
void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius); void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius);
void ItemsCollideCamera(); void ItemsCollideCamera();
void RefreshFixedCamera(short camNumber);
void ObjCamera(ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID, bool cond); void ObjCamera(ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID, bool cond);
void MoveObjCamera(GameVector* ideal, ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID); void MoveObjCamera(GameVector* ideal, ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID);
void RefreshFixedCamera(short camNumber); void ClearObjCamera();
void SetScreenFadeOut(float speed, bool force = false); void SetScreenFadeOut(float speed, bool force = false);
void SetScreenFadeIn(float speed, bool force = false); void SetScreenFadeIn(float speed, bool force = false);
void SetCinematicBars(float height, float speed); void SetCinematicBars(float height, float speed);
void ClearCinematicBars(); void ClearCinematicBars();
void UpdateCamera();
void UpdateFadeScreenAndCinematicBars(); void UpdateFadeScreenAndCinematicBars();
void UpdateMikePos(const ItemInfo& item); void UpdateMikePos(const ItemInfo& item);
void ClearObjCamera();
float GetParticleDistanceFade(const Vector3i& pos); float GetParticleDistanceFade(const Vector3i& pos);

View file

@ -92,7 +92,6 @@ using namespace TEN::Entities::Effects;
int GameTimer = 0; int GameTimer = 0;
int GlobalCounter = 0; int GlobalCounter = 0;
int Wibble = 0;
bool InitializeGame; bool InitializeGame;
bool DoTheGame; bool DoTheGame;
@ -179,27 +178,13 @@ GameStatus ControlPhase()
ApplyActionQueue(); ApplyActionQueue();
ClearActionQueue(); ClearActionQueue();
UpdateCamera();
UpdateAllItems(); UpdateAllItems();
UpdateAllEffects(); UpdateAllEffects();
UpdateLara(LaraItem, isTitle); UpdateLara(LaraItem, isTitle);
g_GameScriptEntities->TestCollidingObjects(); g_GameScriptEntities->TestCollidingObjects();
// Draw flyby cameras.
if (UseSpotCam)
{
CalculateSpotCameras();
}
// Do standard camera.
else
{
TrackCameraInit = false;
CalculateCamera(LaraCollision);
}
// Update oscillator seed.
Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX;
// Smash shatters and clear stopper flags under them. // Smash shatters and clear stopper flags under them.
UpdateShatters(); UpdateShatters();
@ -216,6 +201,7 @@ GameStatus ControlPhase()
// Update effects. // Update effects.
StreamerEffect.Update(); StreamerEffect.Update();
UpdateWibble();
UpdateSparks(); UpdateSparks();
UpdateFireSparks(); UpdateFireSparks();
UpdateSmoke(); UpdateSmoke();

View file

@ -50,15 +50,11 @@ enum FadeStatus
constexpr int MAX_ROOMS = 1024; constexpr int MAX_ROOMS = 1024;
constexpr int WIBBLE_SPEED = 4;
constexpr int WIBBLE_MAX = UCHAR_MAX - WIBBLE_SPEED + 1;
constexpr int LOOP_FRAME_COUNT = 2; constexpr int LOOP_FRAME_COUNT = 2;
extern int GameTimer; extern int GameTimer;
extern int RumbleTimer; extern int RumbleTimer;
extern int GlobalCounter; extern int GlobalCounter;
extern int Wibble;
extern bool InitializeGame; extern bool InitializeGame;
extern bool DoTheGame; extern bool DoTheGame;

View file

@ -40,6 +40,9 @@ using namespace TEN::Math::Random;
using TEN::Renderer::g_Renderer; using TEN::Renderer::g_Renderer;
constexpr int WIBBLE_SPEED = 4;
constexpr int WIBBLE_MAX = UCHAR_MAX - WIBBLE_SPEED + 1;
// New particle class // New particle class
Particle Particles[MAX_PARTICLES]; Particle Particles[MAX_PARTICLES];
ParticleDynamic ParticleDynamics[MAX_PARTICLE_DYNAMICS]; ParticleDynamic ParticleDynamics[MAX_PARTICLE_DYNAMICS];
@ -49,7 +52,9 @@ FX_INFO EffectList[NUM_EFFECTS];
GameBoundingBox DeadlyBounds; GameBoundingBox DeadlyBounds;
SPLASH_SETUP SplashSetup; SPLASH_SETUP SplashSetup;
SPLASH_STRUCT Splashes[MAX_SPLASHES]; SPLASH_STRUCT Splashes[MAX_SPLASHES];
int SplashCount = 0; int SplashCount = 0;
int Wibble = 0;
Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax]; Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax];
NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] = NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] =
@ -180,6 +185,13 @@ void SetSpriteSequence(Particle& particle, GAME_OBJECT_ID objectID)
particle.spriteIndex = Objects[objectID].meshIndex + (int)round(Lerp(0.0f, numSprites, normalizedAge)); particle.spriteIndex = Objects[objectID].meshIndex + (int)round(Lerp(0.0f, numSprites, normalizedAge));
} }
void UpdateWibble()
{
// Update oscillator seed.
Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX;
}
void UpdateSparks() void UpdateSparks()
{ {
auto bounds = GameBoundingBox(LaraItem); auto bounds = GameBoundingBox(LaraItem);

View file

@ -18,6 +18,8 @@ constexpr auto NUM_EFFECTS = 256;
constexpr auto MAX_PARTICLES = 1024; constexpr auto MAX_PARTICLES = 1024;
constexpr auto MAX_PARTICLE_DYNAMICS = 8; constexpr auto MAX_PARTICLE_DYNAMICS = 8;
extern int Wibble;
enum SpriteEnumFlag enum SpriteEnumFlag
{ {
SP_NONE = 0, SP_NONE = 0,
@ -310,5 +312,6 @@ void TriggerRocketFire(int x, int y, int z);
void TriggerExplosionBubbles(int x, int y, int z, short roomNumber); void TriggerExplosionBubbles(int x, int y, int z, short roomNumber);
void Ricochet(Pose& pos); void Ricochet(Pose& pos);
void ProcessEffects(ItemInfo* item); void ProcessEffects(ItemInfo* item);
void UpdateWibble();
void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff); void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff);

View file

@ -221,14 +221,16 @@ namespace TEN::Entities::Vehicles
// SetupRipple(x, kayakItem->Pose.Position.y, z, -2 - (GetRandomControl() & 1), 0, Objects[ID_KAYAK_PADDLE_TRAIL_SPRITE].meshIndex,TO_RAD(kayakItem->Pose.Orientation.y)); // SetupRipple(x, kayakItem->Pose.Position.y, z, -2 - (GetRandomControl() & 1), 0, Objects[ID_KAYAK_PADDLE_TRAIL_SPRITE].meshIndex,TO_RAD(kayakItem->Pose.Orientation.y));
} }
void KayakPaddleTake(ItemInfo* laraItem) void KayakPaddleTake(KayakInfo* kayak, ItemInfo* laraItem)
{ {
kayak->Flags |= KAYAK_FLAG_PADDLE_MESH;
laraItem->Model.MeshIndex[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); laraItem->MeshBits.Clear(KayakLaraLegJoints);
} }
void KayakPaddlePut(ItemInfo* laraItem) void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem)
{ {
kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH;
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
laraItem->MeshBits.Set(KayakLaraLegJoints); laraItem->MeshBits.Set(KayakLaraLegJoints);
} }
@ -910,21 +912,13 @@ namespace TEN::Entities::Vehicles
case KAYAK_STATE_MOUNT_LEFT: case KAYAK_STATE_MOUNT_LEFT:
if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && frame == 24 && !(kayak->Flags & KAYAK_FLAG_PADDLE_MESH)) if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && frame == 24 && !(kayak->Flags & KAYAK_FLAG_PADDLE_MESH))
{ KayakPaddleTake(kayak, laraItem);
kayak->Flags |= KAYAK_FLAG_PADDLE_MESH;
KayakPaddleTake(laraItem);
}
break; break;
case KAYAK_STATE_DISMOUNT: case KAYAK_STATE_DISMOUNT:
if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && frame == 27 && kayak->Flags & KAYAK_FLAG_PADDLE_MESH)
{
kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH;
KayakPaddlePut(laraItem);
}
laraItem->Animation.TargetState = laraItem->Animation.RequiredState; laraItem->Animation.TargetState = laraItem->Animation.RequiredState;
if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && frame == 27 && kayak->Flags & KAYAK_FLAG_PADDLE_MESH)
KayakPaddlePut(kayak, laraItem);
break; break;
case KAYAK_STATE_DISMOUNT_LEFT: case KAYAK_STATE_DISMOUNT_LEFT:

View file

@ -6,13 +6,14 @@ struct ItemInfo;
namespace TEN::Entities::Vehicles namespace TEN::Entities::Vehicles
{ {
KayakInfo* GetKayakInfo(ItemInfo* kayakItem);
void InitializeKayak(short itemNumber); void InitializeKayak(short itemNumber);
void KayakPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void KayakPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoKayakMount(ItemInfo* kayakItem, ItemInfo* laraItem, VehicleMountType mountType); void DoKayakMount(ItemInfo* kayakItem, ItemInfo* laraItem, VehicleMountType mountType);
void KayakPaddleTake(ItemInfo* laraItem); void KayakPaddleTake(KayakInfo* kayak, ItemInfo* laraItem);
void KayakPaddlePut(ItemInfo* laraItem); void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem);
void KayakDraw(ItemInfo* kayakItem); void KayakDraw(ItemInfo* kayakItem);

View file

@ -241,6 +241,18 @@ namespace TEN::Entities::Vehicles
} }
} }
void MinecartWrenchTake(MinecartInfo* minecart, ItemInfo* laraItem)
{
laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND;
minecart->Flags |= MINECART_FLAG_WRENCH_MESH;
}
void MinecartWrenchPut(MinecartInfo* minecart, ItemInfo* laraItem)
{
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH;
}
static int GetMinecartCollision(ItemInfo* minecartItem, short angle, int distance) static int GetMinecartCollision(ItemInfo* minecartItem, short angle, int distance)
{ {
auto probe = GetPointCollision(*minecartItem, angle, distance, -LARA_HEIGHT); auto probe = GetPointCollision(*minecartItem, angle, distance, -LARA_HEIGHT);
@ -755,8 +767,7 @@ namespace TEN::Entities::Vehicles
if (laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME) && if (laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME) &&
minecart->Flags & MINECART_FLAG_WRENCH_MESH) minecart->Flags & MINECART_FLAG_WRENCH_MESH)
{ {
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; MinecartWrenchPut(minecart, laraItem);
minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH;
} }
if (minecart->Flags & MINECART_FLAG_DISMOUNT_RIGHT) if (minecart->Flags & MINECART_FLAG_DISMOUNT_RIGHT)
@ -804,8 +815,7 @@ namespace TEN::Entities::Vehicles
if (!(minecart->Flags & MINECART_FLAG_WRENCH_MESH) && if (!(minecart->Flags & MINECART_FLAG_WRENCH_MESH) &&
laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME)) laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME))
{ {
laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; MinecartWrenchTake(minecart, laraItem);
minecart->Flags |= MINECART_FLAG_WRENCH_MESH;
} }
} }

View file

@ -7,9 +7,13 @@ struct ItemInfo;
namespace TEN::Entities::Vehicles namespace TEN::Entities::Vehicles
{ {
void InitializeMinecart(short itemNumber); void InitializeMinecart(short itemNumber);
MinecartInfo* GetMinecartInfo(ItemInfo* minecartItem);
void MinecartPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void MinecartPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoMinecartMount(ItemInfo* minecartItem, ItemInfo* laraItem, VehicleMountType mountType); void DoMinecartMount(ItemInfo* minecartItem, ItemInfo* laraItem, VehicleMountType mountType);
bool MinecartControl(ItemInfo* laraItem); bool MinecartControl(ItemInfo* laraItem);
void MinecartWrenchTake(MinecartInfo* minecart, ItemInfo* laraItem);
void MinecartWrenchPut(MinecartInfo* minecart, ItemInfo* laraItem);
} }

View file

@ -151,21 +151,13 @@ namespace TEN::Entities::Vehicles
UPV_BITE_RIGHT_RUDDER_RIGHT = 4, UPV_BITE_RIGHT_RUDDER_RIGHT = 4,
UPV_BITE_RIGHT_RUDDER_LEFT = 5 // Unused. UPV_BITE_RIGHT_RUDDER_LEFT = 5 // Unused.
}; };
enum UPVFlags
{
UPV_FLAG_CONTROL = (1 << 0),
UPV_FLAG_SURFACE = (1 << 1),
UPV_FLAG_DIVE = (1 << 2),
UPV_FLAG_DEAD = (1 << 3)
};
UPVInfo* GetUPVInfo(ItemInfo* UPVItem) UPVInfo* GetUPVInfo(ItemInfo* UPVItem)
{ {
return (UPVInfo*)UPVItem->Data; return (UPVInfo*)UPVItem->Data;
} }
void UPVInitialize(short itemNumber) void InitializeUPV(short itemNumber)
{ {
auto* UPVItem = &g_Level.Items[itemNumber]; auto* UPVItem = &g_Level.Items[itemNumber];
UPVItem->Data = UPVInfo(); UPVItem->Data = UPVInfo();

View file

@ -6,7 +6,16 @@ struct ItemInfo;
namespace TEN::Entities::Vehicles namespace TEN::Entities::Vehicles
{ {
void UPVInitialize(short itemNumber); enum UPVFlags
{
UPV_FLAG_CONTROL = (1 << 0),
UPV_FLAG_SURFACE = (1 << 1),
UPV_FLAG_DIVE = (1 << 2),
UPV_FLAG_DEAD = (1 << 3)
};
void InitializeUPV(short itemNumber);
UPVInfo* GetUPVInfo(ItemInfo* UPVItem);
void UPVPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void UPVPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoUPVMount(ItemInfo* UPVItem, ItemInfo* laraItem, VehicleMountType mountType); void DoUPVMount(ItemInfo* UPVItem, ItemInfo* laraItem, VehicleMountType mountType);

View file

@ -583,7 +583,7 @@ static void StartVehicles(ObjectInfo* obj)
obj = &Objects[ID_UPV]; obj = &Objects[ID_UPV];
if (obj->loaded) if (obj->loaded)
{ {
obj->Initialize = UPVInitialize; obj->Initialize = InitializeUPV;
obj->control = UPVEffects; obj->control = UPVEffects;
obj->collision = UPVPlayerCollision; obj->collision = UPVPlayerCollision;
obj->shadowType = ShadowMode::Lara; obj->shadowType = ShadowMode::Lara;

View file

@ -3,6 +3,7 @@
#include "Game/collision/collide_room.h" #include "Game/collision/collide_room.h"
#include "Game/control/flipeffect.h" #include "Game/control/flipeffect.h"
#include "Game/effects/effects.h"
#include "Game/items.h" #include "Game/items.h"
#include "Game/Lara/lara.h" #include "Game/Lara/lara.h"
#include "Game/Setup.h" #include "Game/Setup.h"

View file

@ -73,6 +73,6 @@ void SarcophagusCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* c
} }
else else
{ {
CollectMultiplePickups(sarcItem->Index); CollectCarriedItems(sarcItem);
} }
} }

View file

@ -1311,8 +1311,8 @@ namespace TEN::Renderer
case RendererDebugPage::PlayerStats: case RendererDebugPage::PlayerStats:
PrintDebugMessage("PLAYER STATS"); PrintDebugMessage("PLAYER STATS");
PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID); PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID);
PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber); PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber - Objects[LaraItem->Animation.AnimObjectID].animIndex);
PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber); PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber - GetAnimData(LaraItem).frameBase);
PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState); PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState);
PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState); PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState);
PrintDebugMessage("Velocity: %.3f, %.3f, %.3f", LaraItem->Animation.Velocity.z, LaraItem->Animation.Velocity.y, LaraItem->Animation.Velocity.x); PrintDebugMessage("Velocity: %.3f, %.3f, %.3f", LaraItem->Animation.Velocity.z, LaraItem->Animation.Velocity.y, LaraItem->Animation.Velocity.x);

View file

@ -85,6 +85,9 @@ void Renderer::UpdateLaraAnimations(bool force)
if (!force && rItem.DoneAnimations) if (!force && rItem.DoneAnimations)
return; return;
if (_moveableObjects.empty())
return;
auto& playerObject = *_moveableObjects[ID_LARA]; auto& playerObject = *_moveableObjects[ID_LARA];
// Clear extra rotations. // Clear extra rotations.

View file

@ -227,6 +227,7 @@ static constexpr char ScriptReserved_EnablePointFilter[] = "EnablePointFilter";
// Flow Functions // Flow Functions
static constexpr char ScriptReserved_SetStrings[] = "SetStrings"; static constexpr char ScriptReserved_SetStrings[] = "SetStrings";
static constexpr char ScriptReserved_GetString[] = "GetString"; static constexpr char ScriptReserved_GetString[] = "GetString";
static constexpr char ScriptReserved_IsStringPresent[] = "IsStringPresent";
static constexpr char ScriptReserved_SetLanguageNames[] = "SetLanguageNames"; static constexpr char ScriptReserved_SetLanguageNames[] = "SetLanguageNames";
// Flow Tables // Flow Tables

View file

@ -248,6 +248,12 @@ You will not need to call them manually.
*/ */
tableFlow.set_function(ScriptReserved_GetString, &FlowHandler::GetString, this); tableFlow.set_function(ScriptReserved_GetString, &FlowHandler::GetString, this);
/*** Check if translated string is present.
@function IsStringPresent
@tparam key string key for translated string
*/
tableFlow.set_function(ScriptReserved_IsStringPresent, &FlowHandler::IsStringPresent, this);
/*** Set language names for translations. /*** Set language names for translations.
Specify which translations in the strings table correspond to which languages. Specify which translations in the strings table correspond to which languages.
@function SetLanguageNames @function SetLanguageNames
@ -373,6 +379,11 @@ char const * FlowHandler::GetString(const char* id) const
} }
} }
bool FlowHandler::IsStringPresent(const char* id) const
{
return _translationMap.find(id) != _translationMap.end();
}
Settings* FlowHandler::GetSettings() Settings* FlowHandler::GetSettings()
{ {
return &_settings; return &_settings;

View file

@ -51,6 +51,7 @@ public:
void AddLevel(Level const& level); void AddLevel(Level const& level);
void LoadFlowScript(); void LoadFlowScript();
char const* GetString(const char* id) const; char const* GetString(const char* id) const;
bool IsStringPresent(const char* id) const;
void SetStrings(sol::nested<std::unordered_map<std::string, std::vector<std::string>>>&& src); void SetStrings(sol::nested<std::unordered_map<std::string, std::vector<std::string>>>&& src);
void SetLanguageNames(sol::as_table_t<std::vector<std::string>>&& src); void SetLanguageNames(sol::as_table_t<std::vector<std::string>>&& src);
void SetAnimations(const Animations& src); void SetAnimations(const Animations& src);

View file

@ -1471,7 +1471,8 @@ void GetCarriedItems()
const auto& object = Objects[item.ObjectNumber]; const auto& object = Objects[item.ObjectNumber];
if (object.intelligent || if (object.intelligent ||
(item.ObjectNumber >= ID_SEARCH_OBJECT1 && item.ObjectNumber <= ID_SEARCH_OBJECT3)) (item.ObjectNumber >= ID_SEARCH_OBJECT1 && item.ObjectNumber <= ID_SEARCH_OBJECT3) ||
(item.ObjectNumber == ID_SARCOPHAGUS))
{ {
for (short linkNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) for (short linkNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem)
{ {