diff --git a/CREDITS.md b/CREDITS.md index 4e95706f1c..2fbeb1c54a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -160,6 +160,7 @@ This page lists all the individual contributions to the project by their author. - Linked superweapons - Unit & infantry auto-conversion on ammo change - Restore the ScriptType action#24 `Play speech` from Tiberian Sun + - Modify ammo on impact - **Starkku**: - Misc. minor bugfixes & improvements - AI script actions: diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 2266f70d42..709f5c2ef6 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -3058,6 +3058,20 @@ LaunchSW.DisplayMoney.Offset=0,0 ; X,Y, pixels relative to default Due to the nature of some superweapon types, not all superweapons are suitable for launch. **Please use with caution!** ``` +### Modify ammo on impact + +- When this warhead detonates, it increases the ammo of affected targets by the set amount; a negative value decreases it. + +In `rulesmd.ini`: +```ini +[SOMEWARHEAD] ; WarheadType +Ammo=0 ; integer +``` + +```{note} +This will not raise the ammo above the maximum defined by `[TechnoType] -> Ammo=`, nor below 0. +``` + ### 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. @@ -3241,6 +3255,7 @@ Taunt=false ; boolean - [`ReverseEngineer`](#reverse-engineer-warhead) - [Modify shield](#shields) - [Modify attach-effects](#attached-effects) + - [Modify ammo on impact](New-or-Enhanced-Logics.md#modify-ammo-on-impact) - [Critical hits](#chance-based-extra-damage-or-warhead-detonation--critical-hits) - Due to technical reasons, `Crit.SuppressWhenIntercepted=false` and `Crit.ApplyChancePerTarget=true` will forced to be used. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index f3aafed7eb..e9324812c7 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -419,6 +419,7 @@ HideShakeEffects=false ; boolean :open: #### New: +- [Modify ammo on impact](New-or-Enhanced-Logics.md#modify-ammo-on-impact) (by FS-21) #### Vanilla fixes: - Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish) diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index a279347c60..bfeb3a3da5 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -449,6 +449,8 @@ void WarheadTypeExt::LoadFromINIFile(CCINIClass* const pINI) this->PreventPassengerEscape.Read(exINI, pSection, "PreventPassengerEscape"); this->PreventOccupantEscape.Read(exINI, pSection, "PreventOccupantEscape"); + this->Ammo.Read(exINI, pSection, "Ammo"); + // Convert.From & Convert.To TypeConvertGroup::Parse(this->Convert_Pairs, exINI, pSection, AffectedHouse::All); @@ -514,6 +516,7 @@ void WarheadTypeExt::LoadFromINIFile(CCINIClass* const pINI) || this->ReturnWarhead || this->PenetratesTransport_Level > 0 || this->Taunt + || this->Ammo ); char tempBuffer[32]; @@ -734,7 +737,7 @@ void WarheadTypeExt::Serialize(T& Stm) .Process(this->Parasite_DisableParticleSystem) .Process(this->Parasite_CullingTarget) .Process(this->Parasite_GrappleAnim) - + .Process(this->JumpjetTurnRate) .Process(this->JumpjetSpeed) .Process(this->JumpjetClimb) @@ -816,6 +819,8 @@ void WarheadTypeExt::Serialize(T& Stm) .Process(this->PossibleCellSpreadDetonate) .Process(this->Reflected) .Process(this->DamageAreaTarget) + + .Process(this->Ammo) ; } diff --git a/src/Ext/WarheadType/Body.h b/src/Ext/WarheadType/Body.h index 880101e6e5..e1f9ddd320 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -270,6 +270,8 @@ class WarheadTypeExt final : public AbstractTypeExt Valueable PreventPassengerEscape; Valueable PreventOccupantEscape; + Valueable Ammo; + // Ares tags // http://ares-developers.github.io/Ares-docs/new/warheads/general.html Valueable AffectsEnemies; @@ -567,6 +569,8 @@ class WarheadTypeExt final : public AbstractTypeExt , PreventCrewEscape { false } , PreventPassengerEscape { false } , PreventOccupantEscape { false } + + , Ammo { 0 } { } void ApplyConvert(HouseClass* pHouse, TechnoClass* pTarget); @@ -608,6 +612,7 @@ class WarheadTypeExt final : public AbstractTypeExt void ApplyReturnWarhead(HouseClass* pHouse, TechnoClass* pTarget, TechnoClass* Owner); void ApplyPenetratesTransport(TechnoClass* pTarget, TechnoClass* pInvoker, HouseClass* pInvokerHouse, const CoordStruct& coords, int damage, int distance); double GetCritChance(TechnoClass* pFirer) const; + void ApplyAmmoModifier(TechnoClass* pTarget); public: class ExtContainer final : public Container diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index 1fe0f66fff..3cb8be8874 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -218,6 +218,9 @@ void WarheadTypeExt::DetonateOnOneUnit(HouseClass* pHouse, TechnoClass* pTarget, this->ApplyBuildingUndeploy(pTarget); // Other one time effects + if (this->Ammo != 0) + this->ApplyAmmoModifier(pTarget); + if (this->RemoveDisguise) this->ApplyRemoveDisguise(pTarget); @@ -491,7 +494,8 @@ HouseClass* WarheadTypeExt::ApplyRemoveMindControl(HouseClass* pHouse, TechnoCla void WarheadTypeExt::ExtData::ApplyOwnerChange(HouseClass* pHouse, TechnoClass* pTarget) { const bool isMindControl = this->ChangeOwner_SetAsMindControl; - const bool isImmune = (isMindControl && pTarget->GetTechnoType()->ImmuneToPsionics) || pTarget->IsMindControlled(); + const auto pType = pTarget->GetTechnoType(); + const bool isImmune = (isMindControl && pType->ImmuneToPsionics) || pTarget->IsMindControlled(); if (!isImmune) { @@ -509,7 +513,7 @@ void WarheadTypeExt::ExtData::ApplyOwnerChange(HouseClass* pHouse, TechnoClass* if (isBld) location.Z += static_cast(pTarget)->Type->Height * Unsorted::LevelHeight; else - location.Z += pTarget->GetTechnoType()->MindControlRingOffset; + location.Z += pType->MindControlRingOffset; if (const auto pOwnerAnim = GameCreate(pAnimType, location)) { @@ -908,3 +912,12 @@ void WarheadTypeExt::ApplyPenetratesTransport(TechnoClass* pTarget, TechnoClass* VocClass::PlayAt(cleanSound, transporterCoords); } } + +void WarheadTypeExt::ExtData::ApplyAmmoModifier(TechnoClass* pTarget) +{ + const int maxAmmo = pTarget->GetTechnoType()->Ammo; + int newCurrentAmmo = this->Ammo + pTarget->Ammo; + + newCurrentAmmo = newCurrentAmmo < 0 ? 0 : newCurrentAmmo; + pTarget->Ammo = newCurrentAmmo > maxAmmo ? maxAmmo : newCurrentAmmo; +}