From 6bfb772c05cb0525cb8237eb71b64c5b1c198937 Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Fri, 28 Nov 2025 19:20:53 +0800 Subject: [PATCH 1/2] init --- CREDITS.md | 1 + docs/Fixed-or-Improved-Logics.md | 10 ++++ docs/Whats-New.md | 1 + src/Ext/Team/Hooks.cpp | 93 ++++++++++++++++++++++++++++++++ src/Ext/TechnoType/Body.cpp | 4 ++ src/Ext/TechnoType/Body.h | 4 ++ 6 files changed, 113 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index 4bd17fe2f0..214f87c61a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -462,6 +462,7 @@ This page lists all the individual contributions to the project by their author. - Fix the bug that building with `CloningFacility=true` and `WeaponsFactory=true` may cloning multiple vehicles and then they get stuck - Customize Ares's radar jam logic - Customize if cloning need power + - Allow techno type considered as other type when AI recruit techno for teams - **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 1da0d9b094..cd574e8978 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -1613,6 +1613,16 @@ HeightShadowScaling.MinScale=0.0 ; floating point value ShadowSizeCharacteristicHeight= ; integer, height in leptons ``` +### Allow techno type considered as other type when AI recruit techno for teams + +- It is now possible to make techno type considered as other type when AI recruit techno for teams. + +In `rulesmd.ini`: +```ini +[SOMETECHNO] ; TechnoType +TeamMember.ConsideredAs= ; list of technotypes +``` + ## Terrains ### Animated TerrainTypes diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 086b84778b..31ed715053 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -462,6 +462,7 @@ New: - [Allow deploy controlled MCV](Fixed-or-Improved-Logics.md#allow-deploy-controlled-mcv) (by NetsuNegi) - [Customize if cloning need power](Fixed-or-Improved-Logics.md#customize-if-cloning-need-power) (by NetsuNegi) - [Add Target Filtering Options to AttachEffect System](New-or-Enhanced-Logics.md#attached-effects) (by Flactine) +- Allow techno type considered as other type when AI recruit techno for teams (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/Team/Hooks.cpp b/src/Ext/Team/Hooks.cpp index 64688d2f17..ba1efe93fa 100644 --- a/src/Ext/Team/Hooks.cpp +++ b/src/Ext/Team/Hooks.cpp @@ -1,5 +1,6 @@ #include "Body.h" #include +#include // Bugfix: TAction 7,80,107. DEFINE_HOOK(0x65DF67, TeamTypeClass_CreateMembers_LoadOntoTransport, 0x6) @@ -53,3 +54,95 @@ DEFINE_HOOK(0x65DF67, TeamTypeClass_CreateMembers_LoadOntoTransport, 0x6) return 0x65DF8D; } + +DEFINE_HOOK(0x6EA6BE, TeamClass_CanAddMember_Consideration, 0x6) +{ + enum { SkipGameCode = 0x6EA6F2 }; + + GET(TeamClass*, pTeam, EBP); + GET(FootClass*, pFoot, ESI); + GET(int*, idx, EBX); + const auto pFootType = pFoot->GetTechnoType(); + const auto pFootTypeExt = TechnoTypeExt::ExtMap.Find(pFootType); + const auto pTaskForce = pTeam->Type->TaskForce; + + do + { + const auto pType = pTaskForce->Entries[*idx].Type; + + if (pType == pFootType || pFootTypeExt->TeamMember_ConsideredAs.Contains(pType)) + break; + + *idx = *idx + 1; + } + while (pTaskForce->CountEntries > *idx); + + return SkipGameCode; +} + +DEFINE_HOOK(0x6EA8E7, TeamClass_LiberateMember_Consideration, 0x5) +{ + enum { SkipGameCode = 0x6EA91B }; + + GET(TeamClass*, pTeam, EDI); + GET(FootClass*, pMember, EBP); + int idx = 0; + const auto pMemberType = pMember->GetTechnoType(); + const auto pMemberTypeExt = TechnoTypeExt::ExtMap.Find(pMemberType); + const auto pTaskForce = pTeam->Type->TaskForce; + + do + { + const auto pSearchType = pTaskForce->Entries[idx].Type; + + if (pSearchType == pMemberType || pMemberTypeExt->TeamMember_ConsideredAs.Contains(pSearchType)) + break; + + ++idx; + } + while (pTaskForce->CountEntries > idx); + + R->Stack(STACK_OFFSET(0x14, 0x8), idx); + return SkipGameCode; +} + +DEFINE_HOOK(0x6EAD73, TeamClass_Sub_6EAA90_Consideration, 0x7) +{ + enum { ContinueCheck = 0x6EAD8F, SkipThisMember = 0x6EADB3 }; + + GET(TeamClass*, pTeam, ECX); + GET(UnitClass*, pMember, ESI); + GET_STACK(int, idx, STACK_OFFSET(0x3C, 0x4)); + const auto pMemberType = pMember->Type; + const auto pTaskForce = pTeam->Type->TaskForce; + const auto pSearchType = pTaskForce->Entries[idx].Type; + + return pSearchType == pMemberType || TechnoTypeExt::ExtMap.Find(pMemberType)->TeamMember_ConsideredAs.Contains(pSearchType) ? ContinueCheck : SkipThisMember; +} + +DEFINE_HOOK(0x6EF57F, TeamClass_GetTaskForceMissingMemberTypes_Consideration, 0x5) +{ + enum { ContinueIn = 0x6EF584, SkipThisMember = 0x6EF5A5 }; + + GET(int, idx, EAX); + + if (idx != -1) + return ContinueIn; + + GET(DynamicVectorClass*, vector, ESI); + GET(FootClass*, pMember, EDI); + const auto pMemberTypeExt = TechnoTypeExt::ExtMap.Find(pMember->GetTechnoType()); + + for (const auto pConsideType : pMemberTypeExt->TeamMember_ConsideredAs) + { + idx = vector->FindItemIndex(pConsideType); + + if (idx != -1) + { + R->EAX(idx); + return ContinueIn; + } + } + + return SkipThisMember; +} diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 7ca0e45106..9531255a50 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1011,6 +1011,8 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->AttackMove_PursuitTarget.Read(exINI, pSection, "AttackMove.PursuitTarget"); this->InfantryAutoDeploy.Read(exINI, pSection, "InfantryAutoDeploy"); + + this->TeamMember_ConsideredAs.Read(exINI, pSection, "TeamMember.ConsideredAs"); // Ares 0.2 this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius"); @@ -1669,6 +1671,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->InfantryAutoDeploy) + .Process(this->TeamMember_ConsideredAs) + .Process(this->TurretResponse) ; } diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 7268a70700..cf5917b507 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -437,6 +437,8 @@ class TechnoTypeExt Nullable InfantryAutoDeploy; + ValueableVector TeamMember_ConsideredAs; + Nullable TurretResponse; ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) @@ -827,6 +829,8 @@ class TechnoTypeExt , InfantryAutoDeploy {} + , TeamMember_ConsideredAs {} + , TurretResponse {} { } From bb9b65c150032cd81cc980fcc74e18f4b8d894a5 Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Sat, 29 Nov 2025 16:20:22 +0800 Subject: [PATCH 2/2] Update Hooks.cpp --- src/Ext/Team/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Team/Hooks.cpp b/src/Ext/Team/Hooks.cpp index ba1efe93fa..f3f7b1abb8 100644 --- a/src/Ext/Team/Hooks.cpp +++ b/src/Ext/Team/Hooks.cpp @@ -106,7 +106,7 @@ DEFINE_HOOK(0x6EA8E7, TeamClass_LiberateMember_Consideration, 0x5) return SkipGameCode; } -DEFINE_HOOK(0x6EAD73, TeamClass_Sub_6EAA90_Consideration, 0x7) +DEFINE_HOOK(0x6EAD73, TeamClass_RecruitMember_Consideration, 0x7) { enum { ContinueCheck = 0x6EAD8F, SkipThisMember = 0x6EADB3 };