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

@ -1,6 +1,6 @@
# Changelog
Here you will find the full changelog of TEN's releases from Version 1.0 and up
Here you will find the full changelog of TEN's releases from Version 1.0 and up
The dates are in European standard format where date is presented as **YYYY-MM-DD**
@ -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,24 +6,27 @@ 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);
int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff);
int KayakDoDynamics(int height, int verticalVelocity, int* y);
int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff);
int KayakDoDynamics(int height, int verticalVelocity, int* y);
void KayakDoCurrent(ItemInfo* kayakItem, ItemInfo* laraItem);
bool KayakCanGetOut(ItemInfo* kayakItem, int dir);
int KayakDoShift(ItemInfo* kayakItem, Vector3i* pos, Vector3i* old);
int KayakDoShift(ItemInfo* kayakItem, Vector3i* pos, Vector3i* old);
void KayakToBackground(ItemInfo* kayakItem, ItemInfo* laraItem);
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,141 +13,148 @@
#include "Specific/level.h"
#include "Specific/trutils.h"
/***
Rooms
/// Room object.
// @tenclass Objects.Room
// @pragma nostrip
@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);
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 }
{};
void Room::Register(sol::table& parent)
{
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,
/// 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 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;
}
std::string Room::GetName() const
{
return m_room.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))
Room::Room(ROOM_INFO& room) :
_room(room)
{
s_callbackRemoveName(m_room.Name);
m_room.Name = name;
}
else
};
void Room::Register(sol::table& parent)
{
ScriptAssertF(false, "Could not add name {} - does an object with this name already exist?", name);
TENLog("Name will not be set", LogLevel::Warning, LogConfig::All);
// Register type.
parent.new_usertype<Room>(
ScriptReserved_Room,
sol::no_constructor,
sol::meta_function::index, IndexError,
sol::meta_function::new_index, NewIndexError,
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);
}
}
bool Room::GetFlag(RoomEnvFlags flag) const
{
return ((m_room.flags & flag) == flag);
}
void Room::SetFlag(RoomEnvFlags flag, bool value)
{
if (value)
/// Get the room's number.
// @function Room:GetRoomNumber()
// @treturn int Room number.
int Room::GetRoomNumber() const
{
m_room.flags |= flag;
return _room.RoomNumber;
}
else
/// Get the room's unique string identifier.
// @function Room:GetName()
// @treturn string Room name.
std::string Room::GetName() const
{
m_room.flags &= ~flag;
return _room.Name;
}
}
bool Room::IsTagPresent(const std::string& tag) const
{
if (m_room.Tags.empty())
return false;
/// Get the room's ambient light color.
// @function Room:GetColor()
// @treturn Color Ambient light color.
ScriptColor Room::GetColor() const
{
return ScriptColor(_room.ambient);
}
return std::any_of(
m_room.Tags.begin(), m_room.Tags.end(),
[&tag](const std::string& value) { return (value == tag); });
}
/// 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 previous name if it already exists.
if (s_callbackSetName(name, _room))
{
s_callbackRemoveName(_room.Name);
_room.Name = name;
}
else
{
ScriptAssertF(false, "Could not add name {} - does an object with this name already exist?", name);
TENLog("Name will not be set", LogLevel::Warning, LogConfig::All);
}
}
/// Set the room's reverb type.
// @function Room:SetReverbType()
// @tparam Objects.RoomReverb Reverb type.
void Room::SetReverbType(ReverbType reverb)
{
_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)
{
_room.flags |= flag;
}
else
{
_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 (_room.Tags.empty())
return false;
return std::any_of(
_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;
class Room : public NamedBase<Room, ROOM_INFO&>
{
public:
using IdentifierType = std::reference_wrapper<ROOM_INFO>;
Room(ROOM_INFO& room);
~Room() = default;
//namespace TEN::Scripting
//{
class Room : public NamedBase<Room, ROOM_INFO&>
{
private:
// Members
Room& operator =(const Room& other) = delete;
Room(const Room& other) = delete;
ROOM_INFO& _room;
static void Register(sol::table& parent);
public:
using IdentifierType = std::reference_wrapper<ROOM_INFO>;
[[nodiscard]] bool GetActive() const;
[[nodiscard]] ScriptColor GetColor() const;
static void Register(sol::table& parent);
[[nodiscard]] std::string GetName() const;
void SetName(const std::string& name);
// Constructors
[[nodiscard]] bool GetFlag(RoomEnvFlags flag) const;
void SetFlag(RoomEnvFlags flag, bool value);
Room(ROOM_INFO& room);
Room(const Room& room) = delete;
[[nodiscard]] ReverbType GetReverbType() const;
void SetReverbType(ReverbType reverbType);
// Destructors
[[nodiscard]] bool IsTagPresent(const std::string& tag) const;
~Room() = default;
private:
ROOM_INFO& m_room;
};
// Getters
int GetRoomNumber() const;
std::string GetName() const;
ScriptColor GetColor() const;
ReverbType GetReverbType() const;
// Setters
void SetName(const std::string& name);
void SetReverbType(ReverbType reverbType);
void SetFlag(RoomEnvFlags flag, bool value);
// Inquirers
bool IsTagPresent(const std::string& tag) const;
bool GetActive() const; // TODO: Rename to IsActive().
bool GetFlag(RoomEnvFlags flag) const; // TODO: Rename to HasFlag().
// 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)
{