mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Merge branch 'develop' into DisplayString_Scale
This commit is contained in:
commit
b4cf85af77
13 changed files with 403 additions and 308 deletions
|
@ -16,11 +16,16 @@ Version 1.2
|
|||
* Fix double drawing additive faces.
|
||||
* Fix savegame count not properly increasing.
|
||||
* Fix regeneration of non-ammo pickups with OCB 128.
|
||||
* Overhaul Pushable blocks:
|
||||
- Separate climbable and normal pushable blocks slots.
|
||||
- Add new pushable OCB to manipulate pushable block properties.
|
||||
- Add new Lara animations for pushing over the block off the edge (both TR1-3 and TR4-5 versions).
|
||||
- Fix pushables not working with raising block.
|
||||
* Fix vault bug preventing the player from climbing onto ledges out of deeper sections of wade-depth water.
|
||||
* Fix cold exposure status not recovering in non-cold wade-depth water.
|
||||
* Fix non-elevated combat camera.
|
||||
* Fix camera snap when disengaging the look-around mode.
|
||||
* Improve head-on wall collision.
|
||||
* Overhaul pushables:
|
||||
- Separate climbable and non-climbable pushable object slots.
|
||||
- Add new pushable OCB to manipulate pushable properties.
|
||||
- Add new animations for pushing pushables off edgees (TR1-3 and TR4-5 versions).
|
||||
- Fix pushables not working with raising blocks.
|
||||
- Fix miscellaneous pushable bugs.
|
||||
* Overhaul look-around feature:
|
||||
- Allow for more consistent and wider viewing angles while crawling, crouching, and hanging.
|
||||
|
@ -42,14 +47,14 @@ Lua API changes:
|
|||
* Add DisplaySprite object.
|
||||
* Add Flow:EnableLoadSave() function to disable savegames.
|
||||
* Add Flow:EnablePointFilter() function to disable bilinear filtering.
|
||||
* Add InputGetCursorDisplayPosition() function to get the position of the cursor.
|
||||
* Add Lara:GetAmmoType() function to read the ammo that Lara is using.
|
||||
* Add Lara:GetControlLock() and Lara:SetControlLock() functions to handle controls locking.
|
||||
* Add Logic.HandleEvent() function to call node events.
|
||||
* Add Input.GetCursorDisplayPosition() function to get the position of the cursor.
|
||||
* Add functions to load, save, delete and check existence of savegames.
|
||||
* Add DisplayStringOption.RIGHT and DisplayStringOption.BLINK flags for DisplayString.
|
||||
* Make Vec2 and Vec3 objects float-based instead of integer-based.
|
||||
* Split and organise functions in `Misc` namespace to appropriate new namespaces.
|
||||
* Split and organize functions in `Misc` namespace to appropriate new namespaces.
|
||||
* Add Vec2/Vec3 arithmetic for division with a number and multiplication with another Vec2/Vec3.
|
||||
* Add various Vec2/Vec3 operations such as Normalize() or Lerp().
|
||||
* Add log messages warnings to functions AddCallback and RemoveCallback.
|
||||
|
|
|
@ -450,102 +450,80 @@ auto PlayerStateCollisionRoutines = std::array<PlayerStateRoutine, NUM_LARA_STAT
|
|||
|
||||
void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
auto& player = GetLaraInfo(*item);
|
||||
|
||||
if (lara->Control.Weapon.HasFired)
|
||||
// Alert nearby creatures.
|
||||
if (player.Control.Weapon.HasFired)
|
||||
{
|
||||
AlertNearbyGuards(item);
|
||||
lara->Control.Weapon.HasFired = false;
|
||||
player.Control.Weapon.HasFired = false;
|
||||
}
|
||||
|
||||
if (lara->Status.Poison)
|
||||
// Handle object interation adjustment parameters.
|
||||
if (player.Control.IsMoving)
|
||||
{
|
||||
if (lara->Status.Poison > LARA_POISON_MAX)
|
||||
lara->Status.Poison = LARA_POISON_MAX;
|
||||
|
||||
if (!(Wibble & 0xFF))
|
||||
item->HitPoints -= lara->Status.Poison;
|
||||
}
|
||||
|
||||
if (lara->Control.IsMoving)
|
||||
{
|
||||
if (lara->Control.Count.PositionAdjust > LARA_POSITION_ADJUST_MAX_TIME)
|
||||
if (player.Control.Count.PositionAdjust > LARA_POSITION_ADJUST_MAX_TIME)
|
||||
{
|
||||
lara->Control.IsMoving = false;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
player.Control.IsMoving = false;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
|
||||
++lara->Control.Count.PositionAdjust;
|
||||
++player.Control.Count.PositionAdjust;
|
||||
}
|
||||
else
|
||||
{
|
||||
lara->Control.Count.PositionAdjust = 0;
|
||||
player.Control.Count.PositionAdjust = 0;
|
||||
}
|
||||
|
||||
if (!lara->Control.Locked)
|
||||
lara->LocationPad = -1;
|
||||
if (!player.Control.Locked)
|
||||
player.LocationPad = -1;
|
||||
|
||||
auto prevPos = item->Pose.Position;
|
||||
|
||||
if (lara->Control.HandStatus == HandStatus::Busy &&
|
||||
item->Animation.AnimNumber == LA_STAND_IDLE &&
|
||||
// FAILSAFE: Force hand status reset.
|
||||
if (item->Animation.AnimNumber == LA_STAND_IDLE &&
|
||||
item->Animation.ActiveState == LS_IDLE &&
|
||||
item->Animation.TargetState == LS_IDLE &&
|
||||
!item->Animation.IsAirborne)
|
||||
!item->Animation.IsAirborne &&
|
||||
player.Control.HandStatus == HandStatus::Busy)
|
||||
{
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
|
||||
if (lara->Status.Stamina < LARA_STAMINA_MAX && item->Animation.ActiveState != LS_SPRINT)
|
||||
lara->Status.Stamina++;
|
||||
|
||||
HandlePlayerQuickActions(*item);
|
||||
RumbleLaraHealthCondition(item);
|
||||
|
||||
bool isWater = TestEnvironment(ENV_FLAG_WATER, item);
|
||||
bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, item);
|
||||
bool isCold = TestEnvironment(ENV_FLAG_COLD, item);
|
||||
auto water = GetPlayerWaterData(*item);
|
||||
player.Context.WaterSurfaceDist = -water.HeightFromWater;
|
||||
|
||||
if (player.Context.Vehicle == NO_ITEM)
|
||||
SpawnPlayerSplash(*item, water.WaterHeight, water.WaterDepth);
|
||||
|
||||
bool isWaterOnHeadspace = false;
|
||||
|
||||
int waterDepth = GetWaterDepth(item);
|
||||
int waterHeight = GetWaterHeight(item);
|
||||
|
||||
int heightFromWater;
|
||||
if (waterHeight != NO_HEIGHT)
|
||||
heightFromWater = item->Pose.Position.y - waterHeight;
|
||||
else
|
||||
heightFromWater = NO_HEIGHT;
|
||||
lara->Context.WaterSurfaceDist = -heightFromWater;
|
||||
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
WadeSplash(item, waterHeight, waterDepth);
|
||||
|
||||
if (lara->Context.Vehicle == NO_ITEM && lara->ExtraAnim == NO_ITEM)
|
||||
if (player.Context.Vehicle == NO_ITEM && player.ExtraAnim == NO_ITEM)
|
||||
{
|
||||
switch (lara->Control.WaterStatus)
|
||||
switch (player.Control.WaterStatus)
|
||||
{
|
||||
case WaterStatus::Dry:
|
||||
for (int i = 0; i < NUM_LARA_MESHES; i++)
|
||||
lara->Effect.BubbleNodes[i] = 0.0f;
|
||||
player.Effect.BubbleNodes[i] = 0.0f;
|
||||
|
||||
if (heightFromWater == NO_HEIGHT || heightFromWater < WADE_DEPTH)
|
||||
if (water.HeightFromWater == NO_HEIGHT || water.HeightFromWater < WADE_WATER_DEPTH)
|
||||
break;
|
||||
|
||||
Camera.targetElevation = ANGLE(-22.0f);
|
||||
|
||||
// Water is deep enough to swim; dispatch dive.
|
||||
if (waterDepth >= SWIM_DEPTH && !isSwamp)
|
||||
// Water is at swim depth; dispatch dive.
|
||||
if (water.WaterDepth >= SWIM_WATER_DEPTH && !water.IsSwamp)
|
||||
{
|
||||
if (isWater)
|
||||
if (water.IsWater)
|
||||
{
|
||||
item->Pose.Position.y += CLICK(0.5f) - 28;
|
||||
item->Pose.Position.y += CLICK(0.5f) - 28; // TODO: Demagic.
|
||||
item->Animation.IsAirborne = false;
|
||||
lara->Control.WaterStatus = WaterStatus::Underwater;
|
||||
lara->Status.Air = LARA_AIR_MAX;
|
||||
player.Control.WaterStatus = WaterStatus::Underwater;
|
||||
player.Status.Air = LARA_AIR_MAX;
|
||||
|
||||
for (int i = 0; i < NUM_LARA_MESHES; i++)
|
||||
lara->Effect.BubbleNodes[i] = PLAYER_BUBBLE_NODE_MAX;
|
||||
player.Effect.BubbleNodes[i] = PLAYER_BUBBLE_NODE_MAX;
|
||||
|
||||
UpdateLaraRoom(item, 0);
|
||||
StopSoundEffect(SFX_TR4_LARA_FALL);
|
||||
|
@ -553,22 +531,22 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
if (item->Animation.ActiveState == LS_SWAN_DIVE)
|
||||
{
|
||||
SetAnimation(item, LA_SWANDIVE_DIVE);
|
||||
item->Animation.Velocity.y /= 2.0f;
|
||||
item->Pose.Orientation.x = -ANGLE(45.0f);
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
item->Animation.Velocity.y /= 2;
|
||||
item->Pose.Orientation.x = ANGLE(-45.0f);
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
else if (item->Animation.ActiveState == LS_FREEFALL_DIVE)
|
||||
{
|
||||
SetAnimation(item, LA_SWANDIVE_DIVE);
|
||||
item->Animation.Velocity.y /= 2.0f;
|
||||
item->Pose.Orientation.x = -ANGLE(85.0f);
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
item->Animation.Velocity.y /= 2;
|
||||
item->Pose.Orientation.x = ANGLE(-85.0f);
|
||||
player.Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAnimation(item, LA_FREEFALL_DIVE);
|
||||
item->Animation.Velocity.y = (item->Animation.Velocity.y / 8.0f) * 3.0f;
|
||||
item->Pose.Orientation.x = -ANGLE(45.0f);
|
||||
item->Animation.Velocity.y = (item->Animation.Velocity.y / 8) * 3;
|
||||
item->Pose.Orientation.x = ANGLE(-45.0f);
|
||||
}
|
||||
|
||||
ResetPlayerFlex(item);
|
||||
|
@ -576,13 +554,13 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
}
|
||||
// Water is at wade depth; update water status and do special handling.
|
||||
else if (heightFromWater >= WADE_DEPTH)
|
||||
else if (water.HeightFromWater >= WADE_WATER_DEPTH)
|
||||
{
|
||||
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||
player.Control.WaterStatus = WaterStatus::Wade;
|
||||
|
||||
// Make splash ONLY within this particular threshold before swim depth while airborne (WadeSplash() above interferes otherwise).
|
||||
if (waterDepth > (SWIM_DEPTH - CLICK(1)) &&
|
||||
item->Animation.IsAirborne && !isSwamp)
|
||||
// Make splash ONLY within this particular threshold before swim depth while airborne (SpawnPlayerSplash() above interferes otherwise).
|
||||
if (water.WaterDepth > (SWIM_WATER_DEPTH - CLICK(1)) &&
|
||||
item->Animation.IsAirborne && !water.IsSwamp)
|
||||
{
|
||||
item->Animation.TargetState = LS_IDLE;
|
||||
Splash(item);
|
||||
|
@ -592,12 +570,12 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
{
|
||||
item->Animation.TargetState = LS_IDLE;
|
||||
}
|
||||
else if (isSwamp)
|
||||
else if (water.IsSwamp)
|
||||
{
|
||||
if (item->Animation.ActiveState == LS_SWAN_DIVE ||
|
||||
item->Animation.ActiveState == LS_FREEFALL_DIVE)
|
||||
{
|
||||
item->Pose.Position.y = waterHeight + (BLOCK(1) - 24);
|
||||
item->Pose.Position.y = water.WaterHeight + (BLOCK(1) - 24); // TODO: Demagic.
|
||||
}
|
||||
|
||||
SetAnimation(item, LA_WADE);
|
||||
|
@ -607,25 +585,23 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
break;
|
||||
|
||||
case WaterStatus::Underwater:
|
||||
|
||||
// Disable potential Lara resurfacing if her health is zero or below.
|
||||
// For some reason, originals worked without this condition, but TEN does not. -- Lwmte, 11.08.22
|
||||
|
||||
// Disable potential player resurfacing if health is <= 0.
|
||||
// Originals worked without this condition, but TEN does not. -- Lwmte, 11.08.22
|
||||
if (item->HitPoints <= 0)
|
||||
break;
|
||||
|
||||
// Determine if Lara's head is above water surface. This is needed to prevent
|
||||
// pre-TR5 bug where Lara would keep submerged until her root mesh (butt) is above water level.
|
||||
// Determine if player's head is above water surface. Needed to prevent
|
||||
// pre-TR5 bug where player would keep submerged until root mesh was above water level.
|
||||
isWaterOnHeadspace = TestEnvironment(
|
||||
ENV_FLAG_WATER, item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z,
|
||||
GetCollision(item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, item->RoomNumber).RoomNumber);
|
||||
|
||||
isWaterOnHeadspace = TestEnvironment(ENV_FLAG_WATER, item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z,
|
||||
GetCollision(item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, item->RoomNumber).RoomNumber);
|
||||
|
||||
if (waterDepth == NO_HEIGHT || abs(heightFromWater) >= CLICK(1) || isWaterOnHeadspace ||
|
||||
if (water.WaterDepth == NO_HEIGHT || abs(water.HeightFromWater) >= CLICK(1) || isWaterOnHeadspace ||
|
||||
item->Animation.AnimNumber == LA_UNDERWATER_RESURFACE || item->Animation.AnimNumber == LA_ONWATER_DIVE)
|
||||
{
|
||||
if (!isWater)
|
||||
if (!water.IsWater)
|
||||
{
|
||||
if (waterDepth == NO_HEIGHT || abs(heightFromWater) >= CLICK(1))
|
||||
if (water.WaterDepth == NO_HEIGHT || abs(water.HeightFromWater) >= CLICK(1))
|
||||
{
|
||||
SetAnimation(item, LA_FALL_START);
|
||||
ResetPlayerLean(item);
|
||||
|
@ -633,7 +609,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
item->Animation.IsAirborne = true;
|
||||
item->Animation.Velocity.z = item->Animation.Velocity.y;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
lara->Control.WaterStatus = WaterStatus::Dry;
|
||||
player.Control.WaterStatus = WaterStatus::Dry;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -641,8 +617,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y = waterHeight;
|
||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||
item->Pose.Position.y = water.WaterHeight;
|
||||
player.Control.WaterStatus = WaterStatus::TreadWater;
|
||||
|
||||
UpdateLaraRoom(item, -(STEPUP_HEIGHT - 3));
|
||||
}
|
||||
|
@ -654,8 +630,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y = waterHeight + 1;
|
||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||
item->Pose.Position.y = water.WaterHeight + 1;
|
||||
player.Control.WaterStatus = WaterStatus::TreadWater;
|
||||
|
||||
UpdateLaraRoom(item, 0);
|
||||
}
|
||||
|
@ -663,19 +639,19 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
break;
|
||||
|
||||
case WaterStatus::TreadWater:
|
||||
if (!isWater)
|
||||
if (!water.IsWater)
|
||||
{
|
||||
if (heightFromWater <= WADE_DEPTH)
|
||||
if (water.HeightFromWater <= WADE_WATER_DEPTH)
|
||||
{
|
||||
SetAnimation(item, LA_FALL_START);
|
||||
item->Animation.IsAirborne = true;
|
||||
item->Animation.Velocity.z = item->Animation.Velocity.y;
|
||||
lara->Control.WaterStatus = WaterStatus::Dry;
|
||||
player.Control.WaterStatus = WaterStatus::Dry;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAnimation(item, LA_STAND_IDLE);
|
||||
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||
player.Control.WaterStatus = WaterStatus::Wade;
|
||||
}
|
||||
|
||||
ResetPlayerLean(item);
|
||||
|
@ -686,26 +662,26 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
break;
|
||||
|
||||
case WaterStatus::Wade:
|
||||
Camera.targetElevation = -ANGLE(22.0f);
|
||||
Camera.targetElevation = ANGLE(-22.0f);
|
||||
|
||||
if (heightFromWater >= WADE_DEPTH)
|
||||
if (water.HeightFromWater >= WADE_WATER_DEPTH)
|
||||
{
|
||||
if (heightFromWater > SWIM_DEPTH && !isSwamp)
|
||||
if (water.HeightFromWater > SWIM_WATER_DEPTH && !water.IsSwamp)
|
||||
{
|
||||
SetAnimation(item, LA_ONWATER_IDLE);
|
||||
ResetPlayerLean(item);
|
||||
ResetPlayerFlex(item);
|
||||
item->Animation.IsAirborne = false;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position.y += 1 - heightFromWater;
|
||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||
item->Pose.Position.y += 1 - water.HeightFromWater;
|
||||
player.Control.WaterStatus = WaterStatus::TreadWater;
|
||||
|
||||
UpdateLaraRoom(item, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara->Control.WaterStatus = WaterStatus::Dry;
|
||||
player.Control.WaterStatus = WaterStatus::Dry;
|
||||
|
||||
if (item->Animation.ActiveState == LS_WADE_FORWARD)
|
||||
item->Animation.TargetState = LS_RUN_FORWARD;
|
||||
|
@ -715,150 +691,22 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
|||
}
|
||||
}
|
||||
|
||||
if (TestEnvironment(ENV_FLAG_DAMAGE, item) && item->HitPoints > 0)
|
||||
item->HitPoints--;
|
||||
HandlePlayerStatusEffects(*item, player.Control.WaterStatus, water);
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
item->HitPoints = -1;
|
||||
auto prevPos = item->Pose.Position;
|
||||
|
||||
if (lara->Control.Count.Death == 0)
|
||||
StopSoundTracks(true);
|
||||
|
||||
lara->Control.Count.Death++;
|
||||
if ((item->Flags & IFLAG_INVISIBLE))
|
||||
{
|
||||
lara->Control.Count.Death++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lara->Control.WaterStatus)
|
||||
switch (player.Control.WaterStatus)
|
||||
{
|
||||
case WaterStatus::Dry:
|
||||
case WaterStatus::Wade:
|
||||
if (isSwamp && lara->Context.WaterSurfaceDist < -(LARA_HEIGHT + 8)) // TODO: Find best height. @Sezz 2021.11.10
|
||||
{
|
||||
if (item->HitPoints >= 0)
|
||||
{
|
||||
lara->Status.Air -= 6;
|
||||
if (lara->Status.Air < 0)
|
||||
{
|
||||
lara->Status.Air = -1;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lara->Status.Air < LARA_AIR_MAX && item->HitPoints >= 0)
|
||||
{
|
||||
// HACK: Special case for UPV.
|
||||
if (lara->Context.Vehicle == NO_ITEM)
|
||||
{
|
||||
lara->Status.Air += 10;
|
||||
if (lara->Status.Air > LARA_AIR_MAX)
|
||||
lara->Status.Air = LARA_AIR_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->HitPoints >= 0)
|
||||
{
|
||||
if (lara->Control.WaterStatus == WaterStatus::Dry)
|
||||
{
|
||||
// HACK: Special case for UPV.
|
||||
if (lara->Context.Vehicle != NO_ITEM)
|
||||
{
|
||||
auto& vehicleItem = g_Level.Items[lara->Context.Vehicle];
|
||||
if (vehicleItem.ObjectNumber == ID_UPV)
|
||||
{
|
||||
auto pointColl = GetCollision(item, 0, 0, CLICK(1));
|
||||
|
||||
isCold = isCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber);
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure--;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara->Status.Exposure++;
|
||||
if (lara->Status.Exposure >= LARA_EXPOSURE_MAX)
|
||||
lara->Status.Exposure = LARA_EXPOSURE_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure--;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaraAboveWater(item, coll);
|
||||
break;
|
||||
|
||||
case WaterStatus::Underwater:
|
||||
if (item->HitPoints >= 0)
|
||||
{
|
||||
auto level = g_GameFlow->GetLevel(CurrentLevel);
|
||||
if (level->GetLaraType() != LaraType::Divesuit)
|
||||
lara->Status.Air--;
|
||||
|
||||
if (lara->Status.Air < 0)
|
||||
{
|
||||
item->HitPoints -= 5;
|
||||
lara->Status.Air = -1;
|
||||
}
|
||||
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure -= 2;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lara->Status.Exposure++;
|
||||
if (lara->Status.Exposure >= LARA_EXPOSURE_MAX)
|
||||
lara->Status.Exposure = LARA_EXPOSURE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
LaraUnderwater(item, coll);
|
||||
break;
|
||||
|
||||
case WaterStatus::TreadWater:
|
||||
if (item->HitPoints >= 0)
|
||||
{
|
||||
lara->Status.Air += 10;
|
||||
if (lara->Status.Air > LARA_AIR_MAX)
|
||||
lara->Status.Air = LARA_AIR_MAX;
|
||||
|
||||
if (isCold)
|
||||
{
|
||||
lara->Status.Exposure -= 2;
|
||||
if (lara->Status.Exposure <= 0)
|
||||
{
|
||||
lara->Status.Exposure = 0;
|
||||
item->HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaraWaterSurface(item, coll);
|
||||
break;
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ constexpr auto PLAYER_BUBBLE_NODE_MAX = 12.0f;
|
|||
constexpr auto STEPUP_HEIGHT = (int)CLICK(3 / 2.0f);
|
||||
constexpr auto BAD_JUMP_CEILING = (int)CLICK(6 / 8.0f);
|
||||
constexpr auto SHALLOW_WATER_DEPTH = (int)CLICK(1 / 2.0f);
|
||||
constexpr auto WADE_DEPTH = STEPUP_HEIGHT;
|
||||
constexpr auto SWIM_DEPTH = CLICK(3) - 38;
|
||||
constexpr auto WADE_WATER_DEPTH = STEPUP_HEIGHT;
|
||||
constexpr auto SWIM_WATER_DEPTH = CLICK(2.75f);
|
||||
constexpr auto SLOPE_DIFFERENCE = 60;
|
||||
|
||||
extern LaraInfo Lara;
|
||||
|
|
|
@ -460,9 +460,9 @@ void LaraJumpCollision(ItemInfo* item, CollisionInfo* coll, short moveAngle)
|
|||
|
||||
void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
const auto& player = GetLaraInfo(*item);
|
||||
|
||||
coll->Setup.ForwardAngle = lara->Control.MoveAngle;
|
||||
coll->Setup.ForwardAngle = player.Control.MoveAngle;
|
||||
|
||||
GetCollisionInfo(coll, item, Vector3i(0, LARA_HEIGHT_TREAD, 0));
|
||||
ShiftItem(item, coll);
|
||||
|
@ -474,14 +474,19 @@ void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll)
|
|||
item->Pose.Position = coll->Setup.PrevPosition;
|
||||
}
|
||||
else if (coll->CollisionType == CT_LEFT)
|
||||
{
|
||||
item->Pose.Orientation.y += ANGLE(5.0f);
|
||||
}
|
||||
else if (coll->CollisionType == CT_RIGHT)
|
||||
{
|
||||
item->Pose.Orientation.y -= ANGLE(5.0f);
|
||||
}
|
||||
|
||||
if (GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber) - item->Pose.Position.y > -100)
|
||||
TestLaraWaterStepOut(item, coll);
|
||||
else
|
||||
SetLaraSwimDiveAnimation(item);
|
||||
auto pointColl = GetCollision(item);
|
||||
int waterHeight = GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber);
|
||||
|
||||
if ((pointColl.Position.Floor - item->Pose.Position.y) < SWIM_WATER_DEPTH)
|
||||
TestPlayerWaterStepOut(item, coll);
|
||||
}
|
||||
|
||||
void LaraSwimCollision(ItemInfo* item, CollisionInfo* coll)
|
||||
|
|
|
@ -92,6 +92,184 @@ void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll)
|
|||
lara->Control.IsMonkeySwinging = false;
|
||||
}
|
||||
|
||||
void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWaterData& water)
|
||||
{
|
||||
auto& player = GetLaraInfo(item);
|
||||
|
||||
// Update health status.
|
||||
if (TestEnvironment(ENV_FLAG_DAMAGE, &item) && item.HitPoints > 0)
|
||||
item.HitPoints--;
|
||||
|
||||
// Update poison status.
|
||||
if (player.Status.Poison)
|
||||
{
|
||||
if (player.Status.Poison > LARA_POISON_MAX)
|
||||
player.Status.Poison = LARA_POISON_MAX;
|
||||
|
||||
if (!(Wibble & 0xFF))
|
||||
item.HitPoints -= player.Status.Poison;
|
||||
}
|
||||
|
||||
// Update stamina status.
|
||||
if (player.Status.Stamina < LARA_STAMINA_MAX && item.Animation.ActiveState != LS_SPRINT)
|
||||
player.Status.Stamina++;
|
||||
|
||||
// TODO: Dehardcode values and make cleaner implementation.
|
||||
// Handle environmental status effects.
|
||||
switch (waterStatus)
|
||||
{
|
||||
case WaterStatus::Dry:
|
||||
case WaterStatus::Wade:
|
||||
// TODO: Find best height. -- Sezz 2021.11.10
|
||||
if (water.IsSwamp && player.Context.WaterSurfaceDist < -(LARA_HEIGHT + 8))
|
||||
{
|
||||
if (item.HitPoints >= 0)
|
||||
{
|
||||
player.Status.Air -= 6;
|
||||
if (player.Status.Air < 0)
|
||||
{
|
||||
player.Status.Air = -1;
|
||||
item.HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (player.Status.Air < LARA_AIR_MAX && item.HitPoints >= 0)
|
||||
{
|
||||
// HACK: Special case for UPV.
|
||||
if (player.Context.Vehicle == NO_ITEM)
|
||||
{
|
||||
player.Status.Air += 10;
|
||||
if (player.Status.Air > LARA_AIR_MAX)
|
||||
player.Status.Air = LARA_AIR_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.HitPoints >= 0)
|
||||
{
|
||||
if (player.Control.WaterStatus == WaterStatus::Dry)
|
||||
{
|
||||
// HACK: Special case for UPV.
|
||||
if (player.Context.Vehicle != NO_ITEM)
|
||||
{
|
||||
const auto& vehicleItem = g_Level.Items[player.Context.Vehicle];
|
||||
if (vehicleItem.ObjectNumber == ID_UPV)
|
||||
{
|
||||
auto pointColl = GetCollision(&item, 0, 0, CLICK(1));
|
||||
|
||||
water.IsCold = (water.IsCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber));
|
||||
if (water.IsCold)
|
||||
{
|
||||
player.Status.Exposure--;
|
||||
if (player.Status.Exposure <= 0)
|
||||
{
|
||||
player.Status.Exposure = 0;
|
||||
item.HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Status.Exposure++;
|
||||
if (player.Status.Exposure >= LARA_EXPOSURE_MAX)
|
||||
player.Status.Exposure = LARA_EXPOSURE_MAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (water.IsCold)
|
||||
{
|
||||
player.Status.Exposure--;
|
||||
if (player.Status.Exposure <= 0)
|
||||
{
|
||||
player.Status.Exposure = 0;
|
||||
item.HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Status.Exposure++;
|
||||
if (player.Status.Exposure >= LARA_EXPOSURE_MAX)
|
||||
player.Status.Exposure = LARA_EXPOSURE_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WaterStatus::Underwater:
|
||||
if (item.HitPoints >= 0)
|
||||
{
|
||||
const auto& level = *g_GameFlow->GetLevel(CurrentLevel);
|
||||
if (level.GetLaraType() != LaraType::Divesuit)
|
||||
player.Status.Air--;
|
||||
|
||||
if (player.Status.Air < 0)
|
||||
{
|
||||
item.HitPoints -= 5;
|
||||
player.Status.Air = -1;
|
||||
}
|
||||
|
||||
if (water.IsCold)
|
||||
{
|
||||
player.Status.Exposure -= 2;
|
||||
if (player.Status.Exposure <= 0)
|
||||
{
|
||||
player.Status.Exposure = 0;
|
||||
item.HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Status.Exposure++;
|
||||
if (player.Status.Exposure >= LARA_EXPOSURE_MAX)
|
||||
player.Status.Exposure = LARA_EXPOSURE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WaterStatus::TreadWater:
|
||||
if (item.HitPoints >= 0)
|
||||
{
|
||||
player.Status.Air += 10;
|
||||
if (player.Status.Air > LARA_AIR_MAX)
|
||||
player.Status.Air = LARA_AIR_MAX;
|
||||
|
||||
if (water.IsCold)
|
||||
{
|
||||
player.Status.Exposure -= 2;
|
||||
if (player.Status.Exposure <= 0)
|
||||
{
|
||||
player.Status.Exposure = 0;
|
||||
item.HitPoints -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Update death counter.
|
||||
if (item.HitPoints <= 0)
|
||||
{
|
||||
item.HitPoints = -1;
|
||||
|
||||
if (player.Control.Count.Death == 0)
|
||||
StopSoundTracks(true);
|
||||
|
||||
player.Control.Count.Death++;
|
||||
if ((item.Flags & IFLAG_INVISIBLE))
|
||||
{
|
||||
player.Control.Count.Death++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UsePlayerMedipack(ItemInfo& item)
|
||||
{
|
||||
auto& player = GetLaraInfo(item);
|
||||
|
@ -825,6 +1003,25 @@ LaraInfo*& GetLaraInfo(ItemInfo* item)
|
|||
return (LaraInfo*&)firstPlayerItem.Data;
|
||||
}
|
||||
|
||||
PlayerWaterData GetPlayerWaterData(ItemInfo& item)
|
||||
{
|
||||
bool isWater = TestEnvironment(ENV_FLAG_WATER, &item);
|
||||
bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, &item);
|
||||
bool isCold = TestEnvironment(ENV_FLAG_COLD, &item);
|
||||
|
||||
int waterDepth = GetWaterDepth(&item);
|
||||
int waterHeight = GetWaterHeight(&item);
|
||||
|
||||
auto pointColl = GetCollision(item);
|
||||
int heightFromWater = (waterHeight == NO_HEIGHT) ? NO_HEIGHT : (std::min(item.Pose.Position.y, pointColl.Position.Floor) - waterHeight);
|
||||
|
||||
return PlayerWaterData
|
||||
{
|
||||
isWater, isSwamp, isCold,
|
||||
waterDepth, waterHeight, heightFromWater
|
||||
};
|
||||
}
|
||||
|
||||
short GetLaraSlideDirection(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
short headingAngle = coll->Setup.ForwardAngle;
|
||||
|
|
|
@ -1,17 +1,30 @@
|
|||
#pragma once
|
||||
#include "Game/collision/collide_room.h"
|
||||
|
||||
enum class WaterStatus;
|
||||
struct ItemInfo;
|
||||
struct CollisionInfo;
|
||||
struct LaraInfo;
|
||||
struct VaultTestResult;
|
||||
|
||||
struct PlayerWaterData
|
||||
{
|
||||
bool IsWater = false;
|
||||
bool IsSwamp = false;
|
||||
bool IsCold = false;
|
||||
|
||||
int WaterDepth = 0;
|
||||
int WaterHeight = 0;
|
||||
int HeightFromWater = 0;
|
||||
};
|
||||
|
||||
// -----------------------------
|
||||
// HELPER FUNCTIONS
|
||||
// For State Control & Collision
|
||||
// -----------------------------
|
||||
|
||||
void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll);
|
||||
void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWaterData& water);
|
||||
void HandlePlayerQuickActions(ItemInfo& item);
|
||||
bool CanPlayerLookAround(const ItemInfo& item); // TODO: Move to context file. -- Sezz 2023.08.22
|
||||
void HandlePlayerLookAround(ItemInfo& item, bool invertXAxis = true);
|
||||
|
@ -33,6 +46,7 @@ LaraInfo& GetLaraInfo(ItemInfo& item);
|
|||
const LaraInfo& GetLaraInfo(const ItemInfo& item);
|
||||
LaraInfo*& GetLaraInfo(ItemInfo* item);
|
||||
|
||||
PlayerWaterData GetPlayerWaterData(ItemInfo& item);
|
||||
short GetLaraSlideDirection(ItemInfo* item, CollisionInfo* coll);
|
||||
|
||||
short ModulateLaraTurnRate(short turnRate, short accelRate, short minTurnRate, short maxTurnRate, float axisCoeff, bool invert);
|
||||
|
|
|
@ -877,34 +877,39 @@ CollisionResult LaraCeilingCollisionFront(ItemInfo* item, short angle, int dista
|
|||
return probe;
|
||||
}
|
||||
|
||||
bool TestLaraWaterStepOut(ItemInfo* item, CollisionInfo* coll)
|
||||
bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
auto& player = GetLaraInfo(*item);
|
||||
|
||||
// Get point collision.
|
||||
auto pointColl = GetCollision(item);
|
||||
int vPos = item->Pose.Position.y;
|
||||
|
||||
if (coll->CollisionType == CT_FRONT ||
|
||||
coll->Middle.FloorSlope ||
|
||||
coll->Middle.Floor >= 0)
|
||||
pointColl.Position.FloorSlope ||
|
||||
(pointColl.Position.Floor - vPos) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (coll->Middle.Floor >= -CLICK(0.5f))
|
||||
if ((pointColl.Position.Floor - vPos) >= -CLICK(0.5f))
|
||||
{
|
||||
SetAnimation(item, LA_STAND_IDLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAnimation(item, LA_ONWATER_TO_WADE_1_STEP);
|
||||
item->Animation.TargetState = LS_IDLE;
|
||||
}
|
||||
|
||||
item->Pose.Position.y += coll->Middle.Floor + CLICK(2.75f) - 9;
|
||||
item->Pose.Position.y = pointColl.Position.Floor;
|
||||
UpdateLaraRoom(item, -(STEPUP_HEIGHT - 3));
|
||||
|
||||
item->Pose.Orientation.x = 0;
|
||||
item->Pose.Orientation.z = 0;
|
||||
item->Animation.Velocity.z = 0;
|
||||
item->Animation.Velocity.y = 0;
|
||||
ResetPlayerLean(item);
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Animation.Velocity.z = 0.0f;
|
||||
item->Animation.IsAirborne = false;
|
||||
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||
player.Control.WaterStatus = WaterStatus::Wade;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -933,11 +938,12 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll)
|
|||
return false;
|
||||
}
|
||||
|
||||
//Do extra check if it's a bridge collider:
|
||||
// Extra bridge check.
|
||||
if (coll->Front.Bridge != NO_ITEM)
|
||||
{
|
||||
auto distancePointLara = GetBridgeBorder(coll->Front.Bridge, false) - LaraItem->Pose.Position.y;
|
||||
frontFloor = distancePointLara - 128;
|
||||
int bridgeBorder = GetBridgeBorder(coll->Front.Bridge, false) - item->Pose.Position.y;
|
||||
|
||||
frontFloor = bridgeBorder - CLICK(0.5f);
|
||||
if (frontFloor <= -CLICK(2) ||
|
||||
frontFloor > CLICK(1.25f) - 4)
|
||||
{
|
||||
|
@ -1084,29 +1090,27 @@ bool TestLaraLadderClimbOut(ItemInfo* item, CollisionInfo* coll) // NEW function
|
|||
|
||||
void TestLaraWaterDepth(ItemInfo* item, CollisionInfo* coll)
|
||||
{
|
||||
auto* lara = GetLaraInfo(item);
|
||||
auto& player = GetLaraInfo(*item);
|
||||
|
||||
auto probe = GetCollision(item);
|
||||
int waterDepth = GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, probe.RoomNumber);
|
||||
auto pointColl = GetCollision(item);
|
||||
int waterDepth = GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, pointColl.RoomNumber);
|
||||
|
||||
if (waterDepth == NO_HEIGHT)
|
||||
{
|
||||
item->Animation.Velocity.y = 0;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Pose.Position = coll->Setup.PrevPosition;
|
||||
}
|
||||
// Height check was at CLICK(2) before but changed to this
|
||||
// because now Lara surfaces on a head level, not mid-body level.
|
||||
else if (waterDepth <= LARA_HEIGHT - LARA_HEADROOM / 2)
|
||||
|
||||
else if (waterDepth <= (LARA_HEIGHT - (LARA_HEADROOM / 2)))
|
||||
{
|
||||
SetAnimation(item, LA_UNDERWATER_TO_STAND);
|
||||
ResetPlayerLean(item);
|
||||
item->Animation.TargetState = LS_IDLE;
|
||||
item->Pose.Position.y = probe.Position.Floor;
|
||||
item->Pose.Orientation.x = 0;
|
||||
item->Pose.Orientation.z = 0;
|
||||
item->Pose.Position.y = pointColl.Position.Floor;
|
||||
item->Animation.IsAirborne = false;
|
||||
item->Animation.Velocity.z = 0;
|
||||
item->Animation.Velocity.y = 0;
|
||||
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||
item->Animation.Velocity.y = 0.0f;
|
||||
item->Animation.Velocity.z = 0.0f;
|
||||
player.Control.WaterStatus = WaterStatus::Wade;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ int LaraCeilingFront(ItemInfo* item, short angle, int distance, int height);
|
|||
CollisionResult LaraCollisionFront(ItemInfo* item, short angle, int distance);
|
||||
CollisionResult LaraCeilingCollisionFront(ItemInfo* item, short angle, int distance, int height);
|
||||
|
||||
bool TestLaraWaterStepOut(ItemInfo* item, CollisionInfo* coll);
|
||||
bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll);
|
||||
bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll);
|
||||
bool TestLaraLadderClimbOut(ItemInfo* item, CollisionInfo* coll);
|
||||
void TestLaraWaterDepth(ItemInfo* item, CollisionInfo* coll);
|
||||
|
|
|
@ -1182,6 +1182,8 @@ void CalculateCamera(const CollisionInfo& coll)
|
|||
LastTarget.y = Camera.target.y;
|
||||
LastTarget.z = Camera.target.z;
|
||||
LastTarget.RoomNumber = Camera.target.RoomNumber;
|
||||
|
||||
y -= CLICK(0.25f);
|
||||
}
|
||||
|
||||
Camera.target.RoomNumber = item->RoomNumber;
|
||||
|
@ -1193,8 +1195,8 @@ void CalculateCamera(const CollisionInfo& coll)
|
|||
}
|
||||
else
|
||||
{
|
||||
Camera.target.y += (y - Camera.target.y) >> 2;
|
||||
Camera.speed = Camera.type != CameraType::Look ? 8 : 4;
|
||||
Camera.target.y += (y - Camera.target.y) / 4;
|
||||
Camera.speed = (Camera.type != CameraType::Look) ? 8 : 4;
|
||||
}
|
||||
|
||||
Camera.fixedCamera = false;
|
||||
|
@ -1240,20 +1242,22 @@ void CalculateCamera(const CollisionInfo& coll)
|
|||
{
|
||||
Camera.fixedCamera = false;
|
||||
if (Camera.speed != 1 &&
|
||||
Camera.oldType != CameraType::Look &&
|
||||
!Lara.Control.Look.IsUsingBinoculars)
|
||||
{
|
||||
if (TargetSnaps <= 8)
|
||||
{
|
||||
x = LastTarget.x + ((x - LastTarget.x) >> 2);
|
||||
x = LastTarget.x + ((x - LastTarget.x) / 4);
|
||||
y = LastTarget.y + ((y - LastTarget.y) / 4);
|
||||
z = LastTarget.z + ((z - LastTarget.z) / 4);
|
||||
|
||||
Camera.target.x = x;
|
||||
y = LastTarget.y + ((y - LastTarget.y) >> 2);
|
||||
Camera.target.y = y;
|
||||
z = LastTarget.z + ((z - LastTarget.z) >> 2);
|
||||
Camera.target.z = z;
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetSnaps = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1274,9 +1278,13 @@ void CalculateCamera(const CollisionInfo& coll)
|
|||
}
|
||||
|
||||
if (Camera.type != CameraType::Chase && Camera.flags != CF_CHASE_OBJECT)
|
||||
{
|
||||
FixedCamera(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChaseCamera(item);
|
||||
}
|
||||
}
|
||||
|
||||
Camera.fixedCamera = isFixedCamera;
|
||||
|
@ -1304,14 +1312,13 @@ bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, sh
|
|||
return sphere.Intersects(bounds.ToBoundingOrientedBox(pose));
|
||||
}
|
||||
|
||||
float GetParticleDistanceFade(Vector3i position)
|
||||
float GetParticleDistanceFade(const Vector3i& pos)
|
||||
{
|
||||
float distance = Vector3::Distance(Camera.pos.ToVector3(), position.ToVector3());
|
||||
|
||||
if (distance <= PARTICLE_FADE_THRESHOLD)
|
||||
float dist = Vector3::Distance(Camera.pos.ToVector3(), pos.ToVector3());
|
||||
if (dist <= PARTICLE_FADE_THRESHOLD)
|
||||
return 1.0f;
|
||||
|
||||
return std::clamp(1.0f - ((distance - PARTICLE_FADE_THRESHOLD) / COLL_CHECK_THRESHOLD), 0.0f, 1.0f);
|
||||
return std::clamp(1.0f - ((dist - PARTICLE_FADE_THRESHOLD) / COLL_CHECK_THRESHOLD), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius)
|
||||
|
|
|
@ -115,4 +115,4 @@ void UpdateFadeScreenAndCinematicBars();
|
|||
void UpdateMikePos(const ItemInfo& item);
|
||||
void ClearObjCamera();
|
||||
|
||||
float GetParticleDistanceFade(Vector3i position);
|
||||
float GetParticleDistanceFade(const Vector3i& pos);
|
||||
|
|
|
@ -1236,43 +1236,58 @@ void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byt
|
|||
g_Renderer.AddDynamicLight(x, y, z, falloff, r, g, b);
|
||||
}
|
||||
|
||||
void WadeSplash(ItemInfo* item, int wh, int wd)
|
||||
// TODO: Better implementation.
|
||||
void SpawnPlayerSplash(const ItemInfo& item, int waterHeight, int waterDepth)
|
||||
{
|
||||
auto probe1 = GetCollision(item);
|
||||
auto probe2 = GetCollision(probe1.Block, item->Pose.Position.x, probe1.Position.Ceiling, item->Pose.Position.z);
|
||||
// Get point collision.
|
||||
auto pointColl0 = GetCollision(item);
|
||||
auto pointColl1 = GetCollision(pointColl0.Block, item.Pose.Position.x, pointColl0.Position.Ceiling, item.Pose.Position.z);
|
||||
|
||||
if (!TestEnvironment(ENV_FLAG_WATER, probe1.RoomNumber) ||
|
||||
TestEnvironment(ENV_FLAG_WATER, probe1.RoomNumber) == TestEnvironment(ENV_FLAG_WATER, probe2.RoomNumber))
|
||||
if (!TestEnvironment(ENV_FLAG_WATER, pointColl0.RoomNumber) ||
|
||||
TestEnvironment(ENV_FLAG_WATER, pointColl0.RoomNumber) == TestEnvironment(ENV_FLAG_WATER, pointColl1.RoomNumber))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& bounds = GetBestFrame(item).BoundingBox;
|
||||
if (item.Pose.Position.y + bounds.Y1 > waterHeight)
|
||||
return;
|
||||
|
||||
const auto& bounds = GetBestFrame(*item).BoundingBox;
|
||||
if (item->Pose.Position.y + bounds.Y1 > wh)
|
||||
if (item.Pose.Position.y + bounds.Y2 < waterHeight)
|
||||
return;
|
||||
|
||||
if (item->Pose.Position.y + bounds.Y2 < wh)
|
||||
return;
|
||||
|
||||
if (item->Animation.Velocity.y <= 0.0f || wd >= 474 || SplashCount != 0)
|
||||
if (item.Animation.Velocity.y <= 0.0f || waterDepth >= 474 || SplashCount != 0)
|
||||
{
|
||||
if (!(Wibble & 0xF))
|
||||
{
|
||||
if (!(GetRandomControl() & 0xF) || item->Animation.ActiveState != LS_IDLE)
|
||||
if (!(GetRandomControl() & 0xF) || item.Animation.ActiveState != LS_IDLE)
|
||||
{
|
||||
if (item->Animation.ActiveState != LS_IDLE)
|
||||
SpawnRipple(Vector3(item->Pose.Position.x, wh - 1, item->Pose.Position.z), item->RoomNumber, 112 + (GetRandomControl() & 15), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity);
|
||||
if (item.Animation.ActiveState != LS_IDLE)
|
||||
{
|
||||
SpawnRipple(
|
||||
Vector3(item.Pose.Position.x, waterHeight - 1, item.Pose.Position.z),
|
||||
item.RoomNumber, 112 + (GetRandomControl() & 15),
|
||||
(int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity);
|
||||
}
|
||||
else
|
||||
SpawnRipple(Vector3(item->Pose.Position.x, wh - 1, item->Pose.Position.z), item->RoomNumber, 112 + (GetRandomControl() & 15), (int)RippleFlags::LowOpacity);
|
||||
{
|
||||
SpawnRipple(
|
||||
Vector3(item.Pose.Position.x, waterHeight - 1, item.Pose.Position.z),
|
||||
item.RoomNumber, 112 + (GetRandomControl() & 15),
|
||||
(int)RippleFlags::LowOpacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SplashSetup.y = wh - 1;
|
||||
SplashSetup.x = item->Pose.Position.x;
|
||||
SplashSetup.z = item->Pose.Position.z;
|
||||
SplashSetup.x = item.Pose.Position.x;
|
||||
SplashSetup.y = waterHeight - 1;
|
||||
SplashSetup.z = item.Pose.Position.z;
|
||||
SplashSetup.innerRadius = 16;
|
||||
SplashSetup.splashPower = item->Animation.Velocity.z;
|
||||
SetupSplash(&SplashSetup, probe1.RoomNumber);
|
||||
SplashSetup.splashPower = item.Animation.Velocity.z;
|
||||
|
||||
SetupSplash(&SplashSetup, pointColl0.RoomNumber);
|
||||
SplashCount = 16;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ void TriggerFlashSmoke(int x, int y, int z, short roomNumber);
|
|||
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, const Vector3& color, int additional);
|
||||
void SpawnCorpseEffect(const Vector3& pos);
|
||||
void TriggerAttackFlame(const Vector3i& pos, const Vector3& color, int scale);
|
||||
void WadeSplash(ItemInfo* item, int wh, int wd);
|
||||
void SpawnPlayerSplash(const ItemInfo& item, int waterHeight, int waterDepth);
|
||||
void Splash(ItemInfo* item);
|
||||
void TriggerRocketFire(int x, int y, int z);
|
||||
void TriggerExplosionBubbles(int x, int y, int z, short roomNumber);
|
||||
|
|
|
@ -631,11 +631,11 @@ void StopSoundTracks(bool excludeAmbience)
|
|||
{
|
||||
for (int i = 0; i < (int)SoundTrackType::Count; i++)
|
||||
{
|
||||
auto mode = (SoundTrackType)i;
|
||||
if (excludeAmbience && mode == SoundTrackType::BGM)
|
||||
auto type = (SoundTrackType)i;
|
||||
if (excludeAmbience && type == SoundTrackType::BGM)
|
||||
continue;
|
||||
|
||||
StopSoundTrack((SoundTrackType)i, SOUND_XFADETIME_ONESHOT);
|
||||
StopSoundTrack(type, SOUND_XFADETIME_ONESHOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue