diff --git a/CREDITS.md b/CREDITS.md index 62a03a1a1e..f1fdf90cfd 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -766,6 +766,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 d6d4f24f32..a7e130c1bb 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2962,6 +2962,27 @@ UnlimboDetonate.KeepSelected=false ; 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 ### AreaFire target customization diff --git a/docs/Whats-New.md b/docs/Whats-New.md index bc789670cd..a4b5dde625 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -576,6 +576,7 @@ New: - [Customize `HarvesterLoadRate`](Fixed-or-Improved-Logics.md#customize-harvesterloadrate) (by Noble_Fish) - [Toggle to prevent `ShrapnelWeapon` from targeting buildings multiple times](Fixed-or-Improved-Logics.md#shrapnel-enhancements) (by Starkku) - [Laser drawing Z-adjust customization](Fixed-or-Improved-Logics.md#laser-z-adjust) (by Starkku) +- [Radar / Power Outage warhead](New-or-Enhanced-Logics.md#radar--power-outage-warhead) (by WingHwy) - Customize `HarvesterDumpRate` (by Noble_Fish) - Allow users to define the time interval of `DisplayIncome` (by Noble_Fish) diff --git a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po index 094b5e7d78..e1a6783459 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po +++ b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po @@ -2561,6 +2561,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 d18f8cb6bf..517f503c65 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 @@ -6111,6 +6111,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 bd1fe2a40e..ded9682aa6 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po +++ b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po @@ -1893,6 +1893,11 @@ msgid "" "Logics.md#laser-z-adjust) (by Starkku)" msgstr "[自定义激光绘制的 Z 深校正值](Fixed-or-Improved-Logics.md#laser-z-adjust)(by Starkku)" +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 c2c000a655..d91a7b088e 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -308,6 +308,13 @@ void WarheadTypeExt::ExtData::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"); @@ -695,6 +702,13 @@ void WarheadTypeExt::ExtData::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 88be830a6d..d4662b62eb 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -169,6 +169,13 @@ class WarheadTypeExt Nullable JumpjetNoWobbles; Nullable JumpjetDeviation; + Valueable RadarOutage_Duration; + Valueable RadarOutage_Cap; + Valueable RadarOutage_AffectsHouse; + Valueable PowerOutage_Duration; + Valueable PowerOutage_Cap; + Valueable PowerOutage_AffectsHouse; + Valueable Nonprovocative; Nullable MergeBuildingDamage; @@ -426,6 +433,13 @@ class WarheadTypeExt , JumpjetNoWobbles {} , JumpjetDeviation {} + , RadarOutage_Duration { 0 } + , RadarOutage_Cap { 0 } + , RadarOutage_AffectsHouse { AffectedHouse::Enemies } + , PowerOutage_Duration { 0 } + , PowerOutage_Cap { 0 } + , PowerOutage_AffectsHouse { AffectedHouse::Enemies } + , Nonprovocative { false } , MergeBuildingDamage {} diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index b8fe245d42..5d8860ddee 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -99,6 +99,46 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, 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))