- CVAR cleanup, in particular decoupling from game internals, which now get handled via callbacks.

This commit is contained in:
Christoph Oelckers 2020-04-11 13:48:55 +02:00
parent 05239c63f9
commit 1479e3a1c3
17 changed files with 432 additions and 374 deletions

View file

@ -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);
}
//=============================================================================

View file

@ -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"
//----------------------------------------------------------------------------
//

View file

@ -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); }

View file

@ -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];

View file

@ -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<void (*)(FBaseCVar &)>(callback))
FBoolCVar::FBoolCVar (const char *name, bool def, uint32_t flags, void (*callback)(FBoolCVar &), const char* descr)
: FBaseCVar (name, flags, reinterpret_cast<void (*)(FBaseCVar &)>(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<void (*)(FBaseCVar &)>(callback))
FIntCVar::FIntCVar (const char *name, int def, uint32_t flags, void (*callback)(FIntCVar &), const char* descr)
: FBaseCVar (name, flags, reinterpret_cast<void (*)(FBaseCVar &)>(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<void (*)(FBaseCVar &)>(callback))
FFloatCVar::FFloatCVar (const char *name, float def, uint32_t flags, void (*callback)(FFloatCVar &), const char* descr)
: FBaseCVar (name, flags, reinterpret_cast<void (*)(FBaseCVar &)>(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<void (*)(FBaseCVar &)>(callback))
FStringCVar::FStringCVar (const char *name, const char *def, uint32_t flags, void (*callback)(FStringCVar &), const char* descr)
: FBaseCVar (name, flags, reinterpret_cast<void (*)(FBaseCVar &)>(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<void (*)(FIntCVar &)>(callback))
FColorCVar::FColorCVar (const char *name, int def, uint32_t flags, void (*callback)(FColorCVar &), const char* descr)
: FIntCVar (name, def, flags, reinterpret_cast<void (*)(FIntCVar &)>(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<<i))
{
D_SendServerFlagChange (&ValueVar, i, !!(val & (1<<i)));
callbacks->SendServerFlagChange (&ValueVar, i, !!(val & (1<<i)), silent);
silent = true; // only warn once if SendServerFlagChange needs to.
}
}
}
@ -1262,47 +1148,6 @@ FString C_GetMassCVarString (uint32_t filter, bool compact)
return dump;
}
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<char*>(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<char *>(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);
}
}
}
}

View file

@ -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<char *>(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__

View file

@ -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<char*>(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);

View file

@ -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);

View file

@ -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);

View file

@ -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<char*>(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;

View file

@ -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;

View file

@ -388,7 +388,7 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const uint8_t *patch, i
template<class TDest, class TBlend>
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))
{

View file

@ -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)

View file

@ -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)

View file

@ -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;

View file

@ -6855,8 +6855,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
break;
case CVAR_String:
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->Value));
build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul);
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->mValue));
build->Emit(OP_LS, dest.RegNum, addr.RegNum, nul);
break;
case CVAR_DummyBool:

View file

@ -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()));
}