diff --git a/CREDITS.md b/CREDITS.md index f7f63d5b13..3b61f26aa4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -868,6 +868,7 @@ This page lists all the individual contributions to the project by their author. - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix - Destroyed unit leaves sensors bugfix - **FrozenFog** - Hotkey for deselect object from current selection +- **WingHwy** - Radar / Power Outage warhead - **Aephiex** - initial fix for Ares academy not working on the initial payloads of vehicles built from a war factory - **Multfinite** - Allow to toggle main exception handler via command line argument `-ExceptionHandler=boolean` - **hejiajun107, Xkein** - Fix a jumpjet crash related to voxel shadow drawing diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 12847494aa..8e28a2e50f 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -3244,6 +3244,27 @@ UnlimboDetonate.KeepSelected=true ; boolean `UnlimboDetonate` cannot be used in conjunction with `Parasite`. ``` +### Radar / Power Outage warhead + +- Now you can use the following tags to make the warhead cause a radar or power outage to the affected houses for a specified duration. +- `RadarOutage` disables the radar display (identical to a Lightning Storm), while `PowerOutage` causes a blackout (identical to spy infiltration on a Power Plant). +- If `Duration` is **positive**, it stacks onto the current outage timer, unless `Cap` is **negative** — then the effect does not stack and only the longest single duration is kept. +- If `Duration` is **negative**, it reduces the current outage timer. +- When `Cap` is **positive**, it acts as a ceiling for stacking or a floor for reduction. +- Setting `Cap` to **0** with a negative `Duration` removes the outage entirely. +- The final duration never goes below zero. + +In `rulesmd.ini`: +```ini +[SOMEWARHEAD] ; WarheadType +RadarOutage.Duration=0 ; integer, game frames +RadarOutage.Cap=0 ; integer +RadarOutage.AffectsHouse=enemies ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +PowerOutage.Duration=0 ; integer, game frames +PowerOutage.Cap=0 ; integer +PowerOutage.AffectsHouse=enemies ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +``` + ## Weapons ### Allow Laser drawing position update diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 63e84baff4..491bb111d7 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -636,6 +636,7 @@ HideShakeEffects=false ; boolean - Separately define the global default values of TerrainTypes' `IsPassable` and `CanBeBuiltOn` based on `SpawnsTiberium` (by Noble_Fish) - Customize reveal radius of `RevealToAll` (by NetsuNegi) - [Customize whether aircraft is a cargo plane](Fixed-or-Improved-Logics.md#customize-whether-aircraft-is-a-cargo-plane) (by TaranDahl) +- [Radar / Power Outage warhead](New-or-Enhanced-Logics.md#radar--power-outage-warhead) (by WingHwy) #### Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po index 9ae5d4052d..8486dc5f7d 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po +++ b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po @@ -2926,6 +2926,9 @@ msgstr "单位被摧毁后遗留反隐区域的 bug 修复" msgid "**FrozenFog** - Hotkey for deselect object from current selection" msgstr "**FrozenFog** - 从当前已选中中取消选择对象的快捷键" +msgid "**WingHwy** - Radar / Power Outage warhead" +msgstr "" + msgid "" "**Aephiex** - initial fix for Ares academy not working on the initial " "payloads of vehicles built from a war factory" diff --git a/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po b/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po index af9ee11ca3..17cc65ae83 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po +++ b/docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po @@ -6472,6 +6472,42 @@ msgstr "`UnlimboDetonate.KeepSelected` 允许单位进出 Limbo 状态前保留 msgid "`UnlimboDetonate` cannot be used in conjunction with `Parasite`." msgstr "`UnlimboDetonate` 不能与 `Parasite` 共用。" +msgid "Radar / Power Outage warhead" +msgstr "" + +msgid "" +"Now you can use the following tags to make the warhead cause a radar or " +"power outage to the affected houses for a specified duration." +msgstr "" + +msgid "" +"`RadarOutage` disables the radar display (identical to a Lightning " +"Storm), while `PowerOutage` causes a blackout (identical to spy " +"infiltration on a Power Plant)." +msgstr "" + +msgid "" +"If `Duration` is **positive**, it stacks onto the current outage timer, " +"unless `Cap` is **negative** — then the effect does not stack and only " +"the longest single duration is kept." +msgstr "" + +msgid "If `Duration` is **negative**, it reduces the current outage timer." +msgstr "" + +msgid "" +"When `Cap` is **positive**, it acts as a ceiling for stacking or a floor " +"for reduction." +msgstr "" + +msgid "" +"Setting `Cap` to **0** with a negative `Duration` removes the outage " +"entirely." +msgstr "" + +msgid "The final duration never goes below zero." +msgstr "" + msgid "Weapons" msgstr "武器" diff --git a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po index a88e1fc702..65f6ede2e1 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po +++ b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po @@ -2295,6 +2295,11 @@ msgstr "" "[自定义飞机是否是cargo plane](Fixed-or-Improved-Logics.md#customize-whether-" "aircraft-is-a-cargo-plane)(by TaranDahl)" +msgid "" +"[Radar / Power Outage warhead](New-or-Enhanced-Logics.md#radar--power-" +"outage-warhead) (by WingHwy)" +msgstr "" + msgid "Vanilla fixes:" msgstr "原版问题修复:" diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index b98feb4651..4f0b25d7fe 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -334,6 +334,13 @@ void WarheadTypeExt::LoadFromINIFile(CCINIClass* const pINI) this->JumpjetNoWobbles.Read(exINI, pSection, "JumpjetNoWobbles"); this->JumpjetDeviation.Read(exINI, pSection, "JumpjetDeviation"); + this->RadarOutage_Duration.Read(exINI, pSection, "RadarOutage.Duration"); + this->RadarOutage_Cap.Read(exINI, pSection, "RadarOutage.Cap"); + this->RadarOutage_AffectsHouse.Read(exINI, pSection, "RadarOutage.AffectsHouse"); + this->PowerOutage_Duration.Read(exINI, pSection, "PowerOutage.Duration"); + this->PowerOutage_Cap.Read(exINI, pSection, "PowerOutage.Cap"); + this->PowerOutage_AffectsHouse.Read(exINI, pSection, "PowerOutage.AffectsHouse"); + this->Nonprovocative.Read(exINI, pSection, "Nonprovocative"); this->MergeBuildingDamage.Read(exINI, pSection, "MergeBuildingDamage"); @@ -738,6 +745,13 @@ void WarheadTypeExt::Serialize(T& Stm) .Process(this->JumpjetNoWobbles) .Process(this->JumpjetDeviation) + .Process(this->RadarOutage_Duration) + .Process(this->RadarOutage_Cap) + .Process(this->RadarOutage_AffectsHouse) + .Process(this->PowerOutage_Duration) + .Process(this->PowerOutage_Cap) + .Process(this->PowerOutage_AffectsHouse) + .Process(this->Nonprovocative) .Process(this->MergeBuildingDamage) diff --git a/src/Ext/WarheadType/Body.h b/src/Ext/WarheadType/Body.h index 9a9c5627e6..c50b01951c 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -263,6 +263,13 @@ class WarheadTypeExt final : public AbstractTypeExt Valueable Taunt; + Valueable RadarOutage_Duration; + Valueable RadarOutage_Cap; + Valueable RadarOutage_AffectsHouse; + Valueable PowerOutage_Duration; + Valueable PowerOutage_Cap; + Valueable PowerOutage_AffectsHouse; + // Ares tags // http://ares-developers.github.io/Ares-docs/new/warheads/general.html Valueable AffectsEnemies; @@ -551,6 +558,13 @@ class WarheadTypeExt final : public AbstractTypeExt , ApplyPerTargetEffectsOnDetonate {} , Taunt { false } + + , RadarOutage_Duration { 0 } + , RadarOutage_Cap { 0 } + , RadarOutage_AffectsHouse { AffectedHouse::Enemies } + , PowerOutage_Duration { 0 } + , PowerOutage_Cap { 0 } + , PowerOutage_AffectsHouse { AffectedHouse::Enemies } { } void ApplyConvert(HouseClass* pHouse, TechnoClass* pTarget); diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index b69a39d23f..8bb00863ff 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -118,6 +118,46 @@ void WarheadTypeExt::Detonate(TechnoClass* pOwner, HouseClass* pHouse, BulletExt MapClass::Instance.PlacePowerupCrate(CellClass::Coord2Cell(coords), this->SpawnsCrate_Types.at(index)); } + if (this->RadarOutage_Duration) + { + for (const auto pTargetHouse : HouseClass::Array) + { + if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() + && !pTargetHouse->Type->MultiplayPassive + && EnumFunctions::CanTargetHouse(this->RadarOutage_AffectsHouse, pHouse, pTargetHouse)) + { + int newLeft = Helpers::Alex::getCappedDuration( + pTargetHouse->RadarBlackoutTimer.GetTimeLeft(), + this->RadarOutage_Duration, + this->RadarOutage_Cap + ); + newLeft = Math::max(newLeft, 0); + pTargetHouse->RadarBlackoutTimer.Start(newLeft); + pTargetHouse->RecheckRadar = true; + } + } + } + + if (this->PowerOutage_Duration) + { + for (const auto pTargetHouse : HouseClass::Array) + { + if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() + && !pTargetHouse->Type->MultiplayPassive + && EnumFunctions::CanTargetHouse(this->PowerOutage_AffectsHouse, pHouse, pTargetHouse)) + { + int newLeft = Helpers::Alex::getCappedDuration( + pTargetHouse->PowerBlackoutTimer.GetTimeLeft(), + this->PowerOutage_Duration, + this->PowerOutage_Cap + ); + newLeft = Math::max(newLeft, 0); + pTargetHouse->PowerBlackoutTimer.Start(newLeft); + pTargetHouse->RecheckPower = true; + } + } + } + for (const int swIdx : this->LaunchSW) { if (const auto pSuper = pHouse->Supers.GetItem(swIdx))