diff --git a/code/techno.cpp b/code/techno.cpp index f1b453510..30c8618b7 100644 --- a/code/techno.cpp +++ b/code/techno.cpp @@ -1579,13 +1579,13 @@ void TechnoClass::Draw_Health_Bar(Point2D const & xpoint, Rect const & cliprect) if (IsSelected) { Draw_Shape(*LogicalSurface, *NormalDrawer, (ShapeSet const *)ObjectTypeClass::SelectShapes, powerup ? 6 : 2, xpoint, cliprect, ShapeFlags_Type(SHAPE_ALPHA|SHAPE_WIN_REL|SHAPE_CENTER)); } - offset = Point2D(-5, -24); + offset = UIControls.InfantryHealthBarPos; health_bar_count = 8; } else { if (IsSelected) { Draw_Shape(*LogicalSurface, *NormalDrawer, (ShapeSet const *)ObjectTypeClass::SelectShapes, (LimpetType.Any() ? 8 : 0) + (powerup ? 4 : 0) + 3, xpoint, cliprect, ShapeFlags_Type(SHAPE_ALPHA|SHAPE_WIN_REL|SHAPE_CENTER)); } - offset = Point2D(-15, -25); + offset = UIControls.UnitHealthBarPos; health_bar_count = 17; } diff --git a/code/uicontrol.cpp b/code/uicontrol.cpp index e394ab39a..75ffa160e 100644 --- a/code/uicontrol.cpp +++ b/code/uicontrol.cpp @@ -56,6 +56,9 @@ bool UIControlsClass::Read_INI(CCINIClass const & ini) NavComQueueLineColor = ini.Get_RGBClass(INGAME, "NavComQueueLineColor", NavComQueueLineColor); NavComQueueLineDropShadowColor = ini.Get_RGBClass(INGAME, "NavComQueueLineDropShadowColor", NavComQueueLineDropShadowColor); + InfantryHealthBarPos = ini.Get_Point(INGAME, "InfantryHealthBarPos", InfantryHealthBarPos); + UnitHealthBarPos = ini.Get_Point(INGAME, "UnitHealthBarPos", UnitHealthBarPos); + UnitGroupNumberOffset = ini.Get_Point(PIPS, "UnitGroupNumberOffset", UnitGroupNumberOffset); InfantryGroupNumberOffset = ini.Get_Point(PIPS, "InfantryGroupNumberOffset", InfantryGroupNumberOffset); BuildingGroupNumberOffset = ini.Get_Point(PIPS, "BuildingGroupNumberOffset", BuildingGroupNumberOffset); diff --git a/code/uicontrol.h b/code/uicontrol.h index dabdbc8ec..c83e4122b 100644 --- a/code/uicontrol.h +++ b/code/uicontrol.h @@ -84,4 +84,7 @@ class UIControlsClass Point2D InfantryWithPipGroupNumberOffset = Point2D(-4, -8); Point2D BuildingWithPipGroupNumberOffset = Point2D(-4, -8); Point2D AircraftWithPipGroupNumberOffset = Point2D(-4, -8); + + Point2D InfantryHealthBarPos = Point2D(-5, -24); + Point2D UnitHealthBarPos = Point2D(-15, -25); }; diff --git a/manual/changes/health-bar-offsets.md b/manual/changes/health-bar-offsets.md new file mode 100644 index 000000000..e615006a0 --- /dev/null +++ b/manual/changes/health-bar-offsets.md @@ -0,0 +1,22 @@ +--- +title: Place health bars from UI.INI +category: feature +release: 0.3.0 +targets: +- type: key + id: InfantryHealthBarPos + effect: added +- type: key + id: UnitHealthBarPos + effect: added +- type: format + id: ui-ini + effect: changed +credit: +- JoyfulShush +- CCHyper +--- + +Two keys in the `[Ingame]` section of [UI.INI](/formats/ui-ini/#health-bar-positions) set where an object's row of health pips begins: [`InfantryHealthBarPos`](/keys/infantryhealthbarpos/) for infantry and [`UnitHealthBarPos`](/keys/unithealthbarpos/) for vehicles and aircraft. Each takes a horizontal and a vertical offset in pixels; positive values move the row right and down. Their defaults keep the original position. + +The keys have Vinifera's names, but Vinifera reads the vertical offset first, so swap the two numbers in a Vinifera file. CCHyper is credited for the Vinifera implementation this follows. diff --git a/manual/content/formats/ui-ini.md b/manual/content/formats/ui-ini.md index f7eef6468..c233fe800 100644 --- a/manual/content/formats/ui-ini.md +++ b/manual/content/formats/ui-ini.md @@ -1,7 +1,7 @@ --- format_id: ui-ini title: UI.INI -summary: Sets how a selected object's order lines, a firing vehicle's sighting laser and a control group number are drawn. +summary: Sets how a selected object's order lines, a firing vehicle's sighting laser, control group numbers and health bars are drawn. kind: file source_files: - code/uicontrol.cpp @@ -26,7 +26,7 @@ related: id: configuration-files --- -The file is optional and every key has a default, so a file names only what it changes. The order-line and sighting-laser keys go in `[Ingame]`, and the control group number keys go in `[Pips]`. The values below are examples. +The file is optional and every key has a default, so a file names only what it changes. The order-line, sighting-laser and health-bar keys go in `[Ingame]`, and the control group number keys go in `[Pips]`. The values below are examples. ```ini title="UI.INI" [Ingame] @@ -34,6 +34,7 @@ AlwaysShowActionLines=yes MovementLineDashed=yes MovementLineColor=0,255,0 NavComQueueLineThick=yes +InfantryHealthBarPos=-5,-20 [Pips] UnitWithPipGroupNumberOffset=-4,-15 @@ -63,6 +64,21 @@ The defaults are `-4,-4` without pips and `-4,-8` with pips. A value that does n Vinifera reads the same eight keys from `[Ingame]`, so move them to `[Pips]` when reusing a Vinifera file. Setting all eight to `-8,-33` gives the position Twisted Insurrection uses. +## Health bar positions + +Infantry, vehicles and aircraft show their health as a row of pips. Two `[Ingame]` keys set where that row begins: + +| Object | Key | +| --- | --- | +| Infantry | [`InfantryHealthBarPos`](/keys/infantryhealthbarpos/) | +| Vehicle or aircraft | [`UnitHealthBarPos`](/keys/unithealthbarpos/) | + +A structure, and a vehicle with [`IsCoreDefender=yes`](/keys/iscoredefender/#scope-unittype), draw their health as a pip bar along the near edge of their footprint instead and use neither key. + +Each value is two whole numbers, a horizontal and a vertical offset in pixels, separated by a comma. Positive values move the row right and down, while negative values move it left and up. The offset is measured from the object's position on screen. The first pip is centered on that offset point, and each later pip is two pixels further right, so the offset moves the whole row. A value that does not start with two comma-separated numbers keeps the default, and anything after the second number is ignored. + +Vinifera reads the same two keys with the vertical offset first, so swap the two numbers when reusing a Vinifera file: `InfantryHealthBarPos=-24,-5` becomes `InfantryHealthBarPos=-5,-24`. Vinifera also moves the vehicle row one pixel left by default; set `UnitHealthBarPos=-16,-25` to match it. + ## When the file is read The game reads the file at startup, after it registers the game archives. It reads the file again each time a scenario or saved game loads, after mounting the archives of the player's side, so a copy inside a side's archive applies to games played as that side. It reads the file once more when a match ends and the menus return, after the side's archives [move behind the other archives](/formats/mix/#theater-side-and-speech-archives). Each read starts from the defaults, so only the keys in the copy read last take effect. diff --git a/manual/content/keys/infantryhealthbarpos.md b/manual/content/keys/infantryhealthbarpos.md new file mode 100644 index 000000000..f70fd82be --- /dev/null +++ b/manual/content/keys/infantryhealthbarpos.md @@ -0,0 +1,15 @@ +--- +key: InfantryHealthBarPos +summary: Where an infantry object's row of health pips is drawn. +see_also: [UnitHealthBarPos] +when_omitted: + kind: value + value: "-5,-24" +--- + +`InfantryHealthBarPos=` sets where an infantry object's row of health pips begins. The value is a horizontal and a vertical offset in pixels; positive values move the row right and down. [Health bar positions](/formats/ui-ini/#health-bar-positions) covers the point the offset is measured from and how the row is laid out. + +```ini title="UI.INI" +[Ingame] +InfantryHealthBarPos=-5,-20 +``` diff --git a/manual/content/keys/unithealthbarpos.md b/manual/content/keys/unithealthbarpos.md new file mode 100644 index 000000000..06ebbe9f8 --- /dev/null +++ b/manual/content/keys/unithealthbarpos.md @@ -0,0 +1,17 @@ +--- +key: UnitHealthBarPos +summary: Where a vehicle's or aircraft's row of health pips is drawn. +see_also: [InfantryHealthBarPos] +when_omitted: + kind: value + value: "-15,-25" +--- + +`UnitHealthBarPos=` sets where a vehicle's or aircraft's row of health pips begins. The value is a horizontal and a vertical offset in pixels; positive values move the row right and down. [Health bar positions](/formats/ui-ini/#health-bar-positions) covers the point the offset is measured from and how the row is laid out. + +A vehicle with [`IsCoreDefender=yes`](/keys/iscoredefender/#scope-unittype) draws a structure's pip bar along the near edge of its footprint instead and does not use the key. + +```ini title="UI.INI" +[Ingame] +UnitHealthBarPos=-15,-20 +``` diff --git a/manual/content/using/configuration-files.md b/manual/content/using/configuration-files.md index c2c1106e6..16b7e8aef 100644 --- a/manual/content/using/configuration-files.md +++ b/manual/content/using/configuration-files.md @@ -25,7 +25,7 @@ The game reads its configuration from these files: - `SUN.INI` stores the player's options. - [`KEYBOARD.INI`](/formats/keyboard-ini/) assigns keys to command names. -- [`UI.INI`](/formats/ui-ini/), which a mod or deployment may ship, sets how order lines and the sighting laser are drawn. +- [`UI.INI`](/formats/ui-ini/), which a mod or deployment may ship, sets how order lines, the sighting laser, control group numbers and health bars are drawn. - Rules, art, sound, theme, and scenario files supply game and mod data. A deployment can rename these files in [`OPENTS.INI`](/formats/opents-ini/#the-files-it-reads): the settings file, `UI.INI`, the tutorial file, and the rules, language rules, multiplayer rules, art, AI, sound, theme, and campaign list files together with their expansion copies. `KEYBOARD.INI` and scenario files cannot be renamed. diff --git a/manual/data/ini-keys.yaml b/manual/data/ini-keys.yaml index c4c806725..98b4b7f5d 100644 --- a/manual/data/ini-keys.yaml +++ b/manual/data/ini-keys.yaml @@ -11561,6 +11561,24 @@ InfantryGroupNumberOffset: source: code/uicontrol.cpp guard: null level: UIControlsClass +InfantryHealthBarPos: + key: InfantryHealthBarPos + scopes: + - applies_to: + - UI controls + file: ui.ini + section: + kind: literal + name: Ingame + value_type: point (x,y) + status: generated + _provenance: + default_candidate: null + declared_in: UIControlsClass + member: InfantryHealthBarPos + source: code/uicontrol.cpp + guard: null + level: UIControlsClass InfantryReserve: key: InfantryReserve scopes: @@ -25038,6 +25056,24 @@ UnitGroupNumberOffset: source: code/uicontrol.cpp guard: null level: UIControlsClass +UnitHealthBarPos: + key: UnitHealthBarPos + scopes: + - applies_to: + - UI controls + file: ui.ini + section: + kind: literal + name: Ingame + value_type: point (x,y) + status: generated + _provenance: + default_candidate: null + declared_in: UIControlsClass + member: UnitHealthBarPos + source: code/uicontrol.cpp + guard: null + level: UIControlsClass UnitReload: key: UnitReload scopes: