Merge branch 'MontyTRC89:develop' into develop

This commit is contained in:
davidmarr 2024-10-09 19:59:14 +02:00 committed by GitHub
commit bfcd93f52c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 470 additions and 317 deletions

View file

@ -10,6 +10,11 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Bug fixes
* Fixed original issue with classic switch off trigger incorrectly activating some trigger actions.
* Fixed leveljump vehicle transfer.
* Fixed sarcophagus pick-ups.
* Fixed several binocular bugs.
* Fixed incorrect climbing out of water on bridge objects.
* Fixed faulty death sectors.
* Fixed incorrect diving animation when swandiving from a high place.
* Fixed camera rotating with the player's hips when climbing out of water.
* Fixed AI for TR2 skidoo driver and worker with shotgun.
@ -26,37 +31,43 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed teeth spikes not triggering the player impale animation.
* Fixed TR4 mine crash with OCB 1 when triggered.
* Fixed cases where Atlantean mutant's bombs cause the game to crash.
* Fixed young hair drawing.
* Fixed young Lara hair drawing. https://tombengine.com/docs/level-settings/#young_lara
### Features/Amendments
* Changed Rome Hammer to not hurt player whilst deactivated.
* Changed Statue with blade damage, from 20 to 200.
* Enhanced Rolling Spindle detection to avoid them going down through pits.
* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 )
* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ).
* Enhanced raptor behaviour and handling.
- OCB 0: Classic behaviour
- OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide.
- You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2
* Added TR3 seal mutant.
- OCB 0: Normal enemy behaviour. (TR3 RX-Tech mines level)
- OCB 1: Trap like behaviour. (TR3 Antarctica level)
* Added variable framerate , that allows the engine to run at an unlocked framerate for a much smoother experience. Setting can be toggled on or off in the graphical settings menu.
* Added a customisable global lensflare effect. https://tombengine.com/docs/level-settings/#lensflare
* Added a customisable starry sky and meteor effect (based on TR5). https://tombengine.com/docs/level-settings/#stars
* Added the ability to display "Lara's Home" entry in the main menu.
* Added F12 as alternative to PrtSc for screenshots.
* Added option to enable or disable menu option looping.
- Menu scrolling using held inputs will stop at the last option until a new input is made.
* Added TR3 seal mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant
- You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2
* Add new sound conditions: Quicksand and Underwater.
- Quicksand - sound effect plays when a moveable is in quicksand.
- Underwater - sound plays when the camera is submerged.
* Added TR4 Enemy_Jeep https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep
* Changed Rome Hammer to not hurt player whilst deactivated.
* Changed Statue with blade damage, from 20 to 200.
* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed.
* Changed Water sound condition to ShallowWater.
* Added option to enable or disable menu option looping.
* Menu scrolling using held inputs will stop at the last option until a new input is made.
* Added the ability to display "Lara's Home" entry in the main menu.
* Added F12 as alternative to PrtSc for screenshots.
* Enhanced Rolling Spindle detection to avoid them going down through pits.
* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 )
* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing-dart emitter ).
* Enhanced raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor
- You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2
### Lua API changes
* Added Flow.EnableHomeLevel() function.
* Added Flow.IsStringPresent() function.
* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions.
* Added Input.KeyClearAll()
* Added Flow.EnableHomeLevel()
* Added Flow.LensFlare() and Flow.Starfield() classes.
* Added Input.KeyClearAll() function.
* Added Room:GetRoomNumber() function.
* 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

View file

@ -362,8 +362,6 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
coll->Setup.PrevFrameNumber = item->Animation.FrameNumber;
coll->Setup.PrevState = item->Animation.ActiveState;
UpdateLaraRoom(item, -LARA_HEIGHT / 2);
// Handle look-around.
if (((IsHeld(In::Look) && CanPlayerLookAround(*item)) ||
(player.Control.Look.IsUsingBinoculars || player.Control.Look.IsUsingLasersight)) &&
@ -378,6 +376,8 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
}
player.Control.Look.Mode = LookMode::None;
UpdateLaraRoom(item, -LARA_HEIGHT / 2);
// Process vehicles.
if (HandleLaraVehicle(item, coll))
return;

View file

@ -13,8 +13,12 @@
#include "Game/Lara/PlayerStateMachine.h"
#include "Game/Setup.h"
#include "Objects/TR2/Vehicles/skidoo.h"
#include "Objects/TR2/Vehicles/speedboat.h"
#include "Objects/TR3/Vehicles/kayak.h"
#include "Objects/TR3/Vehicles/minecart.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/motorbike.h"
#include "Specific/level.h"
@ -122,6 +126,9 @@ void InitializeLaraAnims(ItemInfo* item)
player.LeftArm.Locked = false;
player.RightArm.Locked = false;
if (PlayerVehicleObjectID != GAME_OBJECT_ID::ID_NO_OBJECT)
return;
if (TestEnvironment(ENV_FLAG_WATER, item))
{
SetAnimation(item, LA_UNDERWATER_IDLE);
@ -197,6 +204,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem)
{
case GAME_OBJECT_ID::ID_KAYAK:
InitializeKayak(vehicle->Index);
KayakPaddleTake(GetKayakInfo(&g_Level.Items[vehicle->Index]), &playerItem);
break;
case GAME_OBJECT_ID::ID_MOTORBIKE:
@ -215,9 +223,38 @@ static void InitializePlayerVehicle(ItemInfo& playerItem)
InitializeSkidoo(vehicle->Index);
break;
case GAME_OBJECT_ID::ID_MINECART:
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;
default:
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)

View file

@ -935,11 +935,11 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll)
// Extra bridge check.
if (coll->Front.Bridge != NO_VALUE)
{
int bridgeBorder = GetBridgeBorder(g_Level.Items[coll->Front.Bridge], false) - item->Pose.Position.y;
frontFloor = GetBridgeBorder(g_Level.Items[coll->Front.Bridge], false) - item->Pose.Position.y;
frontFloor = bridgeBorder - CLICK(0.5f);
if (frontFloor <= -CLICK(2) ||
frontFloor > CLICK(1.25f) - 4)
int bridgeBorder = frontFloor - CLICK(0.5f);
if (bridgeBorder <= -CLICK(2) ||
bridgeBorder > CLICK(1.25f) - 4)
{
return false;
}

View file

@ -952,9 +952,19 @@ void BinocularCamera(ItemInfo* item)
player.Inventory.IsBusy = false;
Camera.type = BinocularOldCamera;
Camera.target = LastTarget;
AlterFOV(LastFOV);
return;
}
if (IsHeld(In::Action))
{
ClearAction(In::Action);
auto origin = Camera.pos.ToVector3i();
auto target = Camera.target.ToVector3i();
LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192);
}
}
AlterFOV(7 * (ANGLE(11.5f) - player.Control.Look.OpticRange), false);
@ -1022,13 +1032,6 @@ void BinocularCamera(ItemInfo* item)
Camera.oldType = Camera.type;
GetTargetOnLOS(&Camera.pos, &Camera.target, false, false);
if (IsHeld(In::Action))
{
auto origin = Camera.pos.ToVector3i();
auto target = Camera.target.ToVector3i();
LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192);
}
}
void ConfirmCameraTargetPos()
@ -1518,6 +1521,21 @@ void ItemsCollideCamera()
staticList.clear();
}
void UpdateCamera()
{
if (UseSpotCam)
{
// Draw flyby cameras.
CalculateSpotCameras();
}
else
{
// Do the standard camera.
TrackCameraInit = false;
CalculateCamera(LaraCollision);
}
}
void UpdateMikePos(const ItemInfo& item)
{
if (Camera.mikeAtLara)
@ -1545,7 +1563,8 @@ void UpdateMikePos(const ItemInfo& item)
void RumbleScreen()
{
if (!(GlobalCounter & 0x1FF))
SoundEffect(SFX_TR5_KLAXON, nullptr, SoundEnvironment::Land, 0.25f);
// SFX Enum Changed from TR5 and pitch shift removed. User can set this in their sound XML. Stranger1992 31st August 2024
SoundEffect(SFX_TR4_ENVIORONMENT_RUMBLE, nullptr, SoundEnvironment::Land);
if (RumbleTimer >= 0)
RumbleTimer++;

View file

@ -103,16 +103,18 @@ void RumbleScreen();
bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius);
void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius);
void ItemsCollideCamera();
void RefreshFixedCamera(short camNumber);
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 RefreshFixedCamera(short camNumber);
void ClearObjCamera();
void SetScreenFadeOut(float speed, bool force = false);
void SetScreenFadeIn(float speed, bool force = false);
void SetCinematicBars(float height, float speed);
void ClearCinematicBars();
void UpdateCamera();
void UpdateFadeScreenAndCinematicBars();
void UpdateMikePos(const ItemInfo& item);
void ClearObjCamera();
float GetParticleDistanceFade(const Vector3i& pos);

View file

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

View file

@ -50,15 +50,11 @@ enum FadeStatus
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;
extern int GameTimer;
extern int RumbleTimer;
extern int GlobalCounter;
extern int Wibble;
extern bool InitializeGame;
extern bool DoTheGame;

View file

@ -40,6 +40,9 @@ using namespace TEN::Math::Random;
using TEN::Renderer::g_Renderer;
constexpr int WIBBLE_SPEED = 4;
constexpr int WIBBLE_MAX = UCHAR_MAX - WIBBLE_SPEED + 1;
// New particle class
Particle Particles[MAX_PARTICLES];
ParticleDynamic ParticleDynamics[MAX_PARTICLE_DYNAMICS];
@ -49,7 +52,9 @@ FX_INFO EffectList[NUM_EFFECTS];
GameBoundingBox DeadlyBounds;
SPLASH_SETUP SplashSetup;
SPLASH_STRUCT Splashes[MAX_SPLASHES];
int SplashCount = 0;
int Wibble = 0;
Vector3i NodeVectors[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));
}
void UpdateWibble()
{
// Update oscillator seed.
Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX;
}
void UpdateSparks()
{
auto bounds = GameBoundingBox(LaraItem);

View file

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

View file

@ -321,7 +321,7 @@ namespace TEN::Effects::Hair
{
auto& unit = Units[i];
auto objectID = (i == 0) ? ID_SINGLE_BRAID_HAIR : ID_DUAL_PIGTAIL_HAIR;
auto objectID = (i == 0) ? ID_HAIR_PRIMARY : ID_HAIR_SECONDARY;
const auto& object = Objects[objectID];
unit.IsEnabled = (object.loaded && (i == 0 || (i == 1 && isYoung)));

View file

@ -33,9 +33,9 @@ namespace TEN::Entities::Vehicles
constexpr int KAYAK_VELOCITY_LR_ACCEL = 16 * VEHICLE_VELOCITY_SCALE;
constexpr int KAYAK_VELOCITY_HOLD_TURN_DECEL = 0.5f * VEHICLE_VELOCITY_SCALE;
constexpr int KAYAK_VELOCITY_FRICTION_DECEL = 0.5f * VEHICLE_VELOCITY_SCALE;
constexpr int KAYAK_VELOCITY_MAX = 56 * VEHICLE_VELOCITY_SCALE;
constexpr auto KAYAK_FLAG_PADDLE_MESH = 0x80;
constexpr auto KAYAK_WAKE_OFFSET = Vector3(BLOCK(0.1f), 0.0f, BLOCK(0.25f));
// TODO: Very confusing.
@ -221,6 +221,20 @@ 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));
}
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->MeshBits.Clear(KayakLaraLegJoints);
}
void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem)
{
kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH;
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
laraItem->MeshBits.Set(KayakLaraLegJoints);
}
int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff)
{
xDiff = kayakItem->Pose.Position.x - xDiff;
@ -897,28 +911,14 @@ namespace TEN::Entities::Vehicles
break;
case KAYAK_STATE_MOUNT_LEFT:
if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) &&
frame == 24 &&
!(kayak->Flags & 0x80))
{
kayak->Flags |= 0x80;
laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND;
laraItem->MeshBits.Clear(KayakLaraLegJoints);
}
if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && frame == 24 && !(kayak->Flags & KAYAK_FLAG_PADDLE_MESH))
KayakPaddleTake(kayak, laraItem);
break;
case KAYAK_STATE_DISMOUNT:
if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) &&
frame == 27 &&
kayak->Flags & 0x80)
{
kayak->Flags &= ~0x80;
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
laraItem->MeshBits.Set(KayakLaraLegJoints);
}
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;
case KAYAK_STATE_DISMOUNT_LEFT:

View file

@ -6,11 +6,15 @@ struct ItemInfo;
namespace TEN::Entities::Vehicles
{
KayakInfo* GetKayakInfo(ItemInfo* kayakItem);
void InitializeKayak(short itemNumber);
void KayakPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoKayakMount(ItemInfo* kayakItem, ItemInfo* laraItem, VehicleMountType mountType);
void KayakPaddleTake(KayakInfo* kayak, ItemInfo* laraItem);
void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem);
void KayakDraw(ItemInfo* kayakItem);
void KayakDoRipple(ItemInfo* kayakItem, int xOffset, int zOffset);
@ -24,6 +28,5 @@ namespace TEN::Entities::Vehicles
void KayakUserInput(ItemInfo* kayakItem, ItemInfo* laraItem);
void KayakToItemCollision(ItemInfo* kayakItem, ItemInfo* laraItem);
void KayakLaraRapidsDrown(ItemInfo* laraItem);
void PreDrawWakeFx(ItemInfo* kayakItem);
bool KayakControl(ItemInfo* laraItem);
}

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)
{
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) &&
minecart->Flags & MINECART_FLAG_WRENCH_MESH)
{
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH;
MinecartWrenchPut(minecart, laraItem);
}
if (minecart->Flags & MINECART_FLAG_DISMOUNT_RIGHT)
@ -804,8 +815,7 @@ namespace TEN::Entities::Vehicles
if (!(minecart->Flags & MINECART_FLAG_WRENCH_MESH) &&
laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME))
{
laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND;
minecart->Flags |= MINECART_FLAG_WRENCH_MESH;
MinecartWrenchTake(minecart, laraItem);
}
}

View file

@ -7,9 +7,13 @@ struct ItemInfo;
namespace TEN::Entities::Vehicles
{
void InitializeMinecart(short itemNumber);
MinecartInfo* GetMinecartInfo(ItemInfo* minecartItem);
void MinecartPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoMinecartMount(ItemInfo* minecartItem, ItemInfo* laraItem, VehicleMountType mountType);
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_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)
{
return (UPVInfo*)UPVItem->Data;
}
void UPVInitialize(short itemNumber)
void InitializeUPV(short itemNumber)
{
auto* UPVItem = &g_Level.Items[itemNumber];
UPVItem->Data = UPVInfo();

View file

@ -6,7 +6,16 @@ struct ItemInfo;
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 DoUPVMount(ItemInfo* UPVItem, ItemInfo* laraItem, VehicleMountType mountType);

View file

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

View file

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

View file

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

View file

@ -40,8 +40,8 @@ enum GAME_OBJECT_ID : short
ID_LARA_DIRT_MESH,
ID_LARA_CROWBAR_ANIM,
ID_LARA_TORCH_ANIM,
ID_SINGLE_BRAID_HAIR,
ID_DUAL_PIGTAIL_HAIR,
ID_HAIR_PRIMARY,
ID_HAIR_SECONDARY,
ID_SNOWMOBILE_LARA_ANIMS = 50,
ID_SNOWMOBILE,

View file

@ -516,7 +516,7 @@ namespace TEN::Renderer
&moveable,
&g_Level.Meshes[obj->meshIndex + j],
j, MoveablesIds[i] == ID_LARA_SKIN_JOINTS,
MoveablesIds[i] == ID_SINGLE_BRAID_HAIR || MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR, &lastVertex, &lastIndex);
MoveablesIds[i] == ID_HAIR_PRIMARY || MoveablesIds[i] == ID_HAIR_SECONDARY, &lastVertex, &lastIndex);
moveable.ObjectMeshes.push_back(mesh);
_meshes.push_back(mesh);
@ -687,7 +687,7 @@ namespace TEN::Renderer
}
}
}
else if (MoveablesIds[i] == ID_SINGLE_BRAID_HAIR && isSkinPresent)
else if (MoveablesIds[i] == ID_HAIR_PRIMARY && isSkinPresent)
{
for (int j = 0; j < obj->nmeshes; j++)
{
@ -776,7 +776,7 @@ namespace TEN::Renderer
}
}
}
else if (MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR && isSkinPresent)
else if (MoveablesIds[i] == ID_HAIR_SECONDARY && isSkinPresent)
{
for (int j = 0; j < obj->nmeshes; j++)
{

View file

@ -1260,8 +1260,8 @@ namespace TEN::Renderer
case RendererDebugPage::PlayerStats:
PrintDebugMessage("PLAYER STATS");
PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID);
PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber);
PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber);
PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber - Objects[LaraItem->Animation.AnimObjectID].animIndex);
PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber - GetAnimData(LaraItem).frameBase);
PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState);
PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState);
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)
return;
if (_moveableObjects.empty())
return;
auto& playerObject = *_moveableObjects[ID_LARA];
// Clear extra rotations.

View file

@ -22,10 +22,8 @@ static constexpr char ScriptReserved_Sink[] = "Sink";
static constexpr char ScriptReserved_SoundSource[] = "SoundSource";
static constexpr char ScriptReserved_AIObject[] = "AIObject";
static constexpr char ScriptReserved_Volume[] = "Volume";
static constexpr char ScriptReserved_Room[] = "Room";
static constexpr char ScriptReserved_Color[] = "Color";
static constexpr char ScriptReserved_DisplayString[] = "DisplayString";
static constexpr char ScriptReserved_Vec2[] = "Vec2";
static constexpr char ScriptReserved_Rotation[] = "Rotation";
static constexpr char ScriptReserved_LevelFunc[] = "LevelFunc";
@ -198,7 +196,6 @@ static constexpr char ScriptReserved_IsMoveableInside[] = "IsMoveableInside";
static constexpr char ScriptReserved_GetFlag[] = "GetFlag";
static constexpr char ScriptReserved_SetFlag[] = "SetFlag";
static constexpr char ScriptReserved_IsTagPresent[] = "IsTagPresent";
static constexpr char ScriptReserved_SetReverbType[] = "SetReverbType";
// Flow Functions
static constexpr char ScriptReserved_AddLevel[] = "AddLevel";
@ -230,6 +227,7 @@ static constexpr char ScriptReserved_EnablePointFilter[] = "EnablePointFilter";
// Flow Functions
static constexpr char ScriptReserved_SetStrings[] = "SetStrings";
static constexpr char ScriptReserved_GetString[] = "GetString";
static constexpr char ScriptReserved_IsStringPresent[] = "IsStringPresent";
static constexpr char ScriptReserved_SetLanguageNames[] = "SetLanguageNames";
// Flow Tables
@ -371,22 +369,39 @@ static constexpr char ScriptReserved_LogLevelError[] = "ERROR";
// Internal
static constexpr char ScriptReserved_LaraObject[] = "LaraObject";
// Room
constexpr char ScriptReserved_Room[] = "Room";
constexpr char ScriptReserved_RoomGetActive[] = "GetActive";
constexpr char ScriptReserved_RoomGetColor[] = "GetColor";
constexpr char ScriptReserved_RoomGetFlag[] = "GetFlag";
constexpr char ScriptReserved_RoomGetName[] = "GetName";
constexpr char ScriptReserved_RoomGetReverbType[] = "GetReverbType";
constexpr char ScriptReserved_RoomGetRoomNumber[] = "GetRoomNumber";
constexpr char ScriptReserved_RoomIsTagPresent[] = "IsTagPresent";
constexpr char ScriptReserved_RoomSetFlag[] = "SetFlag";
constexpr char ScriptReserved_RoomSetName[] = "SetName";
constexpr char ScriptReserved_RoomSetReverbType[] = "SetReverbType";
// Vec2
constexpr char ScriptReserved_Vec2[] = "Vec2";
constexpr char ScriptReserved_Vec2Cross[] = "Cross";
constexpr char ScriptReserved_Vec2Distance[] = "Distance";
constexpr char ScriptReserved_Vec2Dot[] = "Dot";
constexpr char ScriptReserved_Vec2Length[] = "Length";
constexpr char ScriptReserved_Vec2Lerp[] = "Lerp";
constexpr char ScriptReserved_Vec2SetLength[] = "ToLength";
constexpr char ScriptReserved_Vec2Normalize[] = "Normalize";
constexpr char ScriptReserved_Vec2Rotate[] = "Rotate";
constexpr char ScriptReserved_Vec2Lerp[] = "Lerp";
constexpr char ScriptReserved_Vec2Cross[] = "Cross";
constexpr char ScriptReserved_Vec2Dot[] = "Dot";
constexpr char ScriptReserved_Vec2Distance[] = "Distance";
constexpr char ScriptReserved_Vec2Length[] = "Length";
// Vec3
constexpr char ScriptReserved_Vec3[] = "Vec3";
constexpr char ScriptReserved_Vec3Cross[] = "Cross";
constexpr char ScriptReserved_Vec3Distance[] = "Distance";
constexpr char ScriptReserved_Vec3Dot[] = "Dot";
constexpr char ScriptReserved_Vec3Length[] = "Length";
constexpr char ScriptReserved_Vec3Lerp[] = "Lerp";
constexpr char ScriptReserved_Vec3Normalize[] = "Normalize";
constexpr char ScriptReserved_Vec3Rotate[] = "Rotate";
constexpr char ScriptReserved_Vec3Lerp[] = "Lerp";
constexpr char ScriptReserved_Vec3Cross[] = "Cross";
constexpr char ScriptReserved_Vec3Dot[] = "Dot";
constexpr char ScriptReserved_Vec3Distance[] = "Distance";
constexpr char ScriptReserved_Vec3Length[] = "Length";

View file

@ -248,6 +248,12 @@ You will not need to call them manually.
*/
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.
Specify which translations in the strings table correspond to which languages.
@function SetLanguageNames
@ -371,6 +377,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()
{
return &_settings;

View file

@ -51,6 +51,7 @@ public:
void AddLevel(Level const& level);
void LoadFlowScript();
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 SetLanguageNames(sol::as_table_t<std::vector<std::string>>&& src);
void SetAnimations(const Animations& src);

View file

@ -79,7 +79,7 @@ most can just be ignored (see usage).
@tparam string name Lua name of the item
@tparam Vec3 position position in level
@tparam Rotation rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0))
@tparam int roomID room ID item is in (default: calculated automatically)
@tparam int roomNumber the room number the moveable is in (default: calculated automatically).
@tparam int animNumber animation number
@tparam int frameNumber frame number
@tparam int hp HP of item

View file

@ -1,4 +1,5 @@
#pragma once
#include "Scripting/Internal/ScriptUtil.h"
#include "Scripting/Internal/TEN/Objects/NamedBase.h"
#include "Scripting/Internal/TEN/Objects/Room/RoomObject.h"

View file

@ -53,8 +53,8 @@ The following constants are inside ObjID.
LARA_DIRT_MESH
LARA_CROWBAR_ANIM
LARA_TORCH_ANIM
SINGLE_BRAID_HAIR
DUAL_PIGTAIL_HAIR
HAIR_PRIMARY
HAIR_SECONDARY
SNOWMOBILE_LARA_ANIMS
SNOWMOBILE
QUAD_LARA_ANIMS
@ -1231,8 +1231,8 @@ static const std::unordered_map<std::string, GAME_OBJECT_ID> kObjIDs {
{ "LARA_DIRT_MESH", ID_LARA_DIRT_MESH },
{ "LARA_CROWBAR_ANIM", ID_LARA_CROWBAR_ANIM },
{ "LARA_TORCH_ANIM", ID_LARA_TORCH_ANIM },
{ "SINGLE_BRAID_HAIR", ID_SINGLE_BRAID_HAIR },
{ "DUAL_PIGTAIL_HAIR", ID_DUAL_PIGTAIL_HAIR },
{ "HAIR_PRIMARY", ID_HAIR_PRIMARY },
{ "HAIR_SECONDARY", ID_HAIR_SECONDARY },
{ "SNOWMOBILE_LARA_ANIMS", ID_SNOWMOBILE_LARA_ANIMS },
{ "SNOWMOBILE", ID_SNOWMOBILE },
{ "QUAD_LARA_ANIMS", ID_QUAD_LARA_ANIMS },

View file

@ -13,110 +13,86 @@
#include "Specific/level.h"
#include "Specific/trutils.h"
/***
Rooms
@tenclass Objects.Room
@pragma nostrip
*/
/// Room object.
// @tenclass Objects.Room
// @pragma nostrip
//namespace TEN::Scripting
//{
static auto IndexError = index_error_maker(Room, ScriptReserved_Volume);
static auto NewIndexError = newindex_error_maker(Room, ScriptReserved_Volume);
Room::Room(ROOM_INFO& room) : m_room{ room }
{};
Room::Room(ROOM_INFO& room) :
_room(room)
{
};
void Room::Register(sol::table& parent)
{
parent.new_usertype<Room>(ScriptReserved_Room,
// Register type.
parent.new_usertype<Room>(
ScriptReserved_Room,
sol::no_constructor,
sol::meta_function::index, IndexError,
sol::meta_function::new_index, NewIndexError,
/// Determine whether the room is active or not
// @function Room:GetActive
// @treturn bool true if the room is active
ScriptReserved_GetActive, &Room::GetActive,
ScriptReserved_RoomGetRoomNumber, &Room::GetRoomNumber,
ScriptReserved_RoomGetName, &Room::GetName,
ScriptReserved_RoomGetColor, &Room::GetColor,
ScriptReserved_RoomGetReverbType, &Room::GetReverbType,
ScriptReserved_RoomSetName, &Room::SetName,
ScriptReserved_RoomSetReverbType, &Room::SetReverbType,
ScriptReserved_RoomSetFlag, &Room::SetFlag,
ScriptReserved_RoomIsTagPresent, &Room::IsTagPresent,
ScriptReserved_RoomGetActive, &Room::GetActive,
ScriptReserved_RoomGetFlag, &Room::GetFlag);
}
/// Get the room's ambient light color.
// @function Room:GetColor
// @treturn Color ambient light color of the room
ScriptReserved_GetColor, & Room::GetColor,
/// Get the room's reverb type.
// @function Room:GetReverbType
// @treturn Objects.RoomReverb room's reverb type
ScriptReserved_GetPosition, &Room::GetReverbType,
/// Set the room's reverb type.
// @function Room:SetReverbType
// @tparam Objects.RoomReverb new reverb type of the room
ScriptReserved_SetReverbType, &Room::SetReverbType,
/// Get the room's number.
// @function Room:GetRoomNumber()
// @treturn int Room number.
int Room::GetRoomNumber() const
{
return _room.RoomNumber;
}
/// Get the room's unique string identifier.
// @function Room:GetName
// @treturn string the room's name
ScriptReserved_GetName, &Room::GetName,
/// Set the room's name (its unique string identifier).
// @function Room:SetName
// @tparam string name The room's new name
ScriptReserved_SetName, &Room::SetName,
/// Get the room's specified flag value (true or false).
// @function Room:GetFlag
// @tparam Objects.RoomFlagID flagID The room's flag ID
// @treturn bool the room's specified flag value
ScriptReserved_GetFlag, &Room::GetFlag,
/// Set the room's specified flag value.
// @function Room:SetFlag
// @tparam Objects.RoomFlagID flagID The room's flag ID
// @tparam bool the room's new flag value
ScriptReserved_SetFlag, &Room::SetFlag,
/// Checks if specified tag is set for this room.
// @function Room:IsTagPresent
// @tparam string tag A text tag to check (case sensitive)
// @treturn bool true if tag is present, false if not
ScriptReserved_IsTagPresent, &Room::IsTagPresent);
}
bool Room::GetActive() const
{
return m_room.Active();
}
ScriptColor Room::GetColor() const
{
return ScriptColor{ m_room.ambient };
}
ReverbType Room::GetReverbType() const
{
return m_room.reverbType;
}
void Room::SetReverbType(ReverbType reverb)
{
m_room.reverbType = reverb;
}
// @function Room:GetName()
// @treturn string Room name.
std::string Room::GetName() const
{
return m_room.Name;
return _room.Name;
}
/// Get the room's ambient light color.
// @function Room:GetColor()
// @treturn Color Ambient light color.
ScriptColor Room::GetColor() const
{
return ScriptColor(_room.ambient);
}
/// Get the room's reverb type.
// @function Room:GetReverbType()
// @treturn Objects.RoomReverb Reverb type.
ReverbType Room::GetReverbType() const
{
return _room.reverbType;
}
/// Set the room's unique string identifier.
// @function Room:SetName()
// @tparam string name New name.
void Room::SetName(const std::string& name)
{
if (!ScriptAssert(!name.empty(), "Unable to set name. Name cannot be blank."))
return;
// Remove old name if it already exists.
if (s_callbackSetName(name, m_room))
// Remove previous name if it already exists.
if (s_callbackSetName(name, _room))
{
s_callbackRemoveName(m_room.Name);
m_room.Name = name;
s_callbackRemoveName(_room.Name);
_room.Name = name;
}
else
{
@ -125,29 +101,60 @@ void Room::SetName(const std::string& name)
}
}
bool Room::GetFlag(RoomEnvFlags flag) const
/// Set the room's reverb type.
// @function Room:SetReverbType()
// @tparam Objects.RoomReverb Reverb type.
void Room::SetReverbType(ReverbType reverb)
{
return ((m_room.flags & flag) == flag);
_room.reverbType = reverb;
}
/// Set the room's specified flag.
// @function Room:SetFlag()
// @tparam Objects.RoomFlagID flagID Room flag ID.
// @tparam bool Boolean to set the flag to.
void Room::SetFlag(RoomEnvFlags flag, bool value)
{
if (value)
{
m_room.flags |= flag;
_room.flags |= flag;
}
else
{
m_room.flags &= ~flag;
_room.flags &= ~flag;
}
}
/// Get the room's specified flag value (true or false).
// @function Room:GetFlag()
// @tparam Objects.RoomFlagID flagID Room flag ID.
bool Room::IsTagPresent(const std::string& tag) const
{
if (m_room.Tags.empty())
if (_room.Tags.empty())
return false;
return std::any_of(
m_room.Tags.begin(), m_room.Tags.end(),
[&tag](const std::string& value) { return (value == tag); });
_room.Tags.begin(), _room.Tags.end(),
[&tag](const std::string& value)
{
return (value == tag);
});
}
/// Check if the specified tag is set for the room.
// @function Room:IsTagPresent()
// @tparam string tag Text tag to check (case sensitive).
// @treturn bool Boolean of the tag's presence.
bool Room::GetActive() const
{
return _room.Active();
}
/// Check if the room is active.
// @function Room:GetActive()
// @treturn bool Boolean of the room's active status.
bool Room::GetFlag(RoomEnvFlags flag) const
{
return ((_room.flags & flag) == flag);
}
//}

View file

@ -1,4 +1,5 @@
#pragma once
#include "Game/room.h"
#include "Scripting/Internal/TEN/Objects/NamedBase.h"
@ -7,32 +8,50 @@ enum class ReverbType;
class ScriptColor;
class Vec3;
//namespace TEN::Scripting
//{
class Room : public NamedBase<Room, ROOM_INFO&>
{
private:
// Members
ROOM_INFO& _room;
public:
using IdentifierType = std::reference_wrapper<ROOM_INFO>;
Room(ROOM_INFO& room);
~Room() = default;
Room& operator =(const Room& other) = delete;
Room(const Room& other) = delete;
static void Register(sol::table& parent);
[[nodiscard]] bool GetActive() const;
[[nodiscard]] ScriptColor GetColor() const;
// Constructors
Room(ROOM_INFO& room);
Room(const Room& room) = delete;
// Destructors
~Room() = default;
// Getters
int GetRoomNumber() const;
std::string GetName() const;
ScriptColor GetColor() const;
ReverbType GetReverbType() const;
// Setters
[[nodiscard]] std::string GetName() const;
void SetName(const std::string& name);
[[nodiscard]] bool GetFlag(RoomEnvFlags flag) const;
void SetReverbType(ReverbType reverbType);
void SetFlag(RoomEnvFlags flag, bool value);
[[nodiscard]] ReverbType GetReverbType() const;
void SetReverbType(ReverbType reverbType);
// Inquirers
[[nodiscard]] bool IsTagPresent(const std::string& tag) const;
bool IsTagPresent(const std::string& tag) const;
bool GetActive() const; // TODO: Rename to IsActive().
bool GetFlag(RoomEnvFlags flag) const; // TODO: Rename to HasFlag().
private:
ROOM_INFO& m_room;
// Operators
Room& operator =(const Room& room) = delete;
};
//}

View file

@ -9,10 +9,12 @@ public:
static void Register(sol::table& parent);
// Members
float x = 0;
float y = 0;
// Constructors
Vec2(float x, float y);
Vec2(float value);
Vec2(const Vector2& vector);
@ -28,6 +30,7 @@ public:
float Length() const;
// Meta functions
std::string ToString() const;
static Vec2 Add(const Vec2& vector0, const Vec2& vector1);
static Vec2 Subtract(const Vec2& vector0, const Vec2& vector1);
@ -38,9 +41,11 @@ public:
static bool IsEqualTo(const Vec2& vector0, const Vec2& vector1);
// Converters
Vector2 ToVector2() const;
//Vector2i ToVector2i() const;
// Operators
operator Vector2() const;
};

View file

@ -1,10 +1,10 @@
#pragma once
namespace sol { class state; }
class GameVector;
class Pose;
class Rotation;
class Vector3i;
namespace sol { class state; }
class Vec3
{
@ -12,11 +12,13 @@ public:
static void Register(sol::table& parent);
// Members
float x = 0;
float y = 0;
float z = 0;
// Constructors
Vec3() {};
Vec3(float x, float y, float z);
Vec3(float value);
@ -24,6 +26,7 @@ public:
Vec3(const Vector3i& vector);
// Utilities
Vec3 Normalize() const;
Vec3 Rotate(const Rotation& rot) const;
Vec3 Lerp(const Vec3& vector, float alpha) const;
@ -33,6 +36,7 @@ public:
float Length() const;
// Meta functions
std::string ToString() const;
static Vec3 Add(const Vec3& vector0, const Vec3& vector1);
static Vec3 Subtract(const Vec3& vector0, const Vec3& vector1);
@ -43,10 +47,12 @@ public:
static bool IsEqualTo(const Vec3& vector0, const Vec3& vector1);
// Converters
Vector3 ToVector3() const;
Vector3i ToVector3i() const;
GameVector ToGameVector() const;
// Operators
operator Vector3() const;
};

View file

@ -361,7 +361,7 @@ enum SOUND_EFFECTS
SFX_TR4_LIGHT_BEAM_LOOP = 356,
SFX_TR4_GUIDE_FIRE_LIGHT = 357,
SFX_TR4_AUTOGUNS = 358,
SFX_TR4_EMPTY8 = 359,
SFX_TR4_ENVIORONMENT_RUMBLE = 359,
SFX_TR4_STEAM = 360,
SFX_TR4_GARAGE_DOOR = 361,
SFX_TR4_WIND = 362,

View file

@ -3,43 +3,42 @@
#include "Specific/clock.h"
namespace TEN::Input
{
InputAction::InputAction(ActionID actionID)
{
ID = actionID;
_id = actionID;
}
ActionID InputAction::GetID() const
{
return ID;
return _id;
}
float InputAction::GetValue() const
{
return Value;
return _value;
}
float InputAction::GetTimeActive() const
{
return TimeActive;
return _timeActive;
}
float InputAction::GetTimeInactive() const
{
return TimeInactive;
return _timeInactive;
}
bool InputAction::IsClicked() const
{
return ((Value != 0.0f) && (PrevValue == 0.0f));
return ((_value != 0.0f) && (_prevValue == 0.0f));
}
bool InputAction::IsHeld(float delayInSec) const
{
float delayInFrameTime = (delayInSec == 0.0f) ? 0.0f : round(delayInSec / DELTA_TIME);
return ((Value != 0.0f) && (TimeActive >= delayInFrameTime));
return ((_value != 0.0f) && (_timeActive >= delayInFrameTime));
}
// NOTE: To avoid stutter on second pulse, ensure initialDelayInSec is multiple of delayInSec.
@ -48,12 +47,12 @@ namespace TEN::Input
if (IsClicked())
return true;
if (!IsHeld() || PrevTimeActive == 0.0f || TimeActive == PrevTimeActive)
if (!IsHeld() || _prevTimeActive == 0.0f || _timeActive == _prevTimeActive)
return false;
float activeDelayInFrameTime = (TimeActive > round(initialDelayInSec / DELTA_TIME)) ? round(delayInSec / DELTA_TIME) : round(initialDelayInSec / DELTA_TIME);
float delayInFrameTime = std::floor(TimeActive / activeDelayInFrameTime) * activeDelayInFrameTime;
if (delayInFrameTime > (std::floor(PrevTimeActive / activeDelayInFrameTime) * activeDelayInFrameTime))
float activeDelayInFrameTime = (_timeActive > round(initialDelayInSec / DELTA_TIME)) ? round(delayInSec / DELTA_TIME) : round(initialDelayInSec / DELTA_TIME);
float delayInFrameTime = std::floor(_timeActive / activeDelayInFrameTime) * activeDelayInFrameTime;
if (delayInFrameTime > (std::floor(_prevTimeActive / activeDelayInFrameTime) * activeDelayInFrameTime))
return true;
// Keeping version counting real time for future reference. -- Sezz 2022.10.01
@ -70,7 +69,7 @@ namespace TEN::Input
bool InputAction::IsReleased(float maxDelayInSec) const
{
float maxDelayInFrameTime = (maxDelayInSec == INFINITY) ? INFINITY : round(maxDelayInSec / DELTA_TIME);
return ((Value == 0.0f) && (PrevValue != 0.0f) && (TimeActive <= maxDelayInFrameTime));
return ((_value == 0.0f) && (_prevValue != 0.0f) && (_timeActive <= maxDelayInFrameTime));
}
void InputAction::Update(bool value)
@ -89,57 +88,57 @@ namespace TEN::Input
if (IsClicked())
{
PrevTimeActive = 0.0f;
TimeActive = 0.0f;
TimeInactive += FRAME_TIME;// DELTA_TIME;
_prevTimeActive = 0.0f;
_timeActive = 0.0f;
_timeInactive += FRAME_TIME;// DELTA_TIME;
}
else if (IsReleased())
{
PrevTimeActive = TimeActive;
TimeActive += FRAME_TIME;// DELTA_TIME;
TimeInactive = 0.0f;
_prevTimeActive = _timeActive;
_timeActive += FRAME_TIME;// DELTA_TIME;
_timeInactive = 0.0f;
}
else if (IsHeld())
{
PrevTimeActive = TimeActive;
TimeActive += FRAME_TIME;// DELTA_TIME;
TimeInactive = 0.0f;
_prevTimeActive = _timeActive;
_timeActive += FRAME_TIME;// DELTA_TIME;
_timeInactive = 0.0f;
}
else
{
PrevTimeActive = 0.0f;
TimeActive = 0.0f;
TimeInactive += FRAME_TIME;// DELTA_TIME;
_prevTimeActive = 0.0f;
_timeActive = 0.0f;
_timeInactive += FRAME_TIME;// DELTA_TIME;
}
}
void InputAction::Clear()
{
Value = 0.0f;
PrevValue = 0.0f;
TimeActive = 0.0f;
PrevTimeActive = 0.0f;
TimeInactive = 0.0f;
_value = 0.0f;
_prevValue = 0.0f;
_timeActive = 0.0f;
_prevTimeActive = 0.0f;
_timeInactive = 0.0f;
}
void InputAction::DrawDebug() const
{
PrintDebugMessage("ID: %d", (int)ID);
PrintDebugMessage("ID: %d", (int)_id);
PrintDebugMessage("IsClicked: %d", IsClicked());
PrintDebugMessage("IsHeld: %d", IsHeld());
PrintDebugMessage("IsPulsed (.2s, .6s): %d", IsPulsed(0.2f, 0.6f));
PrintDebugMessage("IsReleased: %d", IsReleased());
PrintDebugMessage("");
PrintDebugMessage("Value: %.3f", Value);
PrintDebugMessage("PrevValue: %.3f", PrevValue);
PrintDebugMessage("TimeActive: %.3f", TimeActive);
PrintDebugMessage("PrevTimeActive: %.3f", PrevTimeActive);
PrintDebugMessage("TimeInactive: %.3f", TimeInactive);
PrintDebugMessage("Value: %.3f", _value);
PrintDebugMessage("PrevValue: %.3f", _prevValue);
PrintDebugMessage("TimeActive: %.3f", _timeActive);
PrintDebugMessage("PrevTimeActive: %.3f", _prevTimeActive);
PrintDebugMessage("TimeInactive: %.3f", _timeInactive);
}
void InputAction::UpdateValue(float value)
{
PrevValue = Value;
Value = value;
_prevValue = _value;
_value = value;
}
}

View file

@ -65,12 +65,12 @@ namespace TEN::Input
private:
// Members
ActionID ID = In::Forward;
float Value = 0.0f;
float PrevValue = 0.0f;
float TimeActive = 0.0f;
float PrevTimeActive = 0.0f;
float TimeInactive = 0.0f;
ActionID _id = In::Forward;
float _value = 0.0f;
float _prevValue = 0.0f;
float _timeActive = 0.0f;
float _prevTimeActive = 0.0f;
float _timeInactive = 0.0f;
public:
// Constructors

View file

@ -1471,7 +1471,8 @@ void GetCarriedItems()
const auto& object = Objects[item.ObjectNumber];
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)
{