From 8ee3806792ad4c73de8820458d9850a39b8eb283 Mon Sep 17 00:00:00 2001 From: jcompto95-tech Date: Sat, 10 Oct 2026 10:30:18 -0400 Subject: [PATCH] The energy shield's flare on the first-person arms (display.viewmodel_shield) Video Setup > FOV and Viewmodels > Arm Shields, off by default. The stock game draws a unit's shield flare (its modifier shader, the cyborg's shield plasma, as its shield is hit, charges and falls) on the body only; the first-person arms never showed it. With Arm Shields on, the hands model is drawn with the unit's own modifier shader and the unit's own function values and change colors, as render_object_list draws the body: the same flare, on the arms. The first-person weapon is drawn without it. The flare is a first-person transparent group, so it is drawn in the viewmodel's projection (display.viewmodel_fov) and lines up with the arms. The setting is read in view_fov.c with the other viewmodel settings. Only the drawing changes. Checked by compiling the changed units. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_015jtk9vPUKbWd48oBMzXuzd --- ...ile_edit.video_settings.fov_viewmodels.xml | 12 ++++++++++ port/linux/README.md | 2 ++ port/linux/game/view_fov.c | 17 ++++++++++++++ port/linux/game/view_fov.h | 3 +++ port/linux/src/port_config.c | 3 +++ source/interface/first_person_weapons.c | 22 +++++++++++++++++++ tools/port_settings.py | 2 ++ 7 files changed, 61 insertions(+) diff --git a/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.video_settings.fov_viewmodels.xml b/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.video_settings.fov_viewmodels.xml index faf580b8..b403333f 100644 --- a/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.video_settings.fov_viewmodels.xml +++ b/port/assets/menus/ce/main_menu.settings_select.player_setup.player_profile_edit.video_settings.fov_viewmodels.xml @@ -16,6 +16,7 @@ + @@ -50,6 +51,15 @@ + + + + + + + + + @@ -64,11 +74,13 @@ + + diff --git a/port/linux/README.md b/port/linux/README.md index 34e28bd0..1d105042 100644 --- a/port/linux/README.md +++ b/port/linux/README.md @@ -339,6 +339,7 @@ the setting for one start of the game. It has priority over the file. | `display.fov` | `0.0` | `HALO_FOV` | The first-person view's field of view on foot, in degrees across at 16:9, from 20 to 150. `0`: the stock view. Refer to "Field of view". | | `display.viewmodel_fov` | `0.0` | `HALO_VIEWMODEL_FOV` | The first-person weapon's and hands' field of view, in degrees across at 16:9, from 20 to 150. `0`: the weapon's stock view, also when `display.fov` widens the world. Refer to "Field of view". | | `display.viewmodel_visible` | `true` | `HALO_VIEWMODEL_VISIBLE` | `true`: the first-person weapon, hands and what is attached to them are drawn. `false`: they are not; firing, animation, sound and lights go on, and other players' models are drawn. | +| `display.viewmodel_shield` | `false` | `HALO_VIEWMODEL_SHIELD` | `true`: the energy shield's flare (its hits, its charging, its fall) is drawn on the first-person arms too, as on the body, with the unit's own shield shader. The stock game draws it on the body only. | | `display.high_res_hud` | `true` | `HALO_HIGH_RES_HUD` | `true`: the HUD (meters, counters, panels and their outlines, the motion sensor, reticles, waypoints, scopes) is drawn from the high-res assets in `port/assets/hud`, 8x the size of the maps' bitmaps. The bitmaps with English text keep the maps' own. `false`: the maps' own bitmaps. | | `display.high_res_text` | `true` | `HALO_HIGH_RES_TEXT` | `true`: the menus' and HUD's text is drawn with the fonts in `port/assets/fonts` (Overpass, in place of the maps' Interstate) at the resolution the game draws at, laid out as before; the menus' titles are drawn from the high-res pictures in `port/assets/titles`, and the controller button icons from those in `port/assets/buttons`. `false`: the maps' bitmap fonts, titles and button icons. | | `display.shadow_resolution` | `128` | `HALO_SHADOW_RESOLUTION` | The size of the maps that the shadows of the objects are drawn in, in pixels each way: `128`, `256`, `512` or `1024` (other values go down to one of these). The game draws the shadow of each object into a map of 128x128 pixels, blurs it and projects it onto the ground. On a large screen, the edges of these shadows show steps that move when the object moves. A larger map makes the edges smooth; the blur is made wider to match, so the shadows are as soft as on the Xbox. Each doubling adds two passes of the blur. `128`: as on the Xbox. | @@ -1046,6 +1047,7 @@ Other changes: | `render/render.c` | The 3D view of each window is antialiased before the HUD is drawn (`display.anti_aliasing`). | | `interface/hud.c` | In multiplayer, players' names are drawn above their heads (`display.player_names`, `display.player_name_scale`). | | `rasterizer/rasterizer_text.c`, `text/draw_string.c` | Text is drawn from an atlas of the fonts' glyphs, rasterized at the resolution the game draws at (`src/text_hires.c`), when the font has every character of the string. Text can be drawn scaled about a point (`rasterizer_text_set_scale`), as the players' names are. Each glyph's advance is centred on the font tag character's, so the layout is the same, and a glyph is cut at a text box only where the font tag's character visibly was. | +| `interface/first_person_weapons.c` | The first-person hands are drawn with the unit's shield modifier shader, as its body is (`display.viewmodel_shield`). | The x86 inline assembly of the game is replaced by C. Thus the compiler can optimize that code for each processor: diff --git a/port/linux/game/view_fov.c b/port/linux/game/view_fov.c index c6f3f6ac..2c0241de 100644 --- a/port/linux/game/view_fov.c +++ b/port/linux/game/view_fov.c @@ -263,6 +263,23 @@ boolean viewmodel_is_visible(void) return visible; } +/* ---------- whether the energy shield's flare is drawn on the arms */ + +boolean viewmodel_shield_is_visible(void) +{ + static boolean initialized, visible; + static unsigned long read_at; + unsigned long changes = config_changes(); + + if (!initialized || read_at != changes) + { + visible = config_boolean("display.viewmodel_shield") != 0; + initialized = TRUE; + read_at = changes; + } + return visible; +} + boolean viewmodel_draws_geometry(boolean first_person) { return !first_person || viewmodel_is_visible(); diff --git a/port/linux/game/view_fov.h b/port/linux/game/view_fov.h index 6f410e0a..de4dcec5 100644 --- a/port/linux/game/view_fov.h +++ b/port/linux/game/view_fov.h @@ -25,6 +25,9 @@ void viewmodel_projection_end(void); /* whether the first-person weapon, hands and attached visuals are drawn (display.viewmodel_visible); its firing, sounds and lights go on either way */ boolean viewmodel_is_visible(void); +/* display.viewmodel_shield: the unit's energy shield flare drawn on the +first-person arms too, as on its body */ +boolean viewmodel_shield_is_visible(void); /* whether a pass draws: not one of the first-person weapon's that is hidden */ boolean viewmodel_draws_geometry(boolean first_person); diff --git a/port/linux/src/port_config.c b/port/linux/src/port_config.c index 32fe5b1f..e225c293 100644 --- a/port/linux/src/port_config.c +++ b/port/linux/src/port_config.c @@ -295,6 +295,9 @@ static const struct config_setting config_settings[] = "as CUSTOM SINGLEPLAYER and CUSTOM MULTIPLAYER. Their tags are checked\n" "as the game's own maps' are before they run; false refuses them\n" "(docs/custom_edition_caches.md)." }, + { "display.viewmodel_shield", _config_boolean, "false", "HALO_VIEWMODEL_SHIELD", _environment_value, _platform_all, + "The energy shield's flare on the first-person arms too, as on the body\n" + "(the stock game draws it on the body only)." }, { "paths.data", _config_string, "\"\"", "HALO_DATA_ROOT", _environment_value, _platform_desktop, "The folder holding the game data's maps folder; empty looks in the\n" diff --git a/source/interface/first_person_weapons.c b/source/interface/first_person_weapons.c index 733f71cf..025b2f56 100644 --- a/source/interface/first_person_weapons.c +++ b/source/interface/first_person_weapons.c @@ -125,6 +125,8 @@ symbols in this file: #include "sound/sound_manager.h" #include "units/units.h" #include "view_fov.h" /* port: port/linux/game/view_fov.c */ +#include "shaders/shader_definitions.h" /* port: (the shield's flare on the arms) */ +#include "shaders/shaders.h" /* ---------- constants */ @@ -544,6 +546,26 @@ void first_person_weapon_draw( FLAG(_render_model_first_person_bit)); } + /* port: the shield's flare on the arms as on the body, the + unit's own modifier shader (display.viewmodel_shield, + view_fov.c); the weapon above is drawn without it */ + if (viewmodel_shield_is_visible()) + { + struct object_definition *unit_definition= object_definition_get(object_get(unit_index)->definition_index); + + if (unit_definition->object.modifier_shader.index!=NONE) + { + struct shader *modifier_shader= shader_definition_get(unit_definition->object.modifier_shader.index); + + if (shader_type_is_valid_for_modifier(modifier_shader->base.type)) + { + model_effect.modifier_shader= modifier_shader; + model_effect.modifier_animation.colors= unit->object.outgoing_change_colors; + model_effect.modifier_animation.values= unit->object.outgoing_function_values; + } + } + } + if (first_person_weapon->hands_node_remapping_table_valid && first_person_interface->hands.index!=NONE) { diff --git a/tools/port_settings.py b/tools/port_settings.py index 944783f6..729e7ae6 100644 --- a/tools/port_settings.py +++ b/tools/port_settings.py @@ -202,6 +202,8 @@ SCREENS["video_settings/fov_viewmodels"] = { "The weapon and hands, horizontal at 16:9.\nDefault keeps the weapon's stock view.", None), ("VIEWMODELS:", "display.viewmodel_visible", ON_OFF, "Draw first-person weapons, hands and attached\nvisuals. Gameplay and sound continue when off.", None), + ("ARM SHIELDS:", "display.viewmodel_shield", ON_OFF, + "The energy shield's flare on your first-person\narms too, as on your body.", None), ], }