Skip to content

Commit 14c934f

Browse files
authored
Improve subterranean harvester pathfinding (#1535)
This PR should allow `MovementZone=Subterannean` harvesters to access docks that are in areas closed off from normal pathfinding such as cliffs and islands. Whether or not it fixes all issues with such harvesters is another thing.
1 parent efffab6 commit 14c934f

File tree

11 files changed

+242
-59
lines changed

11 files changed

+242
-59
lines changed

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ This page lists all the individual contributions to the project by their author.
280280
- Changes / fixes to `Vertical` projectile logic and customizing projectile initial facing behavior
281281
- Bugfixes to map trigger action `125 Build At...`
282282
- Owner change during buildup bugfix
283+
- Subterranean harvester pathfinding fix
283284
- **Morton (MortonPL)**:
284285
- `XDrawOffset` for animations
285286
- Shield passthrough & absorption

Phobos.vcxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
<ClCompile Include="src\Ext\Sidebar\SWSidebar\ToggleSWButtonClass.cpp" />
4141
<ClCompile Include="src\Ext\TechnoType\Hooks.MatrixOp.cpp" />
4242
<ClCompile Include="src\Ext\Techno\Hooks.Airstrike.cpp" />
43-
<ClCompile Include="src\Ext\Unit\Hooks.Harvester.cpp" />
4443
<ClCompile Include="src\Ext\Unit\Hooks.Sinking.cpp" />
4544
<ClCompile Include="src\Misc\Hooks.AlphaImage.cpp" />
4645
<ClCompile Include="src\New\Entity\AttachEffectClass.cpp" />
@@ -91,6 +90,7 @@
9190
<ClCompile Include="src\Ext\TEvent\Body.cpp" />
9291
<ClCompile Include="src\Ext\Trigger\Hooks.cpp" />
9392
<ClCompile Include="src\Ext\Unit\Hooks.Crushing.cpp" />
93+
<ClCompile Include="src\Ext\Unit\Hooks.Harvester.cpp" />
9494
<ClCompile Include="src\Locomotion\TestLocomotionClass.cpp" />
9595
<ClCompile Include="src\Misc\Hooks.Gamespeed.cpp" />
9696
<ClCompile Include="src\Misc\Hooks.Ares.cpp" />

docs/Fixed-or-Improved-Logics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
270270
- Iron Curtain/Custom Tint Support for SHP Turreted Vehicles.
271271
- Reactivate unused trigger events 2, 53, and 54.
272272
- Fixed the bug that vehicle fall on infantry will make all cell content has been removed.
273+
- Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc.
273274

274275
## Fixes / interactions with other extensions
275276

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ Vanilla fixes:
490490
- Reactivate unused trigger events 2, 53, and 54 (by FlyStar)
491491
- Fixed the bug that vehicle fall on infantry will make all cell content has been removed (by NetsuNegi)
492492
- Fixed buildings that have their owner changed during buildup skipping buildup and sometimes not correctly clearing the state (by Starkku)
493+
- Fixed `MovementZone=Subterannean` harvesters being unable to find docks if in area enclosed by water, cliffs etc.
493494
494495
Phobos fixes:
495496
- Fixed the bug that `AllowAirstrike=no` cannot completely prevent air strikes from being launched against it (by NetsuNegi)

src/Ext/Techno/Body.Update.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,63 @@ void TechnoExt::ExtData::DepletedAmmoActions()
225225
}
226226
}
227227

228+
// Subterranean harvester factory exit state machine.
229+
void TechnoExt::ExtData::UpdateSubterraneanHarvester()
230+
{
231+
auto const pThis = static_cast<UnitClass*>(this->OwnerObject());
232+
233+
// Unnecessary for AI players.
234+
if (!pThis->Owner->IsControlledByHuman())
235+
return;
236+
237+
switch (this->SubterraneanHarvStatus)
238+
{
239+
case 0: // No state to handle.
240+
break;
241+
case 1: // Unit has been created.
242+
// If we're still in the factory do not advance.
243+
if (pThis->HasAnyLink())
244+
break;
245+
246+
pThis->ClearNavigationList();
247+
248+
// If we have rally point available, move to it and advance to next state, otherwise end here.
249+
if (this->SubterraneanHarvRallyPoint)
250+
{
251+
pThis->SetDestination(this->SubterraneanHarvRallyPoint, false);
252+
pThis->QueueMission(Mission::Move, true);
253+
this->SubterraneanHarvRallyPoint = nullptr;
254+
this->SubterraneanHarvStatus = 2;
255+
break;
256+
}
257+
else
258+
{
259+
this->SubterraneanHarvStatus = 0;
260+
}
261+
262+
break;
263+
case 2: // Out of factory and on move.
264+
// If we're still moving don't start harvesting.
265+
if (pThis->Destination || pThis->CurrentMission == Mission::Move)
266+
break;
267+
268+
// If harvester stops moving and becomes anything except idle, reset the state machine.
269+
if (pThis->CurrentMission != Mission::Guard)
270+
{
271+
this->SubterraneanHarvStatus = 0;
272+
break;
273+
}
274+
275+
// Go harvest ore.
276+
pThis->ClearNavigationList();
277+
pThis->QueueMission(Mission::Harvest, true);
278+
this->SubterraneanHarvStatus = 0;
279+
break;
280+
default:
281+
break;
282+
}
283+
}
284+
228285
// TODO : Merge into new AttachEffects
229286
bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo)
230287
{

src/Ext/Techno/Body.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,8 @@ void TechnoExt::ExtData::Serialize(T& Stm)
886886
.Process(this->AE)
887887
.Process(this->PreviousType)
888888
.Process(this->AnimRefCount)
889+
.Process(this->SubterraneanHarvStatus)
890+
.Process(this->SubterraneanHarvRallyPoint)
889891
.Process(this->ReceiveDamage)
890892
.Process(this->LastKillWasTeamTarget)
891893
.Process(this->PassengerDeletionTimer)

src/Ext/Techno/Body.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class TechnoExt
3232
TechnoTypeClass* PreviousType; // Type change registered in TechnoClass::AI on current frame and used in FootClass::AI on same frame and reset after.
3333
std::vector<EBolt*> ElectricBolts; // EBolts are not serialized so do not serialize this either.
3434
int AnimRefCount; // Used to keep track of how many times this techno is referenced in anims f.ex Invoker, ParentBuilding etc., for pointer invalidation.
35+
int SubterraneanHarvStatus; // 0 = none, 1 = created, 2 = out from factory
36+
AbstractClass* SubterraneanHarvRallyPoint;
3537
bool ReceiveDamage;
3638
bool LastKillWasTeamTarget;
3739
CDTimerClass PassengerDeletionTimer;
@@ -110,6 +112,8 @@ class TechnoExt
110112
, PreviousType { nullptr }
111113
, ElectricBolts {}
112114
, AnimRefCount { 0 }
115+
, SubterraneanHarvStatus { 0 }
116+
, SubterraneanHarvRallyPoint { nullptr }
113117
, ReceiveDamage { false }
114118
, LastKillWasTeamTarget { false }
115119
, PassengerDeletionTimer {}
@@ -172,6 +176,7 @@ class TechnoExt
172176
void ApplyInterceptor();
173177
bool CheckDeathConditions(bool isInLimbo = false);
174178
void DepletedAmmoActions();
179+
void UpdateSubterraneanHarvester();
175180
void EatPassengers();
176181
void UpdateTiberiumEater();
177182
void UpdateShield();

src/Ext/Techno/Hooks.Misc.cpp

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Body.h"
22

3+
#include <EventClass.h>
34
#include <SpawnManagerClass.h>
45
#include <TunnelLocomotionClass.h>
56
#include <JumpjetLocomotionClass.h>
@@ -846,13 +847,78 @@ DEFINE_HOOK(0x73D6E6, UnitClass_Unload_Subterranean, 0x6)
846847

847848
GET(UnitClass*, pThis, ESI);
848849

849-
if (pThis->Type->Locomotor == LocomotionClass::CLSIDs::Tunnel)
850+
if (auto const pLoco = locomotion_cast<TunnelLocomotionClass*>(pThis->Locomotor))
850851
{
851-
auto const pLoco = static_cast<TunnelLocomotionClass*>(pThis->Locomotor.GetInterfacePtr());
852-
853852
if (pLoco->State != TunnelLocomotionClass::State::Idle)
854853
return ReturnFromFunction;
855854
}
856855

857856
return 0;
858857
}
858+
859+
#pragma region Events
860+
861+
DEFINE_HOOK(0x4C7512, EventClass_Execute_StopCommand, 0x6)
862+
{
863+
GET(TechnoClass* const, pThis, ESI);
864+
865+
if (auto const pUnit = abstract_cast<UnitClass*>(pThis))
866+
{
867+
// issue #112 Make FireOnce=yes work on other TechnoType
868+
// Author: Starkku
869+
if (pUnit->CurrentMission == Mission::Unload && pUnit->Type->DeployFire && !pUnit->Type->IsSimpleDeployer)
870+
{
871+
pUnit->SetTarget(nullptr);
872+
pThis->QueueMission(Mission::Guard, true);
873+
}
874+
875+
// Explicit stop command should reset subterranean harvester state machine.
876+
auto const pExt = TechnoExt::ExtMap.Find(pUnit);
877+
pExt->SubterraneanHarvStatus = 0;
878+
pExt->SubterraneanHarvRallyPoint = nullptr;
879+
}
880+
881+
return 0;
882+
}
883+
884+
DEFINE_HOOK(0x4C7462, EventClass_Execute_MegaMission_MoveCommand, 0x5)
885+
{
886+
enum { SkipGameCode = 0x4C74C0 };
887+
888+
GET(TechnoClass*, pTechno, EDI);
889+
890+
if (pTechno->WhatAmI() != AbstractType::Unit)
891+
return 0;
892+
893+
GET(EventClass*, pThis, ESI);
894+
auto const mission = static_cast<Mission>(pThis->MegaMission.Mission);
895+
auto const pExt = TechnoExt::ExtMap.Find(pTechno);
896+
897+
if (mission == Mission::Move)
898+
{
899+
// Explicitly reset subterranean harvester state machine.
900+
pExt->SubterraneanHarvStatus = 0;
901+
pExt->SubterraneanHarvRallyPoint = nullptr;
902+
903+
// Do not explicitly reset target for KeepTargetOnMove vehicles when issued move command.
904+
if (pExt->TypeExtData->KeepTargetOnMove && pTechno->Target)
905+
{
906+
GET(AbstractClass*, pTarget, EBX);
907+
908+
if (!pTarget && pTechno->IsCloseEnoughToAttack(pTechno->Target))
909+
{
910+
auto const pDestination = pThis->MegaMission.Destination.As_Abstract();
911+
pTechno->SetDestination(pDestination, true);
912+
pExt->KeepTargetOnMove = true;
913+
914+
return SkipGameCode;
915+
}
916+
}
917+
}
918+
919+
pExt->KeepTargetOnMove = false;
920+
921+
return 0;
922+
}
923+
924+
#pragma endregion

src/Ext/Techno/Hooks.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "Body.h"
22

33
#include <AircraftClass.h>
4-
#include <EventClass.h>
54
#include <ScenarioClass.h>
65
#include <TunnelLocomotionClass.h>
76
#include <JumpjetLocomotionClass.h>
@@ -78,6 +77,7 @@ DEFINE_HOOK(0x736480, UnitClass_AI, 0x6)
7877
auto const pExt = TechnoExt::ExtMap.Find(pThis);
7978
pExt->UpdateKeepTargetOnMove();
8079
pExt->DepletedAmmoActions();
80+
pExt->UpdateSubterraneanHarvester();
8181

8282
return 0;
8383
}
@@ -717,39 +717,6 @@ DEFINE_HOOK(0x414665, AircraftClass_Draw_ExtraSHP, 0x6)
717717
return Continue;
718718
}
719719

720-
// Do not explicitly reset target for KeepTargetOnMove vehicles when issued move command.
721-
DEFINE_HOOK(0x4C7462, EventClass_Execute_KeepTargetOnMove, 0x5)
722-
{
723-
enum { SkipGameCode = 0x4C74C0 };
724-
725-
GET(TechnoClass*, pTechno, EDI);
726-
727-
if (pTechno->WhatAmI() != AbstractType::Unit)
728-
return 0;
729-
730-
GET(EventClass*, pThis, ESI);
731-
auto const mission = static_cast<Mission>(pThis->MegaMission.Mission);
732-
auto const pExt = TechnoExt::ExtMap.Find(pTechno);
733-
734-
if (mission == Mission::Move && pExt->TypeExtData->KeepTargetOnMove && pTechno->Target)
735-
{
736-
GET(AbstractClass*, pTarget, EBX);
737-
738-
if (!pTarget && pTechno->IsCloseEnoughToAttack(pTechno->Target))
739-
{
740-
auto const pDestination = pThis->MegaMission.Destination.As_Abstract();
741-
pTechno->SetDestination(pDestination, true);
742-
pExt->KeepTargetOnMove = true;
743-
744-
return SkipGameCode;
745-
}
746-
}
747-
748-
pExt->KeepTargetOnMove = false;
749-
750-
return 0;
751-
}
752-
753720
#pragma region BuildingTypeSelectable
754721

755722
namespace BuildingTypeSelectable

src/Ext/Unit/Hooks.DeployFire.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,7 @@
33
#include <Ext/Techno/Body.h>
44
#include <Utilities/Macro.h>
55

6-
// issue #112 Make FireOnce=yes work on other TechnoTypes
7-
// Author: Starkku
8-
DEFINE_HOOK(0x4C7512, EventClass_Execute_StopUnitDeployFire, 0x6)
9-
{
10-
GET(TechnoClass* const, pThis, ESI);
11-
12-
auto const pUnit = abstract_cast<UnitClass*>(pThis);
13-
if (pUnit && pUnit->CurrentMission == Mission::Unload && pUnit->Type->DeployFire && !pUnit->Type->IsSimpleDeployer)
14-
{
15-
pUnit->SetTarget(nullptr);
16-
pThis->QueueMission(Mission::Guard, true);
17-
}
18-
19-
return 0;
20-
}
21-
22-
DEFINE_HOOK(0x4C77E4, EventClass_Execute_UnitDeployFire, 0x6)
6+
DEFINE_HOOK(0x4C77E4, EventClass_Execute_DeployCommand, 0x6)
237
{
248
enum { DoNotExecute = 0x4C8109 };
259

0 commit comments

Comments
 (0)