Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -775,3 +775,4 @@ This page lists all the individual contributions to the project by their author.
- Wall overlay unit sell exploit fix
- Multiplayer gamespeed fix for RealTimeTimers
- Revert Ares patch to allow OpenTopped transport customization
- Fix for units with Fly, Jumpjet or Rocket locomotors crashing off-map not being cleaned up
1 change: 1 addition & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
- Fixed the bug that vehicle fall on infantry will make all cell content has been removed.
- Fixed buildings that have their owner changed during buildup skipping buildup and sometimes not correctly clearing the state.
- Fixed preplaced aircraft outside visible map being incorrectly flagged as crashing under certain conditions.
- Fixed units with Fly, Jumpjet or Rocket locomotors destroyed while crashing off-map never being fully cleaned up, permanently blocking production slots and counting towards unit limits.
- Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc.
- Fixed an issue where some effects pointing to a unit were not properly cleared when the unit changed its owner.
- Allow Reveal Crate to take effect when picking up by another player controlled house in campaign.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ Phobos fixes:
- Fixed the bug that the upgrade building's power-enhancing effect depends only on its parent building and is not related to the upgrade building itself (by NetsuNegi)
- Fixed an issue where hover vehicles could not be destroyed after malfunctioning on water surfaces (by FlyStar)
- Fixed an issue where shadow matrix scaling was incorrectly applied to `TurretOffset` causing turret shadow misplacement (by Noble_Fish)
- Fixed units with Fly, Jumpjet or Rocket locomotors destroyed while crashing off-map never being fully cleaned up, permanently blocking production slots and counting towards unit limits (by RAZER)

Fixes / interactions with other extensions:
<!-- - Allowed `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades (by Ollerus) -->
Expand Down
57 changes: 57 additions & 0 deletions src/Misc/Hooks.BugFixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,63 @@ DEFINE_HOOK(0x4DB874, FootClass_SetLocation_Extra, 0xA)
return SkipGameCode;
}

// Fix crash descent for aircraft/units off-map.
// In all three locomotors below, MapClass::In_Radar blocks position/coordinate updates
// when outside the map. This means crashing units off-map never descend to ground level
// (or reach their destination), so the cleanup code (fire death weapon, UnInit) never runs.
// The fix: at each locomotor's height/health check, treat off-map as ground-touch.
// FlyLocomotionClass::Process - height check after crash descent calculation.
// If off-map and crashing, skip the height > 0 check and go straight to ground-touch cleanup.
// The IsCrashing guard is needed because healthy non-moving airborne aircraft also reach this
// code path (Is_Moving()==false && Height>0) and must not be sent to cleanup.
DEFINE_HOOK(0x4CD797, FlyLocomotionClass_CrashDescent_OffMap, 0x5)
{
enum { GroundTouchCleanup = 0x4CD7AA };

GET(FlyLocomotionClass*, pThis, ESI);

const auto pLinkedTo = pThis->LinkedTo;

if (pLinkedTo->IsCrashing && !MapClass::Instance.IsWithinUsableArea(pLinkedTo->GetCoords()))
return GroundTouchCleanup;

return 0;
}

// JumpjetLocomotionClass::Process - height check before IsCrashing gate.
// If off-map, skip height check and go to the IsCrashing check directly.
DEFINE_HOOK(0x54CC16, JumpjetLocomotionClass_CrashDescent_OffMap, 0x8)
{
enum { IsCrashingCheck = 0x54CC36 };

GET(JumpjetLocomotionClass*, pThis, EDI);

if (!MapClass::Instance.IsWithinUsableArea(pThis->LinkedTo->GetCoords()))
{
// Replicate the stack init from the stolen bytes (mov byte ptr [esp+21h], 0)
// so the "fell on something" flag is properly zeroed for the crash path.
REF_STACK(BYTE, fellOnSomething, STACK_OFFSET(0x34, -0x13));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you want to change the var below.
I think it should be STACK_OFFSET(0x34, -0x23).
Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing can try this 👍🏻

fellOnSomething = 0;
return IsCrashingCheck;
}

return 0;
}

// RocketLocomotionClass::Process - health check after position update.
// If off-map, bypass the Health > 0 skip and force detonation/cleanup.
DEFINE_HOOK(0x662FD5, RocketLocomotionClass_Process_OffMap, 0x6)
{
enum { ForceCleanup = 0x662FDF };

GET(RocketLocomotionClass*, pThis, EDI);

if (!MapClass::Instance.IsWithinUsableArea(pThis->LinkedTo->GetCoords()))
return ForceCleanup;

return 0;
}

DEFINE_HOOK(0x4DEC7F, FootClass_Crash_FallingDownFix, 0x7)
{
GET(FootClass*, pThis, ESI);
Expand Down
Loading