diff --git a/CREDITS.md b/CREDITS.md index e04a99cb99..ea644cdc69 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -534,6 +534,7 @@ This page lists all the individual contributions to the project by their author. - Make harvesters do addtional scan after unload - Customize the scatter caused by aircraft attack mission - Customize whether `Crater=yes` animation would destroy tiberium + - Fix BalloonHover incorrectly considering ground factors when pathfinding - **tyuah8**: - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix - Destroyed unit leaves sensors bugfix diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 3c81d2b95f..e5852b9333 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -232,6 +232,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Infantry support `IsGattling=yes`. - Fixed the issue that the widespread damage caused by detonation on the bridge/ground cannot affect objects on the ground/bridge who are in the opposite case. - Fixed the bug that `DamageSelf` and `AllowDamageOnSelf` are ineffective on airforce. +- Fixed the bug where technos with `BalloonHover=yes` incorrectly considered ground factors when setting the destination and distributing moving commands. If you don't want this anyway, use `[General]->BalloonHoverPathingFix=false` to disable this fix. ## Fixes / interactions with other extensions diff --git a/docs/Whats-New.md b/docs/Whats-New.md index c8d6ab311d..6d53099428 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -416,6 +416,7 @@ Vanilla fixes: - Second weapon with `ElectricAssault=yes` will not unconditionally attack your building with `Overpowerable=yes` (by FlyStar) - Fixed the issue that the widespread damage caused by detonation on the bridge/ground cannot affect objects on the ground/bridge who are in the opposite case (by CrimRecya) - Fixed the bug that `DamageSelf` and `AllowDamageOnSelf` are ineffective on airforce (by NetsuNegi) +- Fix BalloonHover incorrectly considering ground factors when pathfinding (by TaranDahl) Phobos fixes: - Fixed the bug that `AllowAirstrike=no` cannot completely prevent air strikes from being launched against it (by NetsuNegi) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 9d081b5892..f17b03bf8b 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -273,6 +273,9 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->AnimCraterDestroyTiberium.Read(exINI, GameStrings::General, "AnimCraterDestroyTiberium"); + this->BalloonHoverPathingFix.Read(exINI, GameStrings::General, "BalloonHoverPathingFix"); + Phobos::Optimizations::DisableBalloonHoverPathingFix = !this->BalloonHoverPathingFix; + // Section AITargetTypes int itemsCount = pINI->GetKeyCount("AITargetTypes"); for (int i = 0; i < itemsCount; ++i) @@ -501,6 +504,7 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->DamagedSpeed) .Process(this->HarvesterScanAfterUnload) .Process(this->AnimCraterDestroyTiberium) + .Process(this->BalloonHoverPathingFix) ; } @@ -510,6 +514,7 @@ void RulesExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) this->Serialize(Stm); this->ReplaceVoxelLightSources(); + Phobos::Optimizations::DisableBalloonHoverPathingFix = !this->BalloonHoverPathingFix; } void RulesExt::ExtData::SaveToStream(PhobosStreamWriter& Stm) diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index ddb1e9bc4a..d31d355be2 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -228,6 +228,8 @@ class RulesExt Valueable AnimCraterDestroyTiberium; + Valueable BalloonHoverPathingFix; + ExtData(RulesClass* OwnerObject) : Extension(OwnerObject) , Storage_TiberiumIndex { -1 } , HarvesterDumpAmount { 0.0f } @@ -401,6 +403,8 @@ class RulesExt , HarvesterScanAfterUnload { false } , AnimCraterDestroyTiberium { true } + + , BalloonHoverPathingFix { false } { } virtual ~ExtData() = default; diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index b1cff1a66e..e0f7c978a9 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -2196,3 +2196,76 @@ DEFINE_HOOK(0x489E47, DamageArea_RockerItemsFix2, 0x6) } #pragma region + + +#pragma region BalloonHoverPathingFix + +DEFINE_HOOK(0x64D592, Game_PreProcessMegaMissionList_CheckForTargetCrdRecal1, 0x6) +{ + enum { SkipTargetCrdRecal = 0x64D598 }; + GET(TechnoClass*, pTechno, EBP); + return pTechno->GetTechnoType()->BalloonHover ? SkipTargetCrdRecal : 0; +} + +DEFINE_HOOK(0x64D575, Game_PreProcessMegaMissionList_CheckForTargetCrdRecal2, 0x6) +{ + enum { SkipTargetCrdRecal = 0x64D598 }; + GET(TechnoClass*, pTechno, EBP); + return pTechno->GetTechnoType()->BalloonHover ? SkipTargetCrdRecal : 0; +} + +DEFINE_HOOK(0x64D5C5, Game_PreProcessMegaMissionList_CheckForTargetCrdRecal3, 0x6) +{ + enum { SkipTargetCrdRecal = 0x64D659 }; + GET(TechnoClass*, pTechno, EBP); + return pTechno->GetTechnoType()->BalloonHover ? SkipTargetCrdRecal : 0; +} + +DEFINE_HOOK(0x51BFA2, InfantryClass_IsCellOccupied_Start, 0x6) +{ + enum { MoveOK = 0x51C02D }; + GET(InfantryClass*, pThis, EBP); + return pThis->Type->BalloonHover && pThis->IsInAir() ? MoveOK : 0; +} + +DEFINE_HOOK(0x73F0A7, UnitClass_IsCellOccupied_Start, 0x9) +{ + enum { MoveOK = 0x73F23F }; + GET(UnitClass*, pThis, ECX); + return pThis->Type->BalloonHover && pThis->IsInAir() ? MoveOK : 0; +} + +namespace ApproachTargetContext +{ + bool IsBalloonHover = false; +} + +DEFINE_HOOK(0x4D5690, FootClass_ApproachTarget_SetContext, 0x6) +{ + GET(FootClass*, pThis, ECX); + ApproachTargetContext::IsBalloonHover = pThis->GetTechnoType()->BalloonHover; + return 0; +} + +DEFINE_HOOK_AGAIN(0x4D5A42, FootClass_ApproachTarget_ResetContext, 0x5); +DEFINE_HOOK_AGAIN(0x4D5AB5, FootClass_ApproachTarget_ResetContext, 0x5); +DEFINE_HOOK_AGAIN(0x4D68DE, FootClass_ApproachTarget_ResetContext, 0x5); +DEFINE_HOOK_AGAIN(0x4D6A8B, FootClass_ApproachTarget_ResetContext, 0x5); +DEFINE_HOOK(0x4D5744, FootClass_ApproachTarget_ResetContext, 0x5) +{ + ApproachTargetContext::IsBalloonHover = false; + return 0; +} + +DEFINE_HOOK(0x4834A0, CellClass_IsClearToMove_Start, 0x5) +{ + if (ApproachTargetContext::IsBalloonHover) + { + R->AL(true); + return 0x483605; + } + + return 0; +} + +#pragma endregion diff --git a/src/Phobos.cpp b/src/Phobos.cpp index 577a8d4501..2a7cef4b5b 100644 --- a/src/Phobos.cpp +++ b/src/Phobos.cpp @@ -25,6 +25,7 @@ bool Phobos::DisplayDamageNumbers = false; bool Phobos::IsLoadingSaveGame = false; bool Phobos::Optimizations::Applied = false; +bool Phobos::Optimizations::DisableBalloonHoverPathingFix = false; bool Phobos::Optimizations::DisableRadDamageOnBuildings = true; bool Phobos::Optimizations::DisableSyncLogging = false; @@ -269,6 +270,17 @@ void Phobos::ApplyOptimizations() if (Phobos::Optimizations::DisableRadDamageOnBuildings) Patch::Apply_RAW(0x43FB23, { 0x53, 0x55, 0x56, 0x8B, 0xF1 }); + // Disable BalloonHover path finding fix + if (Phobos::Optimizations::DisableBalloonHoverPathingFix) + { + Patch::Apply_RAW(0x64D592, { 0x0F, 0x8F, 0xB8, 0x00, 0x00, 0x00 }); + Patch::Apply_RAW(0x64D575, { 0x0F, 0x8F, 0xD5, 0x00, 0x00, 0x00 }); + Patch::Apply_RAW(0x64D5C5, { 0x8A, 0x44, 0x24, 0x13, 0x84, 0xC0 }); + Patch::Apply_RAW(0x51BFA2, { 0x85, 0x99, 0x40, 0x01, 0x00, 0x00 }); + Patch::Apply_RAW(0x73F0A7, { 0x8B, 0xD9, 0x8B, 0x8C, 0x24, 0x88, 0x00, 0x00, 0x00 }); + Patch::Apply_RAW(0x4D5690, { 0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8 }); + } + if (SessionClass::IsMultiplayer()) { // Disable MainLoop_SaveGame diff --git a/src/Phobos.h b/src/Phobos.h index 50e4428260..17cd3923d2 100644 --- a/src/Phobos.h +++ b/src/Phobos.h @@ -118,6 +118,7 @@ class Phobos { public: static bool Applied; + static bool DisableBalloonHoverPathingFix; static bool DisableRadDamageOnBuildings; static bool DisableSyncLogging; };