diff --git a/CREDITS.md b/CREDITS.md
index 919ed36608..74205a2a8c 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -932,5 +932,7 @@ This page lists all the individual contributions to the project by their author.
- **Chang_zhi**:
- Interop export interface for accessing scenario local/global variables
- Add `ClampToScreen` tag for `BannerType` to control whether banner position is clamped to the visible area
+- **Nuke**:
+ - Reload speed adjustment on promotion
+ - New `InfoType=EmptyReload` for digital display
- **obsidianus** - Automatic conversion based on health
-- **Nuke** - Reload speed adjustment on promotion
diff --git a/docs/User-Interface.md b/docs/User-Interface.md
index 1feb98e774..9918694a7d 100644
--- a/docs/User-Interface.md
+++ b/docs/User-Interface.md
@@ -120,6 +120,9 @@ The game first takes the absolute value of the difference between the actual cre
- 1 - primary factory,
- 2 - secondary factory.
+ - `InfoType=EmptyReload` displays the empty reload timer while the Techno has no ammo left, and 0 otherwise.
+ If `EmptyReload` is not positive, the effective duration falls back to `Reload`.
+
- `Anchor.Horizontal` and `Anchor.Vertical` set the anchor point from which the display is drawn (depending on `Align`) relative to unit's center/selection box. For buildings, `Anchor.Building` is used instead.
- `Offset` and `Offset.ShieldDelta` (the latter applied when a shield is active) can be used to further modify the position.
- By default, values are displayed in `current/maximum` format (i.e. `20/40`).
@@ -153,7 +156,7 @@ DigitalDisplay.Health.FakeAtDisguise=true ; boolean
[SOMEDIGITALDISPLAYTYPE] ; DigitalDisplayType
; Generic
-InfoType=Health ; Displayed value enumeration (Health|Shield|Ammo|Mindcontrol|Spawns|Passengers|Tiberium|Experience|Occupants|GattlingStage|ROF|Reload|SpawnTimer|GattlingTimer|ProduceCash|PassengerKill|AutoDeath|SuperWeapon|IronCurtain|TemporalLife|FactoryProcess)
+InfoType=Health ; Displayed value enumeration (Health|Shield|Ammo|Mindcontrol|Spawns|Passengers|Tiberium|Experience|Occupants|GattlingStage|ROF|Reload|SpawnTimer|GattlingTimer|ProduceCash|PassengerKill|AutoDeath|SuperWeapon|IronCurtain|TemporalLife|FactoryProcess|EmptyReload)
InfoIndex= ; integer
Offset=0,0 ; integers - horizontal, vertical
Offset.ShieldDelta= ; integers - horizontal, vertical
diff --git a/docs/Whats-New.md b/docs/Whats-New.md
index b5dcd663cf..f2725fe757 100644
--- a/docs/Whats-New.md
+++ b/docs/Whats-New.md
@@ -419,6 +419,7 @@ HideShakeEffects=false ; boolean
:open:
#### New:
+- [New `InfoType=EmptyReload` for digital display](User-Interface.md#digital-display) (by Nuke)
#### Vanilla fixes:
diff --git a/src/Ext/Techno/Body.Visuals.cpp b/src/Ext/Techno/Body.Visuals.cpp
index b511a299bd..4613c31086 100644
--- a/src/Ext/Techno/Body.Visuals.cpp
+++ b/src/Ext/Techno/Body.Visuals.cpp
@@ -624,6 +624,18 @@ void TechnoExt::GetValuesForDisplay(TechnoClass* pThis, TechnoTypeClass* pType,
maxValue = timer.TimeLeft ? timer.TimeLeft : ((pThis->Ammo || pType->EmptyReload <= 0) ? pType->Reload : pType->EmptyReload);
break;
}
+ case DisplayInfoType::EmptyReload:
+ {
+ if (pType->Ammo <= 0)
+ return;
+
+ const auto& timer = pThis->ReloadTimer;
+ value = (pThis->Ammo == 0) ? timer.GetTimeLeft() : 0;
+ maxValue = timer.TimeLeft
+ ? timer.TimeLeft
+ : (pType->EmptyReload > 0 ? pType->EmptyReload : pType->Reload);
+ break;
+ }
case DisplayInfoType::SpawnTimer:
{
const auto pSpawnManager = pThis->SpawnManager;
diff --git a/src/Utilities/Enum.h b/src/Utilities/Enum.h
index 98430c02e5..66fa283f35 100644
--- a/src/Utilities/Enum.h
+++ b/src/Utilities/Enum.h
@@ -331,7 +331,8 @@ enum class DisplayInfoType : BYTE
SuperWeapon = 17,
IronCurtain = 18,
TemporalLife = 19,
- FactoryProcess = 20
+ FactoryProcess = 20,
+ EmptyReload = 21
};
enum class DisplayShowType : unsigned char
diff --git a/src/Utilities/TemplateDef.h b/src/Utilities/TemplateDef.h
index c9592a410f..375fd079da 100644
--- a/src/Utilities/TemplateDef.h
+++ b/src/Utilities/TemplateDef.h
@@ -1553,6 +1553,10 @@ if(_strcmpi(parser.value(), #name) == 0){ value = __uuidof(name ## LocomotionCla
{
value = DisplayInfoType::Reload;
}
+ else if (_strcmpi(str, "emptyreload") == 0)
+ {
+ value = DisplayInfoType::EmptyReload;
+ }
else if (_strcmpi(str, "spawntimer") == 0)
{
value = DisplayInfoType::SpawnTimer;