Skip to content
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,7 @@ This page lists all the individual contributions to the project by their author.
- Add target filtering options to attacheffect system
- Add veterancy-based target filtering for weapons and warheads
- Recipient-specific message and EVA on superweapon activation
- 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
10 changes: 10 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1965,6 +1965,13 @@ 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.
- `PlayerPowerStatus`: 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.
- `PlayerMoney.Max` / `PlayerMoney.Min`: The object will die based on the owner's available credits.
- If only `PlayerMoney.Max` is set, triggers when money is not above this value.
- If only `PlayerMoney.Min` is set, triggers when money is not below this value.
- If both are set, triggers when money is **inside the range**.

- The auto-death behavior can be chosen from the following:
- `kill`: The object will be destroyed normally.
Expand All @@ -1991,6 +1998,9 @@ 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)
AutoDeath.PlayerMoneyLessThan=-1 ; integer
AutoDeath.PlayerMoneyMoreThan=-1 ; integer
```

```{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 @@ -605,6 +605,7 @@ HideShakeEffects=false ; boolean
- [Auto-remove earliest beacon](Fixed-or-Improved-Logics.md#auto-remove-earliest-beacon) (by TaranDahl)
- [Customize the step limit of the credits indicator](User-Interface.md#customize-the-step-limit-of-the-credits-indicator) (by Noble_Fish)
- [Disable the credits indicator smooth transition](User-Interface.md#disable-the-credits-indicator-smooth-transition) (by Noble_Fish)
- [AutoDeath based on player power status and player credits](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
21 changes: 21 additions & 0 deletions docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po
Original file line number Diff line number Diff line change
Expand Up @@ -4425,6 +4425,27 @@ msgstr "`Technos(Dont)Exist.AllowLimboed` 控制是否计入虚拟的科技类
msgid "`Technos(Dont)Exist.Houses` controls which houses are checked."
msgstr "`Technos(Dont)Exist.Houses` 控制检查哪些所属方。"

msgid "`PlayerPowerStatus`: The object will die if its owner's power status matches the configured state."
msgstr "`PlayerPowerStatus`:当对象所属方的电力状态符合设定条件时,则对象死亡。"

msgid "`low` / `consumer`: Trigger when the owner is in low power."
msgstr "`low` / `consumer`:当对象所属方处于电力不足状态时触发。"

msgid "`normal`: Trigger when the owner is not in low power."
msgstr "`normal`:当对象所属方未处于电力不足状态时触发。"

msgid "`PlayerMoney.Max` / `PlayerMoney.Min`: The object will die based on the owner's available credits."
msgstr "`PlayerMoney.Max` / `PlayerMoney.Min`:根据对象所属方的资金决定对象是否死亡。"

msgid "If only `PlayerMoney.Max` is set, triggers when money is not above this value."
msgstr "仅设置 `PlayerMoney.Max` 时,当资金不高于该值时触发。"

msgid "If only `PlayerMoney.Min` is set, triggers when money is not below this value."
msgstr "仅设置 `PlayerMoney.Min` 时,当资金不低于该值时触发。"

msgid "If both are set, triggers when money is **inside the range**."
msgstr "同时设置时,资金处于**区间内**时触发。"

msgid "The auto-death behavior can be chosen from the following:"
msgstr "自毁行为有以下选择:"

Expand Down
26 changes: 26 additions & 0 deletions src/Ext/Techno/Body.Update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,32 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo)
: std::all_of(vTypes.begin(), vTypes.end(), existSingleType);
};

if (pTypeExt->AutoDeath_PlayerPowerStatus != PlayerPowerStatus::None)
{
const bool isLowPower = pOwner->HasLowPower();
const auto status = pTypeExt->AutoDeath_PlayerPowerStatus;
const auto isFirstFrame = (Unsorted::CurrentFrame == 0);

if ((status == PlayerPowerStatus::Normal && !isLowPower) || (status == PlayerPowerStatus::Low && isLowPower) && !isFirstFrame)
{
TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo);
return true;
}
}

if (pTypeExt->AutoDeath_PlayerMoney_Max != -1 || pTypeExt->AutoDeath_PlayerMoney_Min != -1)
{
const int maxMoney = pTypeExt->AutoDeath_PlayerMoney_Max;
const int minMoney = pTypeExt->AutoDeath_PlayerMoney_Min;
const int currentMoney = pOwner->Available_Money();

if ((maxMoney == -1 || currentMoney <= maxMoney) && (minMoney == -1 || currentMoney >= minMoney))
{
TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo);
return true;
}
}

// death if listed technos don't exist
if (!pTypeExt->AutoDeath_TechnosDontExist.empty())
{
Expand Down
11 changes: 11 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,14 @@ 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->AutoDeath_PlayerMoney_Max.Read(exINI, pSection, "AutoDeath.PlayerMoney.Max");
this->AutoDeath_PlayerMoney_Min.Read(exINI, pSection, "AutoDeath.PlayerMoney.Min");

if ((this->AutoDeath_PlayerMoney_Max != -1)
&& (this->AutoDeath_PlayerMoney_Min != -1)
&& (this->AutoDeath_PlayerMoney_Max < this->AutoDeath_PlayerMoney_Min))
Debug::Log("[Developer warning][%s] AutoDeath.PlayerMoney.Min is bigger than AutoDeath.PlayerMoney.Max, AutoDeath will never activate!\n", pSection);

this->Slaved_OwnerWhenMasterKilled.Read(exINI, pSection, "Slaved.OwnerWhenMasterKilled");
this->SlavesFreeSound.Read(exINI, pSection, "SlavesFreeSound");
Expand Down Expand Up @@ -1566,6 +1574,9 @@ 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->AutoDeath_PlayerMoney_Max)
.Process(this->AutoDeath_PlayerMoney_Min)

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

Valueable<SlaveChangeOwnerType> Slaved_OwnerWhenMasterKilled;
NullableIdx<VocClass> SlavesFreeSound;
Expand Down Expand Up @@ -661,6 +664,9 @@ class TechnoTypeExt
, AutoDeath_TechnosExist_Any { true }
, AutoDeath_TechnosExist_AllowLimboed { true }
, AutoDeath_TechnosExist_Houses { AffectedHouse::Owner }
, AutoDeath_PlayerPowerStatus { PlayerPowerStatus::None }
, AutoDeath_PlayerMoney_Max { -1 }
, AutoDeath_PlayerMoney_Min { -1 }

, 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
Low = 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::Low},
{"low", PlayerPowerStatus::Low},
{"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