Skip to content

Commit 275266d

Browse files
authored
[Minor] Refactor kick out stuck units (#1816)
- Fixed the ground congestion will cause jumpjets be unable to take off. - Also fixed the stuck hover units at the entrance of the weapons factory.
1 parent 8f27ae5 commit 275266d

File tree

4 files changed

+53
-34
lines changed

4 files changed

+53
-34
lines changed

src/Ext/Building/Body.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -355,19 +355,6 @@ bool BuildingExt::ExtData::HandleInfiltrate(HouseClass* pInfiltratorHouse, int m
355355
// For unit's weapons factory only
356356
void BuildingExt::KickOutStuckUnits(BuildingClass* pThis)
357357
{
358-
if (const auto pUnit = abstract_cast<UnitClass*>(pThis->GetNthLink()))
359-
{
360-
if (pUnit->Locomotor->Destination() == CoordStruct::Empty)
361-
{
362-
if (const auto pTeam = pUnit->Team)
363-
pTeam->LiberateMember(pUnit);
364-
365-
pThis->SendCommand(RadioCommand::NotifyUnlink, pUnit);
366-
pUnit->QueueMission(Mission::Guard, false);
367-
return; // one after another
368-
}
369-
}
370-
371358
auto buffer = CoordStruct::Empty;
372359
pThis->GetExitCoords(&buffer, 0);
373360

@@ -393,9 +380,6 @@ void BuildingExt::KickOutStuckUnits(BuildingClass* pThis)
393380
if (height < 0 || height > Unsorted::CellHeight)
394381
continue;
395382

396-
if (const auto pTeam = pUnit->Team)
397-
pTeam->LiberateMember(pUnit);
398-
399383
pThis->SendCommand(RadioCommand::RequestLink, pUnit);
400384
pThis->QueueMission(Mission::Unload, false);
401385
return; // one after another

src/Ext/Building/Hooks.cpp

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -204,27 +204,62 @@ DEFINE_HOOK(0x44D455, BuildingClass_Mission_Missile_EMPulseBulletWeapon, 0x8)
204204

205205
#pragma region KickOutStuckUnits
206206

207-
// Kick out stuck units when the factory building is not busy, only factory buildings can enter this hook
208-
DEFINE_HOOK(0x450248, BuildingClass_UpdateFactory_KickOutStuckUnits, 0x6)
207+
DEFINE_HOOK(0x44955D, BuildingClass_WeaponFactoryOutsideBusy_WeaponFactoryCell, 0x6)
209208
{
210-
GET(BuildingClass*, pThis, ESI);
209+
enum { NotBusy = 0x44969B };
211210

212-
// This is not a solution to the problem at its root
213-
// Currently the root cause of the problem is not located
214-
// So the idle weapon factory is asked to search every second for any units that are stuck
215-
if (!(Unsorted::CurrentFrame % 15)) // Check every 15 frames for factories
216-
{
217-
const auto pType = pThis->Type;
211+
GET(BuildingClass* const, pThis, ESI);
218212

219-
if (pType->Factory == AbstractType::UnitType && pType->WeaponsFactory && !pType->Naval && pThis->QueuedMission != Mission::Unload)
220-
{
221-
const auto mission = pThis->CurrentMission;
213+
const auto pLink = pThis->GetNthLink();
214+
215+
if (!pLink)
216+
return NotBusy;
217+
218+
const auto pLinkType = pLink->GetTechnoType();
219+
220+
if (pLinkType->JumpJet && pLinkType->BalloonHover)
221+
return NotBusy;
222+
223+
return 0;
224+
}
225+
226+
// Attempt to kick the stuck unit out again by setting the destination
227+
DEFINE_HOOK(0x44E202, BuildingClass_Mission_Unload_CheckStuck, 0x6)
228+
{
229+
enum { Waiting = 0x44E267, NextStatus = 0x44E20C};
222230

223-
if (mission == Mission::Guard && !pThis->InLimbo || mission == Mission::Unload && pThis->MissionStatus == 3) // Unloading but stuck
224-
BuildingExt::KickOutStuckUnits(pThis);
231+
GET(BuildingClass*, pThis, EBP);
232+
233+
if (!pThis->IsTether)
234+
return NextStatus;
235+
236+
if (const auto pUnit = abstract_cast<UnitClass*>(pThis->GetNthLink()))
237+
{
238+
// Detecting movement status
239+
if (pUnit->Locomotor->Destination() == CoordStruct::Empty)
240+
{
241+
// Evacuate the congestion at the entrance
242+
reinterpret_cast<void(__thiscall*)(BuildingClass*)>(0x449540)(pThis);
243+
const auto pType = pThis->Type;
244+
const auto cell = pThis->GetMapCoords() + pType->FoundationOutside[10];
245+
const auto door = cell - CellStruct { 1, 0 };
246+
const auto pDest = MapClass::Instance.GetCellAt(door);
247+
248+
// Hover units may stop one cell behind their destination, should forcing them to advance one more cell
249+
pUnit->SetDestination((pUnit->Destination != pDest ? pDest : MapClass::Instance.GetCellAt(cell)), true);
225250
}
226251
}
227252

253+
return Waiting;
254+
}
255+
256+
// Check for any stuck units inside after successful unload each time. If there is, kick it out
257+
DEFINE_HOOK(0x44E260, BuildingClass_Mission_Unload_KickOutStuckUnits, 0x7)
258+
{
259+
GET(BuildingClass*, pThis, EBP);
260+
261+
BuildingExt::KickOutStuckUnits(pThis);
262+
228263
return 0;
229264
}
230265

src/Ext/BuildingType/Hooks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ DEFINE_HOOK(0x73F5A7, UnitClass_IsCellOccupied_UnlimboDirection, 0x8)
425425

426426
GET(CellClass* const, pCell, EDI);
427427

428-
return pCell->MapCoords.Y == pType->FoundationOutside[10].Y ? NextObject : ContinueCheck;
428+
return pCell->MapCoords.Y == pBuilding->Location.Y / Unsorted::LeptonsPerCell + pType->FoundationOutside[10].Y ? NextObject : ContinueCheck;
429429
}
430430

431431
#pragma endregion

src/Ext/Techno/Body.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,9 @@ bool TechnoExt::CannotMove(UnitClass* pThis)
749749
landType = LandType::Road;
750750
}
751751

752-
if (movementRestrictedTo != LandType::None &&
753-
movementRestrictedTo != landType &&
754-
landType != LandType::Tunnel)
752+
if (movementRestrictedTo != LandType::None
753+
&& movementRestrictedTo != landType
754+
&& landType != LandType::Tunnel)
755755
{
756756
return true;
757757
}

0 commit comments

Comments
 (0)