From 218fa3b946ae0f0ef395872e9aa49a2c141eca5f Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 25 Aug 2024 15:14:09 +0800 Subject: [PATCH 01/46] Core --- src/Ext/Aircraft/Hooks.cpp | 152 +++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 3a506bae27..e66d8d0463 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -342,3 +343,154 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) return SkipKickOutPassengers; } + +// Aircraft mission hard code are all disposable that no ammo, target died or arrived destination all will call the aircraft return airbase +#pragma region AircraftMissionExpand + +// AreaGuard: return when no ammo or first target died +int __fastcall AircraftClass_Mission_AreaGuard(AircraftClass* pThis) +{ + do + { + const bool flying = pThis->GetHeight() == pThis->Type->GetFlightLevel(); + + if (!pThis->Team) + { + // if (!flying && pThis->Target) // This is what vanilla do, but now there is no need to do so + // break; + + if (pThis->Ammo && pThis->IsArmed()) + { + CoordStruct coords = pThis->GetCoords(); + + if (pThis->TargetAndEstimateDamage(reinterpret_cast(&coords), static_cast(TargetFlags::unknown_1))) + break; + else if (!flying && pThis->HasAnyLink()) + return 30; + + pThis->EnterIdleMode(false, true); + return 1; + } + } + + return flying ? 1 : reinterpret_cast(0x4D6AA0)(pThis); + } + while (false); + + pThis->QueueMission(Mission::Attack, false); + return 1; +} +DEFINE_JUMP(VTABLE, 0x7E24C4, GET_OFFSET(AircraftClass_Mission_AreaGuard)) + +DEFINE_HOOK(0x4C740F, EventClass_RespondToEvent_AircraftAreaGuard, 0x5) +{ + enum { SkipGameCode = 0x4C7435 }; + + GET(EventClass* const, pThis, ESI); + GET(FootClass* const, pFoot, EDI); + + if (pFoot->WhatAmI() == AbstractType::Aircraft && pThis->MegaMission.Target.m_RTTI == static_cast(AbstractType::Cell)) + { + if (AbstractClass* const pTarget = reinterpret_cast(0x6E6E20)(&pThis->MegaMission.Target)) + { + const CoordStruct coords = pTarget->GetCoords() - pFoot->GetCoords(); + + if ((coords.X * coords.X + coords.Y * coords.Y) & 0x7FFF0000) // Horizontal distance too close, no need to move + return SkipGameCode; + } + } + + return 0; +} + +// AttackMove: return when no ammo or arrived destination +bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) +{ + return true; +} +DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) + +DEFINE_HOOK(0x6FA68B, TechnoClass_Update_ShouldReturnToAirbase, 0xA) +{ + enum { SkipGameCode = 0x6FA6F5 }; + + GET(TechnoClass* const, pThis, ESI); + + if (pThis->WhatAmI() == AbstractType::Aircraft && !pThis->Ammo) + { + pThis->EnterIdleMode(false, true); // No ammo, return + return SkipGameCode; + } + + return 0; +} + +DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) +{ + enum { LoseCurrentTarget = 0x4DF3D3, HoldCurrentTarget = 0x4DF4AB }; + + GET(FootClass* const, pThis, ESI); + + return (pThis->WhatAmI() == AbstractType::Aircraft || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldCurrentTarget : LoseCurrentTarget; +} + +DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) +{ + enum { Continue = 0x418C43, Return = 0x418CE8 }; + + GET(AircraftClass* const, pThis, ESI); + + if (!pThis->Target) + { + if (!pThis->vt_entry_4C4() || !pThis->unknown_5C8) + return Continue; + + pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); + pThis->QueueMission(Mission::Move, true); + pThis->unknown_bool_5D1 = false; + } + else + { + pThis->MissionStatus = 1; + } + + R->EAX(1); + return Return; +} + +// Stop: clear the mega mission and return to airbase immediately +DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) +{ + GET(TechnoClass* const, pTechno, ESI); + + if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) + { + if (pTechno->vt_entry_4C4()) + pTechno->vt_entry_4A8(); + + if (!pTechno->HasAnyLink() && pTechno->GetCurrentMission() != Mission::Enter) + pTechno->EnterIdleMode(false, true); + } + + return 0; +} + +// SelectAutoTarget: for all the mission that should let the aircraft auto select a closing target +AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, TargetFlags targetFlags, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) +{ + WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; + WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; + + if (pSecondaryWeapon) // Vanilla (other types) secondary first + targetFlags |= reinterpret_cast(0x772A90)(pSecondaryWeapon); + else if (pPrimaryWeapon) + targetFlags |= reinterpret_cast(0x772A90)(pPrimaryWeapon); + + AbstractClass* const pTarget = reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); + const int range = pThis->SelectWeapon(pTarget) ? pSecondaryWeapon->Range : pPrimaryWeapon->Range; // No need to check pTarget + + return (!pThis->vt_entry_4C4() || (pTarget && pThis->GetCoords().DistanceFrom(pTarget->GetCoords()) < (range << 1))) ? pTarget : nullptr; // Should check lower distance if in AttackMove +} +DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) + +#pragma endregion From a2d91cb03278b91134efe65a552be3418a63d5f6 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 25 Aug 2024 15:16:04 +0800 Subject: [PATCH 02/46] Docs --- CREDITS.md | 2 ++ docs/Fixed-or-Improved-Logics.md | 1 + docs/Whats-New.md | 1 + 3 files changed, 4 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index e1f8766b9b..3bcb3b5555 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -350,6 +350,8 @@ This page lists all the individual contributions to the project by their author. - **Ollerus** - Build limit group enhancement - Customizable rocker amplitude +- **CrimRecya** + - Optimize aircrafts stop action and allow they using area guard and attack moving - **handama** - AI script action to jump back to previous script - **Ares developers** - YRpp and Syringe which are used, save/load, project foundation and generally useful code from Ares diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 2f6f87d0c6..2c38b0c115 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -164,6 +164,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Weapons with `AA=true` Projectile can now correctly fire at air units when both firer and target are over a bridge. - Fixed disguised units not using the correct palette if target has custom palette. - Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc. +- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). When a `target guard` command (Ctrl+Alt) is issued, it's like a combination of the attack move command and the guard command - on its way to its destination, when the first automatically selected target is destroyed (Though its ammos may not depleted yet) or ammos are depleted, it will return. ## Fixes / interactions with other extensions diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 07eb0ebda8..0a8e3bfc1c 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -440,6 +440,7 @@ New: - Option for Warhead to remove all shield types at once (by Starkku) - Allow customizing voxel light source position (by Kerbiter, Morton, based on knowledge of thomassnedon) - Option to fix voxel light source being offset and incorrectly tilting on slopes (by Kerbiter) +- Optimize aircrafts stop action and allow they using area guard and attack moving (by CrimRecya) Vanilla fixes: - Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy) From 615743745f935881f8c4c0ed53d5ef4f0c64fea0 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 25 Aug 2024 16:13:00 +0800 Subject: [PATCH 03/46] Fix a mistake --- docs/Fixed-or-Improved-Logics.md | 2 +- src/Ext/Aircraft/Hooks.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 2c38b0c115..8ae9651e6f 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -164,7 +164,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Weapons with `AA=true` Projectile can now correctly fire at air units when both firer and target are over a bridge. - Fixed disguised units not using the correct palette if target has custom palette. - Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc. -- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). When a `target guard` command (Ctrl+Alt) is issued, it's like a combination of the attack move command and the guard command - on its way to its destination, when the first automatically selected target is destroyed (Though its ammos may not depleted yet) or ammos are depleted, it will return. +- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). ## Fixes / interactions with other extensions diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index e66d8d0463..d5aff6c187 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -395,7 +395,7 @@ DEFINE_HOOK(0x4C740F, EventClass_RespondToEvent_AircraftAreaGuard, 0x5) { const CoordStruct coords = pTarget->GetCoords() - pFoot->GetCoords(); - if ((coords.X * coords.X + coords.Y * coords.Y) & 0x7FFF0000) // Horizontal distance too close, no need to move + if (!((coords.X * coords.X + coords.Y * coords.Y) & 0x7FFF0000)) // Horizontal distance too close, no need to move return SkipGameCode; } } From d855e1dde8f7e1dae7982c5dfcdb34105abb4ad8 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 25 Aug 2024 17:28:54 +0800 Subject: [PATCH 04/46] Optimize and remove some useless hook --- src/Ext/Aircraft/Hooks.cpp | 44 ++++---------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index d5aff6c187..962b600f54 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -382,27 +382,6 @@ int __fastcall AircraftClass_Mission_AreaGuard(AircraftClass* pThis) } DEFINE_JUMP(VTABLE, 0x7E24C4, GET_OFFSET(AircraftClass_Mission_AreaGuard)) -DEFINE_HOOK(0x4C740F, EventClass_RespondToEvent_AircraftAreaGuard, 0x5) -{ - enum { SkipGameCode = 0x4C7435 }; - - GET(EventClass* const, pThis, ESI); - GET(FootClass* const, pFoot, EDI); - - if (pFoot->WhatAmI() == AbstractType::Aircraft && pThis->MegaMission.Target.m_RTTI == static_cast(AbstractType::Cell)) - { - if (AbstractClass* const pTarget = reinterpret_cast(0x6E6E20)(&pThis->MegaMission.Target)) - { - const CoordStruct coords = pTarget->GetCoords() - pFoot->GetCoords(); - - if (!((coords.X * coords.X + coords.Y * coords.Y) & 0x7FFF0000)) // Horizontal distance too close, no need to move - return SkipGameCode; - } - } - - return 0; -} - // AttackMove: return when no ammo or arrived destination bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) { @@ -410,21 +389,6 @@ bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) } DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) -DEFINE_HOOK(0x6FA68B, TechnoClass_Update_ShouldReturnToAirbase, 0xA) -{ - enum { SkipGameCode = 0x6FA6F5 }; - - GET(TechnoClass* const, pThis, ESI); - - if (pThis->WhatAmI() == AbstractType::Aircraft && !pThis->Ammo) - { - pThis->EnterIdleMode(false, true); // No ammo, return - return SkipGameCode; - } - - return 0; -} - DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) { enum { LoseCurrentTarget = 0x4DF3D3, HoldCurrentTarget = 0x4DF4AB }; @@ -481,15 +445,15 @@ AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, v WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; + if (pThis->vt_entry_4C4()) + targetFlags = TargetFlags::unknown_2; + if (pSecondaryWeapon) // Vanilla (other types) secondary first targetFlags |= reinterpret_cast(0x772A90)(pSecondaryWeapon); else if (pPrimaryWeapon) targetFlags |= reinterpret_cast(0x772A90)(pPrimaryWeapon); - AbstractClass* const pTarget = reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); - const int range = pThis->SelectWeapon(pTarget) ? pSecondaryWeapon->Range : pPrimaryWeapon->Range; // No need to check pTarget - - return (!pThis->vt_entry_4C4() || (pTarget && pThis->GetCoords().DistanceFrom(pTarget->GetCoords()) < (range << 1))) ? pTarget : nullptr; // Should check lower distance if in AttackMove + return reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) From 05c8cc5d6afe8fc213db6a21aac635550c274888 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 25 Aug 2024 20:20:53 +0800 Subject: [PATCH 05/46] Remove useless check --- src/Ext/Aircraft/Hooks.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 962b600f54..7112b07511 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -432,8 +432,7 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (pTechno->vt_entry_4C4()) pTechno->vt_entry_4A8(); - if (!pTechno->HasAnyLink() && pTechno->GetCurrentMission() != Mission::Enter) - pTechno->EnterIdleMode(false, true); + pTechno->EnterIdleMode(false, true); } return 0; From a59956bffa78d8e3ee98a39b3d818bde18afa4fb Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sun, 1 Sep 2024 19:53:01 +0800 Subject: [PATCH 06/46] Fit with aircraft waypoint --- src/Ext/Aircraft/Hooks.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 7112b07511..14ecaf5c27 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -389,6 +389,15 @@ bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) } DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) +DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) +{ + enum { SkipGameCode = 0x6FA6F5 }; + + GET(TechnoClass* const, pThis, ESI); + + return (pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetCurrentMission() == Mission::Sleep)) ? SkipGameCode : 0; +} + DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) { enum { LoseCurrentTarget = 0x4DF3D3, HoldCurrentTarget = 0x4DF4AB }; @@ -422,6 +431,18 @@ DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6 return Return; } +// Idle: clear the target if no ammo +DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) +{ + enum { ClearTarget = 0x414D3F }; + + GET(AircraftClass* const, pThis, ESI); + + const Mission mission = pThis->CurrentMission; + + return (!pThis->Ammo || mission == Mission::Sleep || mission == Mission::Enter) ? ClearTarget : 0; +} + // Stop: clear the mega mission and return to airbase immediately DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) { From 77847a6fda2b1c0e67b0987cc0d4f8811ea10854 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Mon, 16 Sep 2024 23:03:51 +0800 Subject: [PATCH 07/46] Add notes --- src/Ext/Aircraft/Hooks.cpp | 61 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 14ecaf5c27..fddb38514d 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -350,35 +350,36 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) // AreaGuard: return when no ammo or first target died int __fastcall AircraftClass_Mission_AreaGuard(AircraftClass* pThis) { - do + const bool flying = pThis->GetHeight() == pThis->Type->GetFlightLevel(); + + if (!pThis->Team) { - const bool flying = pThis->GetHeight() == pThis->Type->GetFlightLevel(); +/* if (!flying && pThis->Target) // This is what vanilla do, but now there is no need to do so + { + pThis->QueueMission(Mission::Attack, false); + return 1; + }*/ - if (!pThis->Team) + if (pThis->Ammo && pThis->IsArmed()) { - // if (!flying && pThis->Target) // This is what vanilla do, but now there is no need to do so - // break; + CoordStruct coords = pThis->GetCoords(); - if (pThis->Ammo && pThis->IsArmed()) + if (pThis->TargetAndEstimateDamage(reinterpret_cast(&coords), static_cast(TargetFlags::unknown_1))) { - CoordStruct coords = pThis->GetCoords(); - - if (pThis->TargetAndEstimateDamage(reinterpret_cast(&coords), static_cast(TargetFlags::unknown_1))) - break; - else if (!flying && pThis->HasAnyLink()) - return 30; - - pThis->EnterIdleMode(false, true); + pThis->QueueMission(Mission::Attack, false); return 1; } - } + else if (!flying && pThis->HasAnyLink()) + { + return 30; + } - return flying ? 1 : reinterpret_cast(0x4D6AA0)(pThis); + pThis->EnterIdleMode(false, true); + return 1; + } } - while (false); - pThis->QueueMission(Mission::Attack, false); - return 1; + return flying ? 1 : reinterpret_cast(0x4D6AA0)(pThis); // FootClass_Mission_AreaGuard (Prevent circular calls) } DEFINE_JUMP(VTABLE, 0x7E24C4, GET_OFFSET(AircraftClass_Mission_AreaGuard)) @@ -404,7 +405,7 @@ DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0 GET(FootClass* const, pThis, ESI); - return (pThis->WhatAmI() == AbstractType::Aircraft || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldCurrentTarget : LoseCurrentTarget; + return (pThis->WhatAmI() == AbstractType::Aircraft || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldCurrentTarget : LoseCurrentTarget; // pThis->InAuxiliarySearchRange(pThis->Target) } DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) @@ -415,12 +416,12 @@ DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6 if (!pThis->Target) { - if (!pThis->vt_entry_4C4() || !pThis->unknown_5C8) + if (!pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) return Continue; - pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); + pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); // pThis->MegaDestination pThis->QueueMission(Mission::Move, true); - pThis->unknown_bool_5D1 = false; + pThis->unknown_bool_5D1 = false; // pThis->HaveAttackMoveTarget } else { @@ -450,8 +451,8 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) { - if (pTechno->vt_entry_4C4()) - pTechno->vt_entry_4A8(); + if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() + pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() pTechno->EnterIdleMode(false, true); } @@ -465,15 +466,15 @@ AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, v WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; - if (pThis->vt_entry_4C4()) - targetFlags = TargetFlags::unknown_2; + if (pThis->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() + targetFlags = TargetFlags::unknown_2; // Select closing targets if (pSecondaryWeapon) // Vanilla (other types) secondary first - targetFlags |= reinterpret_cast(0x772A90)(pSecondaryWeapon); + targetFlags |= reinterpret_cast(0x772A90)(pSecondaryWeapon); // WeaponTypeClass_GetTargetFlags() else if (pPrimaryWeapon) - targetFlags |= reinterpret_cast(0x772A90)(pPrimaryWeapon); + targetFlags |= reinterpret_cast(0x772A90)(pPrimaryWeapon); // WeaponTypeClass_GetTargetFlags() - return reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); + return reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) From ce00c49cd4a22ac939dc2f153ee6ef1c2b4757a6 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 17 Sep 2024 01:24:41 +0800 Subject: [PATCH 08/46] Rename variable --- src/Ext/Aircraft/Hooks.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index fddb38514d..4914eda78d 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -390,7 +390,7 @@ bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) } DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) -DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) +DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircrafts not search for targets while resting at the airport, this is designed to adapt to loop waypoint { enum { SkipGameCode = 0x6FA6F5 }; @@ -461,20 +461,20 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) } // SelectAutoTarget: for all the mission that should let the aircraft auto select a closing target -AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, TargetFlags targetFlags, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) +AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, TargetFlags targetType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; if (pThis->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - targetFlags = TargetFlags::unknown_2; // Select closing targets + targetType = TargetFlags::unknown_2; // Select closing targets if (pSecondaryWeapon) // Vanilla (other types) secondary first - targetFlags |= reinterpret_cast(0x772A90)(pSecondaryWeapon); // WeaponTypeClass_GetTargetFlags() + targetType |= reinterpret_cast(0x772A90)(pSecondaryWeapon); // WeaponTypeClass_GetTargetFlags() else if (pPrimaryWeapon) - targetFlags |= reinterpret_cast(0x772A90)(pPrimaryWeapon); // WeaponTypeClass_GetTargetFlags() + targetType |= reinterpret_cast(0x772A90)(pPrimaryWeapon); // WeaponTypeClass_GetTargetFlags() - return reinterpret_cast(0x6F8DF0)(pThis, targetFlags, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) + return reinterpret_cast(0x6F8DF0)(pThis, targetType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) From e35eac3e41913154aa057f861db2aa811fa4a929 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 18 Sep 2024 15:20:32 +0800 Subject: [PATCH 09/46] Fix a mistake --- src/Ext/Aircraft/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 4914eda78d..0cae4e4d4f 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -441,7 +441,7 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) const Mission mission = pThis->CurrentMission; - return (!pThis->Ammo || mission == Mission::Sleep || mission == Mission::Enter) ? ClearTarget : 0; + return (!pThis->Ammo || mission == Mission::Sleep) ? ClearTarget : 0; } // Stop: clear the mega mission and return to airbase immediately From 8943f30ec05746f158fabce629079694926109b8 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 18 Sep 2024 23:02:45 +0800 Subject: [PATCH 10/46] Update CREDITS.md --- CREDITS.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 9626d25d81..c31353671e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -355,11 +355,10 @@ This page lists all the individual contributions to the project by their author. - Allow to change the speed of gas particles - **CrimRecya** - Fix `LimboKill` not working reliably + - Optimize aircrafts stop action and allow they using area guard and attack moving - **Ollerus** - Build limit group enhancement - Customizable rocker amplitude -- **CrimRecya** - - Optimize aircrafts stop action and allow they using area guard and attack moving - **handama** - AI script action to jump back to previous script - **Ares developers** - YRpp and Syringe which are used, save/load, project foundation and generally useful code from Ares From 3f27ca2558f8ee5e70f9a7d6cd121198db67966a Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 24 Sep 2024 01:26:30 +0800 Subject: [PATCH 11/46] Update --- src/Ext/Aircraft/Hooks.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 0cae4e4d4f..b4f2a77592 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -364,7 +364,7 @@ int __fastcall AircraftClass_Mission_AreaGuard(AircraftClass* pThis) { CoordStruct coords = pThis->GetCoords(); - if (pThis->TargetAndEstimateDamage(reinterpret_cast(&coords), static_cast(TargetFlags::unknown_1))) + if (pThis->TargetAndEstimateDamage(coords, ThreatType::Normal)) { pThis->QueueMission(Mission::Attack, false); return 1; @@ -461,20 +461,20 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) } // SelectAutoTarget: for all the mission that should let the aircraft auto select a closing target -AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, TargetFlags targetType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) +AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; if (pThis->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - targetType = TargetFlags::unknown_2; // Select closing targets + threatType = ThreatType::Area; // Select closing targets if (pSecondaryWeapon) // Vanilla (other types) secondary first - targetType |= reinterpret_cast(0x772A90)(pSecondaryWeapon); // WeaponTypeClass_GetTargetFlags() + threatType |= pSecondaryWeapon->AllowedThreats(); else if (pPrimaryWeapon) - targetType |= reinterpret_cast(0x772A90)(pPrimaryWeapon); // WeaponTypeClass_GetTargetFlags() + threatType |= pPrimaryWeapon->AllowedThreats(); - return reinterpret_cast(0x6F8DF0)(pThis, targetType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) + return reinterpret_cast(0x6F8DF0)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) From 2b5dd08133b2326167165dc636f6957d95652d8c Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 28 Sep 2024 14:15:45 +0800 Subject: [PATCH 12/46] Adapt to Kratos aircraft area guard --- src/Ext/Aircraft/Hooks.cpp | 50 +++++++++++++------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index b4f2a77592..9e54b492ec 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -348,40 +348,26 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) #pragma region AircraftMissionExpand // AreaGuard: return when no ammo or first target died -int __fastcall AircraftClass_Mission_AreaGuard(AircraftClass* pThis) +DEFINE_HOOK_AGAIN(0x41A982, AircraftClass_Mission_AreaGuard, 0x6) +DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) { - const bool flying = pThis->GetHeight() == pThis->Type->GetFlightLevel(); + enum { SkipGameCode = 0x41A97A }; - if (!pThis->Team) + GET(AircraftClass* const, pThis, ESI); + + if (!pThis->Team && pThis->Ammo && pThis->IsArmed()) { -/* if (!flying && pThis->Target) // This is what vanilla do, but now there is no need to do so - { - pThis->QueueMission(Mission::Attack, false); - return 1; - }*/ + CoordStruct coords = pThis->GetCoords(); - if (pThis->Ammo && pThis->IsArmed()) + if (pThis->TargetAndEstimateDamage(coords, ThreatType::Normal)) { - CoordStruct coords = pThis->GetCoords(); - - if (pThis->TargetAndEstimateDamage(coords, ThreatType::Normal)) - { - pThis->QueueMission(Mission::Attack, false); - return 1; - } - else if (!flying && pThis->HasAnyLink()) - { - return 30; - } - - pThis->EnterIdleMode(false, true); - return 1; + pThis->QueueMission(Mission::Attack, false); + return SkipGameCode; } } - return flying ? 1 : reinterpret_cast(0x4D6AA0)(pThis); // FootClass_Mission_AreaGuard (Prevent circular calls) + return 0; } -DEFINE_JUMP(VTABLE, 0x7E24C4, GET_OFFSET(AircraftClass_Mission_AreaGuard)) // AttackMove: return when no ammo or arrived destination bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) @@ -439,9 +425,7 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) GET(AircraftClass* const, pThis, ESI); - const Mission mission = pThis->CurrentMission; - - return (!pThis->Ammo || mission == Mission::Sleep) ? ClearTarget : 0; + return (!pThis->Ammo || pThis->CurrentMission == Mission::Sleep) ? ClearTarget : 0; } // Stop: clear the mega mission and return to airbase immediately @@ -460,22 +444,22 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) return 0; } -// SelectAutoTarget: for all the mission that should let the aircraft auto select a closing target -AbstractClass* __fastcall AircraftClass_SelectAutoTarget(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) +// GreatestThreat: for all the mission that should let the aircraft auto select a target +AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; if (pThis->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - threatType = ThreatType::Area; // Select closing targets + threatType = ThreatType::Area; if (pSecondaryWeapon) // Vanilla (other types) secondary first threatType |= pSecondaryWeapon->AllowedThreats(); else if (pPrimaryWeapon) threatType |= pPrimaryWeapon->AllowedThreats(); - return reinterpret_cast(0x6F8DF0)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_SelectAutoTarget (Prevent circular calls) + return reinterpret_cast(0x6F8DF0)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_GreatestThreat (Prevent circular calls) } -DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_SelectAutoTarget)) +DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat)) #pragma endregion From 4e1d14c6cd351be655f276cfcad7a1cd5cbf6e60 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 10 Oct 2024 11:56:13 +0800 Subject: [PATCH 13/46] Correct select target --- src/Ext/Aircraft/Hooks.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 9e54b492ec..4229bbd3e6 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -447,18 +447,13 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) // GreatestThreat: for all the mission that should let the aircraft auto select a target AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { - WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType; - WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType; - - if (pThis->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - threatType = ThreatType::Area; + if (WeaponTypeClass* const pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType) + threatType |= pPrimaryWeapon->AllowedThreats(); - if (pSecondaryWeapon) // Vanilla (other types) secondary first + if (WeaponTypeClass* const pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType) threatType |= pSecondaryWeapon->AllowedThreats(); - else if (pPrimaryWeapon) - threatType |= pPrimaryWeapon->AllowedThreats(); - return reinterpret_cast(0x6F8DF0)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_GreatestThreat (Prevent circular calls) + return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // FootClass_GreatestThreat (Prevent circular calls) } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat)) From 283f0a93c6d421ed1bd70ca8d00165d3881f6426 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 16 Oct 2024 13:07:17 +0800 Subject: [PATCH 14/46] Small change --- src/Ext/Aircraft/Hooks.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 94c3351eb7..868036a714 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -439,7 +439,8 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() - pTechno->EnterIdleMode(false, true); + if (pTechno->GetHeight() == static_cast(pTechno)->Type->GetFlightLevel()) + pTechno->EnterIdleMode(false, true); } return 0; From 245b52d984bdcb7c3723eb39fd64131a9f3f949c Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 26 Oct 2024 21:18:51 +0800 Subject: [PATCH 15/46] Fix --- src/Ext/Aircraft/Hooks.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 868036a714..23f0da1c57 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -383,7 +383,7 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr GET(TechnoClass* const, pThis, ESI); - return (pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetCurrentMission() == Mission::Sleep)) ? SkipGameCode : 0; + return (pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; } DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) @@ -426,7 +426,15 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) GET(AircraftClass* const, pThis, ESI); - return (!pThis->Ammo || pThis->CurrentMission == Mission::Sleep) ? ClearTarget : 0; + if (!pThis->Ammo && !SessionClass::IsCampaign()) + { + if (TeamClass* const pTeam = pThis->Team) + pTeam->LiberateMember(pThis); + + return ClearTarget; + } + + return 0; } // Stop: clear the mega mission and return to airbase immediately @@ -439,7 +447,7 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() - if (pTechno->GetHeight() == static_cast(pTechno)->Type->GetFlightLevel()) + if (pTechno->GetHeight() > Unsorted::CellHeight) pTechno->EnterIdleMode(false, true); } From 1249ec7d4a2e60eb12f304708091a11f257720dd Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Fri, 8 Nov 2024 00:24:50 +0800 Subject: [PATCH 16/46] Fix merge with const auto --- src/Ext/Aircraft/Hooks.cpp | 124 +++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index e125e4841a..480c8445b4 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -344,6 +344,130 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) return SkipKickOutPassengers; } +// Aircraft mission hard code are all disposable that no ammo, target died or arrived destination all will call the aircraft return airbase +#pragma region AircraftMissionExpand + +// AreaGuard: return when no ammo or first target died +DEFINE_HOOK_AGAIN(0x41A982, AircraftClass_Mission_AreaGuard, 0x6) +DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) +{ + enum { SkipGameCode = 0x41A97A }; + + GET(AircraftClass* const, pThis, ESI); + + if (!pThis->Team && pThis->Ammo && pThis->IsArmed()) + { + auto coords = pThis->GetCoords(); + + if (pThis->TargetAndEstimateDamage(coords, ThreatType::Normal)) + { + pThis->QueueMission(Mission::Attack, false); + return SkipGameCode; + } + } + + return 0; +} + +// AttackMove: return when no ammo or arrived destination +bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) +{ + return true; +} +DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) + +DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircrafts not search for targets while resting at the airport, this is designed to adapt to loop waypoint +{ + enum { SkipGameCode = 0x6FA6F5 }; + + GET(TechnoClass* const, pThis, ESI); + + return (pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; +} + +DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) +{ + enum { LoseCurrentTarget = 0x4DF3D3, HoldCurrentTarget = 0x4DF4AB }; + + GET(FootClass* const, pThis, ESI); + + return (pThis->WhatAmI() == AbstractType::Aircraft || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldCurrentTarget : LoseCurrentTarget; // pThis->InAuxiliarySearchRange(pThis->Target) +} + +DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) +{ + enum { Continue = 0x418C43, Return = 0x418CE8 }; + + GET(AircraftClass* const, pThis, ESI); + + if (!pThis->Target) + { + if (!pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) + return Continue; + + pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); // pThis->MegaDestination + pThis->QueueMission(Mission::Move, true); + pThis->unknown_bool_5D1 = false; // pThis->HaveAttackMoveTarget + } + else + { + pThis->MissionStatus = 1; + } + + R->EAX(1); + return Return; +} + +// Idle: clear the target if no ammo +DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) +{ + enum { ClearTarget = 0x414D3F }; + + GET(AircraftClass* const, pThis, ESI); + + if (!pThis->Ammo && !SessionClass::IsCampaign()) + { + if (const auto pTeam = pThis->Team) + pTeam->LiberateMember(pThis); + + return ClearTarget; + } + + return 0; +} + +// Stop: clear the mega mission and return to airbase immediately +DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) +{ + GET(TechnoClass* const, pTechno, ESI); + + if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) + { + if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() + pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() + + if (pTechno->GetHeight() > Unsorted::CellHeight) + pTechno->EnterIdleMode(false, true); + } + + return 0; +} + +// GreatestThreat: for all the mission that should let the aircraft auto select a target +AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) +{ + if (const auto pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType) + threatType |= pPrimaryWeapon->AllowedThreats(); + + if (const auto pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType) + threatType |= pSecondaryWeapon->AllowedThreats(); + + return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // FootClass_GreatestThreat (Prevent circular calls) +} +DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat)) + +#pragma endregion + static __forceinline bool CheckSpyPlaneCameraCount(AircraftClass* pThis) { auto const pExt = TechnoExt::ExtMap.Find(pThis); From 5a631ecd0e8e4c3a930ef7db52ed75feaca87ee2 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Fri, 8 Nov 2024 19:12:46 +0800 Subject: [PATCH 17/46] General --- docs/Fixed-or-Improved-Logics.md | 11 ++++++++++- src/Ext/Aircraft/Hooks.cpp | 27 +++++++++++++++------------ src/Ext/Rules/Body.cpp | 3 +++ src/Ext/Rules/Body.h | 4 ++++ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index c9a46205a4..999bf3c25f 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -160,7 +160,6 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Weapons with `AA=true` Projectile can now correctly fire at air units when both firer and target are over a bridge. - Fixed disguised units not using the correct palette if target has custom palette. - Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc. -- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). - Building upgrades now consistently use building's `PowerUpN` animation settings corresponding to the upgrade's `PowersUpToLevel` where possible. - Subterranean units are no longer allowed to perform deploy functions like firing weapons or `IsSimpleDeployer` while burrowed or burrowing, they will instead emerge first like they do for transport unloading. - The otherwise unused setting `[AI]` -> `PowerSurplus` (defaults to 50) which determines how much surplus power AI players will strive to have can be restored by setting `[AI]` -> `EnablePowerSurplus` to true. @@ -224,6 +223,16 @@ In `rulesmd.ini`: LandingDir= ; Direction type (integers from 0-255). Accepts negative values as a special case. ``` +### Expand Aircraft Mission + +- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). + +In `rulesmd.ini`: +```ini +[General] +ExpandAircraftMission= ; boolean +``` + ## Animations ### Animation weapon and damage settings diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 480c8445b4..e29c74ec10 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -355,7 +355,7 @@ DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) GET(AircraftClass* const, pThis, ESI); - if (!pThis->Team && pThis->Ammo && pThis->IsArmed()) + if (RulesExt::Global()->ExpandAircraftMission && !pThis->Team && pThis->Ammo && pThis->IsArmed()) { auto coords = pThis->GetCoords(); @@ -372,7 +372,7 @@ DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) // AttackMove: return when no ammo or arrived destination bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) { - return true; + return RulesExt::Global()->ExpandAircraftMission.Get(); } DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) @@ -382,16 +382,16 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr GET(TechnoClass* const, pThis, ESI); - return (pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; + return (RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; } DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) { - enum { LoseCurrentTarget = 0x4DF3D3, HoldCurrentTarget = 0x4DF4AB }; + enum { LoseTarget = 0x4DF3D3, HoldTarget = 0x4DF4AB }; GET(FootClass* const, pThis, ESI); - return (pThis->WhatAmI() == AbstractType::Aircraft || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldCurrentTarget : LoseCurrentTarget; // pThis->InAuxiliarySearchRange(pThis->Target) + return ((RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft) || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldTarget : LoseTarget; // pThis->InAuxiliarySearchRange(pThis->Target) } DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) @@ -402,7 +402,7 @@ DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6 if (!pThis->Target) { - if (!pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) + if (!RulesExt::Global()->ExpandAircraftMission || !pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) return Continue; pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); // pThis->MegaDestination @@ -425,7 +425,7 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) GET(AircraftClass* const, pThis, ESI); - if (!pThis->Ammo && !SessionClass::IsCampaign()) + if (RulesExt::Global()->ExpandAircraftMission && !pThis->Ammo && !SessionClass::IsCampaign()) { if (const auto pTeam = pThis->Team) pTeam->LiberateMember(pThis); @@ -441,7 +441,7 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) { GET(TechnoClass* const, pTechno, ESI); - if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) + if (RulesExt::Global()->ExpandAircraftMission && pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) { if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() @@ -456,11 +456,14 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) // GreatestThreat: for all the mission that should let the aircraft auto select a target AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { - if (const auto pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType) - threatType |= pPrimaryWeapon->AllowedThreats(); + if (RulesExt::Global()->ExpandAircraftMission) + { + if (const auto pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType) + threatType |= pPrimaryWeapon->AllowedThreats(); - if (const auto pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType) - threatType |= pSecondaryWeapon->AllowedThreats(); + if (const auto pSecondaryWeapon = pThis->GetWeapon(1)->WeaponType) + threatType |= pSecondaryWeapon->AllowedThreats(); + } return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // FootClass_GreatestThreat (Prevent circular calls) } diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 0c57e70790..86a9530506 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -135,6 +135,8 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->HeightShadowScaling = false; this->HeightShadowScaling_MinScale.Read(exINI, GameStrings::AudioVisual, "HeightShadowScaling.MinScale"); + this->ExpandAircraftMission.Read(exINI, GameStrings::General, "ExpandAircraftMission"); + this->AllowParallelAIQueues.Read(exINI, "GlobalControls", "AllowParallelAIQueues"); this->ForbidParallelAIQueues_Aircraft.Read(exINI, "GlobalControls", "ForbidParallelAIQueues.Aircraft"); this->ForbidParallelAIQueues_Building.Read(exINI, "GlobalControls", "ForbidParallelAIQueues.Building"); @@ -327,6 +329,7 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->AirShadowBaseScale_log) .Process(this->HeightShadowScaling) .Process(this->HeightShadowScaling_MinScale) + .Process(this->ExpandAircraftMission) .Process(this->AllowParallelAIQueues) .Process(this->ForbidParallelAIQueues_Aircraft) .Process(this->ForbidParallelAIQueues_Building) diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index ec5bbb0363..b42decfd98 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -92,6 +92,8 @@ class RulesExt Valueable HeightShadowScaling_MinScale; double AirShadowBaseScale_log; + Valueable ExpandAircraftMission; + Valueable AllowParallelAIQueues; Valueable ForbidParallelAIQueues_Aircraft; Valueable ForbidParallelAIQueues_Building; @@ -221,6 +223,8 @@ class RulesExt , HeightShadowScaling_MinScale { 0.0 } , AirShadowBaseScale_log { 0.693376137 } + , ExpandAircraftMission { false } + , AllowParallelAIQueues { true } , ForbidParallelAIQueues_Aircraft { false } , ForbidParallelAIQueues_Building { false } From 48f51294087261b0fdf8866d5d2b8ceef055a693 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 10 Dec 2024 16:25:12 +0800 Subject: [PATCH 18/46] Fix aircrafts guard mission from hunt like --- src/Ext/Aircraft/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index e7c57a9c3f..ce418e7a24 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -334,7 +334,7 @@ DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) { auto coords = pThis->GetCoords(); - if (pThis->TargetAndEstimateDamage(coords, ThreatType::Normal)) + if (pThis->TargetAndEstimateDamage(coords, ThreatType::Area)) { pThis->QueueMission(Mission::Attack, false); return SkipGameCode; From acee930274a7b1471c449589230edb08bc0ea589 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 10 Dec 2024 16:25:57 +0800 Subject: [PATCH 19/46] Smooth aircrafts moving actions and enable aircrafts waypoint --- src/Ext/Aircraft/Hooks.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index ce418e7a24..423a861518 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -322,6 +322,34 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) // Aircraft mission hard code are all disposable that no ammo, target died or arrived destination all will call the aircraft return airbase #pragma region AircraftMissionExpand +// Waypoint: Enable and smooth moving action +bool __fastcall AircraftTypeClass_CanUseWaypoint(AircraftTypeClass* pThis) +{ + return RulesExt::Global()->ExpandAircraftMission.Get(); +} +DEFINE_JUMP(VTABLE, 0x7E2908, GET_OFFSET(AircraftTypeClass_CanUseWaypoint)) + +DEFINE_HOOK_AGAIN(0x4168C7, AircraftClass_Mission_Move_SmoothMoving, 0x5) +DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) +{ + enum { EnterIdleAndReturn = 0x416AC0, ContinueMoving1 = 0x416908, ContinueMoving2 = 0x416A47 }; + + GET(AircraftClass* const, pThis, ESI); + GET(CoordStruct* const, pCoords, EAX); + + if (!RulesExt::Global()->ExpandAircraftMission) + return 0; + + const int distance = Game::F2I(Point2D { pCoords->X, pCoords->Y }.DistanceFrom(Point2D { pThis->Location.X, pThis->Location.Y })); + const auto pType = pThis->Type; + + if (distance > std::max((pType->SlowdownDistance >> 1), (2048 / pType->ROT))) + return (R->Origin() == 0x4168C7 ? ContinueMoving1 : ContinueMoving2); + + pThis->EnterIdleMode(false, true); + return EnterIdleAndReturn; +} + // AreaGuard: return when no ammo or first target died DEFINE_HOOK_AGAIN(0x41A982, AircraftClass_Mission_AreaGuard, 0x6) DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) From 3f72785b2f87bb819620de6f43461aa3e2a86ca9 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 10 Dec 2024 16:28:55 +0800 Subject: [PATCH 20/46] Notes --- src/Ext/Aircraft/Hooks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 423a861518..10341763fe 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -446,6 +446,7 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (RulesExt::Global()->ExpandAircraftMission && pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) { + // I think this mega mission clearing should be all technotypes need if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() From 4cfe4d82de1d6f3df9302a2e5afa36e9b353d6a9 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 10 Dec 2024 17:31:50 +0800 Subject: [PATCH 21/46] Core --- CREDITS.md | 1 + docs/Fixed-or-Improved-Logics.md | 3 +++ docs/Whats-New.md | 1 + src/Misc/Hooks.BugFixes.cpp | 34 ++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index f977b2a3ed..16ef4d0567 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -371,6 +371,7 @@ This page lists all the individual contributions to the project by their author. - Allow to change the speed of gas particles - **CrimRecya** - Fix `LimboKill` not working reliably + - Fix `Stop` command not working so well in some cases - **Ollerus** - Build limit group enhancement - Customizable rocker amplitude diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index e72c269b36..c5ef903a89 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -176,6 +176,9 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - `` can now be used as owner for pre-placed objects on skirmish and multiplayer maps. - Follower vehicle index for preplaced vehicles in maps is now explicitly constrained to `[Units]` list in map files and is no longer thrown off by vehicles that could not be created or created vehicles having other vehicles as initial passengers. - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix +- Prevent jumpjets from falling into a state of standing idly by when receive the stop(shortcut: s) command. +- Prevent technos from being unable to stop the attack move mission when receive the stop(shortcut: s) command. +- Prevent aircrafts from briefly pausing in the air before returning when receive the stop(shortcut: s) command. - Unit `Speed` setting now accepts floating-point values. Internally parsed values are clamped down to maximum of 100, multiplied by 256 and divided by 100, the result (which at this point is converted to an integer) then clamped down to maximum of 255 giving effective internal speed value range of 0 to 255, e.g leptons traveled per game frame. - Subterranean movement now benefits from speed multipliers from all sources such as veterancy, AttachEffect etc. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 0b6f8c19c6..8324c04230 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -552,6 +552,7 @@ Vanilla fixes: - Fixed objects with ally target and `AttackFriendlies=true` having their target reset every frame, particularly AI-owned buildings (by Starkku) - Follower vehicle index for preplaced vehicles in maps is now explicitly constrained to `[Units]` list in map files and is no longer thrown off by vehicles that could not be created or created vehicles having other vehicles as initial passengers (by Starkku) - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix (by tyuah8) +- Fix `Stop` command not working so well in some cases (by CrimRecya) - Subterranean movement now benefits from speed multipliers from all sources such as veterancy, AttachEffect etc. (by Starkku) Phobos fixes: diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 984c546dc4..037c26d147 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1064,6 +1064,40 @@ DEFINE_HOOK(0x743664, UnitClass_ReadFromINI_Follower3, 0x6) #pragma endregion +#pragma region StopEventFix + +DEFINE_HOOK(0x4C75E6, EventClass_RespondToEvent_Stop, 0x5) +{ + enum { SkipGameCode = 0x4C762A }; + + GET(TechnoClass* const, pTechno, ESI); + + // Clearing the current target should still be necessary for all technos + pTechno->SetTarget(nullptr); + const auto pFoot = abstract_cast(pTechno); + const auto pJumpjetLoco = pFoot ? locomotion_cast(pFoot->Locomotor) : nullptr; + + // To avoid jumpjets falling into a state of standing idly by + if (!pJumpjetLoco) // If is not jumpjet, clear the destination is enough + pTechno->SetDestination(nullptr, true); + else if (!pFoot->Destination) // When in attack move and have had a target, the destination will be cleaned up, enter the guard mission can prevent the jumpjets stuck in a status of standing idly by + pTechno->QueueMission(Mission::Guard, true); + else if (static_cast(CellClass::Coord2Cell(pFoot->Destination->GetCoords()).DistanceFromSquared(pTechno->GetMapCoords())) > 2) // If the jumpjet is moving, find the forward cell then stop in it + pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(((((pJumpjetLoco->LocomotionFacing.Current().Raw) >> 12) + 1) >> 1) & 7)), true); + + // To avoid technos being unable to stop in attack move mega mission + if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() + pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() + + // To avoid aircrafts pausing in the air and let they returning to air base immediately + if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned && pTechno->GetHeight() > Unsorted::CellHeight) + pTechno->EnterIdleMode(false, true); + + return SkipGameCode; +} + +#pragma endregion + // This shouldn't be here // Author: tyuah8 DEFINE_HOOK_AGAIN(0x4AF94D, EndPiggyback_PowerOn, 0x7) // Drive From 723463b45e62f5fe2c721a27a294cd78881e1efc Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 11 Dec 2024 01:17:49 +0800 Subject: [PATCH 22/46] Fix `AirportBound=no` aircraft's moving action --- src/Ext/Aircraft/Hooks.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 10341763fe..e92dac0353 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -340,13 +340,18 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) if (!RulesExt::Global()->ExpandAircraftMission) return 0; - const int distance = Game::F2I(Point2D { pCoords->X, pCoords->Y }.DistanceFrom(Point2D { pThis->Location.X, pThis->Location.Y })); const auto pType = pThis->Type; + if (!pType->AirportBound || pThis->Airstrike || pThis->Spawned) + return 0; + + const int distance = Game::F2I(Point2D { pCoords->X, pCoords->Y }.DistanceFrom(Point2D { pThis->Location.X, pThis->Location.Y })); + if (distance > std::max((pType->SlowdownDistance >> 1), (2048 / pType->ROT))) return (R->Origin() == 0x4168C7 ? ContinueMoving1 : ContinueMoving2); pThis->EnterIdleMode(false, true); + return EnterIdleAndReturn; } From 02dd0bdbaea41feab458ddce8515feeced4937d8 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 11 Dec 2024 01:53:38 +0800 Subject: [PATCH 23/46] Fix `AirportBound=no` aircraft's stop action --- src/Ext/Aircraft/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index e92dac0353..0c98c8c8a3 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -455,7 +455,7 @@ DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() - if (pTechno->GetHeight() > Unsorted::CellHeight) + if (static_cast(pTechno)->Type->AirportBound && pTechno->GetHeight() > Unsorted::CellHeight) pTechno->EnterIdleMode(false, true); } From 5118bc0515b2493efb35d1de37d5a7261b9d192b Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 11 Dec 2024 01:55:16 +0800 Subject: [PATCH 24/46] Fix `AirportBound=no` aircraft's stop action --- src/Misc/Hooks.BugFixes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 037c26d147..d5e47cf9ce 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1090,7 +1090,7 @@ DEFINE_HOOK(0x4C75E6, EventClass_RespondToEvent_Stop, 0x5) pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() // To avoid aircrafts pausing in the air and let they returning to air base immediately - if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned && pTechno->GetHeight() > Unsorted::CellHeight) + if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned && static_cast(pTechno)->Type->AirportBound && pTechno->GetHeight() > Unsorted::CellHeight) pTechno->EnterIdleMode(false, true); return SkipGameCode; From 14dbf03bb4e899a28b64486d1d468562945115ad Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 11 Dec 2024 02:34:05 +0800 Subject: [PATCH 25/46] Fix a vanilla aircraft's no reloading bug and fix a typo in idle --- src/Ext/Aircraft/Hooks.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 0c98c8c8a3..078048d65f 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -322,13 +322,14 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) // Aircraft mission hard code are all disposable that no ammo, target died or arrived destination all will call the aircraft return airbase #pragma region AircraftMissionExpand -// Waypoint: Enable and smooth moving action +// Waypoint: enable and smooth moving action bool __fastcall AircraftTypeClass_CanUseWaypoint(AircraftTypeClass* pThis) { return RulesExt::Global()->ExpandAircraftMission.Get(); } DEFINE_JUMP(VTABLE, 0x7E2908, GET_OFFSET(AircraftTypeClass_CanUseWaypoint)) +// Move: smooth the planning paths and returning route DEFINE_HOOK_AGAIN(0x4168C7, AircraftClass_Mission_Move_SmoothMoving, 0x5) DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) { @@ -355,6 +356,17 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) return EnterIdleAndReturn; } +// Link: fix the vanilla bug that aircrafts will not reload if they have no link +DEFINE_HOOK(0x414DB6, AircraftClass_Update_ResetNthLink, 0x6) +{ + GET(AircraftClass* const, pThis, ESI); + + if (pThis->CurrentMission == Mission::Sleep && !pThis->Destination && pThis->DockNowHeadingTo && !pThis->GetNthLink()) + pThis->SendCommand(RadioCommand::RequestLink, pThis->DockNowHeadingTo); + + return 0; +} + // AreaGuard: return when no ammo or first target died DEFINE_HOOK_AGAIN(0x41A982, AircraftClass_Mission_AreaGuard, 0x6) DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) @@ -433,10 +445,13 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) GET(AircraftClass* const, pThis, ESI); - if (RulesExt::Global()->ExpandAircraftMission && !pThis->Ammo && !SessionClass::IsCampaign()) + if (RulesExt::Global()->ExpandAircraftMission && !pThis->Ammo && !pThis->Airstrike && !pThis->Spawned) { - if (const auto pTeam = pThis->Team) - pTeam->LiberateMember(pThis); + if (!SessionClass::IsCampaign()) // To avoid AI's aircrafts team repeatedly attempting to attack the target when no ammo + { + if (const auto pTeam = pThis->Team) + pTeam->LiberateMember(pThis); + } return ClearTarget; } From 841cb51793d7f04b70380f41c0ed67cc881db14d Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 11 Dec 2024 12:53:58 +0800 Subject: [PATCH 26/46] Use existing function --- src/Misc/Hooks.BugFixes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index d5e47cf9ce..5a799ecc6c 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1083,7 +1083,7 @@ DEFINE_HOOK(0x4C75E6, EventClass_RespondToEvent_Stop, 0x5) else if (!pFoot->Destination) // When in attack move and have had a target, the destination will be cleaned up, enter the guard mission can prevent the jumpjets stuck in a status of standing idly by pTechno->QueueMission(Mission::Guard, true); else if (static_cast(CellClass::Coord2Cell(pFoot->Destination->GetCoords()).DistanceFromSquared(pTechno->GetMapCoords())) > 2) // If the jumpjet is moving, find the forward cell then stop in it - pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(((((pJumpjetLoco->LocomotionFacing.Current().Raw) >> 12) + 1) >> 1) & 7)), true); + pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(pJumpjetLoco->LocomotionFacing.Current().GetValue<3>())), true); // To avoid technos being unable to stop in attack move mega mission if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() From d553698b41f93d7488d76b1166e27f3b892c0dc1 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 00:20:16 +0800 Subject: [PATCH 27/46] Prevent aircrafts from duplicatedly finding airport and overlapping --- docs/Fixed-or-Improved-Logics.md | 1 + src/Misc/Hooks.BugFixes.cpp | 45 +++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index c5ef903a89..86bb42ac0a 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -178,6 +178,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix - Prevent jumpjets from falling into a state of standing idly by when receive the stop(shortcut: s) command. - Prevent technos from being unable to stop the attack move mission when receive the stop(shortcut: s) command. +- Prevent aircrafts from duplicatedly finding airport and overlapping when receive the stop(shortcut: s) command. - Prevent aircrafts from briefly pausing in the air before returning when receive the stop(shortcut: s) command. - Unit `Speed` setting now accepts floating-point values. Internally parsed values are clamped down to maximum of 100, multiplied by 256 and divided by 100, the result (which at this point is converted to an integer) then clamped down to maximum of 255 giving effective internal speed value range of 0 to 255, e.g leptons traveled per game frame. - Subterranean movement now benefits from speed multipliers from all sources such as veterancy, AttachEffect etc. diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 5a799ecc6c..79a0bbe8dd 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1066,32 +1066,47 @@ DEFINE_HOOK(0x743664, UnitClass_ReadFromINI_Follower3, 0x6) #pragma region StopEventFix -DEFINE_HOOK(0x4C75E6, EventClass_RespondToEvent_Stop, 0x5) +DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { enum { SkipGameCode = 0x4C762A }; GET(TechnoClass* const, pTechno, ESI); - // Clearing the current target should still be necessary for all technos - pTechno->SetTarget(nullptr); - const auto pFoot = abstract_cast(pTechno); - const auto pJumpjetLoco = pFoot ? locomotion_cast(pFoot->Locomotor) : nullptr; + // Check aircrafts + const auto pAircraft = abstract_cast(pTechno); + const bool findAirport = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned && pAircraft->Type->AirportBound; - // To avoid jumpjets falling into a state of standing idly by - if (!pJumpjetLoco) // If is not jumpjet, clear the destination is enough - pTechno->SetDestination(nullptr, true); - else if (!pFoot->Destination) // When in attack move and have had a target, the destination will be cleaned up, enter the guard mission can prevent the jumpjets stuck in a status of standing idly by - pTechno->QueueMission(Mission::Guard, true); - else if (static_cast(CellClass::Coord2Cell(pFoot->Destination->GetCoords()).DistanceFromSquared(pTechno->GetMapCoords())) > 2) // If the jumpjet is moving, find the forward cell then stop in it - pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(pJumpjetLoco->LocomotionFacing.Current().GetValue<3>())), true); + // To avoid aircrafts overlap by keep link if is returning or is in airport now. + if (!findAirport || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + pTechno->SendToEachLink(RadioCommand::NotifyUnlink); // To avoid technos being unable to stop in attack move mega mission if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() - // To avoid aircrafts pausing in the air and let they returning to air base immediately - if (pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned && static_cast(pTechno)->Type->AirportBound && pTechno->GetHeight() > Unsorted::CellHeight) - pTechno->EnterIdleMode(false, true); + // Clearing the current target should still be necessary for all technos + pTechno->SetTarget(nullptr); + + if (findAirport) + { + // To avoid aircrafts pausing in the air and let they returning to air base immediately. + if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + pAircraft->EnterIdleMode(false, true); + } + else + { + // Check Jumpjets + const auto pFoot = abstract_cast(pTechno); + const auto pJumpjetLoco = pFoot ? locomotion_cast(pFoot->Locomotor) : nullptr; + + // To avoid jumpjets falling into a state of standing idly by + if (!pJumpjetLoco) // If is not jumpjet, clear the destination is enough + pTechno->SetDestination(nullptr, true); + else if (!pFoot->Destination) // When in attack move and have had a target, the destination will be cleaned up, enter the guard mission can prevent the jumpjets stuck in a status of standing idly by + pTechno->QueueMission(Mission::Guard, true); + else if (static_cast(CellClass::Coord2Cell(pFoot->Destination->GetCoords()).DistanceFromSquared(pTechno->GetMapCoords())) > 2) // If the jumpjet is moving, find the forward cell then stop in it + pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(pJumpjetLoco->LocomotionFacing.Current().GetValue<3>())), true); + } return SkipGameCode; } From 5028b7b3ca36235692fe5bb3ce83ce830a11f747 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 00:22:55 +0800 Subject: [PATCH 28/46] Resolve the vanilla bug from the root in PR #1449 --- src/Ext/Aircraft/Hooks.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 078048d65f..bad8eaf3c4 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -356,17 +356,6 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) return EnterIdleAndReturn; } -// Link: fix the vanilla bug that aircrafts will not reload if they have no link -DEFINE_HOOK(0x414DB6, AircraftClass_Update_ResetNthLink, 0x6) -{ - GET(AircraftClass* const, pThis, ESI); - - if (pThis->CurrentMission == Mission::Sleep && !pThis->Destination && pThis->DockNowHeadingTo && !pThis->GetNthLink()) - pThis->SendCommand(RadioCommand::RequestLink, pThis->DockNowHeadingTo); - - return 0; -} - // AreaGuard: return when no ammo or first target died DEFINE_HOOK_AGAIN(0x41A982, AircraftClass_Mission_AreaGuard, 0x6) DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) @@ -489,7 +478,8 @@ AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, voi threatType |= pSecondaryWeapon->AllowedThreats(); } - return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // FootClass_GreatestThreat (Prevent circular calls) + // return pThis->FootClass::GreatestThreat(threatType, pSelectCoords, onlyTargetHouseEnemy); + return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat)) From 445b1ac2776fdbbb9624ab9bae7ac4d93f54efb1 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 17:32:01 +0800 Subject: [PATCH 29/46] Temporary fix the issue where 'AirportBound=no' aircrafts cannot accept stop commands --- src/Ext/Aircraft/Hooks.cpp | 51 ++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index bad8eaf3c4..f320d01064 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -329,6 +329,9 @@ bool __fastcall AircraftTypeClass_CanUseWaypoint(AircraftTypeClass* pThis) } DEFINE_JUMP(VTABLE, 0x7E2908, GET_OFFSET(AircraftTypeClass_CanUseWaypoint)) +// KickOut: skip useless tether +DEFINE_JUMP(LJMP, 0x444021, 0x44402E) + // Move: smooth the planning paths and returning route DEFINE_HOOK_AGAIN(0x4168C7, AircraftClass_Mission_Move_SmoothMoving, 0x5) DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) @@ -448,22 +451,50 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) return 0; } -// Stop: clear the mega mission and return to airbase immediately -DEFINE_HOOK(0x4C762A, EventClass_RespondToEvent_StopAircraftAction, 0x6) +// Stop: clear the mega mission and return to airbase immediately (Temporary) +// TODO The complete and accurate fix is in #1449 +DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { + enum { SkipGameCode = 0x4C762A }; + GET(TechnoClass* const, pTechno, ESI); - if (RulesExt::Global()->ExpandAircraftMission && pTechno->WhatAmI() == AbstractType::Aircraft && !pTechno->Airstrike && !pTechno->Spawned) - { - // I think this mega mission clearing should be all technotypes need - if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() + const bool expand = RulesExt::Global()->ExpandAircraftMission.Get(); + + // Check aircrafts + const auto pAircraft = abstract_cast(pTechno); + const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; - if (static_cast(pTechno)->Type->AirportBound && pTechno->GetHeight() > Unsorted::CellHeight) - pTechno->EnterIdleMode(false, true); + // To avoid aircrafts overlap by keep link if is returning or is in airport now. + if (!expand || !commonAircraft || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + pTechno->SendToEachLink(RadioCommand::NotifyUnlink); + + pTechno->SetTarget(nullptr); + + if (expand && commonAircraft) + { + if (pAircraft->Type->AirportBound) + { + // To avoid `AirportBound=yes` aircrafts pausing in the air and let they returning to air base immediately. + if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one + pAircraft->EnterIdleMode(false, true); + } + else if (const auto pDestination = pAircraft->Destination) + { + // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. + if (pAircraft->Ammo && static_cast(CellClass::Coord2Cell(pDestination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it + pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); + else if (!pAircraft->Ammo && (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink()))) + pAircraft->EnterIdleMode(false, true); + } + // Otherwise landing or idling normally without answering the stop command + } + else + { + pTechno->SetDestination(nullptr, true); } - return 0; + return SkipGameCode; } // GreatestThreat: for all the mission that should let the aircraft auto select a target From 17325e2250d741de75f749915810c566b304a6b3 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 17:40:12 +0800 Subject: [PATCH 30/46] Prevent aircrafts with `AirportBound=no` ignore stop command --- docs/Fixed-or-Improved-Logics.md | 1 + src/Misc/Hooks.BugFixes.cpp | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 86bb42ac0a..d47f7015fc 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -180,6 +180,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Prevent technos from being unable to stop the attack move mission when receive the stop(shortcut: s) command. - Prevent aircrafts from duplicatedly finding airport and overlapping when receive the stop(shortcut: s) command. - Prevent aircrafts from briefly pausing in the air before returning when receive the stop(shortcut: s) command. +- Prevent aircrafts with `AirportBound=no` continue moving forward when receive the stop(shortcut: s) command. - Unit `Speed` setting now accepts floating-point values. Internally parsed values are clamped down to maximum of 100, multiplied by 256 and divided by 100, the result (which at this point is converted to an integer) then clamped down to maximum of 255 giving effective internal speed value range of 0 to 255, e.g leptons traveled per game frame. - Subterranean movement now benefits from speed multipliers from all sources such as veterancy, AttachEffect etc. diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 79a0bbe8dd..dbd7d8a36a 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1066,6 +1066,9 @@ DEFINE_HOOK(0x743664, UnitClass_ReadFromINI_Follower3, 0x6) #pragma region StopEventFix +DEFINE_JUMP(LJMP, 0x444021, 0x44402E) // Skip useless tether when kick out aircrafts (temporary) +// TODO: this is already in #1366, should delete if merge + DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { enum { SkipGameCode = 0x4C762A }; @@ -1074,10 +1077,10 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) // Check aircrafts const auto pAircraft = abstract_cast(pTechno); - const bool findAirport = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned && pAircraft->Type->AirportBound; + const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!findAirport || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + if (!commonAircraft || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); // To avoid technos being unable to stop in attack move mega mission @@ -1087,11 +1090,23 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) // Clearing the current target should still be necessary for all technos pTechno->SetTarget(nullptr); - if (findAirport) + if (commonAircraft) { - // To avoid aircrafts pausing in the air and let they returning to air base immediately. - if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) - pAircraft->EnterIdleMode(false, true); + if (pAircraft->Type->AirportBound) + { + // To avoid `AirportBound=yes` aircrafts pausing in the air and let they returning to air base immediately. + if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one + pAircraft->EnterIdleMode(false, true); + } + else if (const auto pDestination = pAircraft->Destination) + { + // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. + if (pAircraft->Ammo && static_cast(CellClass::Coord2Cell(pDestination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it + pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); + else if (!pAircraft->Ammo && (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink()))) + pAircraft->EnterIdleMode(false, true); + } + // Otherwise landing or idling normally without answering the stop command } else { @@ -1106,6 +1121,7 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) pTechno->QueueMission(Mission::Guard, true); else if (static_cast(CellClass::Coord2Cell(pFoot->Destination->GetCoords()).DistanceFromSquared(pTechno->GetMapCoords())) > 2) // If the jumpjet is moving, find the forward cell then stop in it pTechno->SetDestination(pTechno->GetCell()->GetNeighbourCell(static_cast(pJumpjetLoco->LocomotionFacing.Current().GetValue<3>())), true); + // Otherwise landing or idling normally without answering the stop command } return SkipGameCode; From a1c216980430e2fa2e76b3f408fcc4ecd509d310 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 19:21:58 +0800 Subject: [PATCH 31/46] Fix typo --- src/Misc/Hooks.BugFixes.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index dbd7d8a36a..42653647d9 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1080,7 +1080,7 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!commonAircraft || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + if (!commonAircraft || pAircraft->CurrentMission != Mission::Enter || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); // To avoid technos being unable to stop in attack move mega mission @@ -1098,13 +1098,15 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one pAircraft->EnterIdleMode(false, true); } - else if (const auto pDestination = pAircraft->Destination) + else if (pAircraft->Ammo) { // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. - if (pAircraft->Ammo && static_cast(CellClass::Coord2Cell(pDestination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it + if (pAircraft->Destination && static_cast(CellClass::Coord2Cell(pAircraft->Destination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); - else if (!pAircraft->Ammo && (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink()))) - pAircraft->EnterIdleMode(false, true); + } + else if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + { + pAircraft->EnterIdleMode(false, true); } // Otherwise landing or idling normally without answering the stop command } From 6f94f86ded4d294e51b9fde2ca76fa5e8b9d9626 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 19:23:37 +0800 Subject: [PATCH 32/46] Fix typo --- src/Ext/Aircraft/Hooks.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index f320d01064..582a78bb44 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -466,7 +466,7 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!expand || !commonAircraft || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + if (!expand || !commonAircraft || pAircraft->CurrentMission != Mission::Enter || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); pTechno->SetTarget(nullptr); @@ -479,13 +479,15 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one pAircraft->EnterIdleMode(false, true); } - else if (const auto pDestination = pAircraft->Destination) + else if (pAircraft->Ammo) { // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. - if (pAircraft->Ammo && static_cast(CellClass::Coord2Cell(pDestination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it + if (pAircraft->Destination && static_cast(CellClass::Coord2Cell(pAircraft->Destination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); - else if (!pAircraft->Ammo && (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink()))) - pAircraft->EnterIdleMode(false, true); + } + else if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + { + pAircraft->EnterIdleMode(false, true); } // Otherwise landing or idling normally without answering the stop command } From 417505641875ddf7e48da9769d6afb12b496d180 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 12 Dec 2024 19:24:58 +0800 Subject: [PATCH 33/46] Notes --- src/Ext/Aircraft/Hooks.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 582a78bb44..c8034e8581 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -450,6 +450,18 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) return 0; } +/* +// This allows the aircraft to receive stop commands even at low altitudes, but if used, receiving a move command +// then quickly receiving a stop command can result in the aircraft landing in an incorrect direction +DEFINE_HOOK(0x417944, AircraftClass_EnterIdleMode_DockCheck, 0x7) +{ + enum { Continue = 0x417953, Invalid = 0x417AD4 }; + + GET(AircraftClass* const, pThis, ESI); + + return (pThis->GetHeight() > 0) ? Continue : Invalid; // Replace IsInAir() +} +*/ // Stop: clear the mega mission and return to airbase immediately (Temporary) // TODO The complete and accurate fix is in #1449 From 5ea6f1151486e5cdd4cf6d412a142beed8752be7 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 14 Dec 2024 22:10:55 +0800 Subject: [PATCH 34/46] Aircrafts with team will not smooth their route, because of the scripts' location check --- src/Ext/Aircraft/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index c8034e8581..64ba154e4d 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -346,7 +346,7 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) const auto pType = pThis->Type; - if (!pType->AirportBound || pThis->Airstrike || pThis->Spawned) + if (!pType->AirportBound || pThis->Team || pThis->Airstrike || pThis->Spawned) return 0; const int distance = Game::F2I(Point2D { pCoords->X, pCoords->Y }.DistanceFrom(Point2D { pThis->Location.X, pThis->Location.Y })); From 464cca917767252acb6a8a3d1bd2b6e77f69842c Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 17 Dec 2024 21:07:05 +0800 Subject: [PATCH 35/46] Fix a typo that the aircraft can receive the stop command when it is in the airport --- src/Misc/Hooks.BugFixes.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 42653647d9..9ea37a8d78 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1078,9 +1078,10 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) // Check aircrafts const auto pAircraft = abstract_cast(pTechno); const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; + const auto mission = pTechno->CurrentMission; // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!commonAircraft || pAircraft->CurrentMission != Mission::Enter || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + if (!commonAircraft || (mission != Mission::Sleep && mission != Mission::Guard && mission != Mission::Enter) || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); // To avoid technos being unable to stop in attack move mega mission From d1542fb97bed32ceed87c2af6475c7861be2a904 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Tue, 17 Dec 2024 21:10:01 +0800 Subject: [PATCH 36/46] Fix a typo that the aircraft can receive the stop command when it is in the airport --- src/Ext/Aircraft/Hooks.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 64ba154e4d..cc1c0a8539 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -476,9 +476,10 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) // Check aircrafts const auto pAircraft = abstract_cast(pTechno); const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; + const auto mission = pTechno->CurrentMission; // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!expand || !commonAircraft || pAircraft->CurrentMission != Mission::Enter || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + if (!expand || !commonAircraft || (mission != Mission::Sleep && mission != Mission::Guard && mission != Mission::Enter) || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); pTechno->SetTarget(nullptr); From d4a425035dafd3fbe79470f014ec0e0e55154b58 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Wed, 18 Dec 2024 00:42:32 +0800 Subject: [PATCH 37/46] Fix a problem that aircraft will keep losing its target and searching new targets repeatedly when its `AttackMove` target is an object. --- src/Ext/Aircraft/Hooks.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index cc1c0a8539..7709ba035c 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -397,7 +397,7 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr return (RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; } -DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0x6) +DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, 0x6) { enum { LoseTarget = 0x4DF3D3, HoldTarget = 0x4DF4AB }; @@ -406,6 +406,15 @@ DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget, 0 return ((RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft) || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldTarget : LoseTarget; // pThis->InAuxiliarySearchRange(pThis->Target) } +DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, 0x6) +{ + enum { ContinueCheck = 0x4DF462, HoldTarget = 0x4DF4AB }; + + GET(FootClass* const, pThis, ESI); + + return (RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft) ? HoldTarget : ContinueCheck; +} + DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) { enum { Continue = 0x418C43, Return = 0x418CE8 }; From 396f9825ab7c9d5404680422cbd927b6c3347159 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 26 Dec 2024 12:47:27 +0800 Subject: [PATCH 38/46] Rename `ExtendedAircraftMissions` and fix doc typo --- docs/Fixed-or-Improved-Logics.md | 4 ++-- src/Ext/Aircraft/Hooks.cpp | 22 +++++++++++----------- src/Ext/Rules/Body.cpp | 4 ++-- src/Ext/Rules/Body.h | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 9ef1e873f2..2cadf58e91 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -230,12 +230,12 @@ LandingDir= ; Direction type (integers from 0-255). Accepts negative values ### Expand Aircraft Mission -- Now, when a `stop` command (S) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (G) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammos are depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammos are not depleted yet during the process, the aircraft will continue to go to the destination). +- Now, when a `stop` command (`[S]` by default) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (`[G]` by default) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammo is depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammo is not depleted yet during the process, the aircraft will continue to go to the destination). In `rulesmd.ini`: ```ini [General] -ExpandAircraftMission= ; boolean +ExtendedAircraftMissions=false ; boolean ``` ## Animations diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 7709ba035c..501d931ec9 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -325,7 +325,7 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) // Waypoint: enable and smooth moving action bool __fastcall AircraftTypeClass_CanUseWaypoint(AircraftTypeClass* pThis) { - return RulesExt::Global()->ExpandAircraftMission.Get(); + return RulesExt::Global()->ExtendedAircraftMissions.Get(); } DEFINE_JUMP(VTABLE, 0x7E2908, GET_OFFSET(AircraftTypeClass_CanUseWaypoint)) @@ -341,7 +341,7 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) GET(AircraftClass* const, pThis, ESI); GET(CoordStruct* const, pCoords, EAX); - if (!RulesExt::Global()->ExpandAircraftMission) + if (!RulesExt::Global()->ExtendedAircraftMissions) return 0; const auto pType = pThis->Type; @@ -367,7 +367,7 @@ DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) GET(AircraftClass* const, pThis, ESI); - if (RulesExt::Global()->ExpandAircraftMission && !pThis->Team && pThis->Ammo && pThis->IsArmed()) + if (RulesExt::Global()->ExtendedAircraftMissions && !pThis->Team && pThis->Ammo && pThis->IsArmed()) { auto coords = pThis->GetCoords(); @@ -384,7 +384,7 @@ DEFINE_HOOK(0x41A96C, AircraftClass_Mission_AreaGuard, 0x6) // AttackMove: return when no ammo or arrived destination bool __fastcall AircraftTypeClass_CanAttackMove(AircraftTypeClass* pThis) { - return RulesExt::Global()->ExpandAircraftMission.Get(); + return RulesExt::Global()->ExtendedAircraftMissions.Get(); } DEFINE_JUMP(VTABLE, 0x7E290C, GET_OFFSET(AircraftTypeClass_CanAttackMove)) @@ -394,7 +394,7 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr GET(TechnoClass* const, pThis, ESI); - return (RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; + return (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; } DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, 0x6) @@ -403,7 +403,7 @@ DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, GET(FootClass* const, pThis, ESI); - return ((RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft) || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldTarget : LoseTarget; // pThis->InAuxiliarySearchRange(pThis->Target) + return ((RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldTarget : LoseTarget; // pThis->InAuxiliarySearchRange(pThis->Target) } DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, 0x6) @@ -412,7 +412,7 @@ DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, GET(FootClass* const, pThis, ESI); - return (RulesExt::Global()->ExpandAircraftMission && pThis->WhatAmI() == AbstractType::Aircraft) ? HoldTarget : ContinueCheck; + return (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) ? HoldTarget : ContinueCheck; } DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6) @@ -423,7 +423,7 @@ DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6 if (!pThis->Target) { - if (!RulesExt::Global()->ExpandAircraftMission || !pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) + if (!RulesExt::Global()->ExtendedAircraftMissions || !pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) return Continue; pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); // pThis->MegaDestination @@ -446,7 +446,7 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) GET(AircraftClass* const, pThis, ESI); - if (RulesExt::Global()->ExpandAircraftMission && !pThis->Ammo && !pThis->Airstrike && !pThis->Spawned) + if (RulesExt::Global()->ExtendedAircraftMissions && !pThis->Ammo && !pThis->Airstrike && !pThis->Spawned) { if (!SessionClass::IsCampaign()) // To avoid AI's aircrafts team repeatedly attempting to attack the target when no ammo { @@ -480,7 +480,7 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) GET(TechnoClass* const, pTechno, ESI); - const bool expand = RulesExt::Global()->ExpandAircraftMission.Get(); + const bool expand = RulesExt::Global()->ExtendedAircraftMissions.Get(); // Check aircrafts const auto pAircraft = abstract_cast(pTechno); @@ -524,7 +524,7 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) // GreatestThreat: for all the mission that should let the aircraft auto select a target AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) { - if (RulesExt::Global()->ExpandAircraftMission) + if (RulesExt::Global()->ExtendedAircraftMissions) { if (const auto pPrimaryWeapon = pThis->GetWeapon(0)->WeaponType) threatType |= pPrimaryWeapon->AllowedThreats(); diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index d2af29647d..2cfe87a114 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -137,7 +137,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->HeightShadowScaling = false; this->HeightShadowScaling_MinScale.Read(exINI, GameStrings::AudioVisual, "HeightShadowScaling.MinScale"); - this->ExpandAircraftMission.Read(exINI, GameStrings::General, "ExpandAircraftMission"); + this->ExtendedAircraftMissions.Read(exINI, GameStrings::General, "ExtendedAircraftMissions"); this->AllowParallelAIQueues.Read(exINI, "GlobalControls", "AllowParallelAIQueues"); this->ForbidParallelAIQueues_Aircraft.Read(exINI, "GlobalControls", "ForbidParallelAIQueues.Aircraft"); @@ -332,7 +332,7 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->AirShadowBaseScale_log) .Process(this->HeightShadowScaling) .Process(this->HeightShadowScaling_MinScale) - .Process(this->ExpandAircraftMission) + .Process(this->ExtendedAircraftMissions) .Process(this->AllowParallelAIQueues) .Process(this->ForbidParallelAIQueues_Aircraft) .Process(this->ForbidParallelAIQueues_Building) diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index 8a93757699..34be37d8bd 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -93,7 +93,7 @@ class RulesExt Valueable HeightShadowScaling_MinScale; double AirShadowBaseScale_log; - Valueable ExpandAircraftMission; + Valueable ExtendedAircraftMissions; Valueable AllowParallelAIQueues; Valueable ForbidParallelAIQueues_Aircraft; @@ -225,7 +225,7 @@ class RulesExt , HeightShadowScaling_MinScale { 0.0 } , AirShadowBaseScale_log { 0.693376137 } - , ExpandAircraftMission { false } + , ExtendedAircraftMissions { false } , AllowParallelAIQueues { true } , ForbidParallelAIQueues_Aircraft { false } From c3cf57f93c1ece0ea9fd97bbe635ceed9fe4ec28 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 26 Dec 2024 12:50:34 +0800 Subject: [PATCH 39/46] Remove useless --- docs/Fixed-or-Improved-Logics.md | 1 - src/Ext/Aircraft/Hooks.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 2cadf58e91..49aedef465 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -159,7 +159,6 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Setting `[AudioVisual]` -> `ColorAddUse8BitRGB` to true makes game treat values from `[ColorAdd]` as 8-bit RGB (0-255) instead of RGB565 (0-31 for red & blue, 0-63 for green). This works for `LaserTargetColor`, `IronCurtainColor`, `BerserkColor` and `ForceShieldColor`. - Weapons with `AA=true` Projectile can now correctly fire at air units when both firer and target are over a bridge. - Fixed disguised units not using the correct palette if target has custom palette. -- Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc. - Building upgrades now consistently use building's `PowerUpN` animation settings corresponding to the upgrade's `PowersUpToLevel` where possible. - Subterranean units are no longer allowed to perform deploy functions like firing weapons or `IsSimpleDeployer` while burrowed or burrowing, they will instead emerge first like they do for transport unloading. - The otherwise unused setting `[AI]` -> `PowerSurplus` (defaults to 50) which determines how much surplus power AI players will strive to have can be restored by setting `[AI]` -> `EnablePowerSurplus` to true. diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 501d931ec9..9243b7c3d8 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include From 92b2d8c951870918b742d78791943073549fd0e6 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 26 Dec 2024 13:02:16 +0800 Subject: [PATCH 40/46] More readable --- src/Ext/Aircraft/Hooks.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 9243b7c3d8..b363cd8449 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -350,6 +350,8 @@ DEFINE_HOOK(0x416A0A, AircraftClass_Mission_Move_SmoothMoving, 0x5) const int distance = Game::F2I(Point2D { pCoords->X, pCoords->Y }.DistanceFrom(Point2D { pThis->Location.X, pThis->Location.Y })); + // When the horizontal distance between the aircraft and its destination is greater than half of its deceleration distance + // or its turning radius, continue to move forward, otherwise return to airbase or execute the next planning path if (distance > std::max((pType->SlowdownDistance >> 1), (2048 / pType->ROT))) return (R->Origin() == 0x4168C7 ? ContinueMoving1 : ContinueMoving2); @@ -393,19 +395,26 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr GET(TechnoClass* const, pThis, ESI); - return (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight)) ? SkipGameCode : 0; + const bool skip = RulesExt::Global()->ExtendedAircraftMissions + && pThis->WhatAmI() == AbstractType::Aircraft + && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight); + + return skip ? SkipGameCode : 0; } -DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, 0x6) +DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, 0x6) // When it have MegaDestination { enum { LoseTarget = 0x4DF3D3, HoldTarget = 0x4DF4AB }; GET(FootClass* const, pThis, ESI); - return ((RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target))) ? HoldTarget : LoseTarget; // pThis->InAuxiliarySearchRange(pThis->Target) + const bool hold = (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) + || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target)); // pThis->InAuxiliarySearchRange(pThis->Target) + + return hold ? HoldTarget : LoseTarget; } -DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, 0x6) +DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, 0x6) // When it have MegaTarget { enum { ContinueCheck = 0x4DF462, HoldTarget = 0x4DF4AB }; From 5a7fb091b83aff7093b4cd1ddd595d8e889c0eb4 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Thu, 26 Dec 2024 13:08:00 +0800 Subject: [PATCH 41/46] Delete duplicated hooks --- src/Ext/Aircraft/Hooks.cpp | 51 ++----------------------------------- src/Misc/Hooks.BugFixes.cpp | 3 --- 2 files changed, 2 insertions(+), 52 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index b363cd8449..9ad2023c61 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -479,55 +479,8 @@ DEFINE_HOOK(0x417944, AircraftClass_EnterIdleMode_DockCheck, 0x7) return (pThis->GetHeight() > 0) ? Continue : Invalid; // Replace IsInAir() } */ - -// Stop: clear the mega mission and return to airbase immediately (Temporary) -// TODO The complete and accurate fix is in #1449 -DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) -{ - enum { SkipGameCode = 0x4C762A }; - - GET(TechnoClass* const, pTechno, ESI); - - const bool expand = RulesExt::Global()->ExtendedAircraftMissions.Get(); - - // Check aircrafts - const auto pAircraft = abstract_cast(pTechno); - const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; - const auto mission = pTechno->CurrentMission; - - // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!expand || !commonAircraft || (mission != Mission::Sleep && mission != Mission::Guard && mission != Mission::Enter) || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) - pTechno->SendToEachLink(RadioCommand::NotifyUnlink); - - pTechno->SetTarget(nullptr); - - if (expand && commonAircraft) - { - if (pAircraft->Type->AirportBound) - { - // To avoid `AirportBound=yes` aircrafts pausing in the air and let they returning to air base immediately. - if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one - pAircraft->EnterIdleMode(false, true); - } - else if (pAircraft->Ammo) - { - // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. - if (pAircraft->Destination && static_cast(CellClass::Coord2Cell(pAircraft->Destination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it - pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); - } - else if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) - { - pAircraft->EnterIdleMode(false, true); - } - // Otherwise landing or idling normally without answering the stop command - } - else - { - pTechno->SetDestination(nullptr, true); - } - - return SkipGameCode; -} +// Stop: clear the mega mission and return to airbase immediately +// (StopEventFix's DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) in Hooks.BugFixes.cpp) // GreatestThreat: for all the mission that should let the aircraft auto select a target AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, void* _, ThreatType threatType, CoordStruct* pSelectCoords, bool onlyTargetHouseEnemy) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 9ea37a8d78..b5f70242e4 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1066,9 +1066,6 @@ DEFINE_HOOK(0x743664, UnitClass_ReadFromINI_Follower3, 0x6) #pragma region StopEventFix -DEFINE_JUMP(LJMP, 0x444021, 0x44402E) // Skip useless tether when kick out aircrafts (temporary) -// TODO: this is already in #1366, should delete if merge - DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { enum { SkipGameCode = 0x4C762A }; From 83376da1bac94b4370d66096e8a4e9399ebc795e Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Fri, 27 Dec 2024 16:49:18 +0800 Subject: [PATCH 42/46] Update YRpp --- YRpp | 2 +- src/Ext/Aircraft/Hooks.cpp | 12 ++++++------ src/Misc/Hooks.BugFixes.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/YRpp b/YRpp index 0b7b61a49c..1e9fac90aa 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 0b7b61a49c2a5890fee918edcdc58008814f79f7 +Subproject commit 1e9fac90aa646255496138ddde5fef414a6f3528 diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 9ad2023c61..e0559fc047 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -408,10 +408,10 @@ DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, GET(FootClass* const, pThis, ESI); - const bool hold = (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) - || pThis->vt_entry_3B4(reinterpret_cast(pThis->Target)); // pThis->InAuxiliarySearchRange(pThis->Target) + if (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) + return HoldTarget; - return hold ? HoldTarget : LoseTarget; + return pThis->InAuxiliarySearchRange(pThis->Target) ? HoldTarget : LoseTarget; } DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, 0x6) // When it have MegaTarget @@ -431,12 +431,12 @@ DEFINE_HOOK(0x418CD1, AircraftClass_Mission_Attack_ContinueFlyToDestination, 0x6 if (!pThis->Target) { - if (!RulesExt::Global()->ExtendedAircraftMissions || !pThis->vt_entry_4C4() || !pThis->unknown_5C8) // (!pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) + if (!RulesExt::Global()->ExtendedAircraftMissions || !pThis->MegaMissionIsAttackMove() || !pThis->MegaDestination) return Continue; - pThis->SetDestination(reinterpret_cast(pThis->unknown_5C8), false); // pThis->MegaDestination + pThis->SetDestination(pThis->MegaDestination, false); pThis->QueueMission(Mission::Move, true); - pThis->unknown_bool_5D1 = false; // pThis->HaveAttackMoveTarget + pThis->HaveAttackMoveTarget = false; } else { diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index b5f70242e4..628a102c8b 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1082,8 +1082,8 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) pTechno->SendToEachLink(RadioCommand::NotifyUnlink); // To avoid technos being unable to stop in attack move mega mission - if (pTechno->vt_entry_4C4()) // pTechno->MegaMissionIsAttackMove() - pTechno->vt_entry_4A8(); // pTechno->ClearMegaMissionData() + if (pTechno->MegaMissionIsAttackMove()) + pTechno->ClearMegaMissionData(); // Clearing the current target should still be necessary for all technos pTechno->SetTarget(nullptr); From d7f98defb0814775c6d0724e53e8b96da8888741 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 28 Dec 2024 12:18:53 +0800 Subject: [PATCH 43/46] Update YRpp and codes comments --- YRpp | 2 +- src/Ext/Aircraft/Hooks.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/YRpp b/YRpp index 1e9fac90aa..0873214a79 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 1e9fac90aa646255496138ddde5fef414a6f3528 +Subproject commit 0873214a793cf62a8a30072c76f8e5982e928a93 diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index e0559fc047..4424b15b37 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -319,7 +319,7 @@ DEFINE_HOOK(0x415EEE, AircraftClass_Fire_KickOutPassengers, 0x6) } // Aircraft mission hard code are all disposable that no ammo, target died or arrived destination all will call the aircraft return airbase -#pragma region AircraftMissionExpand +#pragma region ExtendedAircraftMissions // Waypoint: enable and smooth moving action bool __fastcall AircraftTypeClass_CanUseWaypoint(AircraftTypeClass* pThis) @@ -408,6 +408,7 @@ DEFINE_HOOK(0x4DF3BA, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget1, GET(FootClass* const, pThis, ESI); + // The aircraft is constantly moving, which may cause its target to constantly enter and leave its range, so it is fixed to hold the target. if (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) return HoldTarget; @@ -420,6 +421,7 @@ DEFINE_HOOK(0x4DF42A, FootClass_UpdateAttackMove_AircraftHoldAttackMoveTarget2, GET(FootClass* const, pThis, ESI); + // Although if the target selected by CS is an object rather than cell. return (RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft) ? HoldTarget : ContinueCheck; } @@ -494,8 +496,7 @@ AbstractClass* __fastcall AircraftClass_GreatestThreat(AircraftClass* pThis, voi threatType |= pSecondaryWeapon->AllowedThreats(); } - // return pThis->FootClass::GreatestThreat(threatType, pSelectCoords, onlyTargetHouseEnemy); - return reinterpret_cast(0x4D9920)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); + return pThis->FootClass::GreatestThreat(threatType, pSelectCoords, onlyTargetHouseEnemy); } DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat)) From 5f508b89cffe0843bf1275ff3346df786146a4d0 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 28 Dec 2024 14:51:16 +0800 Subject: [PATCH 44/46] Change an implementation --- src/Ext/Aircraft/Hooks.cpp | 11 ----------- src/Misc/Hooks.BugFixes.cpp | 4 ++++ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index 4424b15b37..a4006aadbe 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -469,18 +469,7 @@ DEFINE_HOOK(0x414D4D, AircraftClass_Update_ClearTargetIfNoAmmo, 0x6) return 0; } -/* -// This allows the aircraft to receive stop commands even at low altitudes, but if used, receiving a move command -// then quickly receiving a stop command can result in the aircraft landing in an incorrect direction -DEFINE_HOOK(0x417944, AircraftClass_EnterIdleMode_DockCheck, 0x7) -{ - enum { Continue = 0x417953, Invalid = 0x417AD4 }; - - GET(AircraftClass* const, pThis, ESI); - return (pThis->GetHeight() > 0) ? Continue : Invalid; // Replace IsInAir() -} -*/ // Stop: clear the mega mission and return to airbase immediately // (StopEventFix's DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) in Hooks.BugFixes.cpp) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 628a102c8b..4ab0880c4f 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1092,6 +1092,10 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { if (pAircraft->Type->AirportBound) { + // To avoid `AirportBound=yes` aircrafts with ammo at low altitudes cannot correctly receive stop command and queue Mission::Guard with a `Destination`. + if (pAircraft->Ammo) + pTechno->SetDestination(nullptr, true); + // To avoid `AirportBound=yes` aircrafts pausing in the air and let they returning to air base immediately. if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one pAircraft->EnterIdleMode(false, true); From 673927b4ee5c64db1942ff9bc3636f5a29d8a2b7 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Sat, 28 Dec 2024 14:52:16 +0800 Subject: [PATCH 45/46] Change a check function --- src/Ext/Aircraft/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Aircraft/Hooks.cpp b/src/Ext/Aircraft/Hooks.cpp index a4006aadbe..a6ec8dc5da 100644 --- a/src/Ext/Aircraft/Hooks.cpp +++ b/src/Ext/Aircraft/Hooks.cpp @@ -397,7 +397,7 @@ DEFINE_HOOK(0x6FA68B, TechnoClass_Update_AttackMovePaused, 0xA) // To make aircr const bool skip = RulesExt::Global()->ExtendedAircraftMissions && pThis->WhatAmI() == AbstractType::Aircraft - && (!pThis->Ammo || pThis->GetHeight() < Unsorted::CellHeight); + && (!pThis->Ammo || !pThis->IsInAir()); return skip ? SkipGameCode : 0; } From becf4a64da318ce8e31480e53a0dee806f880f37 Mon Sep 17 00:00:00 2001 From: Metadorius Date: Sat, 28 Dec 2024 00:54:12 +0200 Subject: [PATCH 46/46] Doc and spelling/style improvements --- CREDITS.md | 2 +- YRpp | 2 +- docs/Fixed-or-Improved-Logics.md | 21 +++++++++++++-------- docs/Whats-New.md | 2 +- src/Misc/Hooks.BugFixes.cpp | 15 +++++++++------ 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index d693ffb820..e11bea1769 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -372,7 +372,7 @@ This page lists all the individual contributions to the project by their author. - Allow to change the speed of gas particles - **CrimRecya** - Fix `LimboKill` not working reliably - - Optimize aircrafts stop action and allow they using area guard and attack moving + - Allow using waypoints, area guard and attack move with aircraft - Fix `Stop` command not working so well in some cases - **Ollerus** - Build limit group enhancement diff --git a/YRpp b/YRpp index 0873214a79..0cc38feea7 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 0873214a793cf62a8a30072c76f8e5982e928a93 +Subproject commit 0cc38feea7590cf0478e2f194b766eea80b9a26d diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 807bb56a4c..96292a2692 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -176,11 +176,12 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - `` can now be used as owner for pre-placed objects on skirmish and multiplayer maps. - Follower vehicle index for preplaced vehicles in maps is now explicitly constrained to `[Units]` list in map files and is no longer thrown off by vehicles that could not be created or created vehicles having other vehicles as initial passengers. - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix -- Prevent jumpjets from falling into a state of standing idly by when receive the stop(shortcut: s) command. -- Prevent technos from being unable to stop the attack move mission when receive the stop(shortcut: s) command. -- Prevent aircrafts from duplicatedly finding airport and overlapping when receive the stop(shortcut: s) command. -- Prevent aircrafts from briefly pausing in the air before returning when receive the stop(shortcut: s) command. -- Prevent aircrafts with `AirportBound=no` continue moving forward when receive the stop(shortcut: s) command. +- Stop command (`[S]` by default) behavior is now more correct: + - Jumpjets no longer fall into a state of standing by idly. + - Technos are no longer unable to stop the attack move mission. + - Aircraft no longer find airport twice and overlap. + - Aircraft no longer briefly pause in the air before returning. + - Aircraft with `AirportBound=no` continue moving forward. - Unit `Speed` setting now accepts floating-point values. Internally parsed values are clamped down to maximum of 100, multiplied by 256 and divided by 100, the result (which at this point is converted to an integer) then clamped down to maximum of 255 giving effective internal speed value range of 0 to 255, e.g leptons traveled per game frame. - Subterranean movement now benefits from speed multipliers from all sources such as veterancy, AttachEffect etc. @@ -233,14 +234,18 @@ In `rulesmd.ini`: LandingDir= ; Direction type (integers from 0-255). Accepts negative values as a special case. ``` -### Expand Aircraft Mission +### Extended Aircraft Missions -- Now, when a `stop` command (`[S]` by default) is issued to an aircraft, the aircraft will immediately return to the airport. When a `guard` command (`[G]` by default) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted (Note that if the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time). When a `attack move` command (Ctrl+Shift) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammo is depleted or the destination is reached, it will return (Note that if the automatically selected target is destroyed but ammo is not depleted yet during the process, the aircraft will continue to go to the destination). +- Aircraft will now be able to use waypoints. +- When a `guard` command (`[G]` by default) is issued, the aircraft will search for targets around the current location and return immediately when target is not found, target is destroyed or ammos are depleted. + - If the target is destroyed but ammos are not depleted yet, it will also return because the aircraft's command is one-time. +- When an `attack move` command (`[Ctrl]+[Shift]`) is issued, the aircraft will move towards the destination and search for nearby targets on the route for attack. Once ammo is depleted or the destination is reached, it will return. + - If the automatically selected target is destroyed but ammo is not depleted yet during the process, the aircraft will continue flying to the destination. In `rulesmd.ini`: ```ini [General] -ExtendedAircraftMissions=false ; boolean +ExtendedAircraftMissions=false ; boolean ``` ## Animations diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 60662acc41..e0bd0fdf9d 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -445,7 +445,7 @@ New: - Option for Warhead to remove all shield types at once (by Starkku) - Allow customizing voxel light source position (by Kerbiter, Morton, based on knowledge of thomassnedon) - Option to fix voxel light source being offset and incorrectly tilting on slopes (by Kerbiter) -- Optimize aircrafts stop action and allow they using area guard and attack moving (by CrimRecya) +- Allow using waypoints, area guard and attack move with aircraft (by CrimRecya) - AI superweapon delay timer customization (by Starkku) - Disabling `MultipleFactory` bonus from specific BuildingType (by Starkku) - Customizable ChronoSphere teleport delays for units (by Starkku) diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index 4ab0880c4f..b46ed47a0c 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -1072,14 +1072,17 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) GET(TechnoClass* const, pTechno, ESI); - // Check aircrafts + // Check aircraft const auto pAircraft = abstract_cast(pTechno); const bool commonAircraft = pAircraft && !pAircraft->Airstrike && !pAircraft->Spawned; const auto mission = pTechno->CurrentMission; - // To avoid aircrafts overlap by keep link if is returning or is in airport now. - if (!commonAircraft || (mission != Mission::Sleep && mission != Mission::Guard && mission != Mission::Enter) || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + // To avoid aircraft overlap by keep link if is returning or is in airport now. + if (!commonAircraft || (mission != Mission::Sleep && mission != Mission::Guard && mission != Mission::Enter) + || !pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) + { pTechno->SendToEachLink(RadioCommand::NotifyUnlink); + } // To avoid technos being unable to stop in attack move mega mission if (pTechno->MegaMissionIsAttackMove()) @@ -1092,17 +1095,17 @@ DEFINE_HOOK(0x4C75DA, EventClass_RespondToEvent_Stop, 0x6) { if (pAircraft->Type->AirportBound) { - // To avoid `AirportBound=yes` aircrafts with ammo at low altitudes cannot correctly receive stop command and queue Mission::Guard with a `Destination`. + // To avoid `AirportBound=yes` aircraft with ammo at low altitudes cannot correctly receive stop command and queue Mission::Guard with a `Destination`. if (pAircraft->Ammo) pTechno->SetDestination(nullptr, true); - // To avoid `AirportBound=yes` aircrafts pausing in the air and let they returning to air base immediately. + // To avoid `AirportBound=yes` aircraft pausing in the air and let they returning to air base immediately. if (!pAircraft->DockNowHeadingTo || (pAircraft->DockNowHeadingTo != pAircraft->GetNthLink())) // If the aircraft have no valid dock, try to find a new one pAircraft->EnterIdleMode(false, true); } else if (pAircraft->Ammo) { - // To avoid `AirportBound=no` aircrafts ignoring the stop task or directly return to the airport. + // To avoid `AirportBound=no` aircraft ignoring the stop task or directly return to the airport. if (pAircraft->Destination && static_cast(CellClass::Coord2Cell(pAircraft->Destination->GetCoords()).DistanceFromSquared(pAircraft->GetMapCoords())) > 2) // If the aircraft is moving, find the forward cell then stop in it pAircraft->SetDestination(pAircraft->GetCell()->GetNeighbourCell(static_cast(pAircraft->PrimaryFacing.Current().GetValue<3>())), true); }