diff --git a/src/am_map.cpp b/src/am_map.cpp index a72adbd61..57eec604c 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -317,30 +317,26 @@ CVAR (Color, am_ovportalcolor, 0x004022, CVAR_ARCHIVE); struct AMColor { - int Index; uint32_t RGB; void FromCVar(FColorCVar & cv) { - Index = cv.GetIndex(); RGB = uint32_t(cv) | MAKEARGB(255, 0, 0, 0); } void FromRGB(int r,int g, int b) { RGB = MAKEARGB(255, r, g, b); - Index = ColorMatcher.Pick(r, g, b); } void setInvalid() { - Index = -1; - RGB = -1; + RGB = 0; } bool isValid() const { - return Index > -1; + return RGB != 0; } }; @@ -1585,7 +1581,7 @@ void DAutomap::clearFB (const AMColor &color) if (!drawback) { - screen->Clear (0, 0, f_w, f_h, color.Index, color.RGB); + screen->Clear (0, 0, f_w, f_h, -1, color.RGB); } else { @@ -1752,7 +1748,7 @@ void DAutomap::drawMline (mline_t *ml, const AMColor &color) if (clipMline (ml, &fl)) { - screen->DrawLine (f_x + fl.a.x, f_y + fl.a.y, f_x + fl.b.x, f_y + fl.b.y, color.Index, color.RGB); + screen->DrawLine (f_x + fl.a.x, f_y + fl.a.y, f_x + fl.b.x, f_y + fl.b.y, -1, color.RGB); } } @@ -2955,7 +2951,7 @@ void DAutomap::drawThings () if (G_SkillProperty(SKILLP_EasyKey) || am_showkeys_always) { // Already drawn by AM_drawKeys(), so don't draw again - color.Index = -1; + color.RGB = 0; } else if (am_showkeys) { @@ -2964,7 +2960,7 @@ void DAutomap::drawThings () if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); else color = AMColors[AMColors.ThingColor_CountItem]; drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0., color, p.x, p.y); - color.Index = -1; + color.RGB = 0; } else { @@ -2977,7 +2973,7 @@ void DAutomap::drawThings () color = AMColors[AMColors.ThingColor_Item]; } - if (color.Index != -1) + if (color.isValid()) { drawLineCharacter(thintriangle_guy.data(), thintriangle_guy.size(), 16, angle, color, p.x, p.y); } @@ -3150,7 +3146,7 @@ void DAutomap::drawAuthorMarkers () void DAutomap::drawCrosshair (const AMColor &color) { - screen->DrawPixel(f_w/2, (f_h+1)/2, color.Index, color.RGB); + screen->DrawPixel(f_w/2, (f_h+1)/2, -1, color.RGB); } //============================================================================= diff --git a/src/common/engine/palettecontainer.cpp b/src/common/engine/palettecontainer.cpp index 48ff12737..ce7b5df1f 100644 --- a/src/common/engine/palettecontainer.cpp +++ b/src/common/engine/palettecontainer.cpp @@ -34,13 +34,14 @@ #include "palutil.h" #include "sc_man.h" -#include "v_palette.h" #include "m_crc32.h" #include "printf.h" #include "colormatcher.h" #include "templates.h" #include "palettecontainer.h" +#include "v_palette.h" + //---------------------------------------------------------------------------- // diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index 019327807..b10f48081 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -159,7 +159,7 @@ std2: 'class' { RET(TK_Class); } 'mixin' { RET(TK_Mixin); } 'enum' { RET(TK_Enum); } - 'name' { RET(TK_Name); } + 'name' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Name : TK_Identifier); } 'string' { RET(TK_String); } 'sound' { RET(TK_Sound); } 'state' { RET(TK_State); } diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index 7f41ba978..fbf9c6844 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -315,6 +315,14 @@ void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v) } } +struct RemappingWork +{ + uint32_t Color; + uint8_t Foreign; // 0 = local palette, 1 = foreign palette + uint8_t PalEntry; // Entry # in the palette + uint8_t Pad[2]; +}; + static int sortforremap(const void* a, const void* b) { return (*(const uint32_t*)a & 0xFFFFFF) - (*(const uint32_t*)b & 0xFFFFFF); @@ -336,14 +344,6 @@ static int sortforremap2(const void* a, const void* b) } -struct RemappingWork -{ - uint32_t Color; - uint8_t Foreign; // 0 = local palette, 1 = foreign palette - uint8_t PalEntry; // Entry # in the palette - uint8_t Pad[2]; -}; - void MakeRemap(uint32_t* BaseColors, const uint32_t* colors, uint8_t* remap, const uint8_t* useful, int numcolors) { RemappingWork workspace[255 + 256]; diff --git a/src/console/c_cvars.cpp b/src/console/c_cvars.cpp index 6a68d90b0..4cadbb367 100644 --- a/src/console/c_cvars.cpp +++ b/src/console/c_cvars.cpp @@ -39,17 +39,13 @@ #include "configfile.h" #include "c_console.h" #include "c_dispatch.h" +#include "c_cvars.h" +#include "engineerrors.h" +#include "printf.h" -#include "g_game.h" -#include "d_player.h" -#include "v_video.h" -#include "d_netinf.h" -#include "serializer.h" +#include "v_video.h" // for color lookup - move to utility code!!! -#include "menu/menu.h" -#include "vm.h" - -#include "version.h" +//#include "version.h" struct FLatchedValue { @@ -68,7 +64,17 @@ FBaseCVar *CVars = NULL; int cvar_defflags; -FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &)) + +static ConsoleCallbacks* callbacks; + +// Install game-specific handlers, mainly to deal with serverinfo and userinfo CVARs. +// This is to keep the console independent of game implementation details for easier reusability. +void C_InstallHandlers(ConsoleCallbacks* cb) +{ + callbacks = cb; +} + +FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr) { if (var_name != nullptr && (flags & CVAR_SERVERINFO)) { @@ -83,19 +89,19 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa } } - FBaseCVar *var; - var = FindCVar (var_name, NULL); m_Callback = callback; Flags = 0; - Name = NULL; - inCallback = false; + VarName = ""; + Description = descr; + FBaseCVar* var = nullptr; if (var_name) { + var = FindCVar(var_name, NULL); C_AddTabCommand (var_name); - Name = copystring (var_name); + VarName = var_name; m_Next = CVars; CVars = this; } @@ -123,11 +129,11 @@ FBaseCVar::FBaseCVar (const char *var_name, uint32_t flags, void (*callback)(FBa FBaseCVar::~FBaseCVar () { - if (Name) + if (VarName.IsNotEmpty()) { FBaseCVar *var, *prev; - var = FindCVar (Name, &prev); + var = FindCVar (VarName, &prev); if (var == this) { @@ -136,8 +142,8 @@ FBaseCVar::~FBaseCVar () else CVars = m_Next; } - C_RemoveTabCommand(Name); - delete[] Name; + if (var->Flags & CVAR_AUTO) + C_RemoveTabCommand(VarName); } } @@ -150,7 +156,7 @@ void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend) { DoSet (value, type); if ((Flags & CVAR_USERINFO) && !nouserinfosend && !(Flags & CVAR_IGNORE)) - D_UserInfoChanged (this); + if (callbacks && callbacks->UserInfoChanged) callbacks->UserInfoChanged(this); if (m_UseCallback) Callback (); @@ -168,7 +174,7 @@ void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) { return; } - else if ((Flags & CVAR_LATCH) && gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) + else if ((Flags & CVAR_LATCH) && callbacks && callbacks->MustLatch()) { FLatchedValue latch; @@ -183,15 +189,9 @@ void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) Flags &= ~CVAR_UNSAFECONTEXT; } - else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) + else if ((Flags & CVAR_SERVERINFO) && callbacks && callbacks->SendServerInfoChange) { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - Flags &= ~CVAR_UNSAFECONTEXT; - return; - } - D_SendServerInfoChange (this, value, type); + callbacks->SendServerInfoChange (this, value, type); } else { @@ -199,83 +199,6 @@ void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) } } -DEFINE_ACTION_FUNCTION(_CVar, GetInt) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - auto v = self->GetGenericRep(CVAR_Int); - ACTION_RETURN_INT(v.Int); -} - -DEFINE_ACTION_FUNCTION(_CVar, GetFloat) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - auto v = self->GetGenericRep(CVAR_Float); - ACTION_RETURN_FLOAT(v.Float); -} - -DEFINE_ACTION_FUNCTION(_CVar, GetString) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - auto v = self->GetGenericRep(CVAR_String); - ACTION_RETURN_STRING(v.String); -} - -DEFINE_ACTION_FUNCTION(_CVar, SetInt) -{ - // Only menus are allowed to change CVARs. - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - if (!(self->GetFlags() & CVAR_MOD)) - { - // Only menus are allowed to change non-mod CVARs. - if (DMenu::InMenu == 0) - { - ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); - } - } - PARAM_INT(val); - UCVarValue v; - v.Int = val; - self->SetGenericRep(v, CVAR_Int); - return 0; -} - -DEFINE_ACTION_FUNCTION(_CVar, SetFloat) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - if (!(self->GetFlags() & CVAR_MOD)) - { - // Only menus are allowed to change non-mod CVARs. - if (DMenu::InMenu == 0) - { - ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); - } - } - PARAM_FLOAT(val); - UCVarValue v; - v.Float = (float)val; - self->SetGenericRep(v, CVAR_Float); - return 0; -} - -DEFINE_ACTION_FUNCTION(_CVar, SetString) -{ - // Only menus are allowed to change CVARs. - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - if (!(self->GetFlags() & CVAR_MOD)) - { - // Only menus are allowed to change non-mod CVARs. - if (DMenu::InMenu == 0) - { - ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); - } - } - PARAM_STRING(val); - UCVarValue v; - v.String = val.GetChars(); - self->SetGenericRep(v, CVAR_String); - return 0; -} - bool FBaseCVar::ToBool (UCVarValue value, ECVarType type) { switch (type) @@ -591,18 +514,12 @@ void FBaseCVar::DisableCallbacks () m_UseCallback = false; } -DEFINE_ACTION_FUNCTION(_CVar, GetRealType) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - ACTION_RETURN_INT(self->GetRealType()); -} - // // Boolean cvar implementation // -FBoolCVar::FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) +FBoolCVar::FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &), const char* descr) +: FBaseCVar (name, flags, reinterpret_cast(callback), descr) { DefaultValue = def; if (Flags & CVAR_ISDEFAULT) @@ -659,8 +576,8 @@ void FBoolCVar::DoSet (UCVarValue value, ECVarType type) // Integer cvar implementation // -FIntCVar::FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) +FIntCVar::FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &), const char* descr) +: FBaseCVar (name, flags, reinterpret_cast(callback), descr) { DefaultValue = def; if (Flags & CVAR_ISDEFAULT) @@ -717,8 +634,8 @@ void FIntCVar::DoSet (UCVarValue value, ECVarType type) // Floating point cvar implementation // -FFloatCVar::FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) +FFloatCVar::FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &), const char* descr) +: FBaseCVar (name, flags, reinterpret_cast(callback), descr) { DefaultValue = def; if (Flags & CVAR_ISDEFAULT) @@ -785,23 +702,18 @@ void FFloatCVar::DoSet (UCVarValue value, ECVarType type) // String cvar implementation // -FStringCVar::FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) +FStringCVar::FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &), const char* descr) +: FBaseCVar (name, flags, reinterpret_cast(callback), descr) { - DefaultValue = copystring (def); + mDefaultValue = def; if (Flags & CVAR_ISDEFAULT) - Value = copystring (def); + mValue = def; else - Value = NULL; + mValue = ""; } FStringCVar::~FStringCVar () { - if (Value != NULL) - { - delete[] Value; - } - delete[] DefaultValue; } ECVarType FStringCVar::GetRealType () const @@ -811,33 +723,33 @@ ECVarType FStringCVar::GetRealType () const UCVarValue FStringCVar::GetGenericRep (ECVarType type) const { - return FromString (Value, type); + return FromString (mValue, type); } UCVarValue FStringCVar::GetFavoriteRep (ECVarType *type) const { UCVarValue ret; *type = CVAR_String; - ret.String = Value; + ret.String = mValue; return ret; } UCVarValue FStringCVar::GetGenericRepDefault (ECVarType type) const { - return FromString (DefaultValue, type); + return FromString (mDefaultValue, type); } UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const { UCVarValue ret; *type = CVAR_String; - ret.String = DefaultValue; + ret.String = mDefaultValue; return ret; } void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) { - ReplaceString(&DefaultValue, ToString(value, type)); + mDefaultValue = ToString(value, type); if (Flags & CVAR_ISDEFAULT) { SetGenericRep (value, type); @@ -847,15 +759,15 @@ void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) void FStringCVar::DoSet (UCVarValue value, ECVarType type) { - ReplaceString (&Value, ToString (value, type)); + mValue = ToString (value, type); } // // Color cvar implementation // -FColorCVar::FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &)) -: FIntCVar (name, def, flags, reinterpret_cast(callback)) +FColorCVar::FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &), const char* descr) +: FIntCVar (name, def, flags, reinterpret_cast(callback), descr) { } @@ -887,8 +799,6 @@ void FColorCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) void FColorCVar::DoSet (UCVarValue value, ECVarType type) { Value = ToInt2 (value, type); - if (screen) - Index = ColorMatcher.Pick (RPART(Value), GPART(Value), BPART(Value)); } UCVarValue FColorCVar::FromInt2 (int value, ECVarType type) @@ -962,22 +872,6 @@ void FBaseCVar::ResetToDefault () } } -DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault) -{ - PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); - if (!(self->GetFlags() & CVAR_MOD)) - { - // Only menus are allowed to change non-mod CVARs. - if (DMenu::InMenu == 0) - { - ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); - } - } - - self->ResetToDefault(); - return 0; -} - void FBaseCVar::MarkUnsafe() { if (!(Flags & CVAR_MOD) && UnsafeExecutionContext) @@ -995,8 +889,8 @@ void FBaseCVar::MarkUnsafe() // the network. The "host" cvar is responsible for that. // -FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval) -: FBaseCVar (name, 0, NULL), +FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr) +: FBaseCVar (name, 0, NULL, descr), ValueVar (realvar), BitVal (bitval) { @@ -1074,14 +968,9 @@ void FFlagCVar::DoSet (UCVarValue value, ECVarType type) // exec scripts because all flags will base their changes off of the value of // the "master" cvar at the time the script was run, overriding any changes // another flag might have made to the same cvar earlier in the script. - if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) + if (ValueVar.GetFlags() && callbacks && callbacks->SendServerFlagChange) { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - return; - } - D_SendServerFlagChange (&ValueVar, BitNum, newval); + callbacks->SendServerFlagChange(&ValueVar, BitNum, newval, false); } else { @@ -1100,8 +989,8 @@ void FFlagCVar::DoSet (UCVarValue value, ECVarType type) // Similar to FFlagCVar but can have multiple bits // -FMaskCVar::FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval) -: FBaseCVar (name, 0, NULL), +FMaskCVar::FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr) +: FBaseCVar (name, 0, NULL, descr), ValueVar (realvar), BitVal (bitval) { @@ -1176,19 +1065,16 @@ void FMaskCVar::DoSet (UCVarValue value, ECVarType type) // exec scripts because all flags will base their changes off of the value of // the "master" cvar at the time the script was run, overriding any changes // another flag might have made to the same cvar earlier in the script. - if ((ValueVar.GetFlags() & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) + if (ValueVar.GetFlags() && callbacks && callbacks->SendServerFlagChange) { - if (netgame && !players[consoleplayer].settings_controller) - { - Printf ("Only setting controllers can change %s\n", Name); - return; - } - // Ugh... + // The network interface needs to process each bit separately. + bool silent = false; for(int i = 0; i < 32; i++) { if (BitVal & (1<SendServerFlagChange (&ValueVar, i, !!(val & (1<m_Next) - { - if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) - { - UCVarValue val = cvar->GetGenericRep(CVAR_String); - char* c = const_cast(val.String); - arc(cvar->GetName(), c); - } - } - } - else - { - for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) - { - if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) - { - UCVarValue val; - char *c = nullptr; - arc(cvar->GetName(), c); - if (c != nullptr) - { - val.String = c; - cvar->SetGenericRep(val, CVAR_String); - delete[] c; - } - } - } - } - arc.EndObject(); - } -} - void C_ReadCVars (uint8_t **demo_p) { char *ptr = *((char **)demo_p); @@ -1432,21 +1277,6 @@ FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) return var; } -DEFINE_ACTION_FUNCTION(_CVar, FindCVar) -{ - PARAM_PROLOGUE; - PARAM_NAME(name); - ACTION_RETURN_POINTER(FindCVar(name.GetChars(), nullptr)); -} - -DEFINE_ACTION_FUNCTION(_CVar, GetCVar) -{ - PARAM_PROLOGUE; - PARAM_NAME(name); - PARAM_POINTER(plyr, player_t); - ACTION_RETURN_POINTER(GetCVar(plyr ? int(plyr - players) : -1, name.GetChars())); -} - FBaseCVar *FindCVarSub (const char *var_name, int namelen) { FBaseCVar *var; @@ -1480,29 +1310,14 @@ FBaseCVar *GetCVar(int playernum, const char *cvarname) else { // For userinfo cvars, redirect to GetUserCVar - if (cvar->GetFlags() & CVAR_USERINFO) + if ((cvar->GetFlags() & CVAR_USERINFO) && callbacks && callbacks->GetUserCVar) { - return GetUserCVar(playernum, cvarname); + return callbacks->GetUserCVar(playernum, cvarname); } return cvar; } } -FBaseCVar *GetUserCVar(int playernum, const char *cvarname) -{ - if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) - { - return nullptr; - } - FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); - FBaseCVar *cvar; - if (cvar_p == nullptr || (cvar = *cvar_p) == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) - { - return nullptr; - } - return cvar; -} - //=========================================================================== // // C_CreateCVar @@ -1790,58 +1605,3 @@ CCMD (archivecvar) } } -void C_GrabCVarDefaults () -{ - int lump, lastlump = 0; - int lumpversion, gamelastrunversion; - gamelastrunversion = atoi(LASTRUNVERSION); - - while ((lump = fileSystem.FindLump("DEFCVARS", &lastlump)) != -1) - { - // don't parse from wads - if (lastlump > fileSystem.GetLastEntry(fileSystem.GetMaxIwadNum())) - I_FatalError("Cannot load DEFCVARS from a wadfile!\n"); - - FScanner sc(lump); - - sc.MustGetString(); - if (!sc.Compare("version")) - sc.ScriptError("Must declare version for defcvars! (currently: %i)", gamelastrunversion); - sc.MustGetNumber(); - lumpversion = sc.Number; - if (lumpversion > gamelastrunversion) - sc.ScriptError("Unsupported version %i (%i supported)", lumpversion, gamelastrunversion); - if (lumpversion < 219) - sc.ScriptError("Version must be at least 219 (current version %i)", gamelastrunversion); - - FBaseCVar *var; - - while (sc.GetString()) - { - if (sc.Compare("set")) - { - sc.MustGetString(); - } - var = FindCVar (sc.String, NULL); - if (var != NULL) - { - if (var->GetFlags() & CVAR_ARCHIVE) - { - UCVarValue val; - - sc.MustGetString(); - val.String = const_cast(sc.String); - var->SetGenericRepDefault(val, CVAR_String); - } - else - { - sc.ScriptError("Cannot set cvar default for non-config cvar '%s'", sc.String); - } - } - else - { - sc.ScriptError("Unknown cvar '%s'", sc.String); - } - } - } -} diff --git a/src/console/c_cvars.h b/src/console/c_cvars.h index 0a00ccb4f..0e6594cd0 100644 --- a/src/console/c_cvars.h +++ b/src/console/c_cvars.h @@ -33,7 +33,6 @@ #ifndef __C_CVARS_H__ #define __C_CVARS_H__ - #include "zstring.h" #include "tarray.h" @@ -78,7 +77,13 @@ union UCVarValue bool Bool; int Int; float Float; - const char *String; + const char* String; + + UCVarValue() = default; + UCVarValue(bool v) { Bool = v; } + UCVarValue(int v) { Int = v; } + UCVarValue(float v) { Float = v; } + UCVarValue(const char * v) { String = v; } }; enum ECVarType @@ -97,10 +102,24 @@ class FConfigFile; class FxCVar; +class FBaseCVar; + +// These are calls into the game code. Having these hard coded in the CVAR implementation has always been the biggest blocker +// for reusing the CVAR module outside of ZDoom. So now they get called through this struct for easier reusability. +struct ConsoleCallbacks +{ + void (*UserInfoChanged)(FBaseCVar*); + void (*SendServerInfoChange)(FBaseCVar* cvar, UCVarValue value, ECVarType type); + void (*SendServerFlagChange)(FBaseCVar* cvar, int bitnum, bool set, bool silent); + FBaseCVar* (*GetUserCVar)(int playernum, const char* cvarname); + bool (*MustLatch)(); + +}; + class FBaseCVar { public: - FBaseCVar (const char *name, uint32_t flags, void (*callback)(FBaseCVar &)); + FBaseCVar (const char *name, uint32_t flags, void (*callback)(FBaseCVar &), const char *descr); virtual ~FBaseCVar (); inline void Callback () @@ -113,7 +132,7 @@ public: } } - inline const char *GetName () const { return Name; } + inline const char *GetName () const { return VarName.GetChars(); } inline uint32_t GetFlags () const { return Flags; } inline FBaseCVar *GetNext() const { return m_Next; } @@ -123,6 +142,14 @@ public: void ResetToDefault (); void SetArchiveBit () { Flags |= CVAR_ARCHIVE; } void MarkUnsafe(); + void MarkSafe() { Flags &= ~CVAR_UNSAFECONTEXT; } + + int ToInt() + { + ECVarType vt; + auto val = GetFavoriteRep(&vt); + return ToInt(val, vt); + } virtual ECVarType GetRealType () const = 0; @@ -143,6 +170,8 @@ public: static void ResetColors (); // recalc color cvars' indices after screen change static void ListVars (const char *filter, bool plain); + + const char *GetDescription() const { return Description; }; protected: virtual void DoSet (UCVarValue value, ECVarType type) = 0; @@ -156,10 +185,11 @@ protected: static UCVarValue FromFloat (float value, ECVarType type); static UCVarValue FromString (const char *value, ECVarType type); - char *Name; + FString VarName; FString SafeValue; + FString Description; uint32_t Flags; - bool inCallback; + bool inCallback = false; private: FBaseCVar (const FBaseCVar &var) = delete; @@ -171,6 +201,7 @@ private: static bool m_UseCallback; static bool m_DoNoSet; + // These need to go away! friend FString C_GetMassCVarString (uint32_t filter, bool compact); friend void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter); friend void C_ReadCVars (uint8_t **demo_p); @@ -197,6 +228,7 @@ void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact=false); void C_ReadCVars (uint8_t **demo_p); void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter); +void C_InstallHandlers(ConsoleCallbacks* cb); // Backup demo cvars. Called before a demo starts playing to save all // cvars the demo might change. @@ -208,7 +240,6 @@ FBaseCVar *FindCVarSub (const char *var_name, int namelen); // Used for ACS and DECORATE. FBaseCVar *GetCVar(int playernum, const char *cvarname); -FBaseCVar *GetUserCVar(int playernum, const char *cvarname); // Create a new cvar with the specified name and type FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags); @@ -233,7 +264,7 @@ class FBoolCVar : public FBaseCVar { friend class FxCVar; public: - FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &)=NULL); + FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &)=NULL, const char* descr = nullptr); virtual ECVarType GetRealType () const; @@ -259,7 +290,7 @@ class FIntCVar : public FBaseCVar { friend class FxCVar; public: - FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &)=NULL); + FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &)=NULL, const char* descr = nullptr); virtual ECVarType GetRealType () const; @@ -287,15 +318,15 @@ class FFloatCVar : public FBaseCVar { friend class FxCVar; public: - FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &)=NULL); + FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &)=NULL, const char* descr = nullptr); - virtual ECVarType GetRealType () const; + virtual ECVarType GetRealType () const override; - virtual UCVarValue GetGenericRep (ECVarType type) const; - virtual UCVarValue GetFavoriteRep (ECVarType *type) const; - virtual UCVarValue GetGenericRepDefault (ECVarType type) const; - virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const; - virtual void SetGenericRepDefault (UCVarValue value, ECVarType type); + virtual UCVarValue GetGenericRep (ECVarType type) const override ; + virtual UCVarValue GetFavoriteRep (ECVarType *type) const override; + virtual UCVarValue GetGenericRepDefault (ECVarType type) const override; + virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const override; + virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) override; const char *GetHumanString(int precision) const override; float operator= (float floatval) @@ -304,7 +335,7 @@ public: inline float operator *() const { return Value; } protected: - virtual void DoSet (UCVarValue value, ECVarType type); + virtual void DoSet (UCVarValue value, ECVarType type) override; float Value; float DefaultValue; @@ -314,7 +345,7 @@ class FStringCVar : public FBaseCVar { friend class FxCVar; public: - FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &)=NULL); + FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &)=NULL, const char* descr = nullptr); ~FStringCVar (); virtual ECVarType GetRealType () const; @@ -327,21 +358,21 @@ public: const char *operator= (const char *stringrep) { UCVarValue val; val.String = const_cast(stringrep); SetGenericRep (val, CVAR_String); return stringrep; } - inline operator const char * () const { return Value; } - inline const char *operator *() const { return Value; } + inline operator const char * () const { return mValue; } + inline const char *operator *() const { return mValue; } protected: virtual void DoSet (UCVarValue value, ECVarType type); - char *Value; - char *DefaultValue; + FString mValue; + FString mDefaultValue; }; class FColorCVar : public FIntCVar { friend class FxCVar; public: - FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &)=NULL); + FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &)=NULL, const char* descr = nullptr); virtual ECVarType GetRealType () const; @@ -351,22 +382,19 @@ public: inline operator uint32_t () const { return Value; } inline uint32_t operator *() const { return Value; } - inline int GetIndex () const { return Index; } protected: virtual void DoSet (UCVarValue value, ECVarType type); static UCVarValue FromInt2 (int value, ECVarType type); static int ToInt2 (UCVarValue value, ECVarType type); - - int Index; }; class FFlagCVar : public FBaseCVar { friend class FxCVar; public: - FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval); + FFlagCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr); virtual ECVarType GetRealType () const; @@ -395,7 +423,7 @@ class FMaskCVar : public FBaseCVar { friend class FxCVar; public: - FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval); + FMaskCVar (const char *name, FIntCVar &realvar, uint32_t bitval, const char* descr = nullptr); virtual ECVarType GetRealType () const; @@ -448,6 +476,20 @@ void C_ForgetCVars (void); #define EXTERN_CVAR(type,name) extern F##type##CVar name; +#define CUSTOM_CVARD(type,name,def,flags,descr) \ + static void cvarfunc_##name(F##type##CVar &); \ + F##type##CVar name (#name, def, flags, cvarfunc_##name, descr); \ + static void cvarfunc_##name(F##type##CVar &self) + +#define CVARD(type,name,def,flags, descr) \ + F##type##CVar name (#name, def, flags, nullptr, descr); + +#define CVARD_NAMED(type,name,varname,def,flags, descr) \ +F##type##CVar varname (#name, def, flags, nullptr, descr); + +#define CVAR_UNAMED(type,varname) \ +F##type##CVar varname (nullptr, 0, 0, nullptr, nullptr); + extern FBaseCVar *CVars; #endif //__C_CVARS_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index df2c07685..6214eb0cd 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -146,7 +146,6 @@ void DrawFullscreenSubtitle(const char *text); void D_Cleanup(); void FreeSBarInfoScript(); void I_UpdateWindowTitle(); -void C_GrabCVarDefaults (); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -284,6 +283,62 @@ static int pagetic; // CODE -------------------------------------------------------------------- +void D_GrabCVarDefaults() +{ + int lump, lastlump = 0; + int lumpversion, gamelastrunversion; + gamelastrunversion = atoi(LASTRUNVERSION); + + while ((lump = fileSystem.FindLump("DEFCVARS", &lastlump)) != -1) + { + // don't parse from wads + if (lastlump > fileSystem.GetLastEntry(fileSystem.GetMaxIwadNum())) + I_FatalError("Cannot load DEFCVARS from a wadfile!\n"); + + FScanner sc(lump); + + sc.MustGetString(); + if (!sc.Compare("version")) + sc.ScriptError("Must declare version for defcvars! (currently: %i)", gamelastrunversion); + sc.MustGetNumber(); + lumpversion = sc.Number; + if (lumpversion > gamelastrunversion) + sc.ScriptError("Unsupported version %i (%i supported)", lumpversion, gamelastrunversion); + if (lumpversion < 219) + sc.ScriptError("Version must be at least 219 (current version %i)", gamelastrunversion); + + FBaseCVar* var; + + while (sc.GetString()) + { + if (sc.Compare("set")) + { + sc.MustGetString(); + } + var = FindCVar(sc.String, NULL); + if (var != NULL) + { + if (var->GetFlags() & CVAR_ARCHIVE) + { + UCVarValue val; + + sc.MustGetString(); + val.String = const_cast(sc.String); + var->SetGenericRepDefault(val, CVAR_String); + } + else + { + sc.ScriptError("Cannot set cvar default for non-config cvar '%s'", sc.String); + } + } + else + { + sc.ScriptError("Unknown cvar '%s'", sc.String); + } + } + } +} + //========================================================================== // // D_ToggleHud @@ -2772,6 +2827,16 @@ static int D_DoomMain_Internal (void) // reinit from here + ConsoleCallbacks cb = { + D_UserInfoChanged, + D_SendServerInfoChange, + D_SendServerFlagChange, + G_GetUserCVar, + []() { return gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP; } + }; + + C_InstallHandlers(&cb); + do { PClass::StaticInit(); @@ -2883,7 +2948,7 @@ static int D_DoomMain_Internal (void) allwads.ShrinkToFit(); SetMapxxFlag(); - C_GrabCVarDefaults(); //parse DEFCVARS + D_GrabCVarDefaults(); //parse DEFCVARS GameConfig->DoKeySetup(gameinfo.ConfigName); diff --git a/src/d_netinf.h b/src/d_netinf.h index 34df4bcea..2a360d5a7 100644 --- a/src/d_netinf.h +++ b/src/d_netinf.h @@ -54,8 +54,8 @@ void D_SetupUserInfo (void); void D_UserInfoChanged (FBaseCVar *info); -void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType type); -void D_SendServerFlagChange (const FBaseCVar *cvar, int bitnum, bool set); +void D_SendServerInfoChange (FBaseCVar *cvar, UCVarValue value, ECVarType type); +void D_SendServerFlagChange (FBaseCVar *cvar, int bitnum, bool set, bool silent); void D_DoServerInfoChange (uint8_t **stream, bool singlebit); void D_WriteUserInfoStrings (int player, uint8_t **stream, bool compact=false); diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 61ba38191..1ee85a569 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -50,6 +50,7 @@ #include "serializer.h" #include "vm.h" #include "gstrings.h" +#include "g_game.h" static FRandom pr_pickteam ("PickRandomTeam"); @@ -622,8 +623,17 @@ static const char *SetServerVar (char *name, ECVarType type, uint8_t **stream, b EXTERN_CVAR (Float, sv_gravity) -void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType type) +void D_SendServerInfoChange (FBaseCVar *cvar, UCVarValue value, ECVarType type) { + if (gamestate != GS_STARTUP && !demoplayback) + { + if (netgame && !players[consoleplayer].settings_controller) + { + Printf("Only setting controllers can change %s\n", cvar->GetName()); + cvar->MarkSafe(); + return; + } + } size_t namelen; namelen = strlen (cvar->GetName ()); @@ -641,11 +651,18 @@ void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType } } -void D_SendServerFlagChange (const FBaseCVar *cvar, int bitnum, bool set) +void D_SendServerFlagChange (FBaseCVar *cvar, int bitnum, bool set, bool silent) { - int namelen; + if (gamestate != GS_STARTUP && !demoplayback) + { + if (netgame && !players[consoleplayer].settings_controller) + { + if (!silent) Printf("Only setting controllers can change %s\n", cvar->GetName()); + return; + } + } - namelen = (int)strlen (cvar->GetName ()); + int namelen = (int)strlen (cvar->GetName ()); Net_WriteByte (DEM_SINFCHANGEDXOR); Net_WriteByte ((uint8_t)namelen); diff --git a/src/g_game.cpp b/src/g_game.cpp index b9d014e07..4d67036e0 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -538,6 +538,22 @@ static inline int joyint(double val) } } +FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname) +{ + if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) + { + return nullptr; + } + FBaseCVar** cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); + FBaseCVar* cvar; + if (cvar_p == nullptr || (cvar = *cvar_p) == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + return cvar; +} + + // // G_BuildTiccmd // Builds a ticcmd from all of the available inputs @@ -1814,6 +1830,48 @@ static void LoadGameError(const char *label, const char *append = "") Printf ("%s %s\n", message.GetChars(), append); } +void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter) +{ + FBaseCVar* cvar; + FString dump; + + if (arc.BeginObject(label)) + { + if (arc.isWriting()) + { + for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + { + if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) + { + UCVarValue val = cvar->GetGenericRep(CVAR_String); + char* c = const_cast(val.String); + arc(cvar->GetName(), c); + } + } + } + else + { + for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + { + if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_CONFIG_ONLY))) + { + UCVarValue val; + char* c = nullptr; + arc(cvar->GetName(), c); + if (c != nullptr) + { + val.String = c; + cvar->SetGenericRep(val, CVAR_String); + delete[] c; + } + } + } + } + arc.EndObject(); + } +} + + void G_DoLoadGame () { bool hidecon; diff --git a/src/g_game.h b/src/g_game.h index 4b7928b44..28788f77e 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -123,6 +123,9 @@ void G_AddViewPitch (int look, bool mouse = false); // Adds to consoleplayer's viewangle if allowed void G_AddViewAngle (int yaw, bool mouse = false); +class FBaseCVar; +FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname); + extern const AActor *SendItemUse, *SendItemDrop; extern int SendItemDropAmount; diff --git a/src/gamedata/textures/bitmap.cpp b/src/gamedata/textures/bitmap.cpp index aee21372a..37579a8f7 100644 --- a/src/gamedata/textures/bitmap.cpp +++ b/src/gamedata/textures/bitmap.cpp @@ -388,7 +388,7 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const uint8_t *patch, i template void iCopyPaletted(uint8_t *buffer, const uint8_t * patch, int srcwidth, int srcheight, int Pitch, - int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf) + int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf) { int x,y,pos; @@ -412,7 +412,7 @@ void iCopyPaletted(uint8_t *buffer, const uint8_t * patch, int srcwidth, int src } typedef void (*CopyPalettedFunc)(uint8_t *buffer, const uint8_t * patch, int srcwidth, int srcheight, int Pitch, - int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf); + int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf); static const CopyPalettedFunc copypalettedfuncs[]= @@ -435,7 +435,7 @@ static const CopyPalettedFunc copypalettedfuncs[]= // //=========================================================================== void FBitmap::CopyPixelData(int originx, int originy, const uint8_t * patch, int srcwidth, int srcheight, - int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf) + int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf) { if (ClipCopyPixelRect(&ClipRect, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate)) { diff --git a/src/gamedata/textures/bitmap.h b/src/gamedata/textures/bitmap.h index 7b09fb21b..0b4852506 100644 --- a/src/gamedata/textures/bitmap.h +++ b/src/gamedata/textures/bitmap.h @@ -234,7 +234,7 @@ public: int srcheight, int step_x, int step_y, int rotate, int ct, FCopyInfo *inf = NULL, /* for PNG tRNS */ int r=0, int g=0, int b=0); void CopyPixelData(int originx, int originy, const uint8_t * patch, int srcwidth, int srcheight, - int step_x, int step_y, int rotate, PalEntry * palette, FCopyInfo *inf = NULL); + int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf = NULL); void Blit(int originx, int originy, const FBitmap &src, int width, int height, int rotate = 0, FCopyInfo *inf = NULL) diff --git a/src/gamedata/textures/formats/pngtexture.cpp b/src/gamedata/textures/formats/pngtexture.cpp index 1bde18ad0..3253d8017 100644 --- a/src/gamedata/textures/formats/pngtexture.cpp +++ b/src/gamedata/textures/formats/pngtexture.cpp @@ -260,7 +260,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height, case 3: // Paletted PaletteMap = (uint8_t*)ImageArena.Alloc(PaletteSize); - GPalette.MakeRemap (p.palette, PaletteMap, trans, PaletteSize); + MakeRemap ((uint32_t*)GPalette.BaseColors, p.palette, PaletteMap, trans, PaletteSize); for (i = 0; i < PaletteSize; ++i) { if (trans[i] == 0) diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 6f4ea57d4..9e598fc92 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -5807,14 +5807,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) case ACSF_GetUserCVar: if (argCount == 2) { - return DoGetCVar(GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), false); + return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), false); } break; case ACSF_GetUserCVarString: if (argCount == 2) { - return DoGetCVar(GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), true); + return DoGetCVar(G_GetUserCVar(args[0], Level->Behaviors.LookupString(args[1])), true); } break; diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 78bbe2ada..774f2a503 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6855,8 +6855,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) break; case CVAR_String: - build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); - build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->mValue)); + build->Emit(OP_LS, dest.RegNum, addr.RegNum, nul); break; case CVAR_DummyBool: diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 8ed707e81..9d57a2b97 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -52,6 +52,8 @@ #include "utf8.h" #include "fontinternals.h" #include "intermission/intermission.h" +#include "menu/menu.h" +#include "c_cvars.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); @@ -3147,12 +3149,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_AltHUD, GetLatency, Net_GetLatency) // //========================================================================== -//========================================================================== -// -// W_NumLumps -// -//========================================================================== - DEFINE_ACTION_FUNCTION(_Wads, GetNumEntries) { PARAM_PROLOGUE; @@ -3217,6 +3213,126 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) ACTION_RETURN_STRING(isLumpValid ? fileSystem.ReadFile(lump).GetString() : FString()); } +//========================================================================== +// +// CVARs +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(_CVar, GetInt) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + auto v = self->GetGenericRep(CVAR_Int); + ACTION_RETURN_INT(v.Int); +} + +DEFINE_ACTION_FUNCTION(_CVar, GetFloat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + auto v = self->GetGenericRep(CVAR_Float); + ACTION_RETURN_FLOAT(v.Float); +} + +DEFINE_ACTION_FUNCTION(_CVar, GetString) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + auto v = self->GetGenericRep(CVAR_String); + ACTION_RETURN_STRING(v.String); +} + +DEFINE_ACTION_FUNCTION(_CVar, SetInt) +{ + // Only menus are allowed to change CVARs. + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + if (!(self->GetFlags() & CVAR_MOD)) + { + // Only menus are allowed to change non-mod CVARs. + if (DMenu::InMenu == 0) + { + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); + } + } + PARAM_INT(val); + UCVarValue v; + v.Int = val; + self->SetGenericRep(v, CVAR_Int); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, SetFloat) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + if (!(self->GetFlags() & CVAR_MOD)) + { + // Only menus are allowed to change non-mod CVARs. + if (DMenu::InMenu == 0) + { + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); + } + } + PARAM_FLOAT(val); + UCVarValue v; + v.Float = (float)val; + self->SetGenericRep(v, CVAR_Float); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, SetString) +{ + // Only menus are allowed to change CVARs. + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + if (!(self->GetFlags() & CVAR_MOD)) + { + // Only menus are allowed to change non-mod CVARs. + if (DMenu::InMenu == 0) + { + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); + } + } + PARAM_STRING(val); + UCVarValue v; + v.String = val.GetChars(); + self->SetGenericRep(v, CVAR_String); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, GetRealType) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + ACTION_RETURN_INT(self->GetRealType()); +} + +DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault) +{ + PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + if (!(self->GetFlags() & CVAR_MOD)) + { + // Only menus are allowed to change non-mod CVARs. + if (DMenu::InMenu == 0) + { + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); + } + } + + self->ResetToDefault(); + return 0; +} + +DEFINE_ACTION_FUNCTION(_CVar, FindCVar) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + ACTION_RETURN_POINTER(FindCVar(name.GetChars(), nullptr)); +} + +DEFINE_ACTION_FUNCTION(_CVar, GetCVar) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + PARAM_POINTER(plyr, player_t); + ACTION_RETURN_POINTER(GetCVar(plyr ? int(plyr - players) : -1, name.GetChars())); +} +