diff --git a/files/fallout2.cfg b/files/fallout2.cfg index a22d64be..407a9b05 100644 --- a/files/fallout2.cfg +++ b/files/fallout2.cfg @@ -110,6 +110,8 @@ iface_bar_mode=0 iface_bar_side_art=2 iface_bar_sides_ori=0 iface_bar_width=800 +;Set to 1 to use the HRP-style alternate ammo metre in the HP/AC cluster. +ALTERNATE_AMMO_METRE=0 ;Whether to load EDG files (HRP format) when loading maps. If loaded, they override default edge clipping and scroll blocking behavior. edg_support=1 ignore_map_edges=0 diff --git a/src/interface.cc b/src/interface.cc index 3e9da782..599fbba9 100644 --- a/src/interface.cc +++ b/src/interface.cc @@ -111,6 +111,14 @@ constexpr int kCustomIndicatorMaxCount = kCustomIndicatorMaxTag - kCustomIndicat constexpr int kCustomIndicatorDefaultCount = 5; constexpr int kCustomIndicatorTextLength = 19; constexpr int kCustomIndicatorTextBufferSize = kCustomIndicatorTextLength + 1; +constexpr int kAmmoBarLeft = 463; +constexpr int kAmmoBarTop = 26; +constexpr int kAmmoBarMaxRatio = 70; +constexpr int kAmmoAlternateMetreWidth = 5; +constexpr unsigned char kAmmoAlternateMetreBorderColor = 0; +constexpr unsigned char kAmmoAlternateMetreEmptyColor = 14; +constexpr unsigned char kAmmoAlternateMetreFillColor = 196; +constexpr unsigned char kAmmoAlternateMetreFillShadeColor = 14; struct CustomIndicatorDescription { bool isActive; @@ -131,6 +139,8 @@ static int endTurnButtonFree(); static int endCombatButtonInit(); static int endCombatButtonFree(); static void interfaceUpdateAmmoBar(int x, int ratio); +static void interfaceUpdateAlternateAmmoMetre(int x, int ratio); +static void interfaceUpdateAlternateAmmoMetreRow(unsigned char* dest, bool filled); static int _intface_item_reload(); static void interfaceDrawActionButtonOverlay(unsigned char* data, int width, int height, int pitch, int upX, int upY, int darkenColor); static void interfaceRenderCounterAnimationStep(unsigned char* src, unsigned char* dest, int delayMs, Rect* numbersRect, bool refreshMouse); @@ -1444,7 +1454,7 @@ int _intface_update_ammo_lights() } } - interfaceUpdateAmmoBar(463 + gInterfaceBarContentOffset, ratio); + interfaceUpdateAmmoBar(kAmmoBarLeft + gInterfaceBarContentOffset, ratio); return 0; } @@ -2053,6 +2063,11 @@ static int endCombatButtonFree() // 0x460AA0 intface_draw_ammo_lights static void interfaceUpdateAmmoBar(int x, int ratio) { + if (settings.ui.alternate_ammo_metre) { + interfaceUpdateAlternateAmmoMetre(x, ratio); + return; + } + if ((ratio & 1) != 0) { ratio -= 1; } @@ -2084,6 +2099,42 @@ static void interfaceUpdateAmmoBar(int x, int ratio) } } +static void interfaceUpdateAlternateAmmoMetre(int x, int ratio) +{ + if ((ratio & 1) != 0) { + ratio -= 1; + } + + unsigned char* dest = gInterfaceWindowBuffer + gInterfaceBarWidth * kAmmoBarTop + x; + int firstActiveRow = kAmmoBarMaxRatio - ratio; + + for (int row = 0; row <= kAmmoBarMaxRatio; row++) { + bool filled = row < kAmmoBarMaxRatio + && row >= firstActiveRow + && ((row - firstActiveRow) & 1) == 0; + interfaceUpdateAlternateAmmoMetreRow(dest, filled); + dest += gInterfaceBarWidth; + } + + if (!gInterfaceBarInitialized) { + Rect rect; + rect.left = x; + rect.top = kAmmoBarTop; + rect.right = x + kAmmoAlternateMetreWidth - 1; + rect.bottom = kAmmoBarTop + kAmmoBarMaxRatio; + windowRefreshRect(gInterfaceBarWindow, &rect); + } +} + +static void interfaceUpdateAlternateAmmoMetreRow(unsigned char* dest, bool filled) +{ + dest[0] = kAmmoAlternateMetreBorderColor; + dest[1] = filled ? kAmmoAlternateMetreFillColor : kAmmoAlternateMetreEmptyColor; + dest[2] = filled ? kAmmoAlternateMetreFillColor : kAmmoAlternateMetreEmptyColor; + dest[3] = filled ? kAmmoAlternateMetreFillShadeColor : kAmmoAlternateMetreEmptyColor; + dest[4] = kAmmoAlternateMetreBorderColor; +} + // 0x460B20 intface_item_reload static int _intface_item_reload() { diff --git a/src/settings.cc b/src/settings.cc index cec69950..93820d2f 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -113,6 +113,19 @@ void registerSetting(const char* section, const char* key, T& variable, P postPr } }); } +static void registerBoolSettingWithFallback(const char* section, const char* key, const char* fallbackKey, bool& variable) +{ + settingsRegistry.push_back( + { [&, section, key, fallbackKey]() { + settingsRead(section, fallbackKey, variable); + settingsRead(section, key, variable); + }, + [&, section, key, fallbackKey](bool onlyAdd) { + if (onlyAdd && (settingsKeyExists(section, key) || settingsKeyExists(section, fallbackKey))) return; + settingsWrite(section, key, variable); + } }); +} + // SECT must be defined to the settings sub-struct name, which equals the config section string. #define XSTR(x) #x #define STR(x) XSTR(x) @@ -156,6 +169,7 @@ void initSettingsRegistry(bool isMapper) SETTING_P(iface_bar_width, clamp(640, 4320)); SETTING_P(iface_bar_side_art, clamp(0, 999)); SETTING(iface_bar_sides_ori); + registerBoolSettingWithFallback(STR(SECT), "ALTERNATE_AMMO_METRE", "alternate_ammo_meter", settings.ui.alternate_ammo_metre); SETTING_P(splash_screen_size, clamp(0, 2)); SETTING(movie_aspect_fit); SETTING(edg_support); diff --git a/src/settings.h b/src/settings.h index 14f7f27a..b4fb5d54 100644 --- a/src/settings.h +++ b/src/settings.h @@ -59,6 +59,9 @@ struct UISettings { // Iface-bar side graphics extend from the Screen edges to the Iface-Bar if true (otherwise from bar to edges). bool iface_bar_sides_ori = false; + // Use HRP-style alternate ammo metre in the HP/AC cluster. + bool alternate_ammo_metre = false; + // Extends AP bar to 16 dots instead of 10. bool extend_ap_bar = false;