From a5fbfe7c31999359c17e7444184c3072142297f2 Mon Sep 17 00:00:00 2001 From: Starkku Date: Wed, 6 Nov 2024 22:39:28 +0200 Subject: [PATCH] Allow restricting whether AE ArmorMultiplier is applied to damage dealt by specific Warhead(s) --- docs/New-or-Enhanced-Logics.md | 5 ++- src/Ext/Techno/Body.Update.cpp | 3 ++ src/Ext/Techno/Hooks.cpp | 48 ++++++++++++++++++++++---- src/New/Entity/AttachEffectClass.h | 2 ++ src/New/Type/AttachEffectTypeClass.cpp | 4 +++ src/New/Type/AttachEffectTypeClass.h | 4 +++ 6 files changed, 59 insertions(+), 7 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 54b7b58d3c..2e8c80f3fd 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -34,7 +34,8 @@ This page describes all the engine features that are either new and introduced b - `Tint.Color` & `Tint.Intensity` can be used to set a color tint effect and additive lighting increase/decrease on the object the effect is attached to, respectively. - `Tint.VisibleToHouses` can be used to control which houses can see the tint effect. - `FirepowerMultiplier`, `ArmorMultiplier`, `SpeedMultiplier` and `ROFMultiplier` can be used to modify the object's firepower, armor strength, movement speed and weapon reload rate, respectively. - - If `ROFMultiplier.ApplyOnCurrentTimer` is set to true, `ROFMultiplier` is applied on currently running reload timer (if any) when the effect is first applied. + - `ArmorMultiplier.AllowWarheads` and `ArmorMultiplier.DisallowWarheads` can be used to restrict which Warheads the armor multiplier is applied to when dealing damage. + - If `ROFMultiplier.ApplyOnCurrentTimer` is set to true, `ROFMultiplier` is applied on currently running reload timer (if any) when the effect is first applied. - If `Cloakable` is set to true, the object the effect is attached to is granted ability to cloak itself for duration of the effect. - `ForceDecloak`, if set to true, will uncloak and make the object the effect is attached to unable to cloak itself for duration of the effect. - `WeaponRange.Multiplier` and `WeaponRange.ExtraRange` can be used to multiply the weapon firing range of the object the effect is attached to, or give it an increase / decrease (measured in cells), respectively. `ExtraRange` is cumulatively applied from all attached effects after all `Multiplier` values have been applied. @@ -103,6 +104,8 @@ Tint.Intensity= ; floating point value Tint.VisibleToHouses=all ; list of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) FirepowerMultiplier=1.0 ; floating point value ArmorMultiplier=1.0 ; floating point value +ArmorMultiplier.AllowWarheads= ; list of WarheadTypes +ArmorMultiplier.DisallowWarheads= ; list of WarheadTypes SpeedMultiplier=1.0 ; floating point value ROFMultiplier=1.0 ; floating point value ROFMultiplier.ApplyOnCurrentTimer=true ; boolean diff --git a/src/Ext/Techno/Body.Update.cpp b/src/Ext/Techno/Body.Update.cpp index 22425852fa..453ee4e215 100644 --- a/src/Ext/Techno/Body.Update.cpp +++ b/src/Ext/Techno/Body.Update.cpp @@ -983,6 +983,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers() bool hasTint = false; bool reflectsDamage = false; bool hasOnFireDiscardables = false; + bool hasRestrictedArmorMultipliers = false; for (const auto& attachEffect : this->AttachedEffects) { @@ -1001,6 +1002,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers() hasTint |= type->HasTint(); reflectsDamage |= type->ReflectDamage; hasOnFireDiscardables |= (type->DiscardOn & DiscardCondition::Firing) != DiscardCondition::None; + hasRestrictedArmorMultipliers |= (type->ArmorMultiplier != 1.0 && (type->ArmorMultiplier_AllowWarheads.size() > 0 || type->ArmorMultiplier_DisallowWarheads.size() > 0)); } this->AE.FirepowerMultiplier = firepower; @@ -1014,6 +1016,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers() this->AE.HasTint = hasTint; this->AE.ReflectDamage = reflectsDamage; this->AE.HasOnFireDiscardables = hasOnFireDiscardables; + this->AE.HasRestrictedArmorMultipliers = hasRestrictedArmorMultipliers; if (forceDecloak && pThis->CloakState == CloakState::Cloaked) pThis->Uncloak(true); diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 96bd80ed85..88e9183347 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -306,15 +306,51 @@ DEFINE_HOOK(0x4DB218, FootClass_GetMovementSpeed_SpeedMultiplier, 0x6) return 0; } -DEFINE_HOOK_AGAIN(0x6FDC87, TechnoClass_ArmorMultiplier, 0x6) // TechnoClass_AdjustDamage -DEFINE_HOOK(0x701966, TechnoClass_ArmorMultiplier, 0x6) // TechnoClass_ReceiveDamage +static int CalculateArmorMultipliers(TechnoClass* pThis, int damage, WarheadTypeClass* pWarhead) { - TechnoClass* pThis = R->Origin() == 0x701966 ? R->ESI() : R->EDI(); + auto const pExt = TechnoExt::ExtMap.Find(pThis); + double mult = pExt->AE.ArmorMultiplier; + + if (pExt->AE.HasRestrictedArmorMultipliers) + { + for (auto const& attachEffect : pExt->AttachedEffects) + { + if (!attachEffect->IsActive()) + continue; + + auto const type = attachEffect->GetType(); + + if (type->ArmorMultiplier_DisallowWarheads.Contains(pWarhead)) + continue; + + if (type->ArmorMultiplier_AllowWarheads.size() > 0 && !type->ArmorMultiplier_AllowWarheads.Contains(pWarhead)) + continue; + + mult *= type->ArmorMultiplier; + } + } + + return static_cast(damage / mult); +} + +DEFINE_HOOK(0x6FDC87, TechnoClass_AdjustDamage_ArmorMultiplier, 0x6) +{ + GET(TechnoClass*, pTarget, EDI); GET(int, damage, EAX); + GET_STACK(WeaponTypeClass*, pWeapon, STACK_OFFSET(0x18, 0x8)); - auto const pExt = TechnoExt::ExtMap.Find(pThis); - damage = static_cast(damage / pExt->AE.ArmorMultiplier); - R->EAX(damage); + R->EAX(CalculateArmorMultipliers(pTarget, damage, pWeapon->Warhead)); + + return 0; +} + +DEFINE_HOOK(0x701966, TechnoClass_ReceiveDamage_ArmorMultiplier, 0x6) +{ + GET(TechnoClass*, pThis, ESI); + GET(int, damage, EAX); + GET_STACK(WarheadTypeClass*, pWarhead, STACK_OFFSET(0xC4, 0xC)); + + R->EAX(CalculateArmorMultipliers(pThis, damage, pWarhead)); return 0; } diff --git a/src/New/Entity/AttachEffectClass.h b/src/New/Entity/AttachEffectClass.h index 08b103a1c8..7aaac410f2 100644 --- a/src/New/Entity/AttachEffectClass.h +++ b/src/New/Entity/AttachEffectClass.h @@ -94,6 +94,7 @@ struct AttachEffectTechnoProperties bool HasTint; bool ReflectDamage; bool HasOnFireDiscardables; + bool HasRestrictedArmorMultipliers; AttachEffectTechnoProperties() : FirepowerMultiplier { 1.0 } @@ -107,5 +108,6 @@ struct AttachEffectTechnoProperties , HasTint { false } , ReflectDamage { false } , HasOnFireDiscardables { false } + , HasRestrictedArmorMultipliers { false } { } }; diff --git a/src/New/Type/AttachEffectTypeClass.cpp b/src/New/Type/AttachEffectTypeClass.cpp index 8942355920..5a8b96d0f1 100644 --- a/src/New/Type/AttachEffectTypeClass.cpp +++ b/src/New/Type/AttachEffectTypeClass.cpp @@ -123,6 +123,8 @@ void AttachEffectTypeClass::LoadFromINI(CCINIClass* pINI) this->FirepowerMultiplier.Read(exINI, pSection, "FirepowerMultiplier"); this->ArmorMultiplier.Read(exINI, pSection, "ArmorMultiplier"); + this->ArmorMultiplier_AllowWarheads.Read(exINI, pSection, "ArmorMultiplier.AllowWarheads"); + this->ArmorMultiplier_DisallowWarheads.Read(exINI, pSection, "ArmorMultiplier.DisallowWarheads"); this->SpeedMultiplier.Read(exINI, pSection, "SpeedMultiplier"); this->ROFMultiplier.Read(exINI, pSection, "ROFMultiplier"); this->ROFMultiplier_ApplyOnCurrentTimer.Read(exINI, pSection, "ROFMultiplier.ApplyOnCurrentTimer"); @@ -184,6 +186,8 @@ void AttachEffectTypeClass::Serialize(T& Stm) .Process(this->Tint_VisibleToHouses) .Process(this->FirepowerMultiplier) .Process(this->ArmorMultiplier) + .Process(this->ArmorMultiplier_AllowWarheads) + .Process(this->ArmorMultiplier_DisallowWarheads) .Process(this->SpeedMultiplier) .Process(this->ROFMultiplier) .Process(this->ROFMultiplier_ApplyOnCurrentTimer) diff --git a/src/New/Type/AttachEffectTypeClass.h b/src/New/Type/AttachEffectTypeClass.h index ee1d2f709c..a9cddaf3de 100644 --- a/src/New/Type/AttachEffectTypeClass.h +++ b/src/New/Type/AttachEffectTypeClass.h @@ -64,6 +64,8 @@ class AttachEffectTypeClass final : public Enumerable Valueable Tint_VisibleToHouses; Valueable FirepowerMultiplier; Valueable ArmorMultiplier; + ValueableVector ArmorMultiplier_AllowWarheads; + ValueableVector ArmorMultiplier_DisallowWarheads; Valueable SpeedMultiplier; Valueable ROFMultiplier; Valueable ROFMultiplier_ApplyOnCurrentTimer; @@ -113,6 +115,8 @@ class AttachEffectTypeClass final : public Enumerable , Tint_VisibleToHouses { AffectedHouse::All } , FirepowerMultiplier { 1.0 } , ArmorMultiplier { 1.0 } + , ArmorMultiplier_AllowWarheads {} + , ArmorMultiplier_DisallowWarheads {} , SpeedMultiplier { 1.0 } , ROFMultiplier { 1.0 } , ROFMultiplier_ApplyOnCurrentTimer { true }