Skip to content

Commit b21f0f8

Browse files
authored
[Minor] Damage.DealtByInvoker tweak & Damage.ApplyFIrepowerMult (#1728)
previous `Damage.DealtByInvoker` doesn't really apply to anim warhead, this PR makes it inline with anim weapon. Notice that this might change the behavior of anim weapon and warhead a bit, but I think this should be the correct way. Any other feedbacks and reviews are welcome `Damage.ApplyFirepowerMult` determines whether or not firepower modifiers from the animation's invoker are applied on the damage dealt from this animation, if exists
1 parent 1ecd281 commit b21f0f8

File tree

4 files changed

+45
-48
lines changed

4 files changed

+45
-48
lines changed

docs/Fixed-or-Improved-Logics.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,17 @@ LandingDir= ; Direction type (integers from 0-255). Accepts negative values
330330
- `Weapon` can be set to a WeaponType, to create a projectile and immediately detonate it instead of simply dealing `Damage` by `Warhead`. This allows weapon effects to be applied.
331331
- `Damage.Delay` determines delay between two applications of `Damage`. Requires `Damage` to be set to 1.0 or above. Value of 0 disables the delay. Keep in mind that this is measured in animation frames, not game frames. Depending on `Rate`, animation may or may not advance animation frames on every game frame.
332332
- `Damage.DealtByInvoker`, if set to true, makes any `Damage` dealt to be considered as coming from the animation's invoker (f.ex, firer of the weapon if it is Warhead `AnimList/SplashList` animation, the destroyed vehicle if it is `DestroyAnim` animation or the object the animation is attached to). If invoker has died or does not exist, the house the invoker belonged to is still used to deal damage and apply Phobos-introduced Warhead effects. Does not affect which house the `Damage` dealt by `Warhead` is dealt by.
333+
- `Damage.ApplyFirepowerMult` determines whether or not firepower modifiers from the animation's invoker are applied on the damage dealt from this animation, if exists.
333334
- `Damage.ApplyOncePerLoop`, if set to true, makes `Damage` be dealt only once per animation loop (on single loop animations, only once, period) instead of on every frame or intervals defined by `Damage.Delay`. The frame on which it is dealt is determined by `Damage.Delay`, defaulting to after the first animation frame.
334335

335336
In `artmd.ini`:
336337
```ini
337-
[SOMEANIM] ; AnimationType
338-
Weapon= ; WeaponType
339-
Damage.Delay=0 ; integer, animation frames
340-
Damage.DealtByInvoker=false ; boolean
341-
Damage.ApplyOncePerLoop=false ; boolean
338+
[SOMEANIM] ; AnimationType
339+
Weapon= ; WeaponType
340+
Damage.Delay=0 ; integer, animation frames
341+
Damage.DealtByInvoker=false ; boolean
342+
Damage.ApplyOncePerLoop=false ; boolean
343+
Damage.ApplyFirepowerMult=false ; boolean
342344
```
343345

344346
```{note}

src/Ext/Anim/Hooks.cpp

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,70 +42,82 @@ DEFINE_HOOK(0x42453E, AnimClass_AI_Damage, 0x6)
4242

4343
GET(AnimClass*, pThis, ESI);
4444

45+
if (pThis->IsInert)
46+
return SkipDamage;
47+
4548
const auto pTypeExt = AnimTypeExt::ExtMap.Find(pThis->Type);
4649
const int delay = pTypeExt->Damage_Delay.Get();
47-
int damageMultiplier = 1;
48-
double damage = 0;
49-
int appliedDamage = 0;
50+
const bool isTerrain = pThis->OwnerObject && pThis->OwnerObject->WhatAmI() == AbstractType::Terrain;
51+
const int damageMultiplier = isTerrain ? 5 : 1;
52+
const double baseDamage = pThis->Type->Damage;
5053

51-
if (pThis->OwnerObject && pThis->OwnerObject->WhatAmI() == AbstractType::Terrain)
52-
damageMultiplier = 5;
54+
int appliedDamage = 0;
5355

5456
if (pTypeExt->Damage_ApplyOncePerLoop) // If damage is to be applied only once per animation loop
5557
{
5658
if (pThis->Animation.Value == std::max(delay - 1, 1))
57-
appliedDamage = static_cast<int>(std::round(pThis->Type->Damage)) * damageMultiplier;
59+
appliedDamage = static_cast<int>(std::round(baseDamage)) * damageMultiplier;
5860
else
5961
return SkipDamage;
6062
}
61-
else if (delay <= 0 || pThis->Type->Damage < 1.0) // If Damage.Delay is less than 1 or Damage is a fraction.
63+
else if (delay <= 0 || baseDamage < 1.0) // If Damage.Delay is less than 1 or Damage is a fraction.
6264
{
63-
damage = damageMultiplier * pThis->Type->Damage + pThis->Accum;
65+
const double totalDamage = damageMultiplier * baseDamage + pThis->Accum;
6466

6567
// Deal damage if it is at least 1, otherwise accumulate it for later.
66-
if (damage >= 1.0)
68+
if (totalDamage >= 1.0)
6769
{
68-
appliedDamage = static_cast<int>(std::round(damage));
69-
pThis->Accum = damage - appliedDamage;
70+
appliedDamage = static_cast<int>(std::round(totalDamage));
71+
pThis->Accum = totalDamage - appliedDamage;
7072
}
7173
else
7274
{
73-
pThis->Accum = damage;
75+
pThis->Accum = totalDamage;
7476
return SkipDamage;
7577
}
7678
}
7779
else
7880
{
7981
// Accum here is used as a counter for Damage.Delay, which cannot deal fractional damage.
80-
damage = pThis->Accum + 1.0;
81-
pThis->Accum = damage;
82+
pThis->Accum += 1.0;
8283

83-
if (damage < delay)
84+
if (pThis->Accum < delay)
8485
return SkipDamage;
8586

8687
// Use Type->Damage as the actually dealt damage.
87-
appliedDamage = static_cast<int>(std::round(pThis->Type->Damage)) * damageMultiplier;
88+
appliedDamage = static_cast<int>(std::round(baseDamage)) * damageMultiplier;
8889
pThis->Accum = 0.0;
8990
}
9091

91-
if (appliedDamage <= 0 || pThis->IsInert)
92+
if (appliedDamage <= 0)
9293
return SkipDamage;
9394

9495
TechnoClass* pInvoker = nullptr;
95-
HouseClass* pOwner = nullptr;
96+
HouseClass* pOwner = pThis->Owner;
9697

9798
if (pTypeExt->Damage_DealtByInvoker)
9899
{
99-
auto const pExt = AnimExt::ExtMap.Find(pThis);
100+
const auto pExt = AnimExt::ExtMap.Find(pThis);
100101
pInvoker = pExt->Invoker;
101-
pOwner = pExt->InvokerHouse;
102+
103+
if (pExt->InvokerHouse)
104+
pOwner = pExt->InvokerHouse;
102105

103106
if (!pInvoker)
104107
{
105-
pInvoker = pThis->OwnerObject ? abstract_cast<TechnoClass*>(pThis->OwnerObject) : nullptr;
108+
if (pThis->OwnerObject)
109+
pInvoker = abstract_cast<TechnoClass*, true>(pThis->OwnerObject);
110+
else if (pThis->IsBuildingAnim)
111+
pInvoker = pExt->ParentBuilding;
112+
}
106113

107-
if (pInvoker && !pOwner)
114+
if (pInvoker)
115+
{
116+
if (!pOwner)
108117
pOwner = pInvoker->Owner;
118+
119+
if (pTypeExt->Damage_ApplyFirepowerMult)
120+
appliedDamage = static_cast<int>(appliedDamage * pInvoker->FirepowerMultiplier * TechnoExt::ExtMap.Find(pInvoker)->AE.FirepowerMultiplier);
109121
}
110122
}
111123

@@ -115,27 +127,6 @@ DEFINE_HOOK(0x42453E, AnimClass_AI_Damage, 0x6)
115127
}
116128
else
117129
{
118-
if (!pOwner)
119-
{
120-
if (pThis->Owner)
121-
{
122-
pOwner = pThis->Owner;
123-
}
124-
else if (pInvoker)
125-
{
126-
pOwner = pInvoker->Owner;
127-
}
128-
else if (pThis->OwnerObject)
129-
{
130-
pOwner = pThis->OwnerObject->GetOwningHouse();
131-
}
132-
else if (pThis->IsBuildingAnim)
133-
{
134-
auto const pBuilding = AnimExt::ExtMap.Find(pThis)->ParentBuilding;
135-
pOwner = pBuilding ? pBuilding->Owner : nullptr;
136-
}
137-
}
138-
139130
auto pWarhead = pThis->Type->Warhead;
140131

141132
if (!pWarhead)

src/Ext/AnimType/Body.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void AnimTypeExt::ExtData::LoadFromINIFile(CCINIClass* pINI)
9393
this->Damage_Delay.Read(exINI, pID, "Damage.Delay");
9494
this->Damage_DealtByInvoker.Read(exINI, pID, "Damage.DealtByInvoker");
9595
this->Damage_ApplyOncePerLoop.Read(exINI, pID, "Damage.ApplyOncePerLoop");
96+
this->Damage_ApplyFirepowerMult.Read(exINI, pID, "Damage.ApplyFirepowerMult");
9697
this->ExplodeOnWater.Read(exINI, pID, "ExplodeOnWater");
9798
this->Warhead_Detonate.Read(exINI, pID, "Warhead.Detonate");
9899
this->WakeAnim.Read(exINI, pID, "WakeAnim");
@@ -151,6 +152,7 @@ void AnimTypeExt::ExtData::Serialize(T& Stm)
151152
.Process(this->Damage_Delay)
152153
.Process(this->Damage_DealtByInvoker)
153154
.Process(this->Damage_ApplyOncePerLoop)
155+
.Process(this->Damage_ApplyFirepowerMult)
154156
.Process(this->ExplodeOnWater)
155157
.Process(this->Warhead_Detonate)
156158
.Process(this->WakeAnim)

src/Ext/AnimType/Body.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class AnimTypeExt
2929
Valueable<int> Damage_Delay;
3030
Valueable<bool> Damage_DealtByInvoker;
3131
Valueable<bool> Damage_ApplyOncePerLoop;
32+
Valueable<bool> Damage_ApplyFirepowerMult;
3233
Valueable<bool> ExplodeOnWater;
3334
Valueable<bool> Warhead_Detonate;
3435
Valueable<AnimTypeClass*> WakeAnim;
@@ -67,6 +68,7 @@ class AnimTypeExt
6768
, Damage_Delay { 0 }
6869
, Damage_DealtByInvoker { false }
6970
, Damage_ApplyOncePerLoop { false }
71+
, Damage_ApplyFirepowerMult { false }
7072
, ExplodeOnWater { false }
7173
, Warhead_Detonate { false }
7274
, WakeAnim {}

0 commit comments

Comments
 (0)