From 0595e3d774cf3ccde4f2121f0bed856d791ba5f0 Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Sat, 22 Nov 2025 15:11:04 +0800 Subject: [PATCH 1/2] init --- CREDITS.md | 1 + docs/Fixed-or-Improved-Logics.md | 10 ++++++++++ docs/Whats-New.md | 1 + src/Ext/Building/Body.cpp | 11 +++++++++++ src/Ext/Building/Body.h | 1 + src/Ext/Building/Hooks.Production.cpp | 15 +++++++++++++++ src/Ext/BuildingType/Body.cpp | 2 ++ src/Ext/BuildingType/Body.h | 1 + src/Misc/Hooks.Ares.cpp | 6 ++++++ 9 files changed, 48 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index 05687cdc88..e8b7d943a2 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -460,6 +460,7 @@ This page lists all the individual contributions to the project by their author. - Allow deploy controlled MCV - Fix the bug that naval ship will sink even they destroyed in air - Fix the bug that building with `CloningFacility=true` and `WeaponsFactory=true` may cloning multiple vehicles and then they get stuck + - Customize if cloning need power - **Apollo** - Translucent SHP drawing patches - **ststl**: - Customizable `ShowTimer` priority of superweapons diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 716f0ab71a..fd35f69c5b 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -763,6 +763,16 @@ In `rulesmd.ini`: BuildingWaypoints=false ; boolean ``` +### Customize if cloning need power + +- In vanilla, cloning vats can work fine even low power. In ares, they need power to work. Now you can specific it. + +In `rulesmd.ini`: +```ini +[SOMEBUILDING] ; BuildingType +Cloning.Powered=true ; boolean +``` + ## Infantry ### Auto deploy for GI-like infantry diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 182c632579..554b81b730 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -460,6 +460,7 @@ New: - [Dehardcode the `ZAdjust` of warhead anim](Fixed-or-Improved-Logics.md#dehardcode-the-zadjust-of-warhead-anim) (by TaranDahl) - [Interceptor target scan delay customization](New-or-Enhanced-Logics.md#projectile-interception-logic) (by Starkku) - Allow deploy controlled MCV (by NetsuNegi) +- Customize if cloning need power (by NetsuNegi) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/src/Ext/Building/Body.cpp b/src/Ext/Building/Body.cpp index c7ff20a008..f993be1a8b 100644 --- a/src/Ext/Building/Body.cpp +++ b/src/Ext/Building/Body.cpp @@ -448,6 +448,17 @@ WeaponStruct* BuildingExt::GetLaserWeapon(BuildingClass* pThis) return pThis->GetPrimaryWeapon(); } +void BuildingExt::KickOutClone(std::pair& info, void*, BuildingClass* pFactory) +{ + if (!pFactory->IsAlive || pFactory->InLimbo || (BuildingTypeExt::ExtMap.Find(pFactory->Type)->Cloning_Powered && !pFactory->IsPowerOnline()) || pFactory->IsBeingWarpedOut()) + return; + + const auto pClone = static_cast(info.first->CreateObject(info.second)); + + if (pFactory->KickOutUnit(pClone, CellStruct::Empty) != KickOutResult::Succeeded) + pClone->UnInit(); +} + // ============================= // load / save diff --git a/src/Ext/Building/Body.h b/src/Ext/Building/Body.h index d92f5d39aa..170cc378f3 100644 --- a/src/Ext/Building/Body.h +++ b/src/Ext/Building/Body.h @@ -111,4 +111,5 @@ class BuildingExt static void KickOutStuckUnits(BuildingClass* pThis); static const std::vector GetFoundationCells(BuildingClass* pThis, CellStruct baseCoords, bool includeOccupyHeight = false); static WeaponStruct* GetLaserWeapon(BuildingClass* pThis); + static void __fastcall KickOutClone(std::pair& info, void*, BuildingClass* pFactory); }; diff --git a/src/Ext/Building/Hooks.Production.cpp b/src/Ext/Building/Hooks.Production.cpp index f017260b45..3a7ac8f068 100644 --- a/src/Ext/Building/Hooks.Production.cpp +++ b/src/Ext/Building/Hooks.Production.cpp @@ -225,3 +225,18 @@ DEFINE_HOOK(0x443CCA, BuildingClass_KickOutUnit_AircraftType_Phobos, 0xA) return 0; } + +DEFINE_HOOK(0x4449FB, BuildingClass_KickOutUnit_CloningVats, 0x8) +{ + enum { SkipGameCode = 0x444A53 }; + + GET(BuildingClass*, pFactory, ESI); + GET(TechnoTypeClass*, pProductionType, EAX); + const auto pOwner = pFactory->Owner; + auto info = std::make_pair(pProductionType, pOwner); + + for (const auto pVat : pOwner->CloningVats) + BuildingExt::KickOutClone(info, 0, pFactory); + + return SkipGameCode; +} diff --git a/src/Ext/BuildingType/Body.cpp b/src/Ext/BuildingType/Body.cpp index 9e98b66985..919ab6022b 100644 --- a/src/Ext/BuildingType/Body.cpp +++ b/src/Ext/BuildingType/Body.cpp @@ -149,6 +149,7 @@ void BuildingTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->CanC4_AllowZeroDamage.Read(exINI, pSection, "CanC4.AllowZeroDamage"); this->InitialStrength_Cloning.Read(exINI, pSection, "InitialStrength.Cloning"); + this->Cloning_Powered.Read(exINI, pSection, "Cloning.Powered"); this->ExcludeFromMultipleFactoryBonus.Read(exINI, pSection, "ExcludeFromMultipleFactoryBonus"); this->Grinding_AllowAllies.Read(exINI, pSection, "Grinding.AllowAllies"); @@ -291,6 +292,7 @@ void BuildingTypeExt::ExtData::Serialize(T& Stm) .Process(this->Powered_KillSpawns) .Process(this->CanC4_AllowZeroDamage) .Process(this->InitialStrength_Cloning) + .Process(this->Cloning_Powered) .Process(this->ExcludeFromMultipleFactoryBonus) .Process(this->Refinery_UseStorage) .Process(this->Grinding_AllowAllies) diff --git a/src/Ext/BuildingType/Body.h b/src/Ext/BuildingType/Body.h index 5421a48db9..a47d7784f2 100644 --- a/src/Ext/BuildingType/Body.h +++ b/src/Ext/BuildingType/Body.h @@ -32,6 +32,7 @@ class BuildingTypeExt Valueable CanC4_AllowZeroDamage; Valueable Refinery_UseStorage; Valueable> InitialStrength_Cloning; + Valueable Cloning_Powered { true }; Valueable ExcludeFromMultipleFactoryBonus; ValueableIdx Grinding_Sound; diff --git a/src/Misc/Hooks.Ares.cpp b/src/Misc/Hooks.Ares.cpp index b1883788c6..f380bc126a 100644 --- a/src/Misc/Hooks.Ares.cpp +++ b/src/Misc/Hooks.Ares.cpp @@ -108,6 +108,9 @@ void Apply_Ares3_0_Patches() // Apply laser weapon selection fix on Ares' laser fire replacement. Patch::Apply_CALL6(AresHelper::AresBaseAddress + 0x56415, &GetLaserWeapon); + + // Redirect Ares's function to our implementation: + Patch::Apply_LJMP(AresHelper::AresBaseAddress + 0x112D0, &BuildingExt::KickOutClone); } void Apply_Ares3_0p1_Patches() @@ -161,4 +164,7 @@ void Apply_Ares3_0p1_Patches() // Apply laser weapon selection fix on Ares' laser fire replacement. Patch::Apply_CALL6(AresHelper::AresBaseAddress + 0x570C5, &GetLaserWeapon); + + // Redirect Ares's function to our implementation: + Patch::Apply_LJMP(AresHelper::AresBaseAddress + 0x11860, &BuildingExt::KickOutClone); } From 37014d13cff5162c9809629a494ef0dba0fe544e Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Sat, 22 Nov 2025 16:33:37 +0800 Subject: [PATCH 2/2] Update Hooks.Production.cpp --- src/Ext/Building/Hooks.Production.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Building/Hooks.Production.cpp b/src/Ext/Building/Hooks.Production.cpp index 3a7ac8f068..2df3224ce1 100644 --- a/src/Ext/Building/Hooks.Production.cpp +++ b/src/Ext/Building/Hooks.Production.cpp @@ -236,7 +236,7 @@ DEFINE_HOOK(0x4449FB, BuildingClass_KickOutUnit_CloningVats, 0x8) auto info = std::make_pair(pProductionType, pOwner); for (const auto pVat : pOwner->CloningVats) - BuildingExt::KickOutClone(info, 0, pFactory); + BuildingExt::KickOutClone(info, 0, pVat); return SkipGameCode; }