Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Shield.AttachTypes= ; List of ShieldType names
Shield.RemoveTypes= ; List of ShieldType names
Shield.ReplaceOnly=false ; boolean
Shield.ReplaceNonRespawning=false ; boolean
Shield.MinimumReplaceDelay=0 ; integer, game frames
Shield.InheritStateOnReplace=false ; boolean
```
- Now you can have a shield for any TechnoType. It serves as a second health pool with independent `Armor` and `Strength` values.
Expand All @@ -83,7 +84,7 @@ Shield.InheritStateOnReplace=false ; boolean
- `IdleAnim.TemporalAction` indicates what happens to the animation when the shield is attacked by temporal weapons.
- `BreakAnim`, if set, will be played when the shield has been broken.
- `HitAnim`, if set, will be played when the shield is attacked, similar to `WeaponNullifyAnim` for Iron Curtain.
- `BreakWeapon`, if set, will be fired at the TechnoType once the shield breaks. Note: for this to work it requires that the WeaponType used has been explicitly listed in `[WeaponTypes]`, which is only available with Ares.
- `BreakWeapon`, if set, will be fired at the TechnoType once the shield breaks.
- `AbsorbPercent` controls the percentage of damage that will be absorbed by the shield. Defaults to 1.0, meaning full damage absorption.
- `PassPercent` controls the percentage of damage that will *not* be absorbed by the shield, and will be dealt to the unit directly even if the shield is active. Defaults to 0.0 - no penetration.
- `AllowTransfer` controls whether or not the shield can be transferred if the TechnoType changes (such as `(Un)DeploysInto` or Ares type conversion). If not set, defaults to true if shield was attached via `Shield.AttachTypes`, otherwise false.
Expand All @@ -105,6 +106,7 @@ Shield.InheritStateOnReplace=false ; boolean
- `Shield.AttachTypes` & `Shield.RemoveTypes` allows listing ShieldTypes that are attached or removed, respectively from any targets affected by the warhead (positive `Verses` values). Normally only first listed ShieldType in `Shield.AttachTypes` is applied.
- If `Shield.ReplaceOnly` is set, shields from `Shield.AttachTypes` are only applied to affected targets from which shields were simultaneously removed, matching the order listed in `Shield.RemoveTypes`. If `Shield.AttachTypes` contains less items than `Shield.RemoveTypes`, last item from the former is used for any remaining removed shields.
- If `Shield.ReplaceNonRespawning` is set, shield from `Shield.AttachTypes` replaces existing shields that have been broken and cannot respawn on their own.
- `Shield.MinimumReplaceDelay` can be used to control how long after the shield has been broken (in game frames) can it be replaced. If not enough frames have passed, it won't be replaced.
- If `Shield.InheritStateOnReplace` is set, shields replaced via `Shield.ReplaceOnly` inherit the current strength (relative to ShieldType `Strength`) of the previous shield and whether or not the shield was currently broken. Self-healing and respawn timers are always reset.

### Laser Trails
Expand Down
4 changes: 3 additions & 1 deletion src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Shield_Break.Read(exINI, pSection, "Shield.Break");
this->Shield_BreakAnim.Read(exINI, pSection, "Shield.BreakAnim");
this->Shield_HitAnim.Read(exINI, pSection, "Shield.HitAnim");
this->Shield_BreakWeapon.Read(exINI, pSection, "Shield.BreakWeapon");
this->Shield_BreakWeapon.Read(exINI, pSection, "Shield.BreakWeapon", true);
this->Shield_AbsorbPercent.Read(exINI, pSection, "Shield.AbsorbPercent");
this->Shield_PassPercent.Read(exINI, pSection, "Shield.PassPercent");
this->Shield_Respawn_Duration.Read(exINI, pSection, "Shield.Respawn.Duration");
Expand All @@ -86,6 +86,7 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Shield_ReplaceOnly.Read(exINI, pSection, "Shield.ReplaceOnly");
this->Shield_ReplaceNonRespawning.Read(exINI, pSection, "Shield.ReplaceNonRespawning");
this->Shield_InheritStateOnReplace.Read(exINI, pSection, "Shield.InheritStateOnReplace");
this->Shield_MinimumReplaceDelay.Read(exINI, pSection, "Shield.MinimumReplaceDelay");
this->Shield_AffectTypes.Read(exINI, pSection, "Shield.AffectTypes");

this->NotHuman_DeathSequence.Read(exINI, pSection, "NotHuman.DeathSequence");
Expand Down Expand Up @@ -141,6 +142,7 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->Shield_ReplaceOnly)
.Process(this->Shield_ReplaceNonRespawning)
.Process(this->Shield_InheritStateOnReplace)
.Process(this->Shield_MinimumReplaceDelay)
.Process(this->Shield_AffectTypes)

.Process(this->NotHuman_DeathSequence)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class WarheadTypeExt
Valueable<bool> Shield_ReplaceOnly;
Valueable<bool> Shield_ReplaceNonRespawning;
Valueable<bool> Shield_InheritStateOnReplace;
Valueable<int> Shield_MinimumReplaceDelay;
ValueableVector<ShieldTypeClass*> Shield_AffectTypes;

private:
Expand Down Expand Up @@ -116,6 +117,7 @@ class WarheadTypeExt
, Shield_ReplaceOnly { false }
, Shield_ReplaceNonRespawning { false }
, Shield_InheritStateOnReplace { false }
, Shield_MinimumReplaceDelay { 0 }
, Shield_AffectTypes {}

, NotHuman_DeathSequence { -1 }
Expand Down
3 changes: 2 additions & 1 deletion src/Ext/WarheadType/Detonate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ void WarheadTypeExt::ExtData::ApplyShieldModifiers(TechnoClass* pTarget)

if (shieldType)
{
if (shieldType->Strength && (!pExt->Shield || (this->Shield_ReplaceNonRespawning && pExt->Shield->IsBrokenAndNonRespawning())))
if (shieldType->Strength && (!pExt->Shield || (this->Shield_ReplaceNonRespawning && pExt->Shield->IsBrokenAndNonRespawning() &&
pExt->Shield->GetFramesSinceLastBroken() >= this->Shield_MinimumReplaceDelay)))
{
pExt->CurrentShieldType = shieldType;
pExt->Shield = std::make_unique<ShieldClass>(pTarget, true);
Expand Down
9 changes: 8 additions & 1 deletion src/New/Entity/ShieldClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ void ShieldClass::SelfHealing()

if (percentageAmount != 0)
{
if (this->HP < this->Type->Strength && timer->StartTime == -1)
if ((this->HP < this->Type->Strength || percentageAmount < 0) && timer->StartTime == -1)
timer->Start(rate);

if (this->HP > 0 && timer->Completed())
Expand Down Expand Up @@ -525,6 +525,8 @@ void ShieldClass::BreakShield(AnimTypeClass* pBreakAnim, WeaponTypeClass* pBreak

const auto pWeaponType = pBreakWeapon ? pBreakWeapon : this->Type->BreakWeapon.Get(nullptr);

this->LastBreakFrame = Unsorted::CurrentFrame;

if (pWeaponType)
TechnoExt::FireWeaponAtSelf(this->Techno, pWeaponType);
}
Expand Down Expand Up @@ -768,6 +770,11 @@ ShieldTypeClass* ShieldClass::GetType()
return this->Type;
}

int ShieldClass::GetFramesSinceLastBroken()
{
return Unsorted::CurrentFrame - this->LastBreakFrame;
}

bool ShieldClass::IsActive()
{
return
Expand Down
3 changes: 3 additions & 0 deletions src/New/Entity/ShieldClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ShieldClass
bool IsAvailable();
bool IsBrokenAndNonRespawning();
ShieldTypeClass* GetType();
int GetFramesSinceLastBroken();

static void SyncShieldToAnother(TechnoClass* pFrom, TechnoClass* pTo);

Expand Down Expand Up @@ -86,6 +87,8 @@ class ShieldClass
double Respawn_Warhead;
int Respawn_Rate_Warhead;

int LastBreakFrame;

ShieldTypeClass* Type;

struct Timers
Expand Down
2 changes: 1 addition & 1 deletion src/New/Type/ShieldTypeClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void ShieldTypeClass::LoadFromINI(CCINIClass* pINI)

this->BreakAnim.Read(exINI, pSection, "BreakAnim");
this->HitAnim.Read(exINI, pSection, "HitAnim");
this->BreakWeapon.Read(exINI, pSection, "BreakWeapon");
this->BreakWeapon.Read(exINI, pSection, "BreakWeapon", true);

this->AbsorbPercent.Read(exINI, pSection, "AbsorbPercent");
this->PassPercent.Read(exINI, pSection, "PassPercent");
Expand Down