diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 75fc0ddacf..a0d4f2294b 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -691,12 +691,13 @@ OnlyUseLandSequences=false ; boolean ![image](_static/images/projectile-interception-01.gif) *Interception logic used in [Tiberium Crisis](https://www.moddb.com/mods/tiberium-crisis) mod* -- Projectiles can now be made interceptable by certain TechnoTypes by setting `Interceptable=true` on them. The TechnoType scans for interceptable projectiles within a range if it has no other target and will use one of its weapons to shoot at them. Projectiles can define `Armor` and `Strength`. Weapons that cannot target the projectile's armor type will not attempt to intercept it. On interception, if the projectile has `Armor` set, an amount equaling to the intercepting weapon's `Damage` adjusted by Warhead `Verses` and the TechnoType's firepower multipliers is deducted from the projectile's current strength. Regardless of if the current projectile strength was reduced or not, if it sits at 0 or below after interception, the projectile is detonated. +- Projectiles can now be made interceptable by certain TechnoTypes by setting `Interceptable=true` on them. The TechnoType scans for interceptable projectiles within a range if it has no other target and will use one of its weapons to shoot at them. Projectiles can define `Armor` and `Strength`. Weapons that cannot target the projectile's armor type will not attempt to intercept it. On interception, if the projectile has `Armor` set, an amount equaling to the intercepting weapon's `Damage` adjusted by Warhead `Verses` is deducted from the projectile's current strength. Regardless of if the current projectile strength was reduced or not, if it sits at 0 or below after interception, the projectile is detonated. - `Interceptor.Weapon` determines the weapon (0 = `Primary`, 1 = `Secondary`) to be used for intercepting projectiles. - The interceptor weapon may need `AG` and/or `AA` set to true on its projectile to be able to target projectiles depending on their elevation from ground. If you don't set those then the weapon won't be able to target low-flying or high-flying projectiles respectively. - `Interceptor.CanTargetHouses` controls which houses the projectiles (or rather their firers) can belong to be eligible for interception. - `Interceptor.GuardRange` (and `Interceptor.(Rookie|Veteran|EliteGuardRange`) is maximum range of the unit to intercept projectile. The unit weapon range will limit the unit interception range though. - `Interceptor.MinimumGuardRange` (and `Interceptor.(Rookie|Veteran|EliteMinimumGuardRange`) is the minimum range of the unit to intercept projectile. Any projectile under this range will not be intercepted. + - `Interceptor.ApplyFirepowerMult` determines whether or not the intercepting weapon's damage should multiply the TechnoType's firepower multipliers. - `Interceptable.DeleteOnIntercept` determines whether or not the projectile will simply be deleted on detonation upon interception, or if it will properly detonate. Will be overridden by `Interceptor.DeleteOnIntercept` setting on the interceptor. - `Interceptable.WeaponOverride` can be set to a WeaponType that will be used to override characteristics such as `Damage` and `Warhead` of the current projectile for detonation after interception. Will be overridden by `Interceptor.WeaponOverride` setting on the interceptor. - On interceptors, `Interceptor.WeaponReplaceProjectile` can be set to true to make `Interceptor.WeaponOverride` also replace the intercepted projectile's type (including `Image` and other projectile characteristics) and `Speed` with its own. Does not replace particle systems (`AttachedSystem`, *Ares feature*). @@ -715,6 +716,7 @@ Interceptor.EliteGuardRange= ; floating point value Interceptor.MinimumGuardRange=0.0 ; floating point value Interceptor.VeteranMinimumGuardRange= ; floating point value Interceptor.EliteMinimumGuardRange= ; floating point value +Interceptor.ApplyFirepowerMult=true ; boolean Interceptor.DeleteOnIntercept=false ; boolean Interceptor.WeaponOverride= ; WeaponType Interceptor.WeaponReplaceProjectile=false ; boolean diff --git a/src/Ext/Bullet/Body.cpp b/src/Ext/Bullet/Body.cpp index f89cee974b..c4a688156f 100644 --- a/src/Ext/Bullet/Body.cpp +++ b/src/Ext/Bullet/Body.cpp @@ -1,5 +1,6 @@ #include "Body.h" +#include #include #include #include @@ -18,6 +19,8 @@ void BulletExt::ExtData::InterceptBullet(TechnoClass* pSource, WeaponTypeClass* auto pTypeExt = this->TypeExtData; bool canAffect = false; bool isIntercepted = false; + const auto pTechnoTypeExt = TechnoTypeExt::ExtMap.Find(pSource->GetTechnoType()); + const auto pInterceptorType = pTechnoTypeExt->InterceptorType.get(); if (pTypeExt->Armor.isset()) { @@ -26,8 +29,11 @@ void BulletExt::ExtData::InterceptBullet(TechnoClass* pSource, WeaponTypeClass* if (versus != 0.0) { canAffect = true; + int damage = static_cast(pWeapon->Damage * versus); + + if (pInterceptorType->ApplyFirepowerMult) + damage = static_cast(damage * pSource->FirepowerMultiplier * TechnoExt::ExtMap.Find(pSource)->AE.FirepowerMultiplier); - int damage = static_cast(pWeapon->Damage * versus * pSource->FirepowerMultiplier); this->CurrentStrength -= damage; if (Phobos::DisplayDamageNumbers && damage != 0) @@ -45,8 +51,6 @@ void BulletExt::ExtData::InterceptBullet(TechnoClass* pSource, WeaponTypeClass* if (canAffect) { - const auto pTechnoTypeExt = TechnoTypeExt::ExtMap.Find(pSource->GetTechnoType()); - const auto pInterceptorType = pTechnoTypeExt->InterceptorType.get(); const auto pWeaponOverride = pInterceptorType->WeaponOverride.Get(pTypeExt->Interceptable_WeaponOverride); bool detonate = !pInterceptorType->DeleteOnIntercept.Get(pTypeExt->Interceptable_DeleteOnIntercept); diff --git a/src/New/Type/Affiliated/InterceptorTypeClass.cpp b/src/New/Type/Affiliated/InterceptorTypeClass.cpp index 37222d1d4a..7770677eac 100644 --- a/src/New/Type/Affiliated/InterceptorTypeClass.cpp +++ b/src/New/Type/Affiliated/InterceptorTypeClass.cpp @@ -9,6 +9,7 @@ InterceptorTypeClass::InterceptorTypeClass(TechnoTypeClass* OwnedBy) , GuardRange {} , MinimumGuardRange {} , Weapon { 0 } + , ApplyFirepowerMult { true } , DeleteOnIntercept {} , WeaponOverride {} , WeaponReplaceProjectile { false } @@ -24,6 +25,7 @@ void InterceptorTypeClass::LoadFromINI(CCINIClass* pINI, const char* pSection) this->GuardRange.Read(exINI, pSection, "Interceptor.%sGuardRange"); this->MinimumGuardRange.Read(exINI, pSection, "Interceptor.%sMinimumGuardRange"); this->Weapon.Read(exINI, pSection, "Interceptor.Weapon"); + this->ApplyFirepowerMult.Read(exINI, pSection, "Interceptor.ApplyFirepowerMult"); this->DeleteOnIntercept.Read(exINI, pSection, "Interceptor.DeleteOnIntercept"); this->WeaponOverride.Read(exINI, pSection, "Interceptor.WeaponOverride"); this->WeaponReplaceProjectile.Read(exINI, pSection, "Interceptor.WeaponReplaceProjectile"); @@ -42,6 +44,7 @@ bool InterceptorTypeClass::Serialize(T& stm) .Process(this->GuardRange) .Process(this->MinimumGuardRange) .Process(this->Weapon) + .Process(this->ApplyFirepowerMult) .Process(this->DeleteOnIntercept) .Process(this->WeaponOverride) .Process(this->WeaponReplaceProjectile) diff --git a/src/New/Type/Affiliated/InterceptorTypeClass.h b/src/New/Type/Affiliated/InterceptorTypeClass.h index 6759163fdd..f8e6c842b9 100644 --- a/src/New/Type/Affiliated/InterceptorTypeClass.h +++ b/src/New/Type/Affiliated/InterceptorTypeClass.h @@ -22,6 +22,7 @@ class InterceptorTypeClass Valueable WeaponReplaceProjectile; Valueable WeaponCumulativeDamage; Valueable KeepIntact; + Valueable ApplyFirepowerMult; Nullable DeleteOnIntercept; void LoadFromINI(CCINIClass* pINI, const char* pSection);