diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 8d0abfdfb..ff2e01aa4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ January 7, 2008 +- Added support for user-defined crosshairs in the Display Options menu. See + xhairs.txt in zdoom.pk3. It's pretty simple. - Fixed: P_BounceWall() cannot assume that BlockingLine is the line the actor should bounce off of. Since the order lines in a blockmap cell are checked for collision is essentially undefined, there could be another line closer to diff --git a/src/m_menu.h b/src/m_menu.h index 95c4ebd8a..4419828c9 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -98,6 +98,7 @@ typedef enum { absslider, inverter, discrete, + discretes, cdiscrete, discrete_guid, control, @@ -145,6 +146,7 @@ typedef struct menuitem_s { } d; union { struct value_s *values; + struct valuestring_t *valuestrings; GUIDName *guidvalues; char *command; void (*cfunc)(FBaseCVar *cvar, float newval); @@ -174,6 +176,11 @@ typedef struct value_s { const char *name; } value_t; +struct valuestring_t { + float value; + FString name; +}; + typedef struct { // -1 = no cursor here, 1 = ok, 2 = arrows ok diff --git a/src/m_options.cpp b/src/m_options.cpp index 598e7877c..3d0eecf34 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -76,6 +76,7 @@ #include "m_misc.h" #include "hardware.h" +#include "sc_man.h" // Data. #include "m_menu.h" @@ -442,6 +443,7 @@ menu_t ControlsMenu = static void StartMessagesMenu (void); static void StartAutomapMenu (void); static void StartScoreboardMenu (void); +static void InitCrosshairsList(); EXTERN_CVAR (Bool, st_scale) EXTERN_CVAR (Int, r_detail) @@ -456,17 +458,7 @@ EXTERN_CVAR (Bool, vid_palettehack) EXTERN_CVAR (Bool, vid_attachedsurfaces) EXTERN_CVAR (Int, screenblocks) -static value_t Crosshairs[] = -{ - { 0.0, "None" }, - { 1.0, "Cross 1" }, - { 2.0, "Cross 2" }, - { 3.0, "X" }, - { 4.0, "Circle" }, - { 5.0, "Angle" }, - { 6.0, "Triangle" }, - { 7.0, "Dot" } -}; +static TArray Crosshairs; static value_t DetailModes[] = { @@ -512,7 +504,7 @@ static menuitem_t VideoItems[] = { { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { slider, "Screen size", {&screenblocks}, {3.0}, {12.0}, {1.0}, {NULL} }, { slider, "Brightness", {&Gamma}, {1.0}, {3.0}, {0.1}, {NULL} }, - { discrete, "Crosshair", {&crosshair}, {8.0}, {0.0}, {0.0}, {Crosshairs} }, + { discretes,"Crosshair", {&crosshair}, {8.0}, {0.0}, {0.0}, {NULL} }, { discrete, "Column render mode", {&r_columnmethod}, {2.0}, {0.0}, {0.0}, {ColumnMethods} }, { discrete, "Detail mode", {&r_detail}, {4.0}, {0.0}, {0.0}, {DetailModes} }, { discrete, "Stretch short skies", {&r_stretchsky}, {2.0}, {0.0}, {0.0}, {OnOff} }, @@ -1461,6 +1453,17 @@ int M_FindCurVal (float cur, value_t *values, int numvals) return v; } +int M_FindCurVal (float cur, valuestring_t *values, int numvals) +{ + int v; + + for (v = 0; v < numvals; v++) + if (values[v].value == cur) + break; + + return v; +} + int M_FindCurGUID (const GUID &guid, GUIDName *values, int numvals) { int v; @@ -1615,7 +1618,8 @@ void M_OptDrawer () } break; - + + case discretes: case discrete: case cdiscrete: case inverter: @@ -1632,7 +1636,14 @@ void M_OptDrawer () { vals = (int)item->b.numvalues; } - v = M_FindCurVal (value.Float, item->e.values, vals); + if (item->type != discretes) + { + v = M_FindCurVal (value.Float, item->e.values, vals); + } + else + { + v = M_FindCurVal (value.Float, item->e.valuestrings, vals); + } if (v == vals) { @@ -1642,7 +1653,8 @@ void M_OptDrawer () else { screen->DrawText (item->type == cdiscrete ? v : ValueColor, - CurrentMenu->indent + 14, y, item->e.values[v].name, + CurrentMenu->indent + 14, y, + item->type != discretes ? item->e.values[v].name : item->e.valuestrings[v].name, DTA_Clean, true, TAG_DONE); } @@ -2098,6 +2110,7 @@ void M_OptResponder (event_t *ev) S_Sound (CHAN_VOICE, "menu/cursor", 1, ATTN_NONE); break; + case discretes: case discrete: case cdiscrete: { @@ -2106,11 +2119,18 @@ void M_OptResponder (event_t *ev) numvals = (int)item->b.min; value = item->a.cvar->GetGenericRep (CVAR_Float); - cur = M_FindCurVal (value.Float, item->e.values, numvals); + if (item->type != discretes) + { + cur = M_FindCurVal (value.Float, item->e.values, numvals); + } + else + { + cur = M_FindCurVal (value.Float, item->e.valuestrings, numvals); + } if (--cur < 0) cur = numvals - 1; - value.Float = item->e.values[cur].value; + value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value; item->a.cvar->SetGenericRep (value, CVAR_Float); // Hack hack. Rebuild list of resolutions @@ -2232,6 +2252,7 @@ void M_OptResponder (event_t *ev) S_Sound (CHAN_VOICE, "menu/cursor", 1, ATTN_NONE); break; + case discretes: case discrete: case cdiscrete: { @@ -2240,11 +2261,18 @@ void M_OptResponder (event_t *ev) numvals = (int)item->b.min; value = item->a.cvar->GetGenericRep (CVAR_Float); - cur = M_FindCurVal (value.Float, item->e.values, numvals); + if (item->type != discretes) + { + cur = M_FindCurVal (value.Float, item->e.values, numvals); + } + else + { + cur = M_FindCurVal (value.Float, item->e.valuestrings, numvals); + } if (++cur >= numvals) cur = 0; - value.Float = item->e.values[cur].value; + value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value; item->a.cvar->SetGenericRep (value, CVAR_Float); // Hack hack. Rebuild list of resolutions @@ -2398,18 +2426,25 @@ void M_OptResponder (event_t *ev) item->e.mfunc(); } } - else if (item->type == discrete || item->type == cdiscrete) + else if (item->type == discrete || item->type == cdiscrete || item->type == discretes) { int cur; int numvals; numvals = (int)item->b.min; value = item->a.cvar->GetGenericRep (CVAR_Float); - cur = M_FindCurVal (value.Float, item->e.values, numvals); + if (item->type != discretes) + { + cur = M_FindCurVal (value.Float, item->e.values, numvals); + } + else + { + cur = M_FindCurVal (value.Float, item->e.valuestrings, numvals); + } if (++cur >= numvals) cur = 0; - value.Float = item->e.values[cur].value; + value.Float = item->type != discretes ? item->e.values[cur].value : item->e.valuestrings[cur].value; item->a.cvar->SetGenericRep (value, CVAR_Float); // Hack hack. Rebuild list of resolutions @@ -2846,6 +2881,7 @@ static void MakeSoundChanges (void) static void VideoOptions (void) { + InitCrosshairsList(); M_SwitchMenu (&VideoMenu); } @@ -2853,6 +2889,7 @@ CCMD (menu_display) { M_StartControlPanel (true); OptionsActive = true; + InitCrosshairsList(); M_SwitchMenu (&VideoMenu); } @@ -3264,3 +3301,51 @@ void M_Deinit () M_FreeModesList(); } +// Reads any XHAIRS lumps for the names of crosshairs and +// adds them to the display options menu. +void InitCrosshairsList() +{ + int lastlump, lump; + valuestring_t value; + + lastlump = 0; + + Crosshairs.Clear(); + value.value = 0; + value.name = "None"; + Crosshairs.Push(value); + + while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1) + { + SC_OpenLumpNum(lump, "XHAIRS"); + while (SC_GetNumber()) + { + value.value = float(sc_Number); + SC_MustGetString(); + value.name = sc_String; + if (value.value != 0) + { // Check if it already exists. If not, add it. + unsigned int i; + + for (i = 1; i < Crosshairs.Size(); ++i) + { + if (Crosshairs[i].value == value.value) + { + break; + } + } + if (i < Crosshairs.Size()) + { + Crosshairs[i].name = value.name; + } + else + { + Crosshairs.Push(value); + } + } + } + SC_Close(); + } + VideoItems[6].b.numvalues = float(Crosshairs.Size()); + VideoItems[6].e.valuestrings = &Crosshairs[0]; +} diff --git a/wadsrc/wadsrc.vcproj b/wadsrc/wadsrc.vcproj index a95ef1786..c1e1644b2 100644 --- a/wadsrc/wadsrc.vcproj +++ b/wadsrc/wadsrc.vcproj @@ -169,6 +169,10 @@ RelativePath=".\x11r6rgb.txt" > + + diff --git a/wadsrc/zdoom.lst b/wadsrc/zdoom.lst index 95c2b4e50..de6945697 100644 --- a/wadsrc/zdoom.lst +++ b/wadsrc/zdoom.lst @@ -110,6 +110,8 @@ graphics/stfbany.lmp stfbany.lmp ======== # Crosshairs +xhairs.txt xhairs.txt + graphics/xhairs1.imgz xhairs1.imgz graphics/xhairs2.imgz xhairs2.imgz graphics/xhairs3.imgz xhairs3.imgz @@ -119,7 +121,7 @@ graphics/xhairs6.imgz xhairs6.imgz graphics/xhairs7.imgz xhairs7.imgz graphics/xhairb1.imgz xhairb1.imgz -graphics/xhairb2.imgz xhairb2.png +graphics/xhairb2.png xhairb2.png graphics/xhairb3.imgz xhairb3.imgz graphics/xhairb4.imgz xhairb4.imgz graphics/xhairb5.imgz xhairb5.imgz