Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,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
- Modify Ammo on impact
- **Starkku**:
- Misc. minor bugfixes & improvements
- AI script actions:
Expand Down
10 changes: 10 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,16 @@ LaunchSW.DisplayMoney.Houses=all ; Affected House Enumeration (none|owner/self|
LaunchSW.DisplayMoney.Offset=0,0 ; X,Y, pixels relative to default
```

### Modify Ammo on impact

- Warheads can now modify ammo of the affected objects.

In `rulesmd.ini`:
```ini
[SOMEWARHEAD] ; Warhead
AmmoModifier=0 ; integer
```

### Parasite removal

- By default if unit takes negative damage from a Warhead (before `Verses` are calculated), any parasites infecting it are removed and deleted. This behaviour can now be customized to disable the removal for negative damage, or enable it for any arbitrary warhead.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,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)
- Modify Ammo on impact (by FS-21)

Vanilla fixes:
- Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy)
Expand Down
5 changes: 5 additions & 0 deletions src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
|| this->AttachEffects.RemoveGroups.size() > 0
|| this->BuildingSell
|| this->BuildingUndeploy
|| this->AmmoModifier
);

char tempBuffer[32];
Expand Down Expand Up @@ -368,6 +369,8 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
else
this->SpawnsCrate_Weights.push_back(weight);
}

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

template <typename T>
Expand Down Expand Up @@ -540,6 +543,8 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->DamageAreaTarget)

.Process(this->CanKill)

.Process(this->AmmoModifier)
;
}

Expand Down
7 changes: 6 additions & 1 deletion src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ class WarheadTypeExt

Valueable<bool> CanKill;

Valueable<int> AmmoModifier;

private:
Valueable<double> Shield_Respawn_Rate_InMinutes;
Valueable<double> Shield_SelfHealing_Rate_InMinutes;
Expand Down Expand Up @@ -376,6 +378,8 @@ class WarheadTypeExt
, KillWeapon_OnFirer_AffectsHouses { AffectedHouse::All }
, KillWeapon_Affects { AffectedTarget::All }
, KillWeapon_OnFirer_Affects { AffectedTarget::All }

, AmmoModifier { 0 }
{ }

void ApplyConvert(HouseClass* pHouse, TechnoClass* pTarget);
Expand Down Expand Up @@ -403,14 +407,15 @@ class WarheadTypeExt
void InterceptBullets(TechnoClass* pOwner, WeaponTypeClass* pWeapon, CoordStruct coords);
DamageAreaResult DamageAreaWithTarget(const CoordStruct& coords, int damage, TechnoClass* pSource, WarheadTypeClass* pWH, bool affectsTiberium, HouseClass* pSourceHouse, TechnoClass* pTarget);
private:
void DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* pOwner = nullptr, bool bulletWasIntercepted = false);
void DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* pOwner = nullptr, bool bulletWasIntercepted = false, BulletExt::ExtData* pBulletExt = nullptr);
void ApplyRemoveDisguise(HouseClass* pHouse, TechnoClass* pTarget);
void ApplyRemoveMindControl(TechnoClass* pTarget);
void ApplyCrit(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* Owner);
void ApplyShieldModifiers(TechnoClass* pTarget);
void ApplyAttachEffects(TechnoClass* pTarget, HouseClass* pInvokerHouse, TechnoClass* pInvoker);
void ApplyBuildingUndeploy(TechnoClass* pTarget);
double GetCritChance(TechnoClass* pFirer) const;
void ApplyAmmoModifier(TechnoClass* pTarget, HouseClass* pInvokerHouse, BulletExt::ExtData* pBulletExt = nullptr);
};

class ExtContainer final : public Container<WarheadTypeExt>
Expand Down
35 changes: 32 additions & 3 deletions src/Ext/WarheadType/Detonate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <Ext/Anim/Body.h>
#include <Ext/Bullet/Body.h>
#include <Ext/BulletType/Body.h>
#include <Ext/WeaponType/Body.h>
#include <Ext/SWType/Body.h>
#include <Misc/FlyingStrings.h>
#include <Utilities/Helpers.Alex.h>
Expand Down Expand Up @@ -172,7 +173,7 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse,
if (cellSpread)
{
for (auto pTarget : Helpers::Alex::getCellSpreadItems(coords, cellSpread, true))
this->DetonateOnOneUnit(pHouse, pTarget, pOwner, bulletWasIntercepted);
this->DetonateOnOneUnit(pHouse, pTarget, pOwner, bulletWasIntercepted, pBulletExt);
}
else if (pBullet)
{
Expand All @@ -181,7 +182,7 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse,
// Starkku: We should only detonate on the target if the bullet, at the moment of detonation is within acceptable distance of the target.
// Ares uses 64 leptons / quarter of a cell as a tolerance, so for sake of consistency we're gonna do the same here.
if (pBullet->DistanceFrom(pTarget) < Unsorted::LeptonsPerCell / 4)
this->DetonateOnOneUnit(pHouse, pTarget, pOwner, bulletWasIntercepted);
this->DetonateOnOneUnit(pHouse, pTarget, pOwner, bulletWasIntercepted, pBulletExt);
}
}
else if (this->DamageAreaTarget)
Expand All @@ -192,7 +193,7 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse,
}
}

void WarheadTypeExt::ExtData::DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* pOwner, bool bulletWasIntercepted)
void WarheadTypeExt::ExtData::DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* pOwner, bool bulletWasIntercepted, BulletExt::ExtData* pBulletExt)
{
if (!pTarget || pTarget->InLimbo || !pTarget->IsAlive || !pTarget->Health || pTarget->IsSinking || pTarget->BeingWarpedOut)
return;
Expand All @@ -211,6 +212,9 @@ void WarheadTypeExt::ExtData::DetonateOnOneUnit(HouseClass* pHouse, TechnoClass*
if (this->Crit_CurrentChance > 0.0 && (!this->Crit_SuppressWhenIntercepted || !bulletWasIntercepted))
this->ApplyCrit(pHouse, pTarget, pOwner);

if (this->AmmoModifier != 0)
ApplyAmmoModifier(pTarget, pHouse, pBulletExt);

if (this->Convert_Pairs.size() > 0)
this->ApplyConvert(pHouse, pTarget);

Expand Down Expand Up @@ -649,3 +653,28 @@ double WarheadTypeExt::ExtData::GetCritChance(TechnoClass* pFirer) const

return critChance + extraChance;
}

void WarheadTypeExt::ExtData::ApplyAmmoModifier(TechnoClass* pTarget, HouseClass* pInvokerHouse, BulletExt::ExtData* pBulletExt)
{
if (!pTarget)
return;

auto const pWeapon = pBulletExt ? pBulletExt->OwnerObject()->WeaponType : nullptr;

if (pWeapon)
{
auto const pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

if (!EnumFunctions::IsTechnoEligible(pTarget, pWeaponExt->CanTarget)
|| (pInvokerHouse && !EnumFunctions::CanTargetHouse(pWeaponExt->CanTargetHouses, pInvokerHouse, pTarget->Owner)))
{
return;
}
}

int maxAmmo = pTarget->GetTechnoType()->Ammo;
int newCurrentAmmo = this->AmmoModifier + pTarget->Ammo;

newCurrentAmmo = newCurrentAmmo < 0 ? 0 : newCurrentAmmo;
pTarget->Ammo = newCurrentAmmo > maxAmmo ? maxAmmo : newCurrentAmmo;
}