Skip to content

Commit 05243c2

Browse files
committed
PreventNegativeDamage
1 parent 2db1169 commit 05243c2

10 files changed

+108
-71
lines changed

docs/New-or-Enhanced-Logics.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ This page describes all the engine features that are either new and introduced b
7676
- `DisableWeapons` can be used to disable ability to fire any and all weapons.
7777
- On TechnoTypes with `OpenTopped=true`, `OpenTopped.CheckTransportDisableWeapons` can be set to true to make passengers not be able to fire out if transport's weapons are disabled by `DisableWeapons`.
7878
- `Unkillable` can be used to prevent the techno from being killed by taken damage (minimum health will be 1).
79+
- `PreventNegativeDamage` can be used to prevent the techno from taking negative damage. This includes both negative `Damage` and negative `Verses`.
7980
- It is possible to set groups for attach effect types by defining strings in `Groups`.
8081
- Groups can be used instead of types for removing effects and weapon filters.
8182

@@ -186,6 +187,7 @@ ReflectDamage.Override= ; integer
186187
ReflectDamage.UseInvokerAsOwner=false ; boolean
187188
DisableWeapons=false ; boolean
188189
Unkillable=false ; boolean
190+
PreventNegativeDamage=false ; boolean
189191
Groups= ; comma-separated list of strings (group IDs)
190192

191193
[SOMETECHNO] ; TechnoType

src/Ext/Bullet/Hooks.DetonateLogics.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,14 @@ DEFINE_HOOK(0x469AA4, BulletClass_Logics_Extras, 0x5)
316316
if (pThis->WeaponType)
317317
{
318318
auto const pWeaponExt = WeaponTypeExt::ExtMap.Find(pThis->WeaponType);
319-
std::vector<bool> vec;
320-
pBulletExt->ApplyExtraWarheads(pWeaponExt->ExtraWarheads, pWeaponExt->ExtraWarheads_DamageOverrides,
321-
pWeaponExt->ExtraWarheads_DetonationChances, pWeaponExt->ExtraWarheads_FullDetonation, vec, *coords, pOwner);
319+
320+
if (pWeaponExt->ExtraWarheads.size() > 0)
321+
{
322+
std::vector<bool> vec;
323+
324+
pBulletExt->ApplyExtraWarheads(pWeaponExt->ExtraWarheads, pWeaponExt->ExtraWarheads_DamageOverrides,
325+
pWeaponExt->ExtraWarheads_DetonationChances, pWeaponExt->ExtraWarheads_FullDetonation, vec, *coords, pOwner);
326+
}
322327
}
323328

324329
if (pThis->Owner)

src/Ext/Techno/Body.Update.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers()
18191819
bool forceDecloak = false;
18201820
bool disableWeapons = false;
18211821
bool unkillable = false;
1822+
bool preventNegativeDamage = false;
18221823
bool hasRangeModifier = false;
18231824
bool hasTint = false;
18241825
bool reflectsDamage = false;
@@ -1842,6 +1843,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers()
18421843
forceDecloak |= type->ForceDecloak;
18431844
disableWeapons |= type->DisableWeapons;
18441845
unkillable |= type->Unkillable;
1846+
preventNegativeDamage |= type->PreventNegativeDamage;
18451847
hasRangeModifier |= (type->WeaponRange_ExtraRange != 0.0 || type->WeaponRange_Multiplier != 0.0);
18461848
hasTint |= type->HasTint();
18471849
reflectsDamage |= type->ReflectDamage;
@@ -1860,6 +1862,7 @@ void TechnoExt::ExtData::RecalculateStatMultipliers()
18601862
pAE.ForceDecloak = forceDecloak;
18611863
pAE.DisableWeapons = disableWeapons;
18621864
pAE.Unkillable = unkillable;
1865+
pAE.PreventNegativeDamage = preventNegativeDamage;
18631866
pAE.HasRangeModifier = hasRangeModifier;
18641867
pAE.HasTint = hasTint;
18651868
pAE.ReflectDamage = reflectsDamage;

src/Ext/Techno/Hooks.ReceiveDamage.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
2525

2626
const auto pSourceHouse = args->SourceHouse;
2727
const auto pTargetHouse = pThis->Owner;
28+
int& damage = *args->Damage;
2829

2930
// Calculate Damage Multiplier
30-
if (!args->IgnoreDefenses && *args->Damage)
31+
if (!args->IgnoreDefenses && damage)
3132
{
3233
double multiplier = 1.0;
3334

@@ -40,14 +41,14 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
4041

4142
if (multiplier != 1.0)
4243
{
43-
const auto sgnDamage = *args->Damage > 0 ? 1 : -1;
44-
const auto calculateDamage = static_cast<int>(*args->Damage * multiplier);
45-
*args->Damage = calculateDamage ? calculateDamage : sgnDamage;
44+
const auto sgnDamage = damage > 0 ? 1 : -1;
45+
const auto calculateDamage = static_cast<int>(damage * multiplier);
46+
damage = calculateDamage ? calculateDamage : sgnDamage;
4647
}
4748
}
4849

4950
// Raise Combat Alert
50-
if (pRules->CombatAlert && *args->Damage > 1)
51+
if (pRules->CombatAlert && damage > 1)
5152
{
5253
auto raiseCombatAlert = [&]()
5354
{
@@ -104,7 +105,7 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
104105
// Shield Receive Damage
105106
if (!args->IgnoreDefenses)
106107
{
107-
int nDamageLeft = *args->Damage;
108+
int nDamageLeft = damage;
108109

109110
if (const auto pShieldData = pExt->Shield.get())
110111
{
@@ -114,9 +115,9 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
114115

115116
if (nDamageLeft >= 0)
116117
{
117-
*args->Damage = nDamageLeft;
118+
damage = nDamageLeft;
118119

119-
if (auto pTag = pThis->AttachedTag)
120+
if (const auto pTag = pThis->AttachedTag)
120121
pTag->RaiseEvent((TriggerEvent)PhobosTriggerEvent::ShieldBroken, pThis, CellStruct::Empty);
121122
}
122123

@@ -131,11 +132,17 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
131132
&& MapClass::GetTotalDamage(nDamageLeft, args->WH, pThis->GetTechnoType()->Armor, args->DistanceToEpicenter) >= pThis->Health)
132133
{
133134
// Update remaining damage and check if the target will die and should be avoided
134-
*args->Damage = 0;
135+
damage = 0;
135136
pThis->Health = 1;
136137
pThis->EstimatedHealth = 1;
137138
ReceiveDamageTemp::SkipLowDamageCheck = true;
138139
}
140+
141+
if (pExt->AE.PreventNegativeDamage && nDamageLeft != 0 && pWHExt->CanTargetHouse(pSourceHouse, pThis)
142+
&& MapClass::GetTotalDamage(nDamageLeft, args->WH, pThis->GetTechnoType()->Armor, args->DistanceToEpicenter) < 0)
143+
{
144+
damage = 0;
145+
}
139146
}
140147

141148
return 0;

src/Ext/Techno/WeaponHelpers.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -408,16 +408,18 @@ bool TechnoExt::IsAllowedSplitsTarget(TechnoClass* pSource, HouseClass* pOwner,
408408
void TechnoExt::ExtData::ApplyAuxWeapon(WeaponTypeClass* pAuxWeapon, AbstractClass* pTarget, const CoordStruct& offset, int range, const double& accuracy, bool onTurret, bool retarget, bool aroundFirer, bool zeroDamage, bool firepowerMult, TechnoClass* pInvoker)
409409
{
410410
auto const pThis = this->OwnerObject();
411+
411412
if (pThis->InOpenToppedTransport && !pAuxWeapon->FireInTransport)
412413
return;
413414

414415
TechnoClass* pTargetTechno = nullptr;
415416
CellClass* pTargetCell = nullptr;
417+
auto& random = ScenarioClass::Instance->Random;
416418

417-
if (retarget && accuracy < ScenarioClass::Instance->Random.RandomDouble())
419+
if (retarget && accuracy < random.RandomDouble())
418420
{
419421
auto const coord = aroundFirer ? pThis->Location : pTarget->GetCoords();
420-
auto cellSpread = range > 0 ? range : (aroundFirer ? pAuxWeapon->Range : 0);
422+
auto const cellSpread = range > 0 ? range : (aroundFirer ? pAuxWeapon->Range : 0);
421423

422424
std::vector<TechnoClass*> targets;
423425

@@ -432,14 +434,14 @@ void TechnoExt::ExtData::ApplyAuxWeapon(WeaponTypeClass* pAuxWeapon, AbstractCla
432434

433435
if (!targets.empty())
434436
{
435-
pTargetTechno = targets[ScenarioClass::Instance->Random.RandomRanged(0, targets.size() - 1)];
437+
pTargetTechno = targets[random.RandomRanged(0, targets.size() - 1)];
436438
}
437439
else
438440
{
439441
auto const cellTarget = CellClass::Coord2Cell(coord);
440-
int x = ScenarioClass::Instance->Random.RandomRanged(-cellSpread, cellSpread);
441-
int y = ScenarioClass::Instance->Random.RandomRanged(-cellSpread, cellSpread);
442-
CellStruct cell = { static_cast<short>(cellTarget.X + x), static_cast<short>(cellTarget.Y + y) };
442+
const int x = random.RandomRanged(-cellSpread, cellSpread);
443+
const int y = random.RandomRanged(-cellSpread, cellSpread);
444+
const CellStruct cell = { static_cast<short>(cellTarget.X + x), static_cast<short>(cellTarget.Y + y) };
443445
pTargetCell = MapClass::Instance.GetCellAt(cell);
444446
}
445447
}
@@ -465,7 +467,7 @@ void TechnoExt::ExtData::ApplyAuxWeapon(WeaponTypeClass* pAuxWeapon, AbstractCla
465467
if (!pTargetTechno && !pTargetCell)
466468
return;
467469

468-
auto location = TechnoExt::GetFLHAbsoluteCoords(pThis, offset, onTurret);
470+
auto const location = TechnoExt::GetFLHAbsoluteCoords(pThis, offset, onTurret);
469471
auto damage = pAuxWeapon->Damage;
470472

471473
if (firepowerMult)

src/New/Entity/AttachEffectClass.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -454,18 +454,18 @@ void AttachEffectClass::RefreshDuration(int durationOverride)
454454
else
455455
duration = this->DurationOverride ? this->DurationOverride : this->Type->Duration;
456456

457-
if (this->Type->Duration_ApplyVersus_Warhead)
457+
if (this->Type->Duration_ApplyVersus_Warhead && duration > 0)
458458
{
459459
auto const pTechnoExt = TechnoExt::ExtMap.Find(this->Techno);
460-
auto pArmor = this->Techno->GetTechnoType()->Armor;
460+
auto armor = this->Techno->GetTechnoType()->Armor;
461461

462462
if (auto const pShieldData = pTechnoExt->Shield.get())
463463
{
464464
if (pShieldData->IsActive())
465-
pArmor = pShieldData->GetArmorType();
465+
armor = pShieldData->GetArmorType();
466466
}
467467

468-
duration = Math::max(MapClass::GetTotalDamage(duration, this->Type->Duration_ApplyVersus_Warhead, pArmor, 0), 0);
468+
duration = Math::max(MapClass::GetTotalDamage(duration, this->Type->Duration_ApplyVersus_Warhead, armor, 0), 0);
469469
}
470470

471471
if (this->Type->Duration_ApplyFirepowerMult && duration > 0 && this->Invoker)
@@ -524,13 +524,16 @@ bool AttachEffectClass::ShouldBeDiscardedNow()
524524
auto const pTechno = this->Techno;
525525

526526
if (this->Type->DiscardOn_AbovePercent > 0.0 && pTechno->GetHealthPercentage() >= this->Type->DiscardOn_AbovePercent)
527-
return false;
527+
{
528+
this->LastDiscardCheckValue = false;
529+
return true;
530+
}
528531

529532
if (this->Type->DiscardOn_BelowPercent > 0.0 && pTechno->GetHealthPercentage() <= this->Type->DiscardOn_BelowPercent)
530-
return false;
531-
532-
if (discardOn == DiscardCondition::None)
533-
return false;
533+
{
534+
this->LastDiscardCheckValue = false;
535+
return true;
536+
}
534537

535538
if (auto const pFoot = abstract_cast<FootClass*, true>(pTechno))
536539
{
@@ -557,8 +560,8 @@ bool AttachEffectClass::ShouldBeDiscardedNow()
557560

558561
if (pTechno->Target)
559562
{
560-
bool inRange = (discardOn & DiscardCondition::InRange) != DiscardCondition::None;
561-
bool outOfRange = (discardOn & DiscardCondition::OutOfRange) != DiscardCondition::None;
563+
const bool inRange = (discardOn & DiscardCondition::InRange) != DiscardCondition::None;
564+
const bool outOfRange = (discardOn & DiscardCondition::OutOfRange) != DiscardCondition::None;
562565

563566
if (inRange || outOfRange)
564567
{
@@ -570,14 +573,14 @@ bool AttachEffectClass::ShouldBeDiscardedNow()
570573
}
571574
else
572575
{
573-
int weaponIndex = pTechno->SelectWeapon(pTechno->Target);
576+
const int weaponIndex = pTechno->SelectWeapon(pTechno->Target);
574577
auto const pWeapon = pTechno->GetWeapon(weaponIndex)->WeaponType;
575578

576579
if (pWeapon)
577580
distance = WeaponTypeExt::GetRangeWithModifiers(pWeapon, pTechno);
578581
}
579582

580-
int distanceFromTgt = pTechno->DistanceFrom(pTechno->Target);
583+
const int distanceFromTgt = pTechno->DistanceFrom(pTechno->Target);
581584

582585
if ((inRange && distanceFromTgt <= distance) || (outOfRange && distanceFromTgt >= distance))
583586
{

src/New/Entity/AttachEffectClass.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct AttachEffectTechnoProperties
9797
bool ForceDecloak;
9898
bool DisableWeapons;
9999
bool Unkillable;
100+
bool PreventNegativeDamage;
100101
bool HasRangeModifier;
101102
bool HasTint;
102103
bool ReflectDamage;
@@ -115,6 +116,7 @@ struct AttachEffectTechnoProperties
115116
, ForceDecloak { false }
116117
, DisableWeapons { false }
117118
, Unkillable { false }
119+
, PreventNegativeDamage { false }
118120
, HasRangeModifier { false }
119121
, HasTint { false }
120122
, ReflectDamage { false }

0 commit comments

Comments
 (0)