Skip to content
Open
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ This page lists all the individual contributions to the project by their author.
- **Flactine**
- Add target filtering options to attacheffect system
- Add veterancy-based target filtering for weapons and warheads
- Add a new AutoDeath condition based on the owner's power status
- **tyuah8**:
- Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix
- Destroyed unit leaves sensors bugfix
Expand Down
4 changes: 4 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,9 @@ Both `InitialStrength` and `InitialStrength.Cloning` never surpass the type's `S
- `Technos(Dont)Exist.Any` controls whether or not a single listed TechnoType is enough to satisfy the requirement or if all are required.
- `Technos(Dont)Exist.AllowLimboed` controls whether or not limboed TechnoTypes (f.ex those in transports) are counted.
- `Technos(Dont)Exist.Houses` controls which houses are checked.
- `PlayerPower`: The object will die if its owner's power status matches the configured state.
- `low` / `consumer`: Trigger when the owner is in low power.
- `normal`: Trigger when the owner is not in low power.

- The auto-death behavior can be chosen from the following:
- `kill`: The object will be destroyed normally.
Expand All @@ -1950,6 +1953,7 @@ AutoDeath.TechnosExist= ; List of TechnoTypes
AutoDeath.TechnosExist.Any=true ; boolean
AutoDeath.TechnosExist.AllowLimboed=false ; boolean
AutoDeath.TechnosExist.Houses=owner ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all)
AutoDeath.PlayerPowerStatus=none ; Player Power Enumeration (none|low/consumer|normal)
```

```{note}
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ HideShakeEffects=false ; boolean
- Add `ClampToScreen` tag for `BannerType` (defaults to `true`) to control whether banner position is clamped to the visible area (by Chang_zhi)
- [Customizable Berzerk mission](Fixed-or-Improved-Logics.md#enhanced-berzerk-behavior) (by TaranDahl)
- [Tank Bunker foundation and state update delay improvements](Fixed-or-Improved-Logics.md#tank-bunker-improvements) (by Starkku)
- [AutoDeath based on player power status](New-or-Enhanced-Logics.md#kill-object-automatically) (by Flactine)

#### Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
12 changes: 12 additions & 0 deletions src/Ext/Techno/Body.Update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,18 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo)
: std::all_of(vTypes.begin(), vTypes.end(), existSingleType);
};

// death if player power status is not as specified
if (pTypeExt->AutoDeath_PlayerPowerStatus != PlayerPowerStatus::None)
{
const bool isLowPower = pOwner->PowerDrain > pOwner->PowerOutput;

if ((pTypeExt->AutoDeath_PlayerPowerStatus == PlayerPowerStatus::Normal && !isLowPower) || (pTypeExt->AutoDeath_PlayerPowerStatus == PlayerPowerStatus::Consumer && isLowPower))
Comment thread
TaranDahl marked this conversation as resolved.
Outdated
{
TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo);
return true;
}
}

// death if listed technos don't exist
if (!pTypeExt->AutoDeath_TechnosDontExist.empty())
{
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->AutoDeath_TechnosExist_Any.Read(exINI, pSection, "AutoDeath.TechnosExist.Any");
this->AutoDeath_TechnosExist_AllowLimboed.Read(exINI, pSection, "AutoDeath.TechnosExist.AllowLimboed");
this->AutoDeath_TechnosExist_Houses.Read(exINI, pSection, "AutoDeath.TechnosExist.Houses");
this->AutoDeath_PlayerPowerStatus.Read(exINI, pSection, "AutoDeath.PlayerPowerStatus");

this->Slaved_OwnerWhenMasterKilled.Read(exINI, pSection, "Slaved.OwnerWhenMasterKilled");
this->SlavesFreeSound.Read(exINI, pSection, "SlavesFreeSound");
Expand Down Expand Up @@ -1551,6 +1552,7 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->AutoDeath_TechnosExist_Any)
.Process(this->AutoDeath_TechnosExist_AllowLimboed)
.Process(this->AutoDeath_TechnosExist_Houses)
.Process(this->AutoDeath_PlayerPowerStatus)

.Process(this->Slaved_OwnerWhenMasterKilled)
.Process(this->SlavesFreeSound)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class TechnoTypeExt
Valueable<bool> AutoDeath_TechnosExist_Any;
Valueable<bool> AutoDeath_TechnosExist_AllowLimboed;
Valueable<AffectedHouse> AutoDeath_TechnosExist_Houses;
Valueable<PlayerPowerStatus> AutoDeath_PlayerPowerStatus;

Valueable<SlaveChangeOwnerType> Slaved_OwnerWhenMasterKilled;
NullableIdx<VocClass> SlavesFreeSound;
Expand Down Expand Up @@ -656,6 +657,7 @@ class TechnoTypeExt
, AutoDeath_TechnosExist_Any { true }
, AutoDeath_TechnosExist_AllowLimboed { true }
, AutoDeath_TechnosExist_Houses { AffectedHouse::Owner }
, AutoDeath_PlayerPowerStatus { PlayerPowerStatus::None }

, Slaved_OwnerWhenMasterKilled { SlaveChangeOwnerType::Killer }
, SlavesFreeSound {}
Expand Down
7 changes: 7 additions & 0 deletions src/Utilities/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ enum class AutoDeathBehavior
Sell = 2, // buildings only
};

enum class PlayerPowerStatus
{
None = 0,
Normal = 1, // not low power
Consumer = 2, // low power
};

enum class SelfHealGainType
{
NoHeal = 0,
Expand Down
27 changes: 27 additions & 0 deletions src/Utilities/TemplateDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,33 @@ if(_strcmpi(parser.value(), #name) == 0){ value = __uuidof(name ## LocomotionCla
Debug::INIParseFailed(pSection, pKey, pCur);
}
}

template <>
inline bool read<PlayerPowerStatus>(PlayerPowerStatus& value, INI_EX& parser, const char* pSection, const char* pKey)
{
if (parser.ReadString(pSection, pKey))
{
static const std::pair<const char*, PlayerPowerStatus> Names[] =
{
{"none", PlayerPowerStatus::None},
{"consumer", PlayerPowerStatus::Consumer},
{"low", PlayerPowerStatus::Consumer},
{"normal", PlayerPowerStatus::Normal},
};

for (auto const& [name, val] : Names)
{
if (_strcmpi(parser.value(), name) == 0)
{
value = val;
return true;
}
}

Debug::INIParseFailed(pSection, pKey, parser.value(), "Expected a valid PlayerPowerStatus (none, normal, low|consumer");
}
return false;
}
}

// Valueable
Expand Down
Loading