diff --git a/CREDITS.md b/CREDITS.md index 59b2dc7b82..3f2850a71c 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -642,3 +642,6 @@ This page lists all the individual contributions to the project by their author. - **Damfoos** - extensive and thorough testing - **Dmitry Volkov** - extensive and thorough testing - **Rise of the East community** - extensive playtesting of in-dev features +- **ahasasjeb** + - fix: Pause AI building production under EMP (respect ImmuneToEMP) + - EMP effect on spawner aircraft generation with toggle control diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 2663b2e295..ed91b9b80f 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -17,6 +17,8 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed building and defense tab hotkeys not enabling the placement mode after *Cannot build here.* triggered and the placement mode cancelled. - Fixed buildings with `UndeployInto` playing `EVA_NewRallypointEstablished` on undeploying. - Fixed buildings with `Naval=yes` ignoring `WaterBound=no` to be forced to place onto water. +- Fixed AI buildings with `ImmuneToEMP=no` continuing production (infantry, vehicles, buildings) while under EMP; production is now paused for the EMP duration. Buildings with `ImmuneToEMP=yes` are unaffected and continue producing as before. +- EMP effect on spawner aircraft generation can now be controlled via `EMP.PausesSpawning`. When enabled (default), buildings with `ImmuneToEMP=no` no longer continue spawner aircraft generation while under EMP; spawning is paused for the EMP duration. Buildings with `ImmuneToEMP=yes` are unaffected and continue spawning as before. - Fixed AI Aircraft docks bug when Ares tag `[GlobalControls] -> AllowParallelAIQueues=no` is set. - Fixed laser drawing code to allow for thicker lasers in house color draw mode. - Fixed `DeathWeapon` not detonating properly. @@ -510,6 +512,16 @@ AINodeWallsOnly=false ; boolean AICleanWallNode=false ; boolean ``` +### EMP effect on spawner aircraft generation + +- By default buildings with spawner functionality (aircraft carriers) and `ImmuneToEMP=no` pause aircraft spawning while under EMP. This behavior can be disabled to restore vanilla behavior where EMP does not affect spawner aircraft generation. + +In `rulesmd.ini`: +```ini +[General] +EMP.PausesSpawning=yes ; boolean +``` + ### Aircraft docking direction - It is now possible to customize the landing direction for docking aircraft via `AircraftDockingDir(N)` (`N` optionally replaced by 0-based index for each `DockingOffset` separately, `AircraftDockingDir` and `AircraftDockingDir0` are synonymous and will be used if direction is not set for a specific offset) on the dock building. This overrides the aircraft's own [landing direction](#landing-direction) setting and defaults to `[AudioVisual] -> PoseDir`. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 787d5253bc..2eb02a863d 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -457,6 +457,7 @@ Phobos fixes: - Fixed an issue that `FireAngle` was not taken into account when drawing barrel in `TurretShadow` (by CrimRecya) Fixes / interactions with other extensions: +- Pause AI building production and spawner aircraft under EMP (by ahasasjeb) - Allowed `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades (by Ollerus) - Taking over Ares' AlphaImage respawn logic to reduce lags from it (by NetsuNegi) ``` diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 3096023aa4..d3839a8efa 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -310,6 +310,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->DistributeTargetingFrame_AIOnly.Read(exINI, GameStrings::General, "DistributeTargetingFrame.AIOnly"); this->InfantryAutoDeploy.Read(exINI, GameStrings::General, "InfantryAutoDeploy"); + this->EMP_PausesSpawning.Read(exINI, GameStrings::General, "EMP.PausesSpawning"); // Section AITargetTypes int itemsCount = pINI->GetKeyCount("AITargetTypes"); @@ -572,6 +573,7 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->AttackMove_StopWhenTargetAcquired) .Process(this->Parasite_GrappleAnim) .Process(this->InfantryAutoDeploy) + .Process(this->EMP_PausesSpawning) ; } diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index 2584a189dc..1ac5b2c5e7 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -263,6 +263,7 @@ class RulesExt int TintColorBerserk; Valueable InfantryAutoDeploy; + Valueable EMP_PausesSpawning; ExtData(RulesClass* OwnerObject) : Extension(OwnerObject) , Storage_TiberiumIndex { -1 } @@ -468,6 +469,7 @@ class RulesExt , Parasite_GrappleAnim {} , InfantryAutoDeploy { false } + , EMP_PausesSpawning { true } { } virtual ~ExtData() = default; diff --git a/src/Ext/Techno/Body.Update.cpp b/src/Ext/Techno/Body.Update.cpp index 8d2d91efb1..cb68bb0a42 100644 --- a/src/Ext/Techno/Body.Update.cpp +++ b/src/Ext/Techno/Body.Update.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -1627,8 +1629,9 @@ void TechnoExt::ExtData::UpdateTemporal() void TechnoExt::ExtData::UpdateRearmInEMPState() { const auto pThis = this->OwnerObject(); + const bool underEMP = pThis->IsUnderEMP(); - if (!pThis->IsUnderEMP() && !pThis->Deactivated) + if (!underEMP && !pThis->Deactivated) return; const auto pTypeExt = this->TypeExtData; @@ -1638,6 +1641,21 @@ void TechnoExt::ExtData::UpdateRearmInEMPState() if (pThis->ReloadTimer.InProgress() && pTypeExt->NoReload_UnderEMP.Get(RulesExt::Global()->NoReload_UnderEMP)) pThis->ReloadTimer.StartTime++; + + // Freeze AI-controlled factory production while building is EMPed + if (auto const pBuilding = abstract_cast(pThis)) + { + if (pBuilding->Owner && !pBuilding->Owner->IsControlledByHuman()) + { + if (auto const pFactory = pBuilding->Factory) + { + if (pFactory->Object && pFactory->Production.Rate > 0) + { + pFactory->Production.Timer.StartTime++; + } + } + } + } } void TechnoExt::ExtData::UpdateRearmInTemporal() diff --git a/src/Ext/Techno/Hooks.Misc.cpp b/src/Ext/Techno/Hooks.Misc.cpp index 517110b81a..d5d8b84b70 100644 --- a/src/Ext/Techno/Hooks.Misc.cpp +++ b/src/Ext/Techno/Hooks.Misc.cpp @@ -2,8 +2,14 @@ #include #include +#include #include +#include +#include +#include +#include +#include #pragma region SlaveManagerClass @@ -155,6 +161,9 @@ DEFINE_HOOK(0x6B78D3, SpawnManagerClass_Update_Spawns, 0x6) auto const pOwner = pThis->Owner; auto const pTypeExt = TechnoExt::ExtMap.Find(pOwner)->TypeExtData; + if (const auto pOwnerType = pOwner->GetTechnoType(); pOwnerType && pOwnerType->SpawnRegenRate <= 0) + return 0; + if (pTypeExt->Spawns_Queue.empty()) return 0; @@ -170,7 +179,7 @@ DEFINE_HOOK(0x6B78D3, SpawnManagerClass_Update_Spawns, 0x6) } } - if (vec.empty() || !vec[0]) + if (vec.empty()) return 0; R->EAX(vec[0]->CreateObject(pOwner->Owner)); diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 247e2f2a0b..64782f193d 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -160,7 +160,7 @@ DEFINE_HOOK(0x6F9FA9, TechnoClass_AI_PromoteAnim, 0x6) if (pThis->Veterancy.GetRemainingLevel() == Rank::Veteran && pVeteranAnim) promAnim = GameCreate(pVeteranAnim, pThis->GetCenterCoords()); - else if (pEliteAnim) + else if (pThis->Veterancy.GetRemainingLevel() == Rank::Elite && pEliteAnim) promAnim = GameCreate(pEliteAnim, pThis->GetCenterCoords()); if (promAnim)