Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize aircrafts actions #1366

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,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
- **Ollerus**
- Build limit group enhancement
- Customizable rocker amplitude
Expand Down
2 changes: 2 additions & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ 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.
- 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.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,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)
- AI superweapon delay timer customization (by Starkku)
- Disabling `MultipleFactory` bonus from specific BuildingType (by Starkku)
- Customizable ChronoSphere teleport delays for units (by Starkku)
Expand Down
121 changes: 121 additions & 0 deletions src/Ext/Aircraft/Hooks.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <AircraftClass.h>
#include <FlyLocomotionClass.h>
#include <EventClass.h>

#include <Ext/Aircraft/Body.h>
#include <Ext/Techno/Body.h>
Expand Down Expand Up @@ -342,3 +343,123 @@ 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())
{
CoordStruct 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->GetCurrentMission() == Mission::Sleep)) ? 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<DWORD>(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<AbstractClass*>(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);

return (!pThis->Ammo || pThis->CurrentMission == Mission::Sleep) ? ClearTarget : 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()

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)
{
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 (pSecondaryWeapon) // Vanilla (other types) secondary first
threatType |= pSecondaryWeapon->AllowedThreats();
else if (pPrimaryWeapon)
threatType |= pPrimaryWeapon->AllowedThreats();

return reinterpret_cast<AbstractClass*(__thiscall*)(TechnoClass*, ThreatType, CoordStruct*, bool)>(0x6F8DF0)(pThis, threatType, pSelectCoords, onlyTargetHouseEnemy); // TechnoClass_GreatestThreat (Prevent circular calls)
}
DEFINE_JUMP(VTABLE, 0x7E2668, GET_OFFSET(AircraftClass_GreatestThreat))

#pragma endregion
Loading