From 3def3f72540549d89ebf4f18ba329017ed74b8e7 Mon Sep 17 00:00:00 2001 From: Coronia <2217891145@qq.com> Date: Thu, 7 Nov 2024 16:58:02 +0800 Subject: [PATCH] fake health display --- CREDITS.md | 1 + docs/User-Interface.md | 62 ++++++++++++++++++--------------- docs/Whats-New.md | 1 + src/Ext/Techno/Body.Visuals.cpp | 23 ++++++++++++ src/Ext/Techno/Body.h | 1 + src/Ext/TechnoType/Body.cpp | 6 ++++ src/Ext/TechnoType/Body.h | 5 +++ 7 files changed, 71 insertions(+), 28 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 1ddaaf1b51..3170b9ced4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -372,6 +372,7 @@ This page lists all the individual contributions to the project by their author. - **Ollerus** - Build limit group enhancement - Customizable rocker amplitude + - Allow faking digital display for `InfoType=Health` - **handama** - AI script action to jump back to previous script - **TaranDahl (航味麻酱)** - Skirmish AI "sell all buildings and set all technos to hunt" behavior dehardcode diff --git a/docs/User-Interface.md b/docs/User-Interface.md index 2e1ad86969..365ee3847a 100644 --- a/docs/User-Interface.md +++ b/docs/User-Interface.md @@ -34,7 +34,7 @@ IngameScore.LoseTheme= ; Soundtrack theme ID *Default configuration of digital display using example shapes from [Phobos supplementaries](https://github.com/Phobos-developers/PhobosSupplementaries).* - You can now configure various types of numerical counters to be displayed over Techno to represent its attributes, such as health points or shield points. - - `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. + - `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). `HideMaxValue=yes` will make the counter show only the current value (i.e. 20). `Percentage=yes` changes the format to `percent%` (i.e. 50%). - `CanSee` and `CanSee.Observer` can limit visibility to specific players. @@ -46,50 +46,56 @@ IngameScore.LoseTheme= ; Soundtrack theme ID - Default `Shape.Spacing` for buildings is `4,-2`, `4,0` for others. - `ValueScaleDivisor` can be used to adjust scale of displayed values. Both the current & maximum value will be divided by the integer number given, if higher than 1. + - If a TechnoType has a DigitalDisplayType with `InfoType=Health`, it's allowed to display fake values to enemy players. + - `DigitalDisplay.Health.FakeStrength`, if set, will be used as the maximum value of health display. The current value will be displayed as the percentage of its current health multiplies the new maximum value. + - `DigitalDisplay.Health.FakeAtDisguise`, if set to true on an InfantryType with Disguise, will use the disguised TechnoType's `Strength` value as the maximum value of health display. The current value will be displayed as the percentage of its current health multiplies the new maximum value. This will be applied before `DigitalDisplay.Health.FakeStrength`. + In `rulesmd.ini`: ```ini [DigitalDisplayTypes] 0=SOMEDIGITALDISPLAYTYPE [AudioVisual] -Buildings.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes -Infantry.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes -Vehicles.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes -Aircraft.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes +Buildings.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes +Infantry.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes +Vehicles.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes +Aircraft.DefaultDigitalDisplayTypes= ; list of DigitalDisplayTypes -[SOMEDIGITALDISPLAYTYPE] ; DigitalDisplayType +[SOMEDIGITALDISPLAYTYPE] ; DigitalDisplayType ; Generic -InfoType=Health ; Displayed value enumeration (health|shield|ammo|mindcontrol|spawns|passengers|tiberium|experience|occupants|gattlingstage) -Offset=0,0 ; integers - horizontal, vertical -Offset.ShieldDelta= ; integers - horizontal, vertical -Align=right ; Text alignment enumeration (left|right|center/centre) -Anchor.Horizontal=right ; Horizontal position enumeration (left|center/centre|right) -Anchor.Vertical=top ; Vertical position enumeration (top|center/centre|bottom) -Anchor.Building=top ; Hexagon vertex enumeration (top|lefttop|leftbottom|bottom|rightbottom|righttop) -Percentage=false ; boolean -HideMaxValue=false ; boolean -VisibleToHouses=owner ; Affected house enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) -VisibleToHouses.Observer=true ; boolean -ValueScaleDivisor=1 ; integer +InfoType=Health ; Displayed value enumeration (health|shield|ammo|mindcontrol|spawns|passengers|tiberium|experience|occupants|gattlingstage) +Offset=0,0 ; integers - horizontal, vertical +Offset.ShieldDelta= ; integers - horizontal, vertical +Align=right ; Text alignment enumeration (left|right|center/centre) +Anchor.Horizontal=right ; Horizontal position enumeration (left|center/centre|right) +Anchor.Vertical=top ; Vertical position enumeration (top|center/centre|bottom) +Anchor.Building=top ; Hexagon vertex enumeration (top|lefttop|leftbottom|bottom|rightbottom|righttop) +Percentage=false ; boolean +HideMaxValue=false ; boolean +VisibleToHouses=owner ; Affected house enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) +VisibleToHouses.Observer=true ; boolean +ValueScaleDivisor=1 ; integer ; Text -Text.Color=0,255,0 ; integers - Red, Green, Blue -Text.Color.ConditionYellow=255,255,0 ; integers - Red, Green, Blue -Text.Color.ConditionRed=255,0,0 ; integers - Red, Green, Blue -Text.Background=false ; boolean +Text.Color=0,255,0 ; integers - Red, Green, Blue +Text.Color.ConditionYellow=255,255,0 ; integers - Red, Green, Blue +Text.Color.ConditionRed=255,0,0 ; integers - Red, Green, Blue +Text.Background=false ; boolean ; Shape -Shape= ; filename with .shp extension, if not present, game-drawn text will be used instead -Palette=palette.pal ; filename with .pal extension -Shape.Spacing= ; integers - horizontal, vertical spacing between digits +Shape= ; filename with .shp extension, if not present, game-drawn text will be used instead +Palette=palette.pal ; filename with .pal extension +Shape.Spacing= ; integers - horizontal, vertical spacing between digits [SOMETECHNOTYPE] -DigitalDisplay.Disable=false ; boolean -DigitalDisplayTypes= ; list of DigitalDisplayTypes +DigitalDisplay.Disable=false ; boolean +DigitalDisplayTypes= ; list of DigitalDisplayTypes +DigitalDisplay.Health.FakeStrength=-1 ; integer +DigitalDisplay.Health.FakeAtDisguise=true ; boolean ``` In `RA2MD.ini`: ```ini [Phobos] -DigitalDisplay.Enable=false ; boolean +DigitalDisplay.Enable=false ; boolean ``` ```{note} diff --git a/docs/Whats-New.md b/docs/Whats-New.md index fe6adaa3d9..4bdce0c9d2 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -468,6 +468,7 @@ New: - Allow infantry to use land sequences in water (by Starkku) - `` can now be used as owner for pre-placed objects on skirmish and multiplayer maps (by Starkku) - Allow customizing charge turret delays per burst on a weapon (by Starkku) +- Allow faking digital display for `InfoType=Health` (by Ollerus) Vanilla fixes: - Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy) diff --git a/src/Ext/Techno/Body.Visuals.cpp b/src/Ext/Techno/Body.Visuals.cpp index ad07a722a8..0b6979080f 100644 --- a/src/Ext/Techno/Body.Visuals.cpp +++ b/src/Ext/Techno/Body.Visuals.cpp @@ -371,6 +371,10 @@ void TechnoExt::GetValuesForDisplay(TechnoClass* pThis, DisplayInfoType infoType { value = pThis->Health; maxValue = pType->Strength; + + if (!pThis->Owner->IsAlliedWith(HouseClass::CurrentPlayer)) + GetDigitalDisplayFakeHealth(pThis, value, maxValue); + break; } case DisplayInfoType::Shield: @@ -465,3 +469,22 @@ void TechnoExt::GetValuesForDisplay(TechnoClass* pThis, DisplayInfoType infoType } } } + +void TechnoExt::GetDigitalDisplayFakeHealth(TechnoClass* pThis, int& value, int& maxValue) +{ + const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType()); + int newMaxValue = pTypeExt->DigitalDisplay_Health_FakeStrength; + + if (pThis->Disguised && pTypeExt->DigitalDisplay_Health_FakeAtDisguise && pThis->WhatAmI() == AbstractType::Infantry) + { + if (const auto pType = TechnoTypeExt::GetTechnoType(pThis->Disguise)) + newMaxValue = pType->Strength; + } + + if (newMaxValue >= 0) + { + double ratio = static_cast(value) / maxValue; + value = static_cast(ratio * newMaxValue); + maxValue = newMaxValue; + } +} diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index dd958380bd..60e03831d7 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -173,6 +173,7 @@ class TechnoExt static Point2D GetBuildingSelectBracketPosition(TechnoClass* pThis, BuildingSelectBracketPosition bracketPosition); static void ProcessDigitalDisplays(TechnoClass* pThis); static void GetValuesForDisplay(TechnoClass* pThis, DisplayInfoType infoType, int& value, int& maxValue); + static void GetDigitalDisplayFakeHealth(TechnoClass* pThis, int& value, int& maxValue); // WeaponHelpers.cpp static int PickWeaponIndex(TechnoClass* pThis, TechnoClass* pTargetTechno, AbstractClass* pTarget, int weaponIndexOne, int weaponIndexTwo, bool allowFallback = true, bool allowAAFallback = true); diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 94ada02927..c701502e49 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -462,6 +462,9 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Wake_Grapple.Read(exINI, pSection, "Wake.Grapple"); this->Wake_Sinking.Read(exINI, pSection, "Wake.Sinking"); + this->DigitalDisplay_Health_FakeStrength.Read(exINI, pSection, "DigitalDisplay.Health.FakeStrength"); + this->DigitalDisplay_Health_FakeAtDisguise.Read(exINI, pSection, "DigitalDisplay.Health.FakeAtDisguise"); + // Ares 0.2 this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius"); @@ -831,6 +834,9 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->Wake) .Process(this->Wake_Grapple) .Process(this->Wake_Sinking) + + .Process(this->DigitalDisplay_Health_FakeStrength) + .Process(this->DigitalDisplay_Health_FakeAtDisguise) ; } void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 2b06116e3d..7c9f3df18d 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -248,6 +248,8 @@ class TechnoTypeExt std::vector> DeployedWeaponBurstFLHs; std::vector> EliteDeployedWeaponBurstFLHs; + Valueable DigitalDisplay_Health_FakeStrength; + Valueable DigitalDisplay_Health_FakeAtDisguise; ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) , HealthBar_Hide { false } @@ -450,6 +452,9 @@ class TechnoTypeExt , Wake { } , Wake_Grapple { } , Wake_Sinking { } + + , DigitalDisplay_Health_FakeStrength { -1 } + , DigitalDisplay_Health_FakeAtDisguise { true } { } virtual ~ExtData() = default;