Skip to content

Warhead activation target health thresholds #1398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ef68501
Warhead activation target health thresholds
Metadorius Sep 27, 2024
1c00551
Significant changes due to devs feedback
FS-21 Feb 4, 2025
ba4e944
Merge remote-tracking branch 'origin/develop' into feature/warhead-ac…
FS-21 Feb 4, 2025
0828438
tweaks
FS-21 Feb 4, 2025
2a5fe3a
Applied feedback
FS-21 Feb 6, 2025
2a36ba9
Applied more feedback
FS-21 Feb 7, 2025
420a197
Apply suggestions from code review
Metadorius Feb 12, 2025
bd0b8ff
Applied feedback
FS-21 Feb 12, 2025
0c4ce31
Merge remote-tracking branch 'Metadorius/feature/warhead-activation-t…
FS-21 Feb 12, 2025
92aca91
Merge remote-tracking branch 'origin/develop' into feature/warhead-ac…
FS-21 Feb 12, 2025
6cb5dba
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 Feb 18, 2025
f0fdd0e
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 Feb 18, 2025
6c11465
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 Feb 18, 2025
c19d8bc
Merge branch 'develop' into feature/warhead-activation-threshold
Metadorius Feb 20, 2025
9ce4d50
fix
FS-21 Feb 24, 2025
e67d065
deleted residual address
FS-21 May 19, 2025
20a9023
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 May 19, 2025
61b137c
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 May 23, 2025
fc454eb
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 May 29, 2025
44159bd
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 May 30, 2025
ef335f3
Merge branch 'develop' into feature/warhead-activation-threshold
FS-21 Jun 8, 2025
0ac9c41
Post-merge credits fix
Metadorius Jun 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ This page lists all the individual contributions to the project by their author.
- Ability to disable shadow for debris & meteor animations
- Voxel light source position customization
- `UseFixedVoxelLighting`
- Warhead activation target health thresholds
- **Uranusian (Thrifinesma)**:
- Mind Control enhancement
- Custom warhead splash list
Expand Down Expand Up @@ -144,6 +145,7 @@ This page lists all the individual contributions to the project by their author.
- Map Events 604 & 605 for checking if a specific Techno enters in a cell
- Warhead that can not kill
- `Pips.HideIfNoStrength` and `SelfHealing.EnabledBy` additions for shields
- Warhead activation target health thresholds enhancements
- **Starkku**:
- Misc. minor bugfixes & improvements
- AI script actions:
Expand Down
14 changes: 14 additions & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1843,6 +1843,20 @@ Rocker.AmplitudeMultiplier=1.0 ; floating point value, multiplier
Rocker.AmplitudeOverride= ; integer
```

### Customizable Warhead trigger conditions

- It is now possible to make warheads only trigger when target's HP is above and/or below certain percentage.
- Both conditions need to evaluate to true in order for the warhead to trigger.
- If set to `false`, `EffectsRequireVerses` makes the Phobos-introduced warhead effects trigger even if it can't damage the target because of it's current ArmorType (e.g. 0% in `Verses`).

In `rulesmd.ini`:
```ini
[SOMEWARHEAD] ; WarheadType
AffectsAbovePercent=0.0 ; floating point value, percents or absolute
AffectsBelowPercent=1.0 ; floating point value, percents or absolute
EffectsRequireVerses=false ; boolean
```

### Customizable Warhead animation behaviour

- It is possible to make game play random animation from `AnimList` by setting `AnimList.PickRandom` to true. The result is similar to what `EMEffect=true` produces, however it comes with no side-effects (`EMEffect=true` prevents `Inviso=true` projectiles from snapping on targets, making them miss moving targets).
Expand Down
2 changes: 1 addition & 1 deletion docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,7 @@ FireUp.ResetInRetarget=true ; boolean
All new Warhead effects
- Can be used with `CellSpread` and Ares' GenericWarhead superweapon where applicable.
- Cannot be used with `MindControl.Permanent=yes` of Ares.
- Respect `Verses` where applicable unless `EffectsRequireVerses` is set to false. If target has an active shield, its armor type is used instead unless warhead can penetrate the shield.
- Respect `Verses` where applicable unless `EffectsRequireVerses` is set to `false`. If target has an active shield, its armor type is used instead unless warhead can penetrate the shield.
```

### Break Mind Control on impact
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ New:
- Draw visual effects for airburst weapons (by CrimRecya)
- Unit `Speed` setting now accepts floating point values (by Starkku)
- `Strafing` is now disabled by default when using `Trajectory` (by CrimRecya)
- Warhead activation target health thresholds (by FS-21, Kerbiter)

Vanilla fixes:
- Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy)
Expand Down
25 changes: 21 additions & 4 deletions src/Ext/Bullet/Hooks.DetonateLogics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,27 @@
#include <AircraftClass.h>
#include <TacticalClass.h>

DEFINE_HOOK(0x4690D4, BulletClass_Logics_ScreenShake, 0x6)
DEFINE_HOOK(0x4690D4, BulletClass_Logics_NewChecks, 0x6)
{
enum { SkipShaking = 0x469130 };
enum { SkipShaking = 0x469130, GoToExtras = 0x469AA4 };

GET(BulletClass*, pBullet, ESI);
GET(WarheadTypeClass*, pWarhead, EAX);
GET_BASE(CoordStruct*, pCoords, 0x8);

auto const pWHExt = WarheadTypeExt::ExtMap.Find(pWarhead);
auto const pExt = WarheadTypeExt::ExtMap.Find(pWarhead);

if (auto pTarget = abstract_cast<TechnoClass*>(pBullet->Target))
{
// Check if the WH should affect the techno target or skip it
if (!pExt->IsHealthInThreshold(pTarget) && pBullet->Owner != pBullet->Target)
return GoToExtras;
}

// Check for ScreenShake
auto&& [_, visible] = TacticalClass::Instance->CoordsToClient(*pCoords);

if (pWHExt->ShakeIsLocal && !visible)
if (pExt->ShakeIsLocal && !visible)
return SkipShaking;

return 0;
Expand Down Expand Up @@ -310,6 +320,13 @@ DEFINE_HOOK(0x469AA4, BulletClass_Logics_Extras, 0x5)
auto const pWH = pWeaponExt->ExtraWarheads[i];
int damage = defaultDamage;
size_t size = pWeaponExt->ExtraWarheads_DamageOverrides.size();
auto const pWHExt = WarheadTypeExt::ExtMap.Find(pWH);

if (auto const pTarget = abstract_cast<TechnoClass*>(pThis->Target))
{
if (!pWHExt->IsHealthInThreshold(pTarget))
continue;
}

if (size > i)
damage = pWeaponExt->ExtraWarheads_DamageOverrides[i];
Expand Down
9 changes: 4 additions & 5 deletions src/Ext/RadSite/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ void RadSiteExt::ExtData::Initialize()
bool RadSiteExt::ExtData::ApplyRadiationDamage(TechnoClass* pTarget, int& damage)
{
const auto pWarhead = this->Type->GetWarhead();
const auto pWHExt = WarheadTypeExt::ExtMap.Find(pWarhead);

if (!pWHExt->IsHealthInThreshold(pTarget))
return false;

if (!this->Type->GetWarheadDetonate())
{
Expand All @@ -25,14 +29,9 @@ bool RadSiteExt::ExtData::ApplyRadiationDamage(TechnoClass* pTarget, int& damage
else
{
if (this->Type->GetWarheadDetonateFull())
{
WarheadTypeExt::DetonateAt(pWarhead, pTarget, this->RadInvoker, damage, this->RadHouse);
}
else
{
const auto pWHExt = WarheadTypeExt::ExtMap.Find(pWarhead);
pWHExt->DamageAreaWithTarget(pTarget->GetCoords(), damage, this->RadInvoker, pWarhead, true, this->RadHouse, pTarget);
}

if (!pTarget->IsAlive)
return false;
Expand Down
22 changes: 22 additions & 0 deletions src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,25 @@ bool WarheadTypeExt::ExtData::CanAffectTarget(TechnoClass* pTarget) const
if (!pTarget)
return false;

if (!IsHealthInThreshold(pTarget))
return false;

if (!this->EffectsRequireVerses)
return true;

return GeneralUtils::GetWarheadVersusArmor(this->OwnerObject(), pTarget) != 0.0;
}

bool WarheadTypeExt::ExtData::IsHealthInThreshold(TechnoClass* pTarget) const
{
// Check if the WH should affect the techno target or skip it
double hp = pTarget->GetHealthPercentage();
bool hpBelowPercent = hp <= this->AffectsBelowPercent;
bool hpAbovePercent = hp > this->AffectsAbovePercent;

return hpBelowPercent && hpAbovePercent;
}

// Checks if Warhead can affect target that might or might be currently invulnerable.
bool WarheadTypeExt::ExtData::CanAffectInvulnerable(TechnoClass* pTarget) const
{
Expand Down Expand Up @@ -274,6 +287,12 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)

this->AirstrikeTargets.Read(exINI, pSection, "AirstrikeTargets");

this->AffectsAbovePercent.Read(exINI, pSection, "AffectsAbovePercent");
this->AffectsBelowPercent.Read(exINI, pSection, "AffectsBelowPercent");

if (this->AffectsAbovePercent > this->AffectsBelowPercent)
Debug::Log("[Developer warning][%s] AffectsAbovePercent is bigger than AffectsBelowPercent, the warhead will never activate!\n", pSection);

// Convert.From & Convert.To
TypeConvertGroup::Parse(this->Convert_Pairs, exINI, pSection, AffectedHouse::All);

Expand Down Expand Up @@ -493,6 +512,9 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->SuppressReflectDamage_Types)
.Process(this->SuppressReflectDamage_Groups)

.Process(this->AffectsAbovePercent)
.Process(this->AffectsBelowPercent)

.Process(this->InflictLocomotor)
.Process(this->RemoveInflictedLocomotor)

Expand Down
7 changes: 7 additions & 0 deletions src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ class WarheadTypeExt

Valueable<AffectedTarget> AirstrikeTargets;

Valueable<double> AffectsAbovePercent;
Valueable<double> AffectsBelowPercent;

// Ares tags
// http://ares-developers.github.io/Ares-docs/new/warheads/general.html
Valueable<bool> AffectsEnemies;
Expand Down Expand Up @@ -352,6 +355,9 @@ class WarheadTypeExt

, AirstrikeTargets { AffectedTarget::Building }

, AffectsAbovePercent { 0.0 }
, AffectsBelowPercent { 1.0 }

, AffectsEnemies { true }
, AffectsOwner {}
, EffectsRequireVerses { true }
Expand Down Expand Up @@ -386,6 +392,7 @@ class WarheadTypeExt
bool CanAffectTarget(TechnoClass* pTarget) const;
bool CanAffectInvulnerable(TechnoClass* pTarget) const;
bool EligibleForFullMapDetonation(TechnoClass* pTechno, HouseClass* pOwner) const;
bool IsHealthInThreshold(TechnoClass* pTarget) const;

virtual ~ExtData() = default;
virtual void LoadFromINIFile(CCINIClass* pINI) override;
Expand Down