From a8ab7a1beccf8ee1aca089e3030962f3af80dc47 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sat, 11 Oct 2025 17:29:10 +0800 Subject: [PATCH 1/9] update --- src/Ext/Techno/Hooks.cpp | 66 +++++++++++++++++++++++++++++++++++++ src/Ext/TechnoType/Body.cpp | 45 +++++++++++++++++++++++++ src/Ext/TechnoType/Body.h | 6 ++++ src/Ext/WeaponType/Body.cpp | 4 +++ src/Ext/WeaponType/Body.h | 4 +++ 5 files changed, 125 insertions(+) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index fb5669c234..409584f44b 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1459,3 +1459,69 @@ DEFINE_HOOK(0x6F7E1E, TechnoClass_CanAutoTargetObject_AU, 0x6) } #pragma endregion + +#pragma region AttackFriendliesExtension + +DEFINE_JUMP(LJMP, 0x700387, 0x7003BD) + +DEFINE_HOOK(0x700358, TechnoClass_MouseOverObject_AttackFriendlies, 0x6) +{ + enum { CanAttack = 0x700381, Continue = 0x700385 }; + + GET(TechnoClass*, pThis, ESI); + GET(WeaponTypeClass*, pWeapon, EBP); + GET(ObjectClass*, pObject, EDI); + GET_STACK(const bool, IvanBomb, STACK_OFFSET(0x1C, -0xC)); + + const auto pType = pThis->GetTechnoType(); + const auto pWeaponTypeExt = WeaponTypeExt::ExtMap.Find(pWeapon); + + if (pWeaponTypeExt->AttackFriendlies.Get(pType->AttackFriendlies) || + (pWeaponTypeExt->AttackCursorOnFriendlies.Get(pType->AttackCursorOnFriendlies) && !IvanBomb)) + { + return CanAttack; + } + + return Continue; +} + +DEFINE_HOOK_AGAIN(0x6F9CE9, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::SelectAutoTarget +DEFINE_HOOK_AGAIN(0x6F9BAE, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +DEFINE_HOOK_AGAIN(0x6F9204, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +DEFINE_HOOK_AGAIN(0x6F8BBC, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::TryAutoTargetObject +DEFINE_HOOK(0x6F8A92, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +{ + GET(TechnoClass*, pThis, ESI); + + R->CL(TechnoExt::ExtMap.Find(pThis)->TypeExtData->AttackFriendlies); + return R->Origin() + 0x10; +} + +namespace CanAutoTargetTemp +{ + TechnoTypeExt::ExtData* TypeExtData; + WeaponTypeExt::ExtData* WeaponExt; +} + +DEFINE_HOOK(0x6F7E30, TechnoClass_CanAutoTarget_SetContent, 0x6) +{ + GET(TechnoClass*, pThis, EDI); + GET(WeaponTypeClass*, pWeapon, EBP); + + CanAutoTargetTemp::TypeExtData = TechnoExt::ExtMap.Find(pThis)->TypeExtData; + CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon); + + return 0; +} + +DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) +{ + enum { SkipGameCode = 0x6F7F04 }; + + R->CL(CanAutoTargetTemp::WeaponExt->AttackFriendlies.Get( + CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies)); + + return SkipGameCode; +} + +#pragma endregion diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index d8bf5ebdb1..ef0576edd0 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -259,6 +260,50 @@ int TechnoTypeExt::ExtData::SelectMultiWeapon(TechnoClass* const pThis, Abstract return 0; } +void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() +{ + const auto pThis = this->OwnerObject(); + this->AttackFriendlies = pThis->AttackFriendlies; + + if (!AttackFriendlies) + { + int Count = 2; + + if (this->MultiWeapon + && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) + { + Count = 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 (WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) + { + this->AttackFriendlies = true; + return; + } + } + + if (pEliteWeapon) + { + if (WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) + { + this->AttackFriendlies = true; + return; + } + } + } + } +} + // Ares 0.A source const char* TechnoTypeExt::ExtData::GetSelectionGroupID() const { diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 277021f05d..58795f5fbc 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -431,6 +431,8 @@ class TechnoTypeExt Nullable TurretResponse; + bool AttackFriendlies; + ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) , HealthBar_Hide { false } , HealthBar_HidePips { false } @@ -812,6 +814,8 @@ class TechnoTypeExt , InfantryAutoDeploy {} , TurretResponse {} + + , AttackFriendlies { false } { } virtual ~ExtData() = default; @@ -832,6 +836,8 @@ class TechnoTypeExt int SelectForceWeapon(TechnoClass* pThis, AbstractClass* pTarget); int SelectMultiWeapon(TechnoClass* const pThis, AbstractClass* const pTarget); + void UpdateAdditionalAttributes(); + // Ares 0.A const char* GetSelectionGroupID() const; diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index be24ebc24f..0a4a48689c 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -153,6 +153,8 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->DelayedFire_OnlyOnInitialBurst.Read(exINI, pSection, "DelayedFire.OnlyOnInitialBurst"); this->DelayedFire_AnimOffset.Read(exINI, pSection, "DelayedFire.AnimOffset"); this->DelayedFire_AnimOnTurret.Read(exINI, pSection, "DelayedFire.AnimOnTurret"); + this->AttackFriendlies.Read(exINI, pSection, "AttackFriendlies"); + this->AttackCursorOnFriendlies.Read(exINI, pSection, "AttackCursorOnFriendlies"); // handle SkipWeaponPicking if (this->CanTarget != AffectedTarget::All || this->CanTargetHouses != AffectedHouse::All @@ -237,6 +239,8 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm) .Process(this->DelayedFire_OnlyOnInitialBurst) .Process(this->DelayedFire_AnimOffset) .Process(this->DelayedFire_AnimOnTurret) + .Process(this->AttackFriendlies) + .Process(this->AttackCursorOnFriendlies) ; }; diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index 03d6fe37e0..cc537295e3 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -91,6 +91,8 @@ class WeaponTypeExt Valueable DelayedFire_OnlyOnInitialBurst; Nullable DelayedFire_AnimOffset; Valueable DelayedFire_AnimOnTurret; + Nullable AttackFriendlies; + Nullable AttackCursorOnFriendlies; bool SkipWeaponPicking; @@ -164,6 +166,8 @@ class WeaponTypeExt , DelayedFire_OnlyOnInitialBurst { false } , DelayedFire_AnimOffset {} , DelayedFire_AnimOnTurret { true } + , AttackFriendlies {} + , AttackCursorOnFriendlies {} { } int GetBurstDelay(int burstIndex) const; From dfe71d84db9bfb7a6405fa0efb280898f9344851 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sat, 11 Oct 2025 17:30:17 +0800 Subject: [PATCH 2/9] Update Hooks.cpp --- src/Ext/Techno/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 409584f44b..2ee8518a94 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1460,7 +1460,7 @@ DEFINE_HOOK(0x6F7E1E, TechnoClass_CanAutoTargetObject_AU, 0x6) #pragma endregion -#pragma region AttackFriendliesExtension +#pragma region AutoTargetExtension DEFINE_JUMP(LJMP, 0x700387, 0x7003BD) From 1e36427638d7615fd524d9e7509f8d8c6aaa6eef Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 15:05:37 +0800 Subject: [PATCH 3/9] update doc --- CREDITS.md | 1 + docs/New-or-Enhanced-Logics.md | 11 +++++++++++ docs/Whats-New.md | 1 + 3 files changed, 13 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index a89619a151..6947dc383c 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -394,6 +394,7 @@ This page lists all the individual contributions to the project by their author. - Health bar permanently displayed - Unlimbo Detonate warhead - Fast access structure + - Weapons now support `AttackFriendlies` and `AttackCursorOnFriendlies` - **NetsuNegi**: - Forbidding parallel AI queues by type - Jumpjet crash speed fix when crashing onto building diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index f634bc3d76..b58d893641 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2561,6 +2561,17 @@ In `rulesmd.ini`: AreaFire.Target=base ; AreaFire Target Enumeration (base|self|random) ``` +### Can attack allies + +- Weapons now support `AttackFriendlies` and `AttackCursorOnFriendlies`, They override the firer's `AttackFriendlies` and `AttackCursorOnFriendlies`. + +In `rulesmd.ini`: +```ini +[SOMEWEAPON] ; WeaponType +AttackFriendlies= ; boolean +AttackCursorOnFriendlies= ; boolean +``` + ### Burst delay customizations - `Burst.Delays` allows specifying weapon-specific burst shot delays. Takes precedence over the old `BurstDelayX` logic available on VehicleTypes, functions with Infantry & BuildingType weapons (AircraftTypes are not supported due to their weapon firing system being completely different) and allows every shot of `Burst` to have a separate delay instead of only first four shots. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 104bb1ede6..c7352e9efa 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -452,6 +452,7 @@ New: - [Unlimbo Detonate warhead](New-or-Enhanced-Logics.md#unlimbo-detonate-warhead) (by FlyStar) - Attack and damage technos underground (by TaranDahl) - Fast access structure (by FlyStar) +- Weapons now support `AttackFriendlies` and `AttackCursorOnFriendlies` (by FlyStar) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) From 35520fc90407e740cfee4bbf0102698660a62d0a Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 12 Oct 2025 18:42:58 +0800 Subject: [PATCH 4/9] Add missing information --- src/Ext/Rules/Body.cpp | 2 ++ src/Ext/Techno/Hooks.cpp | 1 - src/Ext/TechnoType/Body.cpp | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 048086a786..37b0d40816 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(); } } diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 2ee8518a94..b535ebd831 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1470,7 +1470,6 @@ DEFINE_HOOK(0x700358, TechnoClass_MouseOverObject_AttackFriendlies, 0x6) GET(TechnoClass*, pThis, ESI); GET(WeaponTypeClass*, pWeapon, EBP); - GET(ObjectClass*, pObject, EDI); GET_STACK(const bool, IvanBomb, STACK_OFFSET(0x1C, -0xC)); const auto pType = pThis->GetTechnoType(); diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index ef0576edd0..6c6f7c18cc 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1654,6 +1654,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->InfantryAutoDeploy) .Process(this->TurretResponse) + + .Process(this->AttackFriendlies) ; } void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) From 4beb30c202d656af6a245d15ba9cb7747f175998 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sat, 1 Nov 2025 17:13:08 +0800 Subject: [PATCH 5/9] resolve duplicate code --- src/Ext/Techno/Hooks.cpp | 130 +++++++++++++++++++----------------- src/Ext/TechnoType/Body.cpp | 93 ++++++++++---------------- src/Ext/TechnoType/Body.h | 4 +- 3 files changed, 105 insertions(+), 122 deletions(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 5bb1c51df8..ff78b55fb4 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1467,69 +1467,6 @@ DEFINE_HOOK(0x6F7E1E, TechnoClass_CanAutoTargetObject_AU, 0x6) #pragma endregion -#pragma region AutoTargetExtension - -DEFINE_JUMP(LJMP, 0x700387, 0x7003BD) - -DEFINE_HOOK(0x700358, TechnoClass_MouseOverObject_AttackFriendlies, 0x6) -{ - enum { CanAttack = 0x700381, Continue = 0x700385 }; - - GET(TechnoClass*, pThis, ESI); - GET(WeaponTypeClass*, pWeapon, EBP); - GET_STACK(const bool, IvanBomb, STACK_OFFSET(0x1C, -0xC)); - - const auto pType = pThis->GetTechnoType(); - const auto pWeaponTypeExt = WeaponTypeExt::ExtMap.Find(pWeapon); - - if (pWeaponTypeExt->AttackFriendlies.Get(pType->AttackFriendlies) || - (pWeaponTypeExt->AttackCursorOnFriendlies.Get(pType->AttackCursorOnFriendlies) && !IvanBomb)) - { - return CanAttack; - } - - return Continue; -} - -DEFINE_HOOK_AGAIN(0x6F9CE9, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::SelectAutoTarget -DEFINE_HOOK_AGAIN(0x6F9BAE, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) -DEFINE_HOOK_AGAIN(0x6F9204, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) -DEFINE_HOOK_AGAIN(0x6F8BBC, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::TryAutoTargetObject -DEFINE_HOOK(0x6F8A92, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) -{ - GET(TechnoClass*, pThis, ESI); - - R->CL(TechnoExt::ExtMap.Find(pThis)->TypeExtData->AttackFriendlies); - return R->Origin() + 0x10; -} - -namespace CanAutoTargetTemp -{ - TechnoTypeExt::ExtData* TypeExtData; - WeaponTypeExt::ExtData* WeaponExt; -} - -DEFINE_HOOK(0x6F7E30, TechnoClass_CanAutoTarget_SetContent, 0x6) -{ - GET(TechnoClass*, pThis, EDI); - GET(WeaponTypeClass*, pWeapon, EBP); - - CanAutoTargetTemp::TypeExtData = TechnoExt::ExtMap.Find(pThis)->TypeExtData; - CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon); - - return 0; -} - -DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) -{ - enum { SkipGameCode = 0x6F7F04 }; - - R->CL(CanAutoTargetTemp::WeaponExt->AttackFriendlies.Get( - CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies)); - - return SkipGameCode; -} - #pragma region FallingDown DEFINE_HOOK(0x5F4160, ObjectClass_DropAsBomb_Track, 0x6) @@ -1615,3 +1552,70 @@ DEFINE_HOOK(0x6F9398, TechnoClass_SelectAutoTarget_Scan_FallingDown, 0x9) } #pragma endregion + +#pragma region AutoTargetExtension + +DEFINE_JUMP(LJMP, 0x700387, 0x7003BD) + +DEFINE_HOOK(0x700358, TechnoClass_MouseOverObject_AttackFriendlies, 0x6) +{ + enum { CanAttack = 0x700381, Continue = 0x700385 }; + + GET(TechnoClass*, pThis, ESI); + GET(WeaponTypeClass*, pWeapon, EBP); + GET_STACK(const bool, IvanBomb, STACK_OFFSET(0x1C, -0xC)); + + const auto pType = pThis->GetTechnoType(); + const auto pWeaponTypeExt = WeaponTypeExt::ExtMap.Find(pWeapon); + + if (pWeaponTypeExt->AttackFriendlies.Get(pType->AttackFriendlies) || + (pWeaponTypeExt->AttackCursorOnFriendlies.Get(pType->AttackCursorOnFriendlies) && !IvanBomb)) + { + return CanAttack; + } + + return Continue; +} + +DEFINE_HOOK_AGAIN(0x6F9CE9, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::SelectAutoTarget +DEFINE_HOOK_AGAIN(0x6F9BAE, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +DEFINE_HOOK_AGAIN(0x6F9204, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +DEFINE_HOOK_AGAIN(0x6F8BBC, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) // TechnoClass::TryAutoTargetObject +DEFINE_HOOK(0x6F8A92, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) +{ + GET(TechnoClass*, pThis, ESI); + + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()); + R->CL(pThis->Veterancy.IsElite() ? pTypeExt->AttackFriendlies.Y : pTypeExt->AttackFriendlies.X); + + return R->Origin() + 0x10; +} + +namespace CanAutoTargetTemp +{ + TechnoTypeExt::ExtData* TypeExtData; + WeaponTypeExt::ExtData* WeaponExt; +} + +DEFINE_HOOK(0x6F7E30, TechnoClass_CanAutoTarget_SetContent, 0x6) +{ + GET(TechnoClass*, pThis, EDI); + GET(WeaponTypeClass*, pWeapon, EBP); + + CanAutoTargetTemp::TypeExtData = TechnoExt::ExtMap.Find(pThis)->TypeExtData; + CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon); + + return 0; +} + +DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) +{ + enum { SkipGameCode = 0x6F7F04 }; + + R->CL(CanAutoTargetTemp::WeaponExt->AttackFriendlies.Get( + CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies)); + + return SkipGameCode; +} + +#pragma endregion diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index bc2fdcfde6..a45c910041 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -260,50 +260,6 @@ int TechnoTypeExt::ExtData::SelectMultiWeapon(TechnoClass* const pThis, Abstract return 0; } -void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() -{ - const auto pThis = this->OwnerObject(); - this->AttackFriendlies = pThis->AttackFriendlies; - - if (!AttackFriendlies) - { - int Count = 2; - - if (this->MultiWeapon - && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) - { - Count = 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 (WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) - { - this->AttackFriendlies = true; - return; - } - } - - if (pEliteWeapon) - { - if (WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) - { - this->AttackFriendlies = true; - return; - } - } - } - } -} - // Ares 0.A source const char* TechnoTypeExt::ExtData::GetSelectionGroupID() const { @@ -418,37 +374,60 @@ void TechnoTypeExt::ExtData::UpdateAdditionalAttributes() const auto pThis = this->OwnerObject(); int count = 2; + const bool attackFriendlies = pThis->AttackFriendlies; + this->AttackFriendlies = { attackFriendlies ,attackFriendlies }; + if (this->MultiWeapon && (!pThis->IsGattling && (!pThis->HasMultipleTurrets() || !pThis->Gunner))) { count = pThis->WeaponCount; } - for (int index = 0; index < count; index++) + auto WeaponCheck = [&](WeaponTypeClass* const pWeapon, const bool isElite) { - const auto pWeapon = pThis->GetWeapon(index)->WeaponType; - auto pEliteWeapon = pThis->GetEliteWeapon(index)->WeaponType; + if (!pWeapon) + return; - if (!pEliteWeapon) - pEliteWeapon = pWeapon; + if (isElite) + { + if (pWeapon->Projectile) + this->ThreatTypes.Y |= pWeapon->AllowedThreats(); - if (pWeapon) + this->CombatDamages.Y += (pWeapon->Damage + pWeapon->AmbientDamage); + eliteNum++; + + if (!this->AttackFriendlies.Y + && WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) + { + this->AttackFriendlies.Y = true; + } + } + else { if (pWeapon->Projectile) this->ThreatTypes.X |= pWeapon->AllowedThreats(); this->CombatDamages.X += (pWeapon->Damage + pWeapon->AmbientDamage); num++; + + if (!this->AttackFriendlies.X + && WeaponTypeExt::ExtMap.Find(pWeapon)->AttackFriendlies.Get(false)) + { + this->AttackFriendlies.X = true; + } } + }; - if (pEliteWeapon) - { - if (pEliteWeapon->Projectile) - this->ThreatTypes.Y |= pEliteWeapon->AllowedThreats(); + for (int index = 0; index < count; index++) + { + const auto pWeapon = pThis->GetWeapon(index)->WeaponType; + auto pEliteWeapon = pThis->GetEliteWeapon(index)->WeaponType; - this->CombatDamages.Y += (pEliteWeapon->Damage + pEliteWeapon->AmbientDamage); - eliteNum++; - } + if (!pEliteWeapon) + pEliteWeapon = pWeapon; + + WeaponCheck(pWeapon, false); + WeaponCheck(pEliteWeapon, true); } if (num > 0) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index ad9a2e6fc7..c0434219ed 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -434,7 +434,7 @@ class TechnoTypeExt Nullable TurretResponse; - bool AttackFriendlies; + Vector2D AttackFriendlies; ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) , HealthBar_Hide { false } @@ -821,7 +821,7 @@ class TechnoTypeExt , TurretResponse {} - , AttackFriendlies { false } + , AttackFriendlies { false,false } { } virtual ~ExtData() = default; From 5c0c45198860694fc4f58be806403c11b0ee268f Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sat, 1 Nov 2025 17:16:17 +0800 Subject: [PATCH 6/9] Update Hooks.cpp --- src/Ext/Techno/Hooks.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index ff78b55fb4..58f255fa21 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1568,8 +1568,8 @@ DEFINE_HOOK(0x700358, TechnoClass_MouseOverObject_AttackFriendlies, 0x6) const auto pType = pThis->GetTechnoType(); const auto pWeaponTypeExt = WeaponTypeExt::ExtMap.Find(pWeapon); - if (pWeaponTypeExt->AttackFriendlies.Get(pType->AttackFriendlies) || - (pWeaponTypeExt->AttackCursorOnFriendlies.Get(pType->AttackCursorOnFriendlies) && !IvanBomb)) + if (pWeaponTypeExt->AttackFriendlies.Get(pType->AttackFriendlies) + || (pWeaponTypeExt->AttackCursorOnFriendlies.Get(pType->AttackCursorOnFriendlies) && !IvanBomb)) { return CanAttack; } @@ -1586,8 +1586,8 @@ DEFINE_HOOK(0x6F8A92, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) GET(TechnoClass*, pThis, ESI); const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()); - R->CL(pThis->Veterancy.IsElite() ? pTypeExt->AttackFriendlies.Y : pTypeExt->AttackFriendlies.X); + R->CL(pThis->Veterancy.IsElite() ? pTypeExt->AttackFriendlies.Y : pTypeExt->AttackFriendlies.X); return R->Origin() + 0x10; } @@ -1612,9 +1612,11 @@ DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) { enum { SkipGameCode = 0x6F7F04 }; - R->CL(CanAutoTargetTemp::WeaponExt->AttackFriendlies.Get( - CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies)); + const bool attackFriendlies = CanAutoTargetTemp::WeaponExt->AttackFriendlies.isset() + ? CanAutoTargetTemp::WeaponExt->AttackFriendlies + : CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies; + R->CL(attackFriendlies); return SkipGameCode; } From c692d830244456a9b032ce6f5aafccbf3c84a6d9 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:50:22 +0800 Subject: [PATCH 7/9] Update Hooks.cpp --- src/Ext/Techno/Hooks.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 58f255fa21..a1592cec70 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1593,17 +1593,14 @@ DEFINE_HOOK(0x6F8A92, TechnoClass_CheckAutoTarget_AttackFriendlies, 0xA) namespace CanAutoTargetTemp { - TechnoTypeExt::ExtData* TypeExtData; WeaponTypeExt::ExtData* WeaponExt; } DEFINE_HOOK(0x6F7E30, TechnoClass_CanAutoTarget_SetContent, 0x6) { - GET(TechnoClass*, pThis, EDI); GET(WeaponTypeClass*, pWeapon, EBP); - CanAutoTargetTemp::TypeExtData = TechnoExt::ExtMap.Find(pThis)->TypeExtData; - CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon); + CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.TryFind(pWeapon); return 0; } @@ -1612,9 +1609,15 @@ DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) { enum { SkipGameCode = 0x6F7F04 }; - const bool attackFriendlies = CanAutoTargetTemp::WeaponExt->AttackFriendlies.isset() - ? CanAutoTargetTemp::WeaponExt->AttackFriendlies - : CanAutoTargetTemp::TypeExtData->OwnerObject()->AttackFriendlies; + GET(TechnoClass*, pThis, ESI); + + bool attackFriendlies = pThis->GetTechnoType()->AttackFriendlies; + + if (const auto pWeaponExt = CanAutoTargetTemp::WeaponExt) + { + attackFriendlies = pWeaponExt->AttackFriendlies.isset() + ? pWeaponExt->AttackFriendlies : attackFriendlies; + } R->CL(attackFriendlies); return SkipGameCode; From 2ea0cfc21ed4ea64e0bee18f2c63674bbd80f4a8 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:50:46 +0800 Subject: [PATCH 8/9] Update Hooks.cpp --- src/Ext/Techno/Hooks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index a1592cec70..5100819ce0 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1609,7 +1609,7 @@ DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) { enum { SkipGameCode = 0x6F7F04 }; - GET(TechnoClass*, pThis, ESI); + GET(TechnoClass*, pThis, EDI); bool attackFriendlies = pThis->GetTechnoType()->AttackFriendlies; From d01470c94c391483e0f54084e20a2330524acdc6 Mon Sep 17 00:00:00 2001 From: Fly-Star <100747645+a851903106@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:56:23 +0800 Subject: [PATCH 9/9] Update Hooks.cpp --- src/Ext/Techno/Hooks.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 5100819ce0..5d22ece0ce 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -1614,10 +1614,7 @@ DEFINE_HOOK(0x6F7EF4, TechnoClass_CanAutoTarget_AttackFriendlies, 0xA) bool attackFriendlies = pThis->GetTechnoType()->AttackFriendlies; if (const auto pWeaponExt = CanAutoTargetTemp::WeaponExt) - { - attackFriendlies = pWeaponExt->AttackFriendlies.isset() - ? pWeaponExt->AttackFriendlies : attackFriendlies; - } + attackFriendlies = pWeaponExt->AttackFriendlies.Get(attackFriendlies); R->CL(attackFriendlies); return SkipGameCode;