diff --git a/port/src/main.c b/port/src/main.c index 10150f7ae..901d2eef4 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -176,5 +176,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4); + configRegisterInt(strFmt("Game.Player%d.CrosshairHealth", i), &g_PlayerExtCfg[j].crosshairhealth, 0, CROSSHAIR_HEALTH_ON_WHITE); } } diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index dd999bee4..e8085b564 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -1040,6 +1040,30 @@ static MenuItemHandlerResult menuhandlerCrosshairSize(s32 operation, struct menu return 0; } +static MenuItemHandlerResult menuhandlerCrosshairHealth(s32 operation, struct menuitem *item, union handlerdata *data) +{ + static const char *opts[] = { + "Off", + "On (Green)", + "On (White)" + }; + + switch (operation) { + case MENUOP_GETOPTIONCOUNT: + data->dropdown.value = ARRAYCOUNT(opts); + break; + case MENUOP_GETOPTIONTEXT: + return (intptr_t)opts[data->dropdown.value]; + case MENUOP_SET: + g_PlayerExtCfg[g_ExtMenuPlayer].crosshairhealth = data->dropdown.value; + break; + case MENUOP_GETSELECTEDINDEX: + data->dropdown.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshairhealth; + } + + return 0; +} + struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { { MENUITEMTYPE_SLIDER, @@ -1158,6 +1182,14 @@ struct menuitem g_ExtendedGameMenuItems[] = { 0, (void*)&g_ExtendedGameCrosshairColourMenuDialog, }, + { + MENUITEMTYPE_DROPDOWN, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Crosshair Colour by Health", + 0, + menuhandlerCrosshairHealth, + }, { MENUITEMTYPE_SEPARATOR, 0, diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 7246a418b..9aca1a2a2 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -124,6 +124,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .extcontrols = true, \ .crosshaircolour = 0x00ff0028, \ .crosshairsize = 2, \ + .crosshairhealth = CROSSHAIR_HEALTH_OFF, \ } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { diff --git a/src/game/sight.c b/src/game/sight.c index d8fb87007..cc55ffc59 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -23,9 +23,55 @@ #include #include "video.h" -#define SIGHT_COLOUR PLAYER_EXTCFG().crosshaircolour +#define SIGHT_COLOUR ((PLAYER_EXTCFG().crosshairhealth >= CROSSHAIR_HEALTH_ON_GREEN) ? sightGetCrosshairHealthColor(g_Vars.currentplayer->bondhealth, g_Vars.currentplayer->prop->chr->cshield * 0.125f) : PLAYER_EXTCFG().crosshaircolour) #define SIGHT_SCALE PLAYER_EXTCFG().crosshairsize +static u32 sightGetCrosshairHealthColor(float health, float shield) +{ + const float ratio = MAX(0.0f, MIN(health + shield, 2.0f)); + + int red = 0; + int green = 0; + int blue = 0; + if (ratio < 0.2f) { + // Red (critical health level) + red = 255; + green = 0; + blue = 0; + } else if (ratio < 0.6f) { + // Red-yellow + red = 255; + green = 255 * ((ratio - 0.2f) / 0.4f); + blue = 0; + } else if (ratio < 1.0f) { + if (PLAYER_EXTCFG().crosshairhealth == CROSSHAIR_HEALTH_ON_GREEN) { + // Yellow-green + red = 255 * ((ratio - 0.6f) / 0.4f); + green = 255; + blue = 0; + } else { + // Yellow-white + red = 255; + green = 255; + blue = 255 * ((ratio - 0.6f) / 0.4f); + } + } else { + if (PLAYER_EXTCFG().crosshairhealth == CROSSHAIR_HEALTH_ON_GREEN) { + // Green-cyan (overheal via shield) + red = 0; + green = 255; + blue = 255 * (ratio - 1.0f); + } else { + // White-green (overheal via shield) + red = 255 * (2.0f - ratio); + green = 255; + blue = 255 * (2.0f - ratio); + } + } + + return (red << 24) + (green << 16) + (blue << 8) + (PLAYER_EXTCFG().crosshaircolour & 0xff); +} + static inline f32 sightGetScaleX(void) { return (videoGetAspect() / SCREEN_ASPECT); diff --git a/src/include/constants.h b/src/include/constants.h index 4c3705b7f..612138bcf 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -4718,6 +4718,10 @@ enum weaponnum { #define CROUCHMODE_TOGGLE 2 // press the crouch buttons to toggle stance #define CROUCHMODE_TOGGLE_ANALOG (CROUCHMODE_ANALOG | CROUCHMODE_TOGGLE) +#define CROSSHAIR_HEALTH_OFF 0 +#define CROSSHAIR_HEALTH_ON_GREEN 1 +#define CROSSHAIR_HEALTH_ON_WHITE 2 + #endif #endif diff --git a/src/include/types.h b/src/include/types.h index 2a0491896..0d772d798 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6141,6 +6141,7 @@ struct extplayerconfig { s32 extcontrols; u32 crosshaircolour; u32 crosshairsize; + s32 crosshairhealth; }; #endif