From d7e193d68e0ca45ca8b12c3444807bf87f49cf4d Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:31:25 +0800 Subject: [PATCH 01/14] fix code --- docs/Whats-New.md | 1 + src/Ext/Rules/Body.cpp | 5 ++ src/Ext/TechnoType/Body.cpp | 62 ++++++++++++++++++++++++ src/Ext/TechnoType/Body.h | 6 +++ src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 55 +++++++++++++++++++++ 5 files changed, 129 insertions(+) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 06ea6a6365..3efddd44db 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -495,6 +495,7 @@ Phobos fixes: - Fixed an issue that jumpjet infantries stop incorrectly when assigned a target out of range (by TaranDahl) - Fixed an issue where the 77 trigger event in Ares was not functioning properly (by NetsuNegi) - Fixed an interaction error between the engineer and the Ares rubble (by FlyStar) +- Fixed an issue where the game would only use `Weapon1` and `Weapon2` for auto-targeting even when `MultiWeapon=yes` was set (by FlyStar) Fixes / interactions with other extensions: - Allowed `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades (by Ollerus) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index bd8bf60794..98e6c65de6 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -727,6 +727,11 @@ DEFINE_HOOK(0x679CAF, RulesData_LoadAfterTypeData, 0x5) RulesExt::LoadAfterTypeData(pItem, pINI); + for (const auto pTechnoType : TechnoTypeClass::Array) + { + TechnoTypeExt::ExtMap.Find(pTechnoType)->ParseCombatDamageAndThreatType(pINI); + } + return 0; } diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index d8bf5ebdb1..575509c988 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -362,6 +362,68 @@ void TechnoTypeExt::ExtData::ParseVoiceWeaponAttacks(INI_EX& exINI, const char* } } +void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pINI) +{ + int Num = 0; + int EliteNum = 0; + + this->ThreatTypes = { ThreatType::Normal,ThreatType::Normal }; + this->CombatDamages = { 0,0 }; + + const auto pThis = this->OwnerObject(); + int Count = 2; + + if (this->MultiWeapon && !pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner)) + { + Count = Math::min(this->MultiWeapon_SelectCount, pThis->WeaponCount); + } + + for (int index = 0; index < Count; index++) + { + const auto pWeapon = pThis->GetWeapon(index)->WeaponType; + auto pEliteWeapon = pThis->GetEliteWeapon(index)->WeaponType; + + if (!pEliteWeapon) + pEliteWeapon = pWeapon; + + if (pWeapon) + { + if (const auto pBulletType = pWeapon->Projectile) + { + if (pBulletType->AA) + this->ThreatTypes.X |= ThreatType::Air; + + if (pBulletType->AG && !BulletTypeExt::ExtMap.Find(pBulletType)->AAOnly) + this->ThreatTypes.X |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + } + + this->CombatDamages.X += (pWeapon->Damage + pWeapon->AmbientDamage); + Num++; + } + + if (pEliteWeapon) + { + if (const auto pBulletType = pEliteWeapon->Projectile) + { + if (pBulletType->AA) + this->ThreatTypes.X |= ThreatType::Air; + + if (pBulletType->AG && !BulletTypeExt::ExtMap.Find(pBulletType)->AAOnly) + this->ThreatTypes.X |= (ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + } + + this->CombatDamages.Y += (pEliteWeapon->Damage + pEliteWeapon->AmbientDamage); + EliteNum++; + } + } + + if (Num > 0) + this->CombatDamages.X /= Num; + + if (EliteNum > 0) + this->CombatDamages.Y /= EliteNum; +} + void TechnoTypeExt::ExtData::CalculateSpawnerRange() { const auto pThis = this->OwnerObject(); diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 277021f05d..b1d9891898 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -422,6 +422,8 @@ class TechnoTypeExt ValueableVector MultiWeapon_IsSecondary; Valueable MultiWeapon_SelectCount; bool ReadMultiWeapon; + Vector2D ThreatTypes; + Vector2D CombatDamages; ValueableIdx VoiceIFVRepair; ValueableVector VoiceWeaponAttacks; @@ -804,6 +806,8 @@ class TechnoTypeExt , MultiWeapon_IsSecondary {} , MultiWeapon_SelectCount { 2 } , ReadMultiWeapon { false } + , ThreatTypes { ThreatType::Normal,ThreatType::Normal } + , CombatDamages { 0,0 } , VoiceIFVRepair { -1 } , VoiceWeaponAttacks {} @@ -832,6 +836,8 @@ class TechnoTypeExt int SelectForceWeapon(TechnoClass* pThis, AbstractClass* pTarget); int SelectMultiWeapon(TechnoClass* const pThis, AbstractClass* const pTarget); + void ParseCombatDamageAndThreatType(CCINIClass* const pINI); + // Ares 0.A const char* GetSelectionGroupID() const; diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index 46ca12fb1a..022118663b 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -141,3 +141,58 @@ DEFINE_HOOK(0x7090A0, TechnoClass_VoiceAttack, 0x7) return 0x7091C7; } + +ThreatType __forceinline GetThreatType(TechnoClass* pThis, TechnoTypeExt::ExtData* pTypeExt, ThreatType result) +{ + ThreatType flags = pThis->Veterancy.IsElite() ? pTypeExt->ThreatTypes.Y : pTypeExt->ThreatTypes.X; + return result | flags; +} + +DEFINE_HOOK_AGAIN(0x51E2CF, InfantryClass_SelectAutoTarget_MultiWeapon, 0x6) // InfantryClass_SelectAutoTarget +DEFINE_HOOK(0x7431D4, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitClass_SelectAutoTarget +{ + GET(FootClass*, pThis, ESI); + GET(ThreatType, result, EDI); + enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F, GunnerReturn = 0x7431E4 }; + + const auto pType = pThis->GetTechnoType(); + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + const bool isUnit = R->Origin() == 0x7431D4; + + if (isUnit && !pType->IsGattling && + (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) + { + return GunnerReturn; + } + + R->EDI(GetThreatType(pThis, pTypeExt, result)); + return isUnit ? UnitReturn : InfantryReturn; +} + +DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA) +{ + GET(BuildingClass*, pThis, ESI); + GET_STACK(ThreatType, result, STACK_OFFSET(0x8, 0x4)); + enum { ReturnFlag = 0x445F58 }; + + R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->Type), result)); + return ReturnFlag; +} + +DEFINE_HOOK(0x6F39A3, TechnoClass_CombatDamage_MultiWeapon, 0x6) +{ + GET(TechnoClass*, pThis, ESI); + GET(TechnoTypeClass*, pType, EAX); + enum { ReturnDamage = 0x6F3ABB, GunnerDamage = 0x6F39AD }; + + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + + if (pThis->WhatAmI() == AbstractType::Unit && !pType->IsGattling && + (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) + { + return GunnerDamage; + } + + R->EAX(pThis->Veterancy.IsElite() ? pTypeExt->CombatDamages.Y : pTypeExt->CombatDamages.X); + return ReturnDamage; +} From 464a71be691e41db51cbff120fe25ac45cfcc162 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:54:25 +0800 Subject: [PATCH 02/14] well, right --- src/Ext/TechnoType/Body.cpp | 3 +- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 37 +++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 575509c988..dc2b24a8ce 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -373,7 +373,8 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI const auto pThis = this->OwnerObject(); int Count = 2; - if (this->MultiWeapon && !pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner)) + if (this->MultiWeapon + && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) { Count = Math::min(this->MultiWeapon_SelectCount, pThis->WeaponCount); } diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index 022118663b..b4287d1126 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -159,8 +159,8 @@ DEFINE_HOOK(0x7431D4, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitCla const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); const bool isUnit = R->Origin() == 0x7431D4; - if (isUnit && !pType->IsGattling && - (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) + if (isUnit && !pType->IsGattling + && (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) { return GunnerReturn; } @@ -187,8 +187,8 @@ DEFINE_HOOK(0x6F39A3, TechnoClass_CombatDamage_MultiWeapon, 0x6) const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); - if (pThis->WhatAmI() == AbstractType::Unit && !pType->IsGattling && - (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) + if (pThis->WhatAmI() == AbstractType::Unit && !pType->IsGattling + && (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) { return GunnerDamage; } @@ -196,3 +196,32 @@ DEFINE_HOOK(0x6F39A3, TechnoClass_CombatDamage_MultiWeapon, 0x6) R->EAX(pThis->Veterancy.IsElite() ? pTypeExt->CombatDamages.Y : pTypeExt->CombatDamages.X); return ReturnDamage; } + +DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) +{ + GET(TechnoClass*, pThis, ESI); + enum { NewRange = 0x707F08 }; + + const auto pType = pThis->GetTechnoType(); + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + + if (pTypeExt->MultiWeapon + && (!pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner))) + { + const int selectCount = Math::min(pTypeExt->MultiWeapon_SelectCount, pType->WeaponCount); + int range = 0; + + for (int index = selectCount - 1; index >= 0; --index) + { + const auto weaponRange = pThis->GetWeaponRange(index); + + if (weaponRange > range) + range = weaponRange; + } + + R->EAX(range); + return NewRange; + } + + return 0; +} From 328add370b3f5bf669f06d45c1271d63d14392f3 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:29:43 +0800 Subject: [PATCH 03/14] code fix --- src/Ext/TechnoType/Body.cpp | 2 +- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 38 +++++++----------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index dc2b24a8ce..f97365f3f7 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -376,7 +376,7 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI if (this->MultiWeapon && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) { - Count = Math::min(this->MultiWeapon_SelectCount, pThis->WeaponCount); + Count = Math::min(pThis->WeaponCount, this->MultiWeapon_SelectCount); } for (int index = 0; index < Count; index++) diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index b4287d1126..4e8a8609d5 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -149,50 +149,32 @@ ThreatType __forceinline GetThreatType(TechnoClass* pThis, TechnoTypeExt::ExtDat } DEFINE_HOOK_AGAIN(0x51E2CF, InfantryClass_SelectAutoTarget_MultiWeapon, 0x6) // InfantryClass_SelectAutoTarget -DEFINE_HOOK(0x7431D4, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitClass_SelectAutoTarget +DEFINE_HOOK(0x743203, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitClass_SelectAutoTarget { GET(FootClass*, pThis, ESI); GET(ThreatType, result, EDI); - enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F, GunnerReturn = 0x7431E4 }; + enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F }; - const auto pType = pThis->GetTechnoType(); - const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); - const bool isUnit = R->Origin() == 0x7431D4; - - if (isUnit && !pType->IsGattling - && (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) - { - return GunnerReturn; - } - - R->EDI(GetThreatType(pThis, pTypeExt, result)); - return isUnit ? UnitReturn : InfantryReturn; + R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()), result)); + return R->Origin() == 0x743203 ? UnitReturn : InfantryReturn; } DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA) { GET(BuildingClass*, pThis, ESI); GET_STACK(ThreatType, result, STACK_OFFSET(0x8, 0x4)); - enum { ReturnFlag = 0x445F58 }; + enum { ReturnThreatType = 0x445F58 }; R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->Type), result)); - return ReturnFlag; + return ReturnThreatType; } -DEFINE_HOOK(0x6F39A3, TechnoClass_CombatDamage_MultiWeapon, 0x6) +DEFINE_HOOK(0x6F39F4, TechnoClass_CombatDamage_MultiWeapon, 0x6) { GET(TechnoClass*, pThis, ESI); - GET(TechnoTypeClass*, pType, EAX); - enum { ReturnDamage = 0x6F3ABB, GunnerDamage = 0x6F39AD }; - - const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); - - if (pThis->WhatAmI() == AbstractType::Unit && !pType->IsGattling - && (pType->Gunner || (pType->IsChargeTurret && !pTypeExt->MultiWeapon))) - { - return GunnerDamage; - } + enum { ReturnDamage = 0x6F3ABB }; + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()); R->EAX(pThis->Veterancy.IsElite() ? pTypeExt->CombatDamages.Y : pTypeExt->CombatDamages.X); return ReturnDamage; } @@ -208,7 +190,7 @@ DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) if (pTypeExt->MultiWeapon && (!pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner))) { - const int selectCount = Math::min(pTypeExt->MultiWeapon_SelectCount, pType->WeaponCount); + const int selectCount = Math::min(pType->WeaponCount, pTypeExt->MultiWeapon_SelectCount); int range = 0; for (int index = selectCount - 1; index >= 0; --index) From 9ff8b78bed76f4648ae456ea871fd6d2f701cc39 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:30:13 +0800 Subject: [PATCH 04/14] Update Hooks.MultiWeapon.cpp --- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index 4e8a8609d5..4a086bd068 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -182,7 +182,7 @@ DEFINE_HOOK(0x6F39F4, TechnoClass_CombatDamage_MultiWeapon, 0x6) DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) { GET(TechnoClass*, pThis, ESI); - enum { NewRange = 0x707F08 }; + enum { ReturnRange = 0x707F08 }; const auto pType = pThis->GetTechnoType(); const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); @@ -202,7 +202,7 @@ DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) } R->EAX(range); - return NewRange; + return ReturnRange; } return 0; From dbc5415ff7ab012822f54fbd79850815dae14d16 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:38:24 +0800 Subject: [PATCH 05/14] Support AU --- src/Ext/TechnoType/Body.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index f97365f3f7..c58d88e74e 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -391,11 +391,20 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI { if (const auto pBulletType = pWeapon->Projectile) { - if (pBulletType->AA) + const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType); + const bool AAOnly = pBulletTypeExt->AAOnly; + + if (pBulletType->AA || AAOnly) this->ThreatTypes.X |= ThreatType::Air; - if (pBulletType->AG && !BulletTypeExt::ExtMap.Find(pBulletType)->AAOnly) - this->ThreatTypes.X |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + if (!AAOnly) + { + if (pBulletType->AG) + this->ThreatTypes.X |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + + if (pBulletTypeExt->AU) + this->ThreatTypes.X |= static_cast(0x20000u); + } } this->CombatDamages.X += (pWeapon->Damage + pWeapon->AmbientDamage); @@ -406,11 +415,20 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI { if (const auto pBulletType = pEliteWeapon->Projectile) { - if (pBulletType->AA) - this->ThreatTypes.X |= ThreatType::Air; + const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType); + const bool AAOnly = pBulletTypeExt->AAOnly; - if (pBulletType->AG && !BulletTypeExt::ExtMap.Find(pBulletType)->AAOnly) - this->ThreatTypes.X |= (ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + if (pBulletType->AA || AAOnly) + this->ThreatTypes.Y |= ThreatType::Air; + + if (!AAOnly) + { + if (pBulletType->AG) + this->ThreatTypes.Y |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); + + if (pBulletTypeExt->AU) + this->ThreatTypes.Y |= static_cast(0x20000u); + } } this->CombatDamages.Y += (pEliteWeapon->Damage + pEliteWeapon->AmbientDamage); From a50effd984bf12d2abd77c51630d160f0d8b038a Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:41:05 +0800 Subject: [PATCH 06/14] Update Body.cpp --- src/Ext/TechnoType/Body.cpp | 38 ++----------------------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index c58d88e74e..b2d134111c 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -389,48 +389,14 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI if (pWeapon) { - if (const auto pBulletType = pWeapon->Projectile) - { - const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType); - const bool AAOnly = pBulletTypeExt->AAOnly; - - if (pBulletType->AA || AAOnly) - this->ThreatTypes.X |= ThreatType::Air; - - if (!AAOnly) - { - if (pBulletType->AG) - this->ThreatTypes.X |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); - - if (pBulletTypeExt->AU) - this->ThreatTypes.X |= static_cast(0x20000u); - } - } - + this->ThreatTypes.X |= pWeapon->AllowedThreats(); this->CombatDamages.X += (pWeapon->Damage + pWeapon->AmbientDamage); Num++; } if (pEliteWeapon) { - if (const auto pBulletType = pEliteWeapon->Projectile) - { - const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType); - const bool AAOnly = pBulletTypeExt->AAOnly; - - if (pBulletType->AA || AAOnly) - this->ThreatTypes.Y |= ThreatType::Air; - - if (!AAOnly) - { - if (pBulletType->AG) - this->ThreatTypes.Y |= static_cast(ThreatType::Infantry | ThreatType::Vehicles | ThreatType::Buildings | ThreatType::Boats); - - if (pBulletTypeExt->AU) - this->ThreatTypes.Y |= static_cast(0x20000u); - } - } - + this->ThreatTypes.Y |= pEliteWeapon->AllowedThreats(); this->CombatDamages.Y += (pEliteWeapon->Damage + pEliteWeapon->AmbientDamage); EliteNum++; } From a2d7d851887d84efacbee9601976fdb2966adf6d Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:20:28 +0800 Subject: [PATCH 07/14] Update Body.cpp --- src/Ext/TechnoType/Body.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index b2d134111c..f6422b9e9c 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -376,7 +376,7 @@ void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pI if (this->MultiWeapon && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) { - Count = Math::min(pThis->WeaponCount, this->MultiWeapon_SelectCount); + Count = pThis->WeaponCount; } for (int index = 0; index < Count; index++) From 96aa4f8d0371015dd51e6d7919fa6f02fd93aa3a Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 14:55:11 +0800 Subject: [PATCH 08/14] update secondary --- docs/Fixed-or-Improved-Logics.md | 1 + src/Ext/TechnoType/Body.cpp | 2 +- src/Ext/TechnoType/Body.h | 2 +- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 69 ++++++++++++++++++++---- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 07396800dd..8dc833e7a6 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -298,6 +298,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed an issue that technos head to building's dock even they are not going to dock. - Fixed an issue that the jumpjet vehicles cannot stop correctly after going berserk. - Fixed the issue where Ares' `Flash.Duration` cannot override the weapon's repair flash effect. +- Fixed an issue where the game would only use `Weapon1` and `Weapon2` for auto-targeting even when `MultiWeapon=yes` was set. ```{note} The described behavior is a replica of and is compliant with XNA CnCNet Client's multiplayer save game support. diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index f6422b9e9c..e12359990a 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -362,7 +362,7 @@ void TechnoTypeExt::ExtData::ParseVoiceWeaponAttacks(INI_EX& exINI, const char* } } -void TechnoTypeExt::ExtData::ParseCombatDamageAndThreatType(CCINIClass* const pINI) +void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() { int Num = 0; int EliteNum = 0; diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index b1d9891898..35acf3f701 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -836,7 +836,7 @@ class TechnoTypeExt int SelectForceWeapon(TechnoClass* pThis, AbstractClass* pTarget); int SelectMultiWeapon(TechnoClass* const pThis, AbstractClass* const pTarget); - void ParseCombatDamageAndThreatType(CCINIClass* const pINI); + void UpdateAdditionalAttributes(); // Ares 0.A const char* GetSelectionGroupID() const; diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index 4a086bd068..2aa30445cb 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -1,6 +1,8 @@ #include "Body.h" #include +#include + DEFINE_HOOK(0x7128B2, TechnoTypeClass_ReadINI_MultiWeapon, 0x6) { GET(TechnoTypeClass*, pThis, EBP); @@ -148,12 +150,24 @@ ThreatType __forceinline GetThreatType(TechnoClass* pThis, TechnoTypeExt::ExtDat return result | flags; } -DEFINE_HOOK_AGAIN(0x51E2CF, InfantryClass_SelectAutoTarget_MultiWeapon, 0x6) // InfantryClass_SelectAutoTarget -DEFINE_HOOK(0x743203, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitClass_SelectAutoTarget +DEFINE_HOOK_AGAIN(0x51E2CF, FootClass_SelectAutoTarget_MultiWeapon, 0x6) // InfantryClass_SelectAutoTarget +DEFINE_HOOK(0x7431C9, FootClass_SelectAutoTarget_MultiWeapon, 0x7) // UnitClass_SelectAutoTarget { + enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F, UnitGunner = 0x7431E4 }; + GET(FootClass*, pThis, ESI); GET(ThreatType, result, EDI); - enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F }; + + const bool isUnit = R->Origin() == 0x7431C9; + const auto pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData; + const auto pType = pTypeExt->OwnerObject(); + + if (isUnit + && !pType->IsGattling && pType->TurretCount > 0 + && (pType->Gunner || !pTypeExt->MultiWeapon)) + { + return UnitGunner; + } R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()), result)); return R->Origin() == 0x743203 ? UnitReturn : InfantryReturn; @@ -161,34 +175,69 @@ DEFINE_HOOK(0x743203, UnitClass_SelectAutoTarget_MultiWeapon, 0x6) // UnitCla DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA) { + enum { ReturnThreatType = 0x445F58, Continue = 0x445F0E }; + GET(BuildingClass*, pThis, ESI); GET_STACK(ThreatType, result, STACK_OFFSET(0x8, 0x4)); - enum { ReturnThreatType = 0x445F58 }; + + if (pThis->UpgradeLevel > 0 || pThis->CanOccupyFire()) + { + R->EAX(pThis->GetWeapon(0)); + return Continue; + } R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->Type), result)); return ReturnThreatType; } -DEFINE_HOOK(0x6F39F4, TechnoClass_CombatDamage_MultiWeapon, 0x6) +DEFINE_HOOK(0x6F398E, TechnoClass_CombatDamage_MultiWeapon, 0x7) { + enum { ReturnDamage = 0x6F3ABB, GunnerDamage = 0x6F39AD, Continue = 0x6F39F4 }; + GET(TechnoClass*, pThis, ESI); - enum { ReturnDamage = 0x6F3ABB }; - const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()); + const AbstractType rtti = pThis->WhatAmI(); + + if (rtti == AbstractType::Building) + { + const auto pBuilding = static_cast(pThis); + + if (pBuilding->UpgradeLevel > 0 || pBuilding->CanOccupyFire()) + return Continue; + } + + const auto pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData; + const auto pType = pTypeExt->OwnerObject(); + + if (rtti == AbstractType::Unit + && !pType->IsGattling && pType->TurretCount > 0 + && (pType->Gunner || !pTypeExt->MultiWeapon)) + { + return GunnerDamage; + } + R->EAX(pThis->Veterancy.IsElite() ? pTypeExt->CombatDamages.Y : pTypeExt->CombatDamages.X); return ReturnDamage; } DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) { - GET(TechnoClass*, pThis, ESI); enum { ReturnRange = 0x707F08 }; + GET(TechnoClass*, pThis, ESI); + const auto pType = pThis->GetTechnoType(); const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + const bool specialWeapon = !pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner); - if (pTypeExt->MultiWeapon - && (!pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner))) + if (pThis->WhatAmI() == AbstractType::Unit + && !pType->IsGattling && pType->TurretCount > 0 + && (pType->Gunner || !specialWeapon)) + { + R->EAX(pThis->GetWeaponRange(pThis->CurrentWeaponNumber)); + return ReturnRange; + } + if (pTypeExt->MultiWeapon && specialWeapon) { const int selectCount = Math::min(pType->WeaponCount, pTypeExt->MultiWeapon_SelectCount); int range = 0; From 2765397db2ddf6f925dde2ed035fbade6a6b699f Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 14:56:23 +0800 Subject: [PATCH 09/14] Update Body.cpp --- src/Ext/TechnoType/Body.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index e12359990a..892643d2e4 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -139,7 +139,7 @@ bool TechnoTypeExt::ExtData::IsSecondary(int nWeaponIndex) int TechnoTypeExt::ExtData::SelectMultiWeapon(TechnoClass* const pThis, AbstractClass* const pTarget) { - if (!pTarget || !this->MultiWeapon.Get()) + if (!pTarget || !this->MultiWeapon) return -1; const auto pType = this->OwnerObject(); @@ -147,18 +147,18 @@ int TechnoTypeExt::ExtData::SelectMultiWeapon(TechnoClass* const pThis, Abstract if (pType->IsGattling || (pType->HasMultipleTurrets() && pType->Gunner)) return -1; - const int weaponCount = Math::min(pType->WeaponCount, this->MultiWeapon_SelectCount.Get()); + const int weaponCount = Math::min(pType->WeaponCount, this->MultiWeapon_SelectCount); + const bool noSecondary = this->NoSecondaryWeaponFallback; if (weaponCount < 2) return 0; - else if (weaponCount == 2) + else if (weaponCount == 2 && !noSecondary) return -1; std::vector secondaryCanTargets {}; secondaryCanTargets.resize(weaponCount, false); const bool isElite = pThis->Veterancy.IsElite(); - const bool noSecondary = this->NoSecondaryWeaponFallback.Get(); if (const auto pTargetTechno = abstract_cast(pTarget)) { From 65a72dd0416a370d8365d6b5fcc20cfff1b7b8a7 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 18:05:51 +0800 Subject: [PATCH 10/14] my bad --- src/Ext/Rules/Body.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index a0dbdd8bf6..96b3506a85 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -733,7 +733,7 @@ DEFINE_HOOK(0x679CAF, RulesData_LoadAfterTypeData, 0x5) for (const auto pTechnoType : TechnoTypeClass::Array) { - TechnoTypeExt::ExtMap.Find(pTechnoType)->ParseCombatDamageAndThreatType(pINI); + TechnoTypeExt::ExtMap.Find(pTechnoType)->UpdateAdditionalAttributes(); } return 0; From e296313594186190f337ae840d9c8fb3371255bd Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 18:28:19 +0800 Subject: [PATCH 11/14] Update Hooks.MultiWeapon.cpp --- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index 2aa30445cb..cdf515d843 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -170,7 +170,7 @@ DEFINE_HOOK(0x7431C9, FootClass_SelectAutoTarget_MultiWeapon, 0x7) // UnitClas } R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()), result)); - return R->Origin() == 0x743203 ? UnitReturn : InfantryReturn; + return isUnit ? UnitReturn : InfantryReturn; } DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA) From 1fba059582b1c21446417050a7b805f7ada04622 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 18:43:33 +0800 Subject: [PATCH 12/14] Update Body.cpp --- src/Ext/Rules/Body.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 96b3506a85..0f7df2be3f 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -57,6 +57,8 @@ void RulesExt::LoadAfterTypeData(RulesClass* pThis, CCINIClass* pINI) // Spawner range if (pTechnoTypeExt->Spawner_LimitRange) pTechnoTypeExt->CalculateSpawnerRange(); + + pTechnoTypeExt->UpdateAdditionalAttributes(); } } @@ -731,12 +733,6 @@ DEFINE_HOOK(0x679CAF, RulesData_LoadAfterTypeData, 0x5) RulesExt::LoadAfterTypeData(pItem, pINI); - for (const auto pTechnoType : TechnoTypeClass::Array) - { - TechnoTypeExt::ExtMap.Find(pTechnoType)->UpdateAdditionalAttributes(); - } - - return 0; } DEFINE_HOOK(0x668F6A, RulesData_InitializeAfterAllLoaded, 0x5) From 9606984ffa2c3824c14e2b04d518ba0a73fbe332 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 18:54:28 +0800 Subject: [PATCH 13/14] Update Body.cpp --- src/Ext/Rules/Body.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 0f7df2be3f..37b0d40816 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -733,6 +733,7 @@ DEFINE_HOOK(0x679CAF, RulesData_LoadAfterTypeData, 0x5) RulesExt::LoadAfterTypeData(pItem, pINI); + return 0; } DEFINE_HOOK(0x668F6A, RulesData_InitializeAfterAllLoaded, 0x5) From 986f7de7baa50de8ae88f71ea8feac664a992dbd Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Mon, 13 Oct 2025 19:49:33 +0800 Subject: [PATCH 14/14] codestyle --- src/Ext/TechnoType/Body.cpp | 22 ++++++++++---------- src/Ext/TechnoType/Hooks.MultiWeapon.cpp | 26 +++++++++++++----------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 892643d2e4..edde10ab88 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -364,22 +364,22 @@ void TechnoTypeExt::ExtData::ParseVoiceWeaponAttacks(INI_EX& exINI, const char* void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() { - int Num = 0; - int EliteNum = 0; + int num = 0; + int eliteNum = 0; this->ThreatTypes = { ThreatType::Normal,ThreatType::Normal }; this->CombatDamages = { 0,0 }; const auto pThis = this->OwnerObject(); - int Count = 2; + int count = 2; if (this->MultiWeapon && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) { - Count = pThis->WeaponCount; + count = pThis->WeaponCount; } - for (int index = 0; index < Count; index++) + for (int index = 0; index < count; index++) { const auto pWeapon = pThis->GetWeapon(index)->WeaponType; auto pEliteWeapon = pThis->GetEliteWeapon(index)->WeaponType; @@ -391,22 +391,22 @@ void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() { this->ThreatTypes.X |= pWeapon->AllowedThreats(); this->CombatDamages.X += (pWeapon->Damage + pWeapon->AmbientDamage); - Num++; + num++; } if (pEliteWeapon) { this->ThreatTypes.Y |= pEliteWeapon->AllowedThreats(); this->CombatDamages.Y += (pEliteWeapon->Damage + pEliteWeapon->AmbientDamage); - EliteNum++; + eliteNum++; } } - if (Num > 0) - this->CombatDamages.X /= Num; + if (num > 0) + this->CombatDamages.X /= num; - if (EliteNum > 0) - this->CombatDamages.Y /= EliteNum; + if (eliteNum > 0) + this->CombatDamages.Y /= eliteNum; } void TechnoTypeExt::ExtData::CalculateSpawnerRange() diff --git a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp index cdf515d843..56c0c9ad90 100644 --- a/src/Ext/TechnoType/Hooks.MultiWeapon.cpp +++ b/src/Ext/TechnoType/Hooks.MultiWeapon.cpp @@ -146,7 +146,7 @@ DEFINE_HOOK(0x7090A0, TechnoClass_VoiceAttack, 0x7) ThreatType __forceinline GetThreatType(TechnoClass* pThis, TechnoTypeExt::ExtData* pTypeExt, ThreatType result) { - ThreatType flags = pThis->Veterancy.IsElite() ? pTypeExt->ThreatTypes.Y : pTypeExt->ThreatTypes.X; + const ThreatType flags = pThis->Veterancy.IsElite() ? pTypeExt->ThreatTypes.Y : pTypeExt->ThreatTypes.X; return result | flags; } @@ -156,11 +156,11 @@ DEFINE_HOOK(0x7431C9, FootClass_SelectAutoTarget_MultiWeapon, 0x7) // UnitClas enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F, UnitGunner = 0x7431E4 }; GET(FootClass*, pThis, ESI); - GET(ThreatType, result, EDI); + GET(const ThreatType, result, EDI); const bool isUnit = R->Origin() == 0x7431C9; - const auto pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData; - const auto pType = pTypeExt->OwnerObject(); + const auto pType = pThis->GetTechnoType(); + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); if (isUnit && !pType->IsGattling && pType->TurretCount > 0 @@ -169,7 +169,7 @@ DEFINE_HOOK(0x7431C9, FootClass_SelectAutoTarget_MultiWeapon, 0x7) // UnitClas return UnitGunner; } - R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()), result)); + R->EDI(GetThreatType(pThis, pTypeExt, result)); return isUnit ? UnitReturn : InfantryReturn; } @@ -178,7 +178,7 @@ DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA) enum { ReturnThreatType = 0x445F58, Continue = 0x445F0E }; GET(BuildingClass*, pThis, ESI); - GET_STACK(ThreatType, result, STACK_OFFSET(0x8, 0x4)); + GET_STACK(const ThreatType, result, STACK_OFFSET(0x8, 0x4)); if (pThis->UpgradeLevel > 0 || pThis->CanOccupyFire()) { @@ -206,8 +206,8 @@ DEFINE_HOOK(0x6F398E, TechnoClass_CombatDamage_MultiWeapon, 0x7) return Continue; } - const auto pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData; - const auto pType = pTypeExt->OwnerObject(); + const auto pType = pThis->GetTechnoType(); + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); if (rtti == AbstractType::Unit && !pType->IsGattling && pType->TurretCount > 0 @@ -227,16 +227,18 @@ DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6) GET(TechnoClass*, pThis, ESI); const auto pType = pThis->GetTechnoType(); - const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); const bool specialWeapon = !pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner); - if (pThis->WhatAmI() == AbstractType::Unit - && !pType->IsGattling && pType->TurretCount > 0 - && (pType->Gunner || !specialWeapon)) + if (!pType->IsGattling && pType->TurretCount > 0 + && (pType->Gunner || !specialWeapon) + && pThis->WhatAmI() == AbstractType::Unit) { R->EAX(pThis->GetWeaponRange(pThis->CurrentWeaponNumber)); return ReturnRange; } + + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + if (pTypeExt->MultiWeapon && specialWeapon) { const int selectCount = Math::min(pType->WeaponCount, pTypeExt->MultiWeapon_SelectCount);