diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index e2f4a86138..6c878d58fe 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -379,6 +379,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - `EVA.Tag` already supports being set for specific countries, and `EVAIndex` is no longer reset after load game. - `DisableWeapons.Duration` now makes `Gattling=yes` rate tick down and stops the sounds from playing, no longer interferes with target acquisition and works together with Phobos' `OpenTopped.CheckTransportDisableWeapons`. - Allowed Ares' `SW.AuxBuildings` and `SW.NegBuildings` to count building upgrades. +- Allowed infantry to use `Convert.Deploy` without requiring `IsSimpleDeployer=true`. ## Newly added global settings diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 70b3c07a57..0f1d78bbc2 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -701,6 +701,21 @@ SpyEffect.InfiltratorSuperWeapon= ; SuperWeaponType ## Infantry +### Allow infantry to perform type conversion when deploying and undeploying + +- Now infantry can perform type conversion when executing the `Deploy` and `Undeploy` sequences. + +In `rulesmd.ini`: +```ini +[SOMEINFANTRY] ; InfantryType +Convert.Deploy= ; InfantryType +Convert.Undeploy= ; InfantryType +``` + +```{note} +For the sake of logical clarity, this feature does not allow the converted unit to trigger another conversion before the current sequence ends. If continuous conversion is needed, please use `Convert.Land/Water`. +``` + ### Customizable FLH when infantry is prone or deployed - Now infantry can override `PrimaryFireFLH` and `SecondaryFireFLH` if is prone (crawling) or deployed. Also works in conjunction with [burst-index specific firing offsets](#firing-offsets-for-specific-burst-shots). diff --git a/docs/Whats-New.md b/docs/Whats-New.md index b48035d31e..c7f490d54d 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -582,6 +582,7 @@ HideShakeEffects=false ; boolean - Restored the original Tiberian Sun behavior of playing the `[AudioVisual] -> DeploySound=` sound effect when clicking the sidebar to execute `Deploy` (by Noble_Fish) - Allow `RemoveMindControl` warhead to mute `MindClearedSound` (by Noble_Fish) - Introduce weight selection rules for ExtraWarheads (by Noble_Fish) +- [Allow infantry to perform type conversion when deploying and undeploying](New-or-Enhanced-Logics.md#allow-infantry-to-perform-type-conversion-when-deploying-and-undeploying) (by Noble_Fish) #### Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) @@ -742,6 +743,7 @@ HideShakeEffects=false ; boolean - [Aux technos and TechLevel requirement of superweapon](New-or-Enhanced-Logics.md#aux-technos-and-techlevel-requirement-of-superweapon) (by NetsuNegi & Ollerus) - [Export interface for external call](index.md#interoperability) (by TaranDahl) - Allowed `MindControl.Permanent` warhead to mute `MindClearedSound` (by NetsuNegi & Noble_Fish) +- Allowed infantry to use `Convert.Deploy` without requiring `IsSimpleDeployer=true` (by Noble_Fish) ``` diff --git a/src/Ext/Infantry/Hooks.cpp b/src/Ext/Infantry/Hooks.cpp index 668855d8c3..19b5829703 100644 --- a/src/Ext/Infantry/Hooks.cpp +++ b/src/Ext/Infantry/Hooks.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -11,6 +12,15 @@ DEFINE_HOOK(0x51B2BD, InfantryClass_UpdateTarget_IsControlledByHuman, 0x6) return (!pTarget || pThis->Owner->IsControlledByHuman()) ? 0x51B33F : 0; } + +DEFINE_HOOK(0x520AE9, InfantryClass_DoingAI_DeployConvert, 0x6) +{ + GET(InfantryClass*, pThis, ESI); + auto const pExt = TechnoExt::ExtMap.Find(pThis); + pExt->DeployConvertAction(); + return 0; +} + #pragma region WhatActionObjectFix namespace WhatActionObjectTemp diff --git a/src/Ext/Techno/Body.Update.cpp b/src/Ext/Techno/Body.Update.cpp index 8b8ed569bd..0002a79dba 100644 --- a/src/Ext/Techno/Body.Update.cpp +++ b/src/Ext/Techno/Body.Update.cpp @@ -216,6 +216,41 @@ void TechnoExt::ExtData::AmmoAutoConvertActions() } } +void TechnoExt::ExtData::DeployConvertAction() +{ + const auto pTypeExt = this->TypeExtData; + + if (!pTypeExt->Convert_Deploy && !pTypeExt->Convert_Undeploy) + return; + + const auto pThis = abstract_cast(this->OwnerObject()); + + if (!pThis) + return; + + const auto curSeq = pThis->SequenceAnim; + + if (curSeq != Sequence::Deploy && curSeq != Sequence::Undeploy) + { + this->HasDeployConvertedInCurrentSequence = false; + return; + } + + if (this->HasDeployConvertedInCurrentSequence) + return; + + if (curSeq == Sequence::Deploy && pTypeExt->Convert_Deploy) + { + this->HasDeployConvertedInCurrentSequence = true; + TechnoExt::ConvertToType(pThis, pTypeExt->Convert_Deploy); + } + else if (curSeq == Sequence::Undeploy && pTypeExt->Convert_Undeploy) + { + this->HasDeployConvertedInCurrentSequence = true; + TechnoExt::ConvertToType(pThis, pTypeExt->Convert_Undeploy); + } +} + // Subterranean harvester factory exit state machine. void TechnoExt::ExtData::UpdateSubterraneanHarvester() { diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index 8746ebcee6..14a7f3d8e1 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -1342,6 +1342,7 @@ void TechnoExt::ExtData::Serialize(T& Stm) .Process(this->HoverShutdown) .Process(this->LastTargetCrd) .Process(this->LastTargetCrdClearTimer) + .Process(this->HasDeployConvertedInCurrentSequence) ; } diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 08a7061b96..4a156b6de3 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -106,6 +106,8 @@ class TechnoExt CoordStruct LastTargetCrd; CDTimerClass LastTargetCrdClearTimer; + bool HasDeployConvertedInCurrentSequence; + ExtData(TechnoClass* OwnerObject) : Extension(OwnerObject) , TypeExtData { nullptr } , Shield {} @@ -177,6 +179,8 @@ class TechnoExt , HoverShutdown { false } , LastTargetCrd { CoordStruct::Empty } , LastTargetCrdClearTimer {} + + , HasDeployConvertedInCurrentSequence { false } { } void OnEarlyUpdate(); @@ -217,6 +221,8 @@ class TechnoExt void UpdateTintValues(); void AmmoAutoConvertActions(); + void DeployConvertAction(); + void UpdateLastTargetCrd(); int GetSight(); diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index cd1699164a..95fcdd0ce0 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1010,6 +1010,7 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->CurleyShuffle.Read(exINI, pSection, "CurleyShuffle"); this->Convert_Deploy.Read(exINI, pSection, "Convert.Deploy"); + this->Convert_Undeploy.Read(exINI, pSection, "Convert.Undeploy"); this->Convert_HumanToComputer.Read(exINI, pSection, "Convert.HumanToComputer"); this->Convert_ComputerToHuman.Read(exINI, pSection, "Convert.ComputerToHuman"); this->Convert_ResetMindControl.Read(exINI, pSection, "Convert.ResetMindControl"); @@ -1736,6 +1737,7 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->TiberiumEaterType) .Process(this->Convert_Deploy) + .Process(this->Convert_Undeploy) .Process(this->Convert_HumanToComputer) .Process(this->Convert_ComputerToHuman) .Process(this->Convert_ResetMindControl) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index f8cad1c703..a0899dbb92 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -289,6 +289,7 @@ class TechnoTypeExt Nullable CurleyShuffle; Valueable Convert_Deploy; // Ares + Valueable Convert_Undeploy; Valueable Convert_HumanToComputer; Valueable Convert_ComputerToHuman; Valueable Convert_ResetMindControl; @@ -771,6 +772,7 @@ class TechnoTypeExt , CurleyShuffle {} , Convert_Deploy { } + , Convert_Undeploy { } , Convert_HumanToComputer { } , Convert_ComputerToHuman { } , Convert_ResetMindControl { false }