Skip to content

Penetrates damage on transporter #1766

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

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ This page lists all the individual contributions to the project by their author.
- Fix the bug that Locomotor warhead won't stop working when firer (except for vehicle) stop firing
- Fix the bug that hover vehicle will sink if destroyed on bridge
- Customize squid grapple animation
- Penetrates damage on transporter
- **Apollo** - Translucent SHP drawing patches
- **ststl**:
- Customizable `ShowTimer` priority of superweapons
Expand Down
30 changes: 30 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,36 @@ In `rulesmd.ini`:
RemoveParasite= ; boolean
```

### Penetrates damage on transporter

- Warheads can now damage passenger on impact.
- If `PenetratesTransport.Level` of warhead larger than `PenetratesTransport.Level` of target and it's passengers, it will enable penetrates damage logic on passenger.
- `PenetratesTransport.PassThrough` is the chance of penetration, actual chance will multiply by `PenetratesTransport.PassThroughMultiplier` of target.
- `PenetratesTransport.FatalRate` is the chance of one hit kill passenger, actual change will multiply by `PenetratesTransport.FatalRateMultiplier` of target.
- `PenetratesTransport.DamageAll` control whether it will damage all passengers or random one passenger in transport.
- `PenetratesTransport.DamageMultiplier` is multiplier of damage on passenger.
- `PenetratesTransport.CleanSound` will play when all passengers has been killed.

In `rulesmd.ini`
```ini
[SOMEWARHEAD] ; WarheadType
PenetratesTransport.Level=0 ; integer
PenetratesTransport.PassThrough=1.0 ; double
PenetratesTransport.FatalRate=0.0 ; double
PenetratesTransport.DamageMultiplier=1.0 ; double
PenetratesTransport.DamageAll=false ; boolean
PenetratesTransport.CleanSound= ; sound entry

[SOMETECHNO] ; TechnoType
PenetratesTransport.Level= ; integer
PenetratesTransport.PassThroughMultiplier=1.0 ; double
PenetratesTransport.FatalRateMultiplier=1.0 ; double
PenetratesTransport.DamageMultiplier=1.0 ; double

[CombatDamage]
PenetratesTransport.Level=10 ; integer, default value of technotype's penetrate level
```

### Remove disguise on impact

- Warheads can now remove disguise from disguised spies or mirage tanks. This will work even if the disguised was acquired by default through `PermaDisguise`.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ New:
- [Units can customize the attack voice that plays when using more weapons](New-or-Enhanced-Logics.md#multi-voiceattack) (by FlyStar)
- Customize squid grapple animation (by NetsuNegi)
- [Auto deploy for GI-like infantry](Fixed-or-Improved-Logics.md#auto-deploy-for-gi-like-infantry) (by TaranDahl)
- Penetrates damage on transporter (by NetsuNegi)

Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
3 changes: 3 additions & 0 deletions src/Ext/Rules/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
this->AttackMove_StopWhenTargetAcquired.Read(exINI, GameStrings::General, "AttackMove.StopWhenTargetAcquired");

this->Parasite_GrappleAnim.Read(exINI, GameStrings::AudioVisual, "Parasite.GrappleAnim");

this->PenetratesTransport_Level.Read(exINI, GameStrings::CombatDamage, "PenetratesTransport.Level");

this->AINormalTargetingDelay.Read(exINI, GameStrings::General, "AINormalTargetingDelay");
this->PlayerNormalTargetingDelay.Read(exINI, GameStrings::General, "PlayerNormalTargetingDelay");
Expand Down Expand Up @@ -554,6 +556,7 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->AttackMove_StopWhenTargetAcquired)
.Process(this->Parasite_GrappleAnim)
.Process(this->InfantryAutoDeploy)
.Process(this->PenetratesTransport_Level)
;
}

Expand Down
5 changes: 5 additions & 0 deletions src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ class RulesExt
Nullable<bool> AttackMove_StopWhenTargetAcquired;

NullableIdx<AnimTypeClass> Parasite_GrappleAnim;

Valueable<int> PenetratesTransport_Level;

// cache tint color
int TintColorIronCurtain;
Expand Down Expand Up @@ -449,7 +451,10 @@ class RulesExt
, AttackMove_StopWhenTargetAcquired { }

, Parasite_GrappleAnim {}

, InfantryAutoDeploy { false }

, PenetratesTransport_Level { 10 }
{ }

virtual ~ExtData() = default;
Expand Down
34 changes: 34 additions & 0 deletions src/Ext/Techno/Hooks.ReceiveDamage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ DEFINE_HOOK(0x702672, TechnoClass_ReceiveDamage_RevengeWeapon, 0x5)
return 0;
}

DEFINE_HOOK(0x518434, InfantryClass_ReceiveDamage_SkipDeathAnim, 0x7)
{
enum { SkipDeathAnim = 0x5185F1 };

GET(InfantryClass*, pThis, ESI);

return pThis->Transporter ? SkipDeathAnim : 0;
}

// Issue #237 NotHuman additional animations support
// Author: Otamaa
DEFINE_HOOK(0x518505, InfantryClass_ReceiveDamage_NotHuman, 0x4)
Expand Down Expand Up @@ -393,3 +402,28 @@ DEFINE_HOOK(0x701E18, TechnoClass_ReceiveDamage_ReflectDamage, 0x7)

return 0;
}

DEFINE_HOOK(0x702823, TechnoClass_ReceiveDamage_SkipDamagedParticle, 0x7)
{
enum { SkipParticle = 0x702A25, RemoveParticle = 0x70283C, SpawnParticle = 0x702857 };

GET(TechnoClass*, pThis, ESI);

if (pThis->Transporter)
return SkipParticle;

return pThis->GetHealthPercentage() <= RulesClass::Instance->ConditionYellow ? SpawnParticle : RemoveParticle;
}

DEFINE_HOOK(0x737E6E, UnitClass_ReceiveDamage_SkipExplode, 0xA)
{
enum { ContinueCheck = 0x737E78, SkipExplode = 0x737F74 };

GET(UnitClass*, pThis, ESI);

if (pThis->Transporter)
return SkipExplode;

R->EAX(pThis->GetHeight());
return ContinueCheck;
}
12 changes: 11 additions & 1 deletion src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,12 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->AttackMove_StopWhenTargetAcquired.Read(exINI, pSection, "AttackMove.StopWhenTargetAcquired");
this->AttackMove_PursuitTarget.Read(exINI, pSection, "AttackMove.PursuitTarget");

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

this->PenetratesTransport_Level.Read(exINI, pSection, "PenetratesTransport.Level");
this->PenetratesTransport_PassThroughMultiplier.Read(exINI, pSection, "PenetratesTransport.PassThroughMultiplier");
this->PenetratesTransport_FatalRateMultiplier.Read(exINI, pSection, "PenetratesTransport.FatalRateMultiplier");
this->PenetratesTransport_DamageMultiplier.Read(exINI, pSection, "PenetratesTransport.DamageMultiplier");

// Ares 0.2
this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius");
Expand Down Expand Up @@ -1580,6 +1585,11 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->AttackMove_Follow_IfMindControlIsFull)
.Process(this->AttackMove_StopWhenTargetAcquired)
.Process(this->AttackMove_PursuitTarget)

.Process(this->PenetratesTransport_Level)
.Process(this->PenetratesTransport_PassThroughMultiplier)
.Process(this->PenetratesTransport_FatalRateMultiplier)
.Process(this->PenetratesTransport_DamageMultiplier)

.Process(this->MultiWeapon)
.Process(this->MultiWeapon_IsSecondary)
Expand Down
10 changes: 10 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ class TechnoTypeExt
Nullable<bool> AttackMove_StopWhenTargetAcquired;
Valueable<bool> AttackMove_PursuitTarget;

Nullable<int> PenetratesTransport_Level;
Valueable<double> PenetratesTransport_PassThroughMultiplier;
Valueable<double> PenetratesTransport_FatalRateMultiplier;
Valueable<double> PenetratesTransport_DamageMultiplier;

Valueable<bool> MultiWeapon;
ValueableVector<bool> MultiWeapon_IsSecondary;
Valueable<int> MultiWeapon_SelectCount;
Expand Down Expand Up @@ -775,6 +780,11 @@ class TechnoTypeExt
, AttackMove_StopWhenTargetAcquired { }
, AttackMove_PursuitTarget { false }

, PenetratesTransport_Level {}
, PenetratesTransport_PassThroughMultiplier { 1.0 }
, PenetratesTransport_FatalRateMultiplier { 1.0 }
, PenetratesTransport_DamageMultiplier { 1.0 }

, MultiWeapon { false }
, MultiWeapon_IsSecondary {}
, MultiWeapon_SelectCount { 2 }
Expand Down
15 changes: 15 additions & 0 deletions src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
if (this->AffectsAbovePercent > this->AffectsBelowPercent)
Debug::Log("[Developer warning][%s] AffectsAbovePercent is bigger than AffectsBelowPercent, the warhead will never activate!\n", pSection);

this->PenetratesTransport_Level.Read(exINI, pSection, "PenetratesTransport.Level");
this->PenetratesTransport_PassThrough.Read(exINI, pSection, "PenetratesTransport.PassThrough");
this->PenetratesTransport_FatalRate.Read(exINI, pSection, "PenetratesTransport.FatalRate");
this->PenetratesTransport_DamageMultiplier.Read(exINI, pSection, "PenetratesTransport.DamageMultiplier");
this->PenetratesTransport_DamageAll.Read(exINI, pSection, "PenetratesTransport.DamageAll");
this->PenetratesTransport_CleanSound.Read(exINI, pSection, "PenetratesTransport.CleanSound");

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

Expand Down Expand Up @@ -356,6 +363,7 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
|| this->AttachEffects.RemoveGroups.size() > 0
|| this->BuildingSell
|| this->BuildingUndeploy
|| this->PenetratesTransport_Level > 0
);

char tempBuffer[32];
Expand Down Expand Up @@ -528,6 +536,13 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->AffectsNeutral)
.Process(this->HealthCheck)

.Process(this->PenetratesTransport_Level)
.Process(this->PenetratesTransport_PassThrough)
.Process(this->PenetratesTransport_FatalRate)
.Process(this->PenetratesTransport_DamageMultiplier)
.Process(this->PenetratesTransport_DamageAll)
.Process(this->PenetratesTransport_CleanSound)

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

Expand Down
17 changes: 16 additions & 1 deletion src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ class WarheadTypeExt
Valueable<double> AffectsAbovePercent;
Valueable<bool> AffectsNeutral;

Valueable<int> PenetratesTransport_Level;
Valueable<double> PenetratesTransport_PassThrough;
Valueable<double> PenetratesTransport_FatalRate;
Valueable<double> PenetratesTransport_DamageMultiplier;
Valueable<bool> PenetratesTransport_DamageAll;
ValueableIdx<VocClass> PenetratesTransport_CleanSound;

// Ares tags
// http://ares-developers.github.io/Ares-docs/new/warheads/general.html
Valueable<bool> AffectsEnemies;
Expand Down Expand Up @@ -373,6 +380,13 @@ class WarheadTypeExt
, AffectsAbovePercent { 0.0 }
, AffectsNeutral { true }

, PenetratesTransport_Level { 0 }
, PenetratesTransport_PassThrough { 1.0 }
, PenetratesTransport_FatalRate { 0.0 }
, PenetratesTransport_DamageMultiplier { 1.0 }
, PenetratesTransport_DamageAll { false }
, PenetratesTransport_CleanSound { -1 }

, AffectsEnemies { true }
, AffectsOwner {}
, EffectsRequireVerses { true }
Expand Down Expand Up @@ -426,13 +440,14 @@ class WarheadTypeExt
void InterceptBullets(TechnoClass* pOwner, BulletClass* pInterceptor, const 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, const CoordStruct& coords, int damage, TechnoClass* pOwner = nullptr, bool bulletWasIntercepted = false);
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);
void ApplyPenetratesTransport(TechnoClass* pTarget, TechnoClass* pInvoker, HouseClass* pInvokerHouse, const CoordStruct& coords, int damage);
double GetCritChance(TechnoClass* pFirer) const;
};

Expand Down
Loading
Loading