Skip to content

Commit d86c159

Browse files
committed
fix TechnoClass_Init crash & fix Shield.SelfHealing.RestartInCombatDelay not working
1 parent e901028 commit d86c159

File tree

4 files changed

+65
-53
lines changed

4 files changed

+65
-53
lines changed

src/Ext/Techno/Hooks.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ DEFINE_HOOK(0x6F421C, TechnoClass_Init_DefaultDisguise, 0x6)
228228
{
229229
GET(TechnoClass*, pThis, ESI);
230230

231-
auto const pExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData;
231+
auto const pExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType());
232232

233233
// mirage is not here yet
234234
if (pThis->WhatAmI() == AbstractType::Infantry && pExt->DefaultDisguise)
@@ -251,7 +251,7 @@ DEFINE_HOOK(0x414057, TechnoClass_Init_InitialStrength, 0x6) // AircraftCl
251251
{
252252
GET(TechnoClass*, pThis, ESI);
253253

254-
auto pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData;
254+
auto const pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType());
255255

256256
if (R->Origin() != 0x517D69)
257257
{
@@ -262,7 +262,7 @@ DEFINE_HOOK(0x414057, TechnoClass_Init_InitialStrength, 0x6) // AircraftCl
262262
}
263263
else
264264
{
265-
auto strength = pTypeExt->InitialStrength.Get(R->EDX<int>());
265+
auto const strength = pTypeExt->InitialStrength.Get(R->EDX<int>());
266266
pThis->Health = strength;
267267
pThis->EstimatedHealth = strength;
268268
}

src/New/Entity/ShieldClass.cpp

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,18 @@ bool ShieldClass::ShieldIsBrokenTEvent(ObjectClass* pAttached)
160160

161161
int ShieldClass::ReceiveDamage(args_ReceiveDamage* args)
162162
{
163-
if (!this->HP || this->Temporal || *args->Damage == 0)
164-
return *args->Damage;
163+
int& damage = *args->Damage;
164+
int& health = this->HP;
165+
166+
if (!health || this->Temporal || damage == 0)
167+
return damage;
168+
169+
auto const pTechno = this->Techno;
165170

166171
// Handle a special case where parasite damages shield but not the unit and unit itself cannot be targeted by repair weapons.
167-
if (*args->Damage < 0)
172+
if (damage < 0)
168173
{
169-
if (auto const pFoot = abstract_cast<FootClass*, true>(this->Techno))
174+
if (auto const pFoot = abstract_cast<FootClass*, true>(pTechno))
170175
{
171176
if (auto const pParasite = pFoot->ParasiteEatingMe)
172177
{
@@ -177,108 +182,114 @@ int ShieldClass::ReceiveDamage(args_ReceiveDamage* args)
177182
}
178183
}
179184

180-
auto const pWHExt = WarheadTypeExt::ExtMap.Find(args->WH);
181-
bool IC = pWHExt->CanAffectInvulnerable(this->Techno);
185+
auto const pWH = args->WH;
186+
auto const pWHExt = WarheadTypeExt::ExtMap.Find(pWH);
187+
const bool IC = pWHExt->CanAffectInvulnerable(pTechno);
188+
189+
if (!IC || CanBePenetrated(pWH) || TechnoExt::IsTypeImmune(pTechno, args->Attacker))
190+
return damage;
182191

183-
if (!IC || CanBePenetrated(args->WH) || this->Techno->GetTechnoType()->Immune || TechnoExt::IsTypeImmune(this->Techno, args->Attacker))
184-
return *args->Damage;
192+
auto const pTechnoType = pTechno->GetTechnoType();
193+
194+
if (pTechnoType->Immune)
195+
return damage;
185196

186197
int nDamage = 0;
187198
int shieldDamage = 0;
188199
int healthDamage = 0;
200+
auto const pType = this->Type;
189201

190-
if (pWHExt->CanTargetHouse(args->SourceHouse, this->Techno) && !args->WH->Temporal)
202+
if (pWHExt->CanTargetHouse(args->SourceHouse, pTechno) && !pWH->Temporal)
191203
{
192-
if (*args->Damage > 0)
193-
nDamage = MapClass::GetTotalDamage(*args->Damage, args->WH, this->GetArmorType(), args->DistanceToEpicenter);
204+
if (damage > 0)
205+
nDamage = MapClass::GetTotalDamage(damage, pWH, this->GetArmorType(pTechnoType), args->DistanceToEpicenter);
194206
else
195-
nDamage = -MapClass::GetTotalDamage(-*args->Damage, args->WH, this->GetArmorType(), args->DistanceToEpicenter);
207+
nDamage = -MapClass::GetTotalDamage(damage, pWH, this->GetArmorType(pTechnoType), args->DistanceToEpicenter);
196208

197-
bool affectsShield = pWHExt->Shield_AffectTypes.size() <= 0 || pWHExt->Shield_AffectTypes.Contains(this->Type);
198-
double absorbPercent = affectsShield ? pWHExt->Shield_AbsorbPercent.Get(this->Type->AbsorbPercent) : this->Type->AbsorbPercent;
199-
double passPercent = affectsShield ? pWHExt->Shield_PassPercent.Get(this->Type->PassPercent) : this->Type->PassPercent;
209+
const bool affectsShield = pWHExt->Shield_AffectTypes.size() <= 0 || pWHExt->Shield_AffectTypes.Contains(pType);
210+
const double absorbPercent = affectsShield ? pWHExt->Shield_AbsorbPercent.Get(pType->AbsorbPercent) : pType->AbsorbPercent;
211+
const double passPercent = affectsShield ? pWHExt->Shield_PassPercent.Get(pType->PassPercent) : pType->PassPercent;
200212

201213
shieldDamage = (int)((double)nDamage * absorbPercent);
202214
// passthrough damage shouldn't be affected by shield armor
203-
healthDamage = (int)((double)*args->Damage * passPercent);
215+
healthDamage = (int)((double)damage * passPercent);
204216
}
205217

206-
int originalShieldDamage = shieldDamage;
207-
int min = pWHExt->Shield_ReceivedDamage_Minimum.Get(this->Type->ReceivedDamage_Minimum);
208-
int max = pWHExt->Shield_ReceivedDamage_Maximum.Get(this->Type->ReceivedDamage_Maximum);
209-
int minDmg = static_cast<int>(min * pWHExt->Shield_ReceivedDamage_MinMultiplier);
210-
int maxDmg = static_cast<int>(max * pWHExt->Shield_ReceivedDamage_MaxMultiplier);
218+
const int originalShieldDamage = shieldDamage;
219+
const int min = pWHExt->Shield_ReceivedDamage_Minimum.Get(pType->ReceivedDamage_Minimum);
220+
const int max = pWHExt->Shield_ReceivedDamage_Maximum.Get(pType->ReceivedDamage_Maximum);
221+
const int minDmg = static_cast<int>(min * pWHExt->Shield_ReceivedDamage_MinMultiplier);
222+
const int maxDmg = static_cast<int>(max * pWHExt->Shield_ReceivedDamage_MaxMultiplier);
211223
shieldDamage = Math::clamp(shieldDamage, minDmg, maxDmg);
212224

213225
if (Phobos::DisplayDamageNumbers && shieldDamage != 0)
214-
GeneralUtils::DisplayDamageNumberString(shieldDamage, DamageDisplayType::Shield, this->Techno->GetRenderCoords(), TechnoExt::ExtMap.Find(this->Techno)->DamageNumberOffset);
226+
GeneralUtils::DisplayDamageNumberString(shieldDamage, DamageDisplayType::Shield, pTechno->GetRenderCoords(), TechnoExt::ExtMap.Find(pTechno)->DamageNumberOffset);
215227

216228
if (shieldDamage > 0)
217229
{
218-
bool whModifiersApplied = this->Timers.SelfHealing_WHModifier.InProgress();
219-
bool restart = whModifiersApplied ? this->SelfHealing_RestartInCombat_Warhead : this->Type->SelfHealing_RestartInCombat;
230+
const bool whModifiersApplied = this->Timers.SelfHealing_WHModifier.InProgress();
231+
const bool restart = whModifiersApplied ? this->SelfHealing_RestartInCombat_Warhead : pType->SelfHealing_RestartInCombat;
220232

221233
if (restart)
222234
{
223-
int delay = whModifiersApplied ? this->SelfHealing_RestartInCombatDelay_Warhead : this->Type->SelfHealing_RestartInCombatDelay;
235+
const int delay = whModifiersApplied ? this->SelfHealing_RestartInCombatDelay_Warhead : pType->SelfHealing_RestartInCombatDelay;
224236

225237
if (delay > 0)
226238
{
227-
this->Timers.SelfHealing_CombatRestart.Start(this->Type->SelfHealing_RestartInCombatDelay);
239+
this->Timers.SelfHealing_CombatRestart.Start(delay);
228240
this->Timers.SelfHealing.Stop();
229241
}
230242
else
231243
{
232-
const int rate = whModifiersApplied ? this->SelfHealing_Rate_Warhead : this->Type->SelfHealing_Rate;
244+
const int rate = whModifiersApplied ? this->SelfHealing_Rate_Warhead : pType->SelfHealing_Rate;
233245
this->Timers.SelfHealing.Start(rate); // when attacked, restart the timer
234246
}
235247
}
236-
237248
if (!pWHExt->Nonprovocative)
238249
this->ResponseAttack();
239250

240251
if (pWHExt->DecloakDamagedTargets)
241-
this->Techno->Uncloak(false);
252+
pTechno->Uncloak(false);
242253

243-
int residueDamage = shieldDamage - this->HP;
254+
const int residueDamage = shieldDamage - health;
244255

245256
if (residueDamage >= 0)
246257
{
247-
int actualResidueDamage = Math::max(0, int((double)(originalShieldDamage - this->HP) /
248-
GeneralUtils::GetWarheadVersusArmor(args->WH, this->GetArmorType()))); //only absord percentage damage
258+
const int actualResidueDamage = Math::max(0, int((double)(originalShieldDamage - health) /
259+
GeneralUtils::GetWarheadVersusArmor(pWH, this->GetArmorType(pTechnoType)))); //only absord percentage damage
249260

250261
this->BreakShield(pWHExt->Shield_BreakAnim, pWHExt->Shield_BreakWeapon.Get(nullptr));
251262

252-
return this->Type->AbsorbOverDamage ? healthDamage : actualResidueDamage + healthDamage;
263+
return pType->AbsorbOverDamage ? healthDamage : actualResidueDamage + healthDamage;
253264
}
254265
else
255266
{
256-
if (this->Type->HitFlash && pWHExt->Shield_HitFlash)
267+
if (pType->HitFlash && pWHExt->Shield_HitFlash)
257268
{
258-
int size = this->Type->HitFlash_FixedSize.Get((shieldDamage * 2));
269+
const int size = pType->HitFlash_FixedSize.Get((shieldDamage * 2));
259270
SpotlightFlags flags = SpotlightFlags::NoColor;
260271

261-
if (this->Type->HitFlash_Black)
272+
if (pType->HitFlash_Black)
262273
{
263274
flags = SpotlightFlags::NoColor;
264275
}
265276
else
266277
{
267-
if (!this->Type->HitFlash_Red)
278+
if (!pType->HitFlash_Red)
268279
flags = SpotlightFlags::NoRed;
269-
if (!this->Type->HitFlash_Green)
280+
if (!pType->HitFlash_Green)
270281
flags |= SpotlightFlags::NoGreen;
271-
if (!this->Type->HitFlash_Blue)
282+
if (!pType->HitFlash_Blue)
272283
flags |= SpotlightFlags::NoBlue;
273284
}
274285

275-
MapClass::FlashbangWarheadAt(size, args->WH, this->Techno->Location, true, flags);
286+
MapClass::FlashbangWarheadAt(size, pWH, pTechno->Location, true, flags);
276287
}
277288

278289
if (!pWHExt->Shield_SkipHitAnim)
279290
this->WeaponNullifyAnim(pWHExt->Shield_HitAnim);
280291

281-
this->HP = -residueDamage;
292+
health = -residueDamage;
282293

283294
this->UpdateIdleAnim();
284295

@@ -287,13 +298,13 @@ int ShieldClass::ReceiveDamage(args_ReceiveDamage* args)
287298
}
288299
else if (shieldDamage < 0)
289300
{
290-
const int nLostHP = this->Type->Strength - this->HP;
301+
const int nLostHP = pType->Strength - health;
291302

292303
if (!nLostHP)
293304
{
294-
int result = *args->Damage;
305+
int result = damage;
295306

296-
if (result * GeneralUtils::GetWarheadVersusArmor(args->WH, this->Techno->GetTechnoType()->Armor) > 0)
307+
if (result * GeneralUtils::GetWarheadVersusArmor(pWH, pTechno->GetTechnoType()->Armor) > 0)
297308
result = 0;
298309

299310
return result;
@@ -302,9 +313,9 @@ int ShieldClass::ReceiveDamage(args_ReceiveDamage* args)
302313
const int nRemainLostHP = nLostHP + shieldDamage;
303314

304315
if (nRemainLostHP < 0)
305-
this->HP = this->Type->Strength;
316+
health = pType->Strength;
306317
else
307-
this->HP -= shieldDamage;
318+
health -= shieldDamage;
308319

309320
this->UpdateIdleAnim();
310321

@@ -1006,13 +1017,14 @@ int ShieldClass::DrawShieldBar_PipAmount(int length) const
10061017
: 0;
10071018
}
10081019

1009-
ArmorType ShieldClass::GetArmorType() const
1020+
ArmorType ShieldClass::GetArmorType(TechnoTypeClass* pTechnoType) const
10101021
{
10111022
const auto pShieldType = this->Type;
10121023

10131024
if (this->Techno && pShieldType->InheritArmorFromTechno)
10141025
{
1015-
const auto pTechnoType = this->Techno->GetTechnoType();
1026+
if (!pTechnoType)
1027+
pTechnoType = this->Techno->GetTechnoType();
10161028

10171029
if (pShieldType->InheritArmor_Allowed.empty() || pShieldType->InheritArmor_Allowed.Contains(pTechnoType)
10181030
&& (pShieldType->InheritArmor_Disallowed.empty() || !pShieldType->InheritArmor_Disallowed.Contains(pTechnoType)))

src/New/Entity/ShieldClass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ShieldClass
6161
{
6262
return this->Type;
6363
}
64-
ArmorType GetArmorType() const;
64+
ArmorType GetArmorType(TechnoTypeClass* pTechnoType = nullptr) const;
6565
int GetFramesSinceLastBroken() const;
6666
void SetAnimationVisibility(bool visible);
6767

src/Utilities/GeneralUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const double GeneralUtils::GetWarheadVersusArmor(WarheadTypeClass* pWH, TechnoCl
101101
auto const pShield = TechnoExt::ExtMap.Find(pThis)->Shield.get();
102102

103103
if (pShield && pShield->IsActive() && !pShield->CanBePenetrated(pWH))
104-
armorType = pShield->GetArmorType();
104+
armorType = pShield->GetArmorType(pType);
105105

106106
return GeneralUtils::GetWarheadVersusArmor(pWH, armorType);
107107
}

0 commit comments

Comments
 (0)