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

Fix unit get stuck in factory #1347

Open
wants to merge 26 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ 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
- Units will not always stuck in the factory
- **TaranDahl**
- Units are now unable to kick out from a factory that is in construction process
- **Ollerus**
- Build limit group enhancement
- Customizable rocker amplitude
Expand Down
1 change: 1 addition & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
- OverlayTypes now read and use `ZAdjust` if specified in their `artmd.ini` entry.
- 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.
- Units are now unable to kick out from a factory that is in construction process, and will not always stuck in the factory.
- Fixed disguised units not using the correct palette if target has custom palette.
- 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.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ Vanilla fixes:
- Units with `Sensors=true` will no longer reveal ally buildings (by Starkku)
- Air units are now reliably included by target scan with large range and Warhead detonation by large `CellSpread` (by Starkku)
- Weapons with `AA=true` Projectile can now correctly fire at air units when both firer and target are over a bridge (by Starkku)
- Units are now unable to kick out from a factory that is in construction process, and will not always stuck in the factory (by CrimRecya & TaranDahl)
- Fixed disguised units not using the correct palette if target has custom palette (by NetsuNegi)
- Building upgrades now consistently use building's `PowerUpN` animation settings corresponding to the upgrade's `PowersUpToLevel` where possible (by Starkku)
- 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 (by Starkku)
Expand Down
47 changes: 46 additions & 1 deletion src/Ext/Building/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ bool BuildingExt::ExtData::HandleInfiltrate(HouseClass* pInfiltratorHouse,int mo
int idx = this->TypeExtData->SpyEffect_VictimSuperWeapon;
if (idx >= 0)
launchTheSWHere(pVictimHouse->Supers.Items[idx], pVictimHouse);

idx = this->TypeExtData->SpyEffect_InfiltratorSuperWeapon;
if (idx >= 0)
launchTheSWHere(pInfiltratorHouse->Supers.Items[idx], pInfiltratorHouse);
Expand All @@ -343,6 +343,51 @@ bool BuildingExt::ExtData::HandleInfiltrate(HouseClass* pInfiltratorHouse,int mo
return true;
}

void BuildingExt::KickOutStuckUnits(BuildingClass* pThis)
{
if (TechnoClass* const pTechno = pThis->GetNthLink())
{
if (UnitClass* const pUnit = abstract_cast<UnitClass*>(pTechno))
{
if (!pUnit->unknown_bool_418 && pUnit->GetCurrentSpeed() <= 0)
{
if (TeamClass* const pTeam = pUnit->Team)
pTeam->LiberateMember(pUnit);

pThis->SendCommand(RadioCommand::NotifyUnlink, pUnit);
pUnit->QueueMission(Mission::Guard, false);
return; // one after another
}
}
}

CoordStruct buffer = CoordStruct::Empty;

if (CellClass* const pCell = MapClass::Instance->GetCellAt(*pThis->GetExitCoords(&buffer, 0)))
{
for (ObjectClass* pObject = pCell->FirstObject; pObject; pObject = pObject->NextObject)
{
if (UnitClass* const pUnit = abstract_cast<UnitClass*>(pObject))
{
if (pThis->Owner != pUnit->Owner || pUnit->unknown_bool_418)
continue;

const int height = pUnit->GetHeight();

if (height < 0 || height > Unsorted::CellHeight)
continue;

if (TeamClass* const pTeam = pUnit->Team)
pTeam->LiberateMember(pUnit);

pThis->SendCommand(RadioCommand::RequestLink, pUnit);
pThis->QueueMission(Mission::Unload, false);
return; // one after another
}
}
}
}

// =============================
// load / save

Expand Down
1 change: 1 addition & 0 deletions src/Ext/Building/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,5 @@ class BuildingExt
static bool CanGrindTechno(BuildingClass* pBuilding, TechnoClass* pTechno);
static bool DoGrindingExtras(BuildingClass* pBuilding, TechnoClass* pTechno, int refund);
static bool CanUndeployOnSell(BuildingClass* pThis);
static void KickOutStuckUnits(BuildingClass* pThis);
};
33 changes: 33 additions & 0 deletions src/Ext/Building/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,39 @@ DEFINE_HOOK(0x443CCA, BuildingClass_KickOutUnit_AircraftType_Phobos, 0xA)
return 0;
}

// Kick out stuck units when the factory building is not busy
DEFINE_HOOK(0x450248, BuildingClass_UpdateFactory_KickOutStuckUnits, 0x6)
{
GET(BuildingClass*, pThis, ESI);

if (!(Unsorted::CurrentFrame % 15))
{
BuildingTypeClass* const pType = pThis->Type;

if (pType->Factory == AbstractType::UnitType && pType->WeaponsFactory && !pType->Naval && pThis->QueuedMission != Mission::Unload)
{
const Mission mission = pThis->CurrentMission;

if (mission == Mission::Guard || (mission == Mission::Unload && pThis->MissionStatus == 1))
BuildingExt::KickOutStuckUnits(pThis);
}
}

return 0;
}

// Should not kick out units if the factory building is in construction process
DEFINE_HOOK(0x4444A0, BuildingClass_KickOutUnit_NoKickOutInConstruction, 0xA)
{
enum { ThisIsOK = 0x444565, ThisIsNotOK = 0x4444B3};

GET(BuildingClass* const, pThis, ESI);

const Mission mission = pThis->GetCurrentMission();

return (mission == Mission::Unload || mission == Mission::Construction) ? ThisIsNotOK : ThisIsOK;
}

// Ares didn't have something like 0x7397E4 in its UnitDelivery code
DEFINE_HOOK(0x44FBBF, CreateBuildingFromINIFile_AfterCTOR_BeforeUnlimbo, 0x8)
{
Expand Down
Loading