From a92959fc26b976dd0be2ad533a0dcd1e3881d3ac Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sat, 9 May 2026 21:54:45 +0800 Subject: [PATCH 01/16] RadarOutage & PowerOutage by warhead --- src/Ext/WarheadType/Body.cpp | 10 ++++++++++ src/Ext/WarheadType/Body.h | 10 ++++++++++ src/Ext/WarheadType/Detonate.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index c2c000a655..fc22bb7bdd 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -308,6 +308,11 @@ 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_AffectsHouse.Read(exINI, pSection, "RadarOutage.AffectsHouse"); + this->PowerOutage_Duration.Read(exINI, pSection, "PowerOutage.Duration"); + this->PowerOutage_AffectsHouse.Read(exINI, pSection, "PowerOutage.AffectsHouse"); + this->Nonprovocative.Read(exINI, pSection, "Nonprovocative"); this->MergeBuildingDamage.Read(exINI, pSection, "MergeBuildingDamage"); @@ -695,6 +700,11 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm) .Process(this->JumpjetNoWobbles) .Process(this->JumpjetDeviation) + .Process(this->RadarOutage_Duration) + .Process(this->RadarOutage_AffectsHouse) + .Process(this->PowerOutage_Duration) + .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..169daf2300 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -169,6 +169,11 @@ class WarheadTypeExt Nullable JumpjetNoWobbles; Nullable JumpjetDeviation; + Valueable RadarOutage_Duration; + Valueable RadarOutage_AffectsHouse; + Valueable PowerOutage_Duration; + Valueable PowerOutage_AffectsHouse; + Valueable Nonprovocative; Nullable MergeBuildingDamage; @@ -426,6 +431,11 @@ class WarheadTypeExt , JumpjetNoWobbles {} , JumpjetDeviation {} + , RadarOutage_Duration { 0 } + , RadarOutage_AffectsHouse { AffectedHouse::Owner } + , PowerOutage_Duration { 0 } + , PowerOutage_AffectsHouse { AffectedHouse::Owner } + , Nonprovocative { false } , MergeBuildingDamage {} diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index b8fe245d42..1c61366c62 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -99,6 +99,32 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, MapClass::Instance.PlacePowerupCrate(CellClass::Coord2Cell(coords), this->SpawnsCrate_Types.at(index)); } + if (this->RadarOutage_Duration > 0) + { + for (const auto pTargetHouse : HouseClass::Array) + { + if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() + && !pTargetHouse->Type->MultiplayPassive + && EnumFunctions::CanTargetHouse(this->RadarOutage_AffectsHouse, pHouse, pTargetHouse)) + { + pTargetHouse->CreateRadarOutage(this->RadarOutage_Duration); + } + } + } + + if (this->PowerOutage_Duration > 0) + { + for (const auto pTargetHouse : HouseClass::Array) + { + if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() + && !pTargetHouse->Type->MultiplayPassive + && EnumFunctions::CanTargetHouse(this->PowerOutage_AffectsHouse, pHouse, pTargetHouse)) + { + pTargetHouse->CreatePowerOutage(this->PowerOutage_Duration); + } + } + } + for (const int swIdx : this->LaunchSW) { if (const auto pSuper = pHouse->Supers.GetItem(swIdx)) From 5e2d643dde5dfca8b2dc51b1df4db1c5c17a65fa Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 02:07:59 +0800 Subject: [PATCH 02/16] update --- src/Ext/WarheadType/Body.cpp | 4 +++ src/Ext/WarheadType/Body.h | 8 ++++-- src/Ext/WarheadType/Detonate.cpp | 46 +++++++++++++++++++++++++++++--- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index fc22bb7bdd..886484a902 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -309,8 +309,10 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->JumpjetDeviation.Read(exINI, pSection, "JumpjetDeviation"); this->RadarOutage_Duration.Read(exINI, pSection, "RadarOutage.Duration"); + this->RadarOutage_Max.Read(exINI, pSection, "RadarOutage.Max"); this->RadarOutage_AffectsHouse.Read(exINI, pSection, "RadarOutage.AffectsHouse"); this->PowerOutage_Duration.Read(exINI, pSection, "PowerOutage.Duration"); + this->PowerOutage_Max.Read(exINI, pSection, "PowerOutage.Max"); this->PowerOutage_AffectsHouse.Read(exINI, pSection, "PowerOutage.AffectsHouse"); this->Nonprovocative.Read(exINI, pSection, "Nonprovocative"); @@ -701,8 +703,10 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm) .Process(this->JumpjetDeviation) .Process(this->RadarOutage_Duration) + .Process(this->RadarOutage_Max) .Process(this->RadarOutage_AffectsHouse) .Process(this->PowerOutage_Duration) + .Process(this->PowerOutage_Max) .Process(this->PowerOutage_AffectsHouse) .Process(this->Nonprovocative) diff --git a/src/Ext/WarheadType/Body.h b/src/Ext/WarheadType/Body.h index 169daf2300..dc2290339e 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -170,8 +170,10 @@ class WarheadTypeExt Nullable JumpjetDeviation; Valueable RadarOutage_Duration; + Valueable RadarOutage_Max; Valueable RadarOutage_AffectsHouse; Valueable PowerOutage_Duration; + Valueable PowerOutage_Max; Valueable PowerOutage_AffectsHouse; Valueable Nonprovocative; @@ -432,9 +434,11 @@ class WarheadTypeExt , JumpjetDeviation {} , RadarOutage_Duration { 0 } - , RadarOutage_AffectsHouse { AffectedHouse::Owner } + , RadarOutage_Max { 0 } + , RadarOutage_AffectsHouse { AffectedHouse::Enemies } , PowerOutage_Duration { 0 } - , PowerOutage_AffectsHouse { AffectedHouse::Owner } + , PowerOutage_Max { 0 } + , PowerOutage_AffectsHouse { AffectedHouse::Enemies } , Nonprovocative { false } diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index 1c61366c62..1b76e3ee9d 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -99,7 +99,7 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, MapClass::Instance.PlacePowerupCrate(CellClass::Coord2Cell(coords), this->SpawnsCrate_Types.at(index)); } - if (this->RadarOutage_Duration > 0) + if (this->RadarOutage_Duration) { for (const auto pTargetHouse : HouseClass::Array) { @@ -107,12 +107,31 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, && !pTargetHouse->Type->MultiplayPassive && EnumFunctions::CanTargetHouse(this->RadarOutage_AffectsHouse, pHouse, pTargetHouse)) { - pTargetHouse->CreateRadarOutage(this->RadarOutage_Duration); + int duration = this->RadarOutage_Duration; + int currentLeft = pTargetHouse->RadarBlackoutTimer.GetTimeLeft(); + + if (duration < 0) + { + int newLeft = currentLeft + duration; + if (newLeft < 0) + newLeft = 0; + pTargetHouse->RadarBlackoutTimer.Start(newLeft); + } + else + { + int newLeft = currentLeft + duration; + int maxOutage = this->RadarOutage_Max; + if (maxOutage > 0 && newLeft > maxOutage) + newLeft = maxOutage; + pTargetHouse->RadarBlackoutTimer.Start(newLeft); + } + + pTargetHouse->RecheckRadar = true; } } } - if (this->PowerOutage_Duration > 0) + if (this->PowerOutage_Duration) { for (const auto pTargetHouse : HouseClass::Array) { @@ -120,7 +139,26 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, && !pTargetHouse->Type->MultiplayPassive && EnumFunctions::CanTargetHouse(this->PowerOutage_AffectsHouse, pHouse, pTargetHouse)) { - pTargetHouse->CreatePowerOutage(this->PowerOutage_Duration); + int duration = this->PowerOutage_Duration; + int currentLeft = pTargetHouse->PowerBlackoutTimer.GetTimeLeft(); + + if (duration < 0) + { + int newLeft = currentLeft + duration; + if (newLeft < 0) + newLeft = 0; + pTargetHouse->PowerBlackoutTimer.Start(newLeft); + } + else + { + int newLeft = currentLeft + duration; + int maxOutage = this->PowerOutage_Max; + if (maxOutage > 0 && newLeft > maxOutage) + newLeft = maxOutage; + pTargetHouse->PowerBlackoutTimer.Start(newLeft); + } + + pTargetHouse->RecheckPower = true; } } } From 8a43be0c528c1adc550da5ba350b6002862bb969 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 02:38:22 +0800 Subject: [PATCH 03/16] Doc --- docs/New-or-Enhanced-Logics.md | 19 +++++++++++++++++++ docs/Whats-New.md | 1 + 2 files changed, 20 insertions(+) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index d6d4f24f32..57db7fa09e 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2962,6 +2962,25 @@ UnlimboDetonate.KeepSelected=false ; boolean `UnlimboDetonate` cannot be used in conjunction with `Parasite`. ``` +### Radar / Power Outage warhead + +- Now you can use the following tags to cause a radar or power outage to the affected houses for a specified duration. + - The radar outage disables the radar display, identical to the effect of a Lightning Storm. + - The power outage causes a blackout, identical to the spy infiltration on a Power Plant. + - Positive duration stacks onto any existing outage timer up to the specified maximum, if set. + - Negative duration reduces the existing outage timer, down to a minimum of 0. + +In `rulesmd.ini`: +```ini +[SOMEWARHEAD] ; WarheadType +RadarOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. +RadarOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +RadarOutage.AffectsHouse=owner ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +PowerOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. +PowerOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +PowerOutage.AffectsHouse=owner ; List of 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 2a49c5c8c0..1761f4e56b 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -576,6 +576,7 @@ New: - 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) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) From 1993a63e614b4334e36d70a56eb5cc79bc0ef687 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 02:39:04 +0800 Subject: [PATCH 04/16] CREDITS --- CREDITS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.md b/CREDITS.md index 170bc75fae..150c67cd96 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -765,6 +765,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 From 4cb8d6f8b5b0b44e0d443ad1915f1ef0a999fb26 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 02:43:59 +0800 Subject: [PATCH 05/16] f --- docs/New-or-Enhanced-Logics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 57db7fa09e..5ec653e6b0 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2975,10 +2975,10 @@ In `rulesmd.ini`: [SOMEWARHEAD] ; WarheadType RadarOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. RadarOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. -RadarOutage.AffectsHouse=owner ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +RadarOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) PowerOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. PowerOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. -PowerOutage.AffectsHouse=owner ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +PowerOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) ``` ## Weapons From df8ba0f2e923da1caa1f94caa0addff76e0959da Mon Sep 17 00:00:00 2001 From: Noble_Fish <1065703286@qq.com> Date: Sun, 10 May 2026 15:49:10 +0800 Subject: [PATCH 06/16] [doc] fix & improve --- docs/New-or-Enhanced-Logics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 5ec653e6b0..60d1254d1d 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2972,12 +2972,12 @@ UnlimboDetonate.KeepSelected=false ; boolean In `rulesmd.ini`: ```ini -[SOMEWARHEAD] ; WarheadType -RadarOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. -RadarOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +[SOMEWARHEAD] ; WarheadType +RadarOutage.Duration=0 ; integer, game frames +RadarOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. RadarOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) -PowerOutage.Duration=0 ; integer, game frames. Positive stacks, negative reduces. -PowerOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +PowerOutage.Duration=0 ; integer, game frames +PowerOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. PowerOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) ``` From cba7d4aa591b9ca7b3e304208f68b6096bd8b8f0 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 17:53:41 +0800 Subject: [PATCH 07/16] Update New-or-Enhanced-Logics.md --- docs/New-or-Enhanced-Logics.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 60d1254d1d..76d3d55fc6 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2964,20 +2964,18 @@ UnlimboDetonate.KeepSelected=false ; boolean ### Radar / Power Outage warhead -- Now you can use the following tags to cause a radar or power outage to the affected houses for a specified duration. - - The radar outage disables the radar display, identical to the effect of a Lightning Storm. - - The power outage causes a blackout, identical to the spy infiltration on a Power Plant. - - Positive duration stacks onto any existing outage timer up to the specified maximum, if set. - - Negative duration reduces the existing outage timer, down to a minimum of 0. +- These tags cause a radar or power outage to the affected houses for a specified duration. +- Radar outage disables the radar display (identical to a Lightning Storm), while power outage causes a blackout (identical to spy infiltration on a Power Plant). +- Positive duration stacks onto any existing outage timer, up to a configurable maximum. Negative duration reduces the existing timer, down to a minimum of 0. In `rulesmd.ini`: ```ini [SOMEWARHEAD] ; WarheadType RadarOutage.Duration=0 ; integer, game frames -RadarOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +RadarOutage.Max=0 ; integer, max duration or 0 for no limit RadarOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) PowerOutage.Duration=0 ; integer, game frames -PowerOutage.Max=0 ; integer, max stacked duration in frames. 0 = no limit. +PowerOutage.Max=0 ; integer, max duration or 0 for no limit PowerOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) ``` From 2b8b441036e8eb3e46baf5b65807c5ce3e6a758f Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Sun, 10 May 2026 18:12:12 +0800 Subject: [PATCH 08/16] Fix New-or-Enhanced-Logics.md --- docs/New-or-Enhanced-Logics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 76d3d55fc6..eebcf0eaf3 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2964,7 +2964,7 @@ UnlimboDetonate.KeepSelected=false ; boolean ### Radar / Power Outage warhead -- These tags cause a radar or power outage to the affected houses for a specified duration. +- Now you can use these tags to make the warhead cause a radar or power outage to the affected houses for a specified duration. - Radar outage disables the radar display (identical to a Lightning Storm), while power outage causes a blackout (identical to spy infiltration on a Power Plant). - Positive duration stacks onto any existing outage timer, up to a configurable maximum. Negative duration reduces the existing timer, down to a minimum of 0. From 3155d6e0d191538ab8108db55242113ce1991969 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 20:58:01 +0800 Subject: [PATCH 09/16] Update New-or-Enhanced-Logics.md --- docs/New-or-Enhanced-Logics.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index eebcf0eaf3..ef57f2ad70 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2964,19 +2964,23 @@ UnlimboDetonate.KeepSelected=false ; boolean ### Radar / Power Outage warhead -- Now you can use these tags to make the warhead cause a radar or power outage to the affected houses for a specified duration. -- Radar outage disables the radar display (identical to a Lightning Storm), while power outage causes a blackout (identical to spy infiltration on a Power Plant). -- Positive duration stacks onto any existing outage timer, up to a configurable maximum. Negative duration reduces the existing timer, down to a minimum of 0. +- These tags allow the warhead to apply a radar or power outage to the affected houses for a specified duration. +- Radar outage disables the radar display (same as a Lightning Storm), while power outage causes a blackout (same as a spy infiltrating 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.Max=0 ; integer, max duration or 0 for no limit -RadarOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +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.Max=0 ; integer, max duration or 0 for no limit -PowerOutage.AffectsHouse=enemies ; List of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +PowerOutage.Cap=0 ; integer +PowerOutage.AffectsHouse=enemies ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) ``` ## Weapons From eaf9984f79d4e2cd476993b961a631a3e75c2a9c Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 21:02:02 +0800 Subject: [PATCH 10/16] Update Body.cpp --- src/Ext/WarheadType/Body.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index 886484a902..d91a7b088e 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -309,10 +309,10 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->JumpjetDeviation.Read(exINI, pSection, "JumpjetDeviation"); this->RadarOutage_Duration.Read(exINI, pSection, "RadarOutage.Duration"); - this->RadarOutage_Max.Read(exINI, pSection, "RadarOutage.Max"); + 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_Max.Read(exINI, pSection, "PowerOutage.Max"); + this->PowerOutage_Cap.Read(exINI, pSection, "PowerOutage.Cap"); this->PowerOutage_AffectsHouse.Read(exINI, pSection, "PowerOutage.AffectsHouse"); this->Nonprovocative.Read(exINI, pSection, "Nonprovocative"); @@ -703,10 +703,10 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm) .Process(this->JumpjetDeviation) .Process(this->RadarOutage_Duration) - .Process(this->RadarOutage_Max) + .Process(this->RadarOutage_Cap) .Process(this->RadarOutage_AffectsHouse) .Process(this->PowerOutage_Duration) - .Process(this->PowerOutage_Max) + .Process(this->PowerOutage_Cap) .Process(this->PowerOutage_AffectsHouse) .Process(this->Nonprovocative) From 174b533d5aebe1fed8c006698a3f06f5e0610bd8 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 21:07:01 +0800 Subject: [PATCH 11/16] Update Body.h --- src/Ext/WarheadType/Body.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ext/WarheadType/Body.h b/src/Ext/WarheadType/Body.h index dc2290339e..d4662b62eb 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -170,10 +170,10 @@ class WarheadTypeExt Nullable JumpjetDeviation; Valueable RadarOutage_Duration; - Valueable RadarOutage_Max; + Valueable RadarOutage_Cap; Valueable RadarOutage_AffectsHouse; Valueable PowerOutage_Duration; - Valueable PowerOutage_Max; + Valueable PowerOutage_Cap; Valueable PowerOutage_AffectsHouse; Valueable Nonprovocative; @@ -434,10 +434,10 @@ class WarheadTypeExt , JumpjetDeviation {} , RadarOutage_Duration { 0 } - , RadarOutage_Max { 0 } + , RadarOutage_Cap { 0 } , RadarOutage_AffectsHouse { AffectedHouse::Enemies } , PowerOutage_Duration { 0 } - , PowerOutage_Max { 0 } + , PowerOutage_Cap { 0 } , PowerOutage_AffectsHouse { AffectedHouse::Enemies } , Nonprovocative { false } From 45650c7c109a6e592fb87a39f59dfbbcc87066d8 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 21:09:33 +0800 Subject: [PATCH 12/16] Update Detonate.cpp --- src/Ext/WarheadType/Detonate.cpp | 47 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index 1b76e3ee9d..0532d0b76c 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -126,6 +126,21 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, pTargetHouse->RadarBlackoutTimer.Start(newLeft); } +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; } } @@ -135,33 +150,21 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, { for (const auto pTargetHouse : HouseClass::Array) { - if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() - && !pTargetHouse->Type->MultiplayPassive + if (!pTargetHouse->Defeated && !pTargetHouse->IsObserver() + && !pTargetHouse->Type->MultiplayPassive && EnumFunctions::CanTargetHouse(this->PowerOutage_AffectsHouse, pHouse, pTargetHouse)) { - int duration = this->PowerOutage_Duration; - int currentLeft = pTargetHouse->PowerBlackoutTimer.GetTimeLeft(); - - if (duration < 0) - { - int newLeft = currentLeft + duration; - if (newLeft < 0) - newLeft = 0; - pTargetHouse->PowerBlackoutTimer.Start(newLeft); - } - else - { - int newLeft = currentLeft + duration; - int maxOutage = this->PowerOutage_Max; - if (maxOutage > 0 && newLeft > maxOutage) - newLeft = maxOutage; - pTargetHouse->PowerBlackoutTimer.Start(newLeft); - } - + 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) { From 324bf82478b4ff39c189df0c415c475aed9bef9d Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 21:28:54 +0800 Subject: [PATCH 13/16] Update Detonate.cpp --- src/Ext/WarheadType/Detonate.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index 0532d0b76c..5d8860ddee 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -100,33 +100,6 @@ void WarheadTypeExt::ExtData::Detonate(TechnoClass* pOwner, HouseClass* pHouse, } 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 duration = this->RadarOutage_Duration; - int currentLeft = pTargetHouse->RadarBlackoutTimer.GetTimeLeft(); - - if (duration < 0) - { - int newLeft = currentLeft + duration; - if (newLeft < 0) - newLeft = 0; - pTargetHouse->RadarBlackoutTimer.Start(newLeft); - } - else - { - int newLeft = currentLeft + duration; - int maxOutage = this->RadarOutage_Max; - if (maxOutage > 0 && newLeft > maxOutage) - newLeft = maxOutage; - pTargetHouse->RadarBlackoutTimer.Start(newLeft); - } - -if (this->RadarOutage_Duration) { for (const auto pTargetHouse : HouseClass::Array) { From a96e7a0cece2ef1689824a1359cea07d80aebf4d Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 21:40:35 +0800 Subject: [PATCH 14/16] Update New-or-Enhanced-Logics.md --- docs/New-or-Enhanced-Logics.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index ef57f2ad70..1209fa193b 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2964,12 +2964,12 @@ UnlimboDetonate.KeepSelected=false ; boolean ### Radar / Power Outage warhead -- These tags allow the warhead to apply a radar or power outage to the affected houses for a specified duration. -- Radar outage disables the radar display (same as a Lightning Storm), while power outage causes a blackout (same as a spy infiltrating 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. +- 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. +- Radar outage disables the radar display (identical to a Lightning Storm), while power outage 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`: From 2a28d988fe48e7bc885dc3f8154430fdc2cf8ea7 Mon Sep 17 00:00:00 2001 From: WingHwy <127025413+WingHwy@users.noreply.github.com> Date: Mon, 11 May 2026 22:28:16 +0800 Subject: [PATCH 15/16] Update New-or-Enhanced-Logics.md --- docs/New-or-Enhanced-Logics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 1209fa193b..a7e130c1bb 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2965,7 +2965,7 @@ UnlimboDetonate.KeepSelected=false ; boolean ### 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. -- Radar outage disables the radar display (identical to a Lightning Storm), while power outage causes a blackout (identical to spy infiltration on a Power Plant). +- `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. From 1da6c953406587f1f55519f31fd5e36627f1c073 Mon Sep 17 00:00:00 2001 From: Noble_Fish <1065703286@qq.com> Date: Sun, 17 May 2026 16:55:28 +0800 Subject: [PATCH 16/16] Create .po sections. --- docs/locale/zh_CN/LC_MESSAGES/CREDITS.po | 3 ++ .../LC_MESSAGES/New-or-Enhanced-Logics.po | 36 +++++++++++++++++++ docs/locale/zh_CN/LC_MESSAGES/Whats-New.po | 5 +++ 3 files changed, 44 insertions(+) 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 "原版问题修复:"