diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 82ff3323..8c0a9e3e 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -31,9 +31,9 @@ CCMD (addbot) return; } - if (consoleplayer != Net_Arbitrator) + if (!players[consoleplayer].settings_controller) { - Printf ("Only player %d can add bots\n", Net_Arbitrator + 1); + Printf ("Only setting controllers can add bots\n"); return; } @@ -78,17 +78,17 @@ extern bool CheckCheatmode (); CCMD (freeze) { - if (CheckCheatmode ()) - return; + if (CheckCheatmode ()) + return; - if (netgame && consoleplayer != Net_Arbitrator) - { - Printf ("Only player %d can use freeze mode\n", Net_Arbitrator + 1); - return; - } + if (netgame && !players[consoleplayer].settings_controller) + { + Printf ("Only setting controllers can use freeze mode\n"); + return; + } - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_FREEZE); + Net_WriteByte (DEM_GENERICCHEAT); + Net_WriteByte (CHT_FREEZE); } CCMD (listbots) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index bd9618e8..46208a84 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -315,9 +315,9 @@ CCMD (changemap) return; } - if (who->player - players != Net_Arbitrator && multiplayer) + if (!players[who->player - players].settings_controller && netgame) { - Printf ("Only player %d can change the map.\n", Net_Arbitrator+1); + Printf ("Only setting controllers can change the map.\n"); return; } @@ -589,7 +589,7 @@ CCMD (fov) } else { - Printf ("The arbitrator has disabled FOV changes.\n"); + Printf ("A setting controller has disabled FOV changes.\n"); return; } } diff --git a/src/c_console.cpp b/src/c_console.cpp index 82e2ccc9..9a3920a1 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -449,7 +449,7 @@ void C_DeinitConsole () { GameAtExit *next = cmd->Next; AddCommandString (cmd->Command); - free (cmd); + M_Free (cmd); cmd = next; } @@ -1146,7 +1146,7 @@ void C_DrawConsole (bool hw2d) DTA_DestWidth, screen->GetWidth(), DTA_DestHeight, screen->GetHeight(), DTA_ColorOverlay, conshade, - DTA_Alpha, hw2d ? FLOAT2FIXED(con_alpha) : FRACUNIT, + DTA_Alpha, (hw2d && gamestate != GS_FULLCONSOLE) ? FLOAT2FIXED(con_alpha) : FRACUNIT, DTA_Masked, false, TAG_DONE); if (conline && visheight < screen->GetHeight()) @@ -1675,7 +1675,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) if (HistSize == MAXHISTSIZE) { HistTail = HistTail->Newer; - free (HistTail->Older); + M_Free (HistTail->Older); HistTail->Older = NULL; } else diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 9393db8d..7a6f316d 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1,1593 +1,1593 @@ -/* -** c_cvars.cpp -** Defines all the different console variable types -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include - -#include "cmdlib.h" -#include "configfile.h" -#include "c_console.h" -#include "c_dispatch.h" -#include "m_alloc.h" - -#include "doomstat.h" -#include "c_cvars.h" -#include "d_player.h" - -#include "d_netinf.h" - -#include "i_system.h" -#include "v_palette.h" -#include "v_video.h" - -struct FLatchedValue -{ - FBaseCVar *Variable; - UCVarValue Value; - ECVarType Type; -}; - -static TArray LatchedValues; - -bool FBaseCVar::m_DoNoSet = false; -bool FBaseCVar::m_UseCallback = false; - -FBaseCVar *CVars = NULL; - -int cvar_defflags; - -FBaseCVar::FBaseCVar (const FBaseCVar &var) -{ - I_FatalError ("Use of cvar copy constructor"); -} - -FBaseCVar::FBaseCVar (const char *var_name, DWORD flags, void (*callback)(FBaseCVar &)) -{ - FBaseCVar *var; - - var = FindCVar (var_name, NULL); - - m_Callback = callback; - Flags = 0; - Name = NULL; - - if (var_name) - { - C_AddTabCommand (var_name); - Name = copystring (var_name); - m_Next = CVars; - CVars = this; - } - - if (var) - { - ECVarType type; - UCVarValue value; - - value = var->GetFavoriteRep (&type); - ForceSet (value, type); - - if (var->Flags & CVAR_AUTO) - delete var; - else - var->~FBaseCVar(); - - Flags = flags; - } - else - { - Flags = flags | CVAR_ISDEFAULT; - } -} - -FBaseCVar::~FBaseCVar () -{ - if (Name) - { - FBaseCVar *var, *prev; - - var = FindCVar (Name, &prev); - - if (var == this) - { - if (prev) - prev->m_Next = m_Next; - else - CVars = m_Next; - } - delete[] Name; - } -} - -void FBaseCVar::ForceSet (UCVarValue value, ECVarType type) -{ - DoSet (value, type); - if (Flags & CVAR_USERINFO) - D_UserInfoChanged (this); - if (m_UseCallback) - Callback (); - - Flags &= ~CVAR_ISDEFAULT; -} - -void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) -{ - if ((Flags & CVAR_NOSET) && m_DoNoSet) - { - return; - } - else if ((Flags & CVAR_LATCH) && gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) - { - FLatchedValue latch; - - latch.Variable = this; - latch.Type = type; - if (type != CVAR_String) - latch.Value = value; - else - latch.Value.String = copystring(value.String); - LatchedValues.Push (latch); - } - else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) - { - if (netgame && consoleplayer != Net_Arbitrator) - { - Printf ("Only player %d can change %s\n", Net_Arbitrator+1, Name); - return; - } - D_SendServerInfoChange (this, value, type); - } - else - { - ForceSet (value, type); - } -} - -bool FBaseCVar::ToBool (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return value.Bool; - - case CVAR_Int: - return !!value.Int; - - case CVAR_Float: - return value.Float != 0.f; - - case CVAR_String: - if (stricmp (value.String, "true") == 0) - return true; - else if (stricmp (value.String, "false") == 0) - return false; - else - return !!strtol (value.String, NULL, 0); - - case CVAR_GUID: - return false; - - default: - return false; - } -} - -int FBaseCVar::ToInt (UCVarValue value, ECVarType type) -{ - int res; -#if __GNUC__ <= 2 - float tmp; -#endif - - switch (type) - { - case CVAR_Bool: res = (int)value.Bool; break; - case CVAR_Int: res = value.Int; break; -#if __GNUC__ <= 2 - case CVAR_Float: tmp = value.Float; res = (int)tmp; break; -#else - case CVAR_Float: res = (int)value.Float; break; -#endif - case CVAR_String: res = strtol (value.String, NULL, 0); break; - case CVAR_GUID: res = 0; break; - default: res = 0; break; - } - return res; -} - -float FBaseCVar::ToFloat (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return (float)value.Bool; - - case CVAR_Int: - return (float)value.Int; - - case CVAR_Float: - return value.Float; - - case CVAR_String: - return strtod (value.String, NULL); - - case CVAR_GUID: - return 0.f; - - default: - return 0.f; - } -} - -static char cstrbuf[40]; -static GUID cGUID; -static char truestr[] = "true"; -static char falsestr[] = "false"; - -char *FBaseCVar::ToString (UCVarValue value, ECVarType type) -{ - switch (type) - { - case CVAR_Bool: - return value.Bool ? truestr : falsestr; - - case CVAR_String: - return value.String; - - case CVAR_Int: - sprintf (cstrbuf, "%i", value.Int); - break; - - case CVAR_Float: - sprintf (cstrbuf, "%g", value.Float); - break; - - case CVAR_GUID: - FormatGUID (cstrbuf, *value.pGUID); - break; - - default: - strcpy (cstrbuf, ""); - break; - } - return cstrbuf; -} - -const GUID *FBaseCVar::ToGUID (UCVarValue value, ECVarType type) -{ - UCVarValue trans; - - switch (type) - { - case CVAR_String: - trans = FromString (value.String, CVAR_GUID); - return trans.pGUID; - - case CVAR_GUID: - return value.pGUID; - - default: - return NULL; - } -} - -UCVarValue FBaseCVar::FromBool (bool value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value; - break; - - case CVAR_Int: - ret.Int = value; - break; - - case CVAR_Float: - ret.Float = value; - break; - - case CVAR_String: - ret.String = value ? truestr : falsestr; - break; - - case CVAR_GUID: - ret.pGUID = NULL; - break; - - default: - break; - } - - return ret; -} - -UCVarValue FBaseCVar::FromInt (int value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value != 0; - break; - - case CVAR_Int: - ret.Int = value; - break; - - case CVAR_Float: - ret.Float = (float)value; - break; - - case CVAR_String: - sprintf (cstrbuf, "%i", value); - ret.String = cstrbuf; - break; - - case CVAR_GUID: - ret.pGUID = NULL; - break; - - default: - break; - } - - return ret; -} - -UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = value != 0.f; - break; - - case CVAR_Int: - ret.Int = (int)value; - break; - - case CVAR_Float: - ret.Float = value; - break; - - case CVAR_String: - sprintf (cstrbuf, "%g", value); - ret.String = cstrbuf; - break; - - case CVAR_GUID: - ret.pGUID = NULL; - break; - - default: - break; - } - - return ret; -} - -static BYTE HexToByte (const char *hex) -{ - BYTE v = 0; - for (int i = 0; i < 2; ++i) - { - v <<= 4; - if (hex[i] >= '0' && hex[i] <= '9') - { - v += hex[i] - '0'; - } - else if (hex[i] >= 'A' && hex[i] <= 'F') - { - v += hex[i] - 'A'; - } - else // The string is already verified to contain valid hexits - { - v += hex[i] - 'a'; - } - } - return v; -} - -UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) -{ - UCVarValue ret; - int i; - - switch (type) - { - case CVAR_Bool: - if (stricmp (value, "true") == 0) - ret.Bool = true; - else if (stricmp (value, "false") == 0) - ret.Bool = false; - else - ret.Bool = strtol (value, NULL, 0) != 0; - break; - - case CVAR_Int: - ret.Int = strtol (value, NULL, 0); - break; - - case CVAR_Float: - ret.Float = (float)strtod (value, NULL); - break; - - case CVAR_String: - ret.String = const_cast(value); - break; - - case CVAR_GUID: - // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} - // 01234567890123456789012345678901234567 - // 0 1 2 3 - - ret.pGUID = NULL; - for (i = 0; i < 38; ++i) - { - if (value[i] == 0) - { - break; - } - bool goodv = true; - switch (i) - { - case 0: - if (value[i] != '{') - goodv = false; - break; - case 9: - case 14: - case 19: - case 24: - if (value[i] != '-') - goodv = false; - break; - case 37: - if (value[i] != '}') - goodv = false; - break; - default: - if (value[i] < '0' && value[i] > '9' && - value[i] < 'A' && value[i] > 'F' && - value[i] < 'a' && value[i] > 'f') - { - goodv = false; - } - break; - } - } - if (i == 38 && value[i] == 0) - { - cGUID.Data1 = strtoul (value + 1, NULL, 16); - cGUID.Data2 = strtoul (value + 10, NULL, 16); - cGUID.Data3 = strtoul (value + 15, NULL, 16); - cGUID.Data4[0] = HexToByte (value + 20); - cGUID.Data4[1] = HexToByte (value + 22); - cGUID.Data4[2] = HexToByte (value + 25); - cGUID.Data4[3] = HexToByte (value + 27); - cGUID.Data4[4] = HexToByte (value + 29); - cGUID.Data4[5] = HexToByte (value + 31); - cGUID.Data4[6] = HexToByte (value + 33); - cGUID.Data4[7] = HexToByte (value + 35); - ret.pGUID = &cGUID; - } - break; - - default: - break; - } - - return ret; -} - -UCVarValue FBaseCVar::FromGUID (const GUID &guid, ECVarType type) -{ - UCVarValue ret; - - switch (type) - { - case CVAR_Bool: - ret.Bool = false; - break; - - case CVAR_Int: - ret.Int = 0; - break; - - case CVAR_Float: - ret.Float = 0.f; - break; - - case CVAR_String: - ret.pGUID = &guid; - ret.String = ToString (ret, CVAR_GUID); - break; - - case CVAR_GUID: - ret.pGUID = &guid; - break; - - default: - break; - } - - return ret; -} -FBaseCVar *cvar_set (const char *var_name, const char *val) -{ - FBaseCVar *var; - - if ( (var = FindCVar (var_name, NULL)) ) - { - UCVarValue value; - value.String = const_cast(val); - var->SetGenericRep (value, CVAR_String); - } - - return var; -} - -FBaseCVar *cvar_forceset (const char *var_name, const char *val) -{ - FBaseCVar *var; - UCVarValue vval; - - if ( (var = FindCVar (var_name, NULL)) ) - { - vval.String = const_cast(val); - var->ForceSet (vval, CVAR_String); - } - - return var; -} - -void FBaseCVar::EnableNoSet () -{ - m_DoNoSet = true; -} - -void FBaseCVar::EnableCallbacks () -{ - m_UseCallback = true; - FBaseCVar *cvar = CVars; - - while (cvar) - { - if (!(cvar->Flags & CVAR_NOINITCALL)) - { - cvar->Callback (); - } - cvar = cvar->m_Next; - } -} - -// -// Boolean cvar implementation -// - -FBoolCVar::FBoolCVar (const char *name, bool def, DWORD flags, void (*callback)(FBoolCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FBoolCVar::GetRealType () const -{ - return CVAR_Bool; -} - -UCVarValue FBoolCVar::GetGenericRep (ECVarType type) const -{ - return FromBool (Value, type); -} - -UCVarValue FBoolCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = Value; - return ret; -} - -UCVarValue FBoolCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromBool (DefaultValue, type); -} - -UCVarValue FBoolCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = DefaultValue; - return ret; -} - -void FBoolCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToBool (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FBoolCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToBool (value, type); -} - -// -// Integer cvar implementation -// - -FIntCVar::FIntCVar (const char *name, int def, DWORD flags, void (*callback)(FIntCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FIntCVar::GetRealType () const -{ - return CVAR_Int; -} - -UCVarValue FIntCVar::GetGenericRep (ECVarType type) const -{ - return FromInt (Value, type); -} - -UCVarValue FIntCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Int; - ret.Int = Value; - return ret; -} - -UCVarValue FIntCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromInt (DefaultValue, type); -} - -UCVarValue FIntCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Int; - ret.Int = DefaultValue; - return ret; -} - -void FIntCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToInt (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FIntCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToInt (value, type); -} - -// -// Floating point cvar implementation -// - -FFloatCVar::FFloatCVar (const char *name, float def, DWORD flags, void (*callback)(FFloatCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) -{ - DefaultValue = def; - if (Flags & CVAR_ISDEFAULT) - Value = def; -} - -ECVarType FFloatCVar::GetRealType () const -{ - return CVAR_Float; -} - -UCVarValue FFloatCVar::GetGenericRep (ECVarType type) const -{ - return FromFloat (Value, type); -} - -UCVarValue FFloatCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Float; - ret.Float = Value; - return ret; -} - -UCVarValue FFloatCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromFloat (DefaultValue, type); -} - -UCVarValue FFloatCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Float; - ret.Float = DefaultValue; - return ret; -} - -void FFloatCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToFloat (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FFloatCVar::DoSet (UCVarValue value, ECVarType type) -{ - Value = ToFloat (value, type); -} - -// -// String cvar implementation -// - -FStringCVar::FStringCVar (const char *name, const char *def, DWORD flags, void (*callback)(FStringCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) -{ - DefaultValue = copystring (def); - if (Flags & CVAR_ISDEFAULT) - Value = copystring (def); - else - Value = NULL; -} - -FStringCVar::~FStringCVar () -{ - if (Value != NULL) - { - delete[] Value; - } - delete[] DefaultValue; -} - -ECVarType FStringCVar::GetRealType () const -{ - return CVAR_String; -} - -UCVarValue FStringCVar::GetGenericRep (ECVarType type) const -{ - return FromString (Value, type); -} - -UCVarValue FStringCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_String; - ret.String = Value; - return ret; -} - -UCVarValue FStringCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromString (DefaultValue, type); -} - -UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_String; - ret.String = DefaultValue; - return ret; -} - -void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - if (DefaultValue) - delete[] DefaultValue; - DefaultValue = ToString (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -void FStringCVar::DoSet (UCVarValue value, ECVarType type) -{ - ReplaceString (&Value, ToString (value, type)); -} - -// -// Color cvar implementation -// - -FColorCVar::FColorCVar (const char *name, int def, DWORD flags, void (*callback)(FColorCVar &)) -: FIntCVar (name, def, flags, reinterpret_cast(callback)) -{ -} - -ECVarType FColorCVar::GetRealType () const -{ - return CVAR_Color; -} - -UCVarValue FColorCVar::GetGenericRep (ECVarType type) const -{ - return FromInt2 (Value, type); -} - -UCVarValue FColorCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromInt2 (DefaultValue, type); -} - -void FColorCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - DefaultValue = ToInt2 (value, type); - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } -} - -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) -{ - if (type == CVAR_String) - { - UCVarValue ret; - sprintf (cstrbuf, "%02x %02x %02x", - RPART(value), GPART(value), BPART(value)); - ret.String = cstrbuf; - return ret; - } - return FromInt (value, type); -} - -int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) -{ - int ret; - - if (type == CVAR_String) - { - FString string; - // Only allow named colors after the screen exists (i.e. after - // we've got some lumps loaded, so X11R6RGB can be read). Since - // the only time this might be called before that is when loading - // zdoom.ini, this shouldn't be a problem. - if (screen && !(string = V_GetColorStringByName (value.String)).IsEmpty() ) - { - ret = V_GetColorFromString (NULL, string); - } - else - { - ret = V_GetColorFromString (NULL, value.String); - } - } - else - { - ret = ToInt (value, type); - } - return ret; -} - -// -// GUID cvar implementation -// - -FGUIDCVar::FGUIDCVar (const char *name, const GUID *def, DWORD flags, void (*callback)(FGUIDCVar &)) -: FBaseCVar (name, flags, reinterpret_cast(callback)) -{ - if (def != NULL) - { - DefaultValue = *def; - if (Flags & CVAR_ISDEFAULT) - Value = *def; - } - else - { - memset (&Value, 0, sizeof(DefaultValue)); - memset (&DefaultValue, 0, sizeof(DefaultValue)); - } -} - -ECVarType FGUIDCVar::GetRealType () const -{ - return CVAR_GUID; -} - -UCVarValue FGUIDCVar::GetGenericRep (ECVarType type) const -{ - return FromGUID (Value, type); -} - -UCVarValue FGUIDCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_GUID; - ret.pGUID = &Value; - return ret; -} - -UCVarValue FGUIDCVar::GetGenericRepDefault (ECVarType type) const -{ - return FromGUID (DefaultValue, type); -} - -UCVarValue FGUIDCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_GUID; - ret.pGUID = &DefaultValue; - return ret; -} - -void FGUIDCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - const GUID *guid = ToGUID (value, type); - if (guid != NULL) - { - Value = *guid; - if (Flags & CVAR_ISDEFAULT) - { - SetGenericRep (value, type); - Flags |= CVAR_ISDEFAULT; - } - } -} - -void FGUIDCVar::DoSet (UCVarValue value, ECVarType type) -{ - const GUID *guid = ToGUID (value, type); - if (guid != NULL) - { - Value = *guid; - } -} - -// -// More base cvar stuff -// - -void FBaseCVar::ResetColors () -{ - FBaseCVar *var = CVars; - - while (var) - { - if (var->GetRealType () == CVAR_Color) - { - var->DoSet (var->GetGenericRep (CVAR_Int), CVAR_Int); - } - var = var->m_Next; - } -} - -void FBaseCVar::ResetToDefault () -{ - if (!(Flags & CVAR_ISDEFAULT)) - { - UCVarValue val; - ECVarType type; - - val = GetFavoriteRepDefault (&type); - SetGenericRep (val, type); - Flags |= CVAR_ISDEFAULT; - } -} - -// -// Flag cvar implementation -// -// This type of cvar is not a "real" cvar. Instead, it gets and sets -// the value of a FIntCVar, modifying it bit-by-bit. As such, it has -// no default, and is not written to the .cfg or transferred around -// the network. The "host" cvar is responsible for that. -// - -FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, DWORD bitval) -: FBaseCVar (name, 0, NULL), -ValueVar (realvar), -BitVal (bitval) -{ - int bit; - - Flags &= ~CVAR_ISDEFAULT; - - assert (bitval != 0); - - bit = 0; - while ((bitval >>= 1) != 0) - { - ++bit; - } - BitNum = bit; - - assert ((1u << BitNum) == BitVal); -} - -ECVarType FFlagCVar::GetRealType () const -{ - return CVAR_Dummy; -} - -UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const -{ - return FromBool ((ValueVar & BitVal) != 0, type); -} - -UCVarValue FFlagCVar::GetFavoriteRep (ECVarType *type) const -{ - UCVarValue ret; - *type = CVAR_Bool; - ret.Bool = (ValueVar & BitVal) != 0; - return ret; -} - -UCVarValue FFlagCVar::GetGenericRepDefault (ECVarType type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - return FromBool ((def.Int & BitVal) != 0, type); -} - -UCVarValue FFlagCVar::GetFavoriteRepDefault (ECVarType *type) const -{ - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - def.Bool = (def.Int & BitVal) != 0; - *type = CVAR_Bool; - return def; -} - -void FFlagCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) -{ - bool newdef = ToBool (value, type); - ECVarType dummy; - UCVarValue def; - def = ValueVar.GetFavoriteRepDefault (&dummy); - if (newdef) - def.Int |= BitVal; - else - def.Int &= ~BitVal; - ValueVar.SetGenericRepDefault (def, CVAR_Int); -} - -void FFlagCVar::DoSet (UCVarValue value, ECVarType type) -{ - bool newval = ToBool (value, type); - - // Server cvars that get changed by this need to use a special message, because - // changes are not processed until the next net update. This is a problem with - // 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.Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) - { - if (netgame && consoleplayer != Net_Arbitrator) - { - Printf ("Only player %d can change %s\n", Net_Arbitrator+1, Name); - return; - } - D_SendServerFlagChange (&ValueVar, BitNum, newval); - } - else - { - int val = *ValueVar; - if (newval) - val |= BitVal; - else - val &= ~BitVal; - ValueVar = val; - } -} - -//////////////////////////////////////////////////////////////////////// -static int STACK_ARGS sortcvars (const void *a, const void *b) -{ - return strcmp (((*(FBaseCVar **)a))->GetName(), ((*(FBaseCVar **)b))->GetName()); -} - -void FilterCompactCVars (TArray &cvars, DWORD filter) -{ - FBaseCVar *cvar = CVars; - while (cvar) - { - if (cvar->Flags & filter) - cvars.Push (cvar); - cvar = cvar->m_Next; - } - if (cvars.Size () > 0) - { - cvars.ShrinkToFit (); - qsort (&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars); - } -} - -void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact) -{ - FBaseCVar *cvar = CVars; - BYTE *ptr = *demo_p; - - if (compact) - { - TArray cvars; - ptr += sprintf ((char *)ptr, "\\\\%ux", filter); - FilterCompactCVars (cvars, filter); - while (cvars.Pop (cvar)) - { - UCVarValue val = cvar->GetGenericRep (CVAR_String); - ptr += sprintf ((char *)ptr, "\\%s", val.String); - } - } - else - { - cvar = CVars; - while (cvar) - { - if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_NOSAVE)) - { - UCVarValue val = cvar->GetGenericRep (CVAR_String); - ptr += sprintf ((char *)ptr, "\\%s\\%s", - cvar->GetName (), val.String); - } - cvar = cvar->m_Next; - } - } - - *demo_p = ptr + 1; -} - -void C_ReadCVars (BYTE **demo_p) -{ - char *ptr = *((char **)demo_p); - char *breakpt; - - if (*ptr++ != '\\') - return; - - if (*ptr == '\\') - { // compact mode - TArray cvars; - FBaseCVar *cvar; - DWORD filter; - - ptr++; - breakpt = strchr (ptr, '\\'); - *breakpt = 0; - filter = strtoul (ptr, NULL, 16); - *breakpt = '\\'; - ptr = breakpt + 1; - - FilterCompactCVars (cvars, filter); - - while (cvars.Pop (cvar)) - { - UCVarValue val; - breakpt = strchr (ptr, '\\'); - if (breakpt) - *breakpt = 0; - val.String = ptr; - cvar->ForceSet (val, CVAR_String); - if (breakpt) - { - *breakpt = '\\'; - ptr = breakpt + 1; - } - else - break; - } - } - else - { - char *value; - - while ( (breakpt = strchr (ptr, '\\')) ) - { - *breakpt = 0; - value = breakpt + 1; - if ( (breakpt = strchr (value, '\\')) ) - *breakpt = 0; - - cvar_set (ptr, value); - - *(value - 1) = '\\'; - if (breakpt) - { - *breakpt = '\\'; - ptr = breakpt + 1; - } - else - { - break; - } - } - } - *demo_p += strlen (*((char **)demo_p)) + 1; -} - -static struct backup_s -{ - char *name, *string; -} CVarBackups[MAX_DEMOCVARS]; - -static int numbackedup = 0; - -void C_BackupCVars (void) -{ - struct backup_s *backup = CVarBackups; - FBaseCVar *cvar = CVars; - - while (cvar) - { - if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) - && !(cvar->Flags & CVAR_LATCH)) - { - if (backup == &CVarBackups[MAX_DEMOCVARS]) - I_Error ("C_BackupDemoCVars: Too many cvars to save (%d)", MAX_DEMOCVARS); - backup->name = copystring (cvar->GetName()); - backup->string = copystring (cvar->GetGenericRep (CVAR_String).String); - backup++; - } - cvar = cvar->m_Next; - } - numbackedup = backup - CVarBackups; -} - -void C_RestoreCVars (void) -{ - struct backup_s *backup = CVarBackups; - int i; - - for (i = numbackedup; i; i--, backup++) - { - cvar_set (backup->name, backup->string); - delete[] backup->name; - delete[] backup->string; - backup->name = backup->string = NULL; - } - numbackedup = 0; -} - -FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) -{ - FBaseCVar *var; - FBaseCVar *dummy; - - if (var_name == NULL) - return NULL; - - if (prev == NULL) - prev = &dummy; - - var = CVars; - *prev = NULL; - while (var) - { - if (stricmp (var->GetName (), var_name) == 0) - break; - *prev = var; - var = var->m_Next; - } - return var; -} - -FBaseCVar *FindCVarSub (const char *var_name, int namelen) -{ - FBaseCVar *var; - - if (var_name == NULL) - return NULL; - - var = CVars; - while (var) - { - const char *probename = var->GetName (); - - if (strnicmp (probename, var_name, namelen) == 0 && - probename[namelen] == 0) - { - break; - } - var = var->m_Next; - } - return var; -} - -void UnlatchCVars (void) -{ - FLatchedValue var; - - while (LatchedValues.Pop (var)) - { - DWORD oldflags = var.Variable->Flags; - var.Variable->Flags &= ~(CVAR_LATCH | CVAR_SERVERINFO); - var.Variable->SetGenericRep (var.Value, var.Type); - if (var.Type == CVAR_String) - delete[] var.Value.String; - var.Variable->Flags = oldflags; - } -} - -void C_SetCVarsToDefaults (void) -{ - FBaseCVar *cvar = CVars; - - while (cvar) - { - // Only default save-able cvars - if (cvar->Flags & CVAR_ARCHIVE) - { - UCVarValue val; - ECVarType type; - val = cvar->GetFavoriteRepDefault (&type); - cvar->SetGenericRep (val, type); - } - cvar = cvar->m_Next; - } -} - -void C_ArchiveCVars (FConfigFile *f, int type) -{ - // type 0: Game-specific cvars - // type 1: Global cvars - // type 2: Unknown cvars - // type 3: Unknown global cvars - // type 4: User info cvars - // type 5: Server info cvars - static const DWORD filters[6] = - { - CVAR_ARCHIVE, - CVAR_ARCHIVE|CVAR_GLOBALCONFIG, - CVAR_ARCHIVE|CVAR_AUTO, - CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_AUTO, - CVAR_ARCHIVE|CVAR_USERINFO, - CVAR_ARCHIVE|CVAR_SERVERINFO - }; - - FBaseCVar *cvar = CVars; - DWORD filter; - - filter = filters[type]; - - while (cvar) - { - if ((cvar->Flags & - (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE)) - == filter) - { - UCVarValue val; - val = cvar->GetGenericRep (CVAR_String); - f->SetValueForKey (cvar->GetName (), val.String); - } - cvar = cvar->m_Next; - } -} - -void FBaseCVar::CmdSet (const char *newval) -{ - UCVarValue val; - - // Casting away the const is safe in this case. - val.String = const_cast(newval); - SetGenericRep (val, CVAR_String); - - if (GetFlags() & CVAR_NOSET) - Printf ("%s is write protected.\n", GetName()); - else if (GetFlags() & CVAR_LATCH) - Printf ("%s will be changed for next game.\n", GetName()); -} - -CCMD (set) -{ - if (argv.argc() != 3) - { - Printf ("usage: set \n"); - } - else - { - FBaseCVar *var; - - var = FindCVar (argv[1], NULL); - if (var == NULL) - var = new FStringCVar (argv[1], NULL, CVAR_AUTO | CVAR_UNSETTABLE | cvar_defflags); - - var->CmdSet (argv[2]); - } -} - -CCMD (unset) -{ - if (argv.argc() != 2) - { - Printf ("usage: unset \n"); - } - else - { - FBaseCVar *var = FindCVar (argv[1], NULL); - if (var != NULL) - { - if (var->GetFlags() & CVAR_UNSETTABLE) - { - delete var; - } - else - { - Printf ("Cannot unset %s\n", argv[1]); - } - } - } -} - -CCMD (get) -{ - FBaseCVar *var, *prev; - - if (argv.argc() >= 2) - { - if ( (var = FindCVar (argv[1], &prev)) ) - { - UCVarValue val; - val = var->GetGenericRep (CVAR_String); - Printf ("\"%s\" is \"%s\"\n", var->GetName(), val.String); - } - else - { - Printf ("\"%s\" is unset\n", argv[1]); - } - } - else - { - Printf ("get: need variable name\n"); - } -} - -CCMD (toggle) -{ - FBaseCVar *var, *prev; - UCVarValue val; - - if (argv.argc() > 1) - { - if ( (var = FindCVar (argv[1], &prev)) ) - { - val = var->GetGenericRep (CVAR_Bool); - val.Bool = !val.Bool; - var->SetGenericRep (val, CVAR_Bool); - Printf ("\"%s\" is \"%s\"\n", var->GetName(), - val.Bool ? "true" : "false"); - } - } -} - -void FBaseCVar::ListVars (const char *filter, bool plain) -{ - FBaseCVar *var = CVars; - int count = 0; - - while (var) - { - if (CheckWildcards (filter, var->GetName())) - { - DWORD flags = var->GetFlags(); - UCVarValue val; - - val = var->GetGenericRep (CVAR_String); - if (plain) - { // plain formatting does not include user-defined cvars - if (!(flags & CVAR_UNSETTABLE)) - { - ++count; - Printf ("%s : %s\n", var->GetName(), var->GetGenericRep(CVAR_String).String); - } - } - else - { - ++count; - Printf ("%c%c%c %s : :%s\n", - flags & CVAR_ARCHIVE ? 'A' : ' ', - flags & CVAR_USERINFO ? 'U' : - flags & CVAR_SERVERINFO ? 'S' : - flags & CVAR_AUTO ? 'C' : ' ', - flags & CVAR_NOSET ? '-' : - flags & CVAR_LATCH ? 'L' : - flags & CVAR_UNSETTABLE ? '*' : ' ', - var->GetName(), - var->GetGenericRep (CVAR_String).String); - } - } - var = var->m_Next; - } - Printf ("%d cvars\n", count); -} - -CCMD (cvarlist) -{ - if (argv.argc() == 1) - { - FBaseCVar::ListVars (NULL, false); - } - else - { - FBaseCVar::ListVars (argv[1], false); - } -} - -CCMD (cvarlistplain) -{ - FBaseCVar::ListVars (NULL, true); -} - -CCMD (archivecvar) -{ - - if (argv.argc() == 1) - { - Printf ("Usage: archivecvar \n"); - } - else - { - FBaseCVar *var = FindCVar (argv[1], NULL); - - if (var != NULL && (var->GetFlags() & CVAR_AUTO)) - { - var->SetArchiveBit (); - } - } -} +/* +** c_cvars.cpp +** Defines all the different console variable types +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include + +#include "cmdlib.h" +#include "configfile.h" +#include "c_console.h" +#include "c_dispatch.h" +#include "m_alloc.h" + +#include "doomstat.h" +#include "c_cvars.h" +#include "d_player.h" + +#include "d_netinf.h" + +#include "i_system.h" +#include "v_palette.h" +#include "v_video.h" + +struct FLatchedValue +{ + FBaseCVar *Variable; + UCVarValue Value; + ECVarType Type; +}; + +static TArray LatchedValues; + +bool FBaseCVar::m_DoNoSet = false; +bool FBaseCVar::m_UseCallback = false; + +FBaseCVar *CVars = NULL; + +int cvar_defflags; + +FBaseCVar::FBaseCVar (const FBaseCVar &var) +{ + I_FatalError ("Use of cvar copy constructor"); +} + +FBaseCVar::FBaseCVar (const char *var_name, DWORD flags, void (*callback)(FBaseCVar &)) +{ + FBaseCVar *var; + + var = FindCVar (var_name, NULL); + + m_Callback = callback; + Flags = 0; + Name = NULL; + + if (var_name) + { + C_AddTabCommand (var_name); + Name = copystring (var_name); + m_Next = CVars; + CVars = this; + } + + if (var) + { + ECVarType type; + UCVarValue value; + + value = var->GetFavoriteRep (&type); + ForceSet (value, type); + + if (var->Flags & CVAR_AUTO) + delete var; + else + var->~FBaseCVar(); + + Flags = flags; + } + else + { + Flags = flags | CVAR_ISDEFAULT; + } +} + +FBaseCVar::~FBaseCVar () +{ + if (Name) + { + FBaseCVar *var, *prev; + + var = FindCVar (Name, &prev); + + if (var == this) + { + if (prev) + prev->m_Next = m_Next; + else + CVars = m_Next; + } + delete[] Name; + } +} + +void FBaseCVar::ForceSet (UCVarValue value, ECVarType type) +{ + DoSet (value, type); + if (Flags & CVAR_USERINFO) + D_UserInfoChanged (this); + if (m_UseCallback) + Callback (); + + Flags &= ~CVAR_ISDEFAULT; +} + +void FBaseCVar::SetGenericRep (UCVarValue value, ECVarType type) +{ + if ((Flags & CVAR_NOSET) && m_DoNoSet) + { + return; + } + else if ((Flags & CVAR_LATCH) && gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) + { + FLatchedValue latch; + + latch.Variable = this; + latch.Type = type; + if (type != CVAR_String) + latch.Value = value; + else + latch.Value.String = copystring(value.String); + LatchedValues.Push (latch); + } + else if ((Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) + { + if (netgame && !players[consoleplayer].settings_controller) + { + Printf ("Only setting controllers can change %s\n", Name); + return; + } + D_SendServerInfoChange (this, value, type); + } + else + { + ForceSet (value, type); + } +} + +bool FBaseCVar::ToBool (UCVarValue value, ECVarType type) +{ + switch (type) + { + case CVAR_Bool: + return value.Bool; + + case CVAR_Int: + return !!value.Int; + + case CVAR_Float: + return value.Float != 0.f; + + case CVAR_String: + if (stricmp (value.String, "true") == 0) + return true; + else if (stricmp (value.String, "false") == 0) + return false; + else + return !!strtol (value.String, NULL, 0); + + case CVAR_GUID: + return false; + + default: + return false; + } +} + +int FBaseCVar::ToInt (UCVarValue value, ECVarType type) +{ + int res; +#if __GNUC__ <= 2 + float tmp; +#endif + + switch (type) + { + case CVAR_Bool: res = (int)value.Bool; break; + case CVAR_Int: res = value.Int; break; +#if __GNUC__ <= 2 + case CVAR_Float: tmp = value.Float; res = (int)tmp; break; +#else + case CVAR_Float: res = (int)value.Float; break; +#endif + case CVAR_String: res = strtol (value.String, NULL, 0); break; + case CVAR_GUID: res = 0; break; + default: res = 0; break; + } + return res; +} + +float FBaseCVar::ToFloat (UCVarValue value, ECVarType type) +{ + switch (type) + { + case CVAR_Bool: + return (float)value.Bool; + + case CVAR_Int: + return (float)value.Int; + + case CVAR_Float: + return value.Float; + + case CVAR_String: + return strtod (value.String, NULL); + + case CVAR_GUID: + return 0.f; + + default: + return 0.f; + } +} + +static char cstrbuf[40]; +static GUID cGUID; +static char truestr[] = "true"; +static char falsestr[] = "false"; + +char *FBaseCVar::ToString (UCVarValue value, ECVarType type) +{ + switch (type) + { + case CVAR_Bool: + return value.Bool ? truestr : falsestr; + + case CVAR_String: + return value.String; + + case CVAR_Int: + sprintf (cstrbuf, "%i", value.Int); + break; + + case CVAR_Float: + sprintf (cstrbuf, "%g", value.Float); + break; + + case CVAR_GUID: + FormatGUID (cstrbuf, *value.pGUID); + break; + + default: + strcpy (cstrbuf, ""); + break; + } + return cstrbuf; +} + +const GUID *FBaseCVar::ToGUID (UCVarValue value, ECVarType type) +{ + UCVarValue trans; + + switch (type) + { + case CVAR_String: + trans = FromString (value.String, CVAR_GUID); + return trans.pGUID; + + case CVAR_GUID: + return value.pGUID; + + default: + return NULL; + } +} + +UCVarValue FBaseCVar::FromBool (bool value, ECVarType type) +{ + UCVarValue ret; + + switch (type) + { + case CVAR_Bool: + ret.Bool = value; + break; + + case CVAR_Int: + ret.Int = value; + break; + + case CVAR_Float: + ret.Float = value; + break; + + case CVAR_String: + ret.String = value ? truestr : falsestr; + break; + + case CVAR_GUID: + ret.pGUID = NULL; + break; + + default: + break; + } + + return ret; +} + +UCVarValue FBaseCVar::FromInt (int value, ECVarType type) +{ + UCVarValue ret; + + switch (type) + { + case CVAR_Bool: + ret.Bool = value != 0; + break; + + case CVAR_Int: + ret.Int = value; + break; + + case CVAR_Float: + ret.Float = (float)value; + break; + + case CVAR_String: + sprintf (cstrbuf, "%i", value); + ret.String = cstrbuf; + break; + + case CVAR_GUID: + ret.pGUID = NULL; + break; + + default: + break; + } + + return ret; +} + +UCVarValue FBaseCVar::FromFloat (float value, ECVarType type) +{ + UCVarValue ret; + + switch (type) + { + case CVAR_Bool: + ret.Bool = value != 0.f; + break; + + case CVAR_Int: + ret.Int = (int)value; + break; + + case CVAR_Float: + ret.Float = value; + break; + + case CVAR_String: + sprintf (cstrbuf, "%g", value); + ret.String = cstrbuf; + break; + + case CVAR_GUID: + ret.pGUID = NULL; + break; + + default: + break; + } + + return ret; +} + +static BYTE HexToByte (const char *hex) +{ + BYTE v = 0; + for (int i = 0; i < 2; ++i) + { + v <<= 4; + if (hex[i] >= '0' && hex[i] <= '9') + { + v += hex[i] - '0'; + } + else if (hex[i] >= 'A' && hex[i] <= 'F') + { + v += hex[i] - 'A'; + } + else // The string is already verified to contain valid hexits + { + v += hex[i] - 'a'; + } + } + return v; +} + +UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) +{ + UCVarValue ret; + int i; + + switch (type) + { + case CVAR_Bool: + if (stricmp (value, "true") == 0) + ret.Bool = true; + else if (stricmp (value, "false") == 0) + ret.Bool = false; + else + ret.Bool = strtol (value, NULL, 0) != 0; + break; + + case CVAR_Int: + ret.Int = strtol (value, NULL, 0); + break; + + case CVAR_Float: + ret.Float = (float)strtod (value, NULL); + break; + + case CVAR_String: + ret.String = const_cast(value); + break; + + case CVAR_GUID: + // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + // 01234567890123456789012345678901234567 + // 0 1 2 3 + + ret.pGUID = NULL; + for (i = 0; i < 38; ++i) + { + if (value[i] == 0) + { + break; + } + bool goodv = true; + switch (i) + { + case 0: + if (value[i] != '{') + goodv = false; + break; + case 9: + case 14: + case 19: + case 24: + if (value[i] != '-') + goodv = false; + break; + case 37: + if (value[i] != '}') + goodv = false; + break; + default: + if (value[i] < '0' && value[i] > '9' && + value[i] < 'A' && value[i] > 'F' && + value[i] < 'a' && value[i] > 'f') + { + goodv = false; + } + break; + } + } + if (i == 38 && value[i] == 0) + { + cGUID.Data1 = strtoul (value + 1, NULL, 16); + cGUID.Data2 = strtoul (value + 10, NULL, 16); + cGUID.Data3 = strtoul (value + 15, NULL, 16); + cGUID.Data4[0] = HexToByte (value + 20); + cGUID.Data4[1] = HexToByte (value + 22); + cGUID.Data4[2] = HexToByte (value + 25); + cGUID.Data4[3] = HexToByte (value + 27); + cGUID.Data4[4] = HexToByte (value + 29); + cGUID.Data4[5] = HexToByte (value + 31); + cGUID.Data4[6] = HexToByte (value + 33); + cGUID.Data4[7] = HexToByte (value + 35); + ret.pGUID = &cGUID; + } + break; + + default: + break; + } + + return ret; +} + +UCVarValue FBaseCVar::FromGUID (const GUID &guid, ECVarType type) +{ + UCVarValue ret; + + switch (type) + { + case CVAR_Bool: + ret.Bool = false; + break; + + case CVAR_Int: + ret.Int = 0; + break; + + case CVAR_Float: + ret.Float = 0.f; + break; + + case CVAR_String: + ret.pGUID = &guid; + ret.String = ToString (ret, CVAR_GUID); + break; + + case CVAR_GUID: + ret.pGUID = &guid; + break; + + default: + break; + } + + return ret; +} +FBaseCVar *cvar_set (const char *var_name, const char *val) +{ + FBaseCVar *var; + + if ( (var = FindCVar (var_name, NULL)) ) + { + UCVarValue value; + value.String = const_cast(val); + var->SetGenericRep (value, CVAR_String); + } + + return var; +} + +FBaseCVar *cvar_forceset (const char *var_name, const char *val) +{ + FBaseCVar *var; + UCVarValue vval; + + if ( (var = FindCVar (var_name, NULL)) ) + { + vval.String = const_cast(val); + var->ForceSet (vval, CVAR_String); + } + + return var; +} + +void FBaseCVar::EnableNoSet () +{ + m_DoNoSet = true; +} + +void FBaseCVar::EnableCallbacks () +{ + m_UseCallback = true; + FBaseCVar *cvar = CVars; + + while (cvar) + { + if (!(cvar->Flags & CVAR_NOINITCALL)) + { + cvar->Callback (); + } + cvar = cvar->m_Next; + } +} + +// +// Boolean cvar implementation +// + +FBoolCVar::FBoolCVar (const char *name, bool def, DWORD flags, void (*callback)(FBoolCVar &)) +: FBaseCVar (name, flags, reinterpret_cast(callback)) +{ + DefaultValue = def; + if (Flags & CVAR_ISDEFAULT) + Value = def; +} + +ECVarType FBoolCVar::GetRealType () const +{ + return CVAR_Bool; +} + +UCVarValue FBoolCVar::GetGenericRep (ECVarType type) const +{ + return FromBool (Value, type); +} + +UCVarValue FBoolCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Bool; + ret.Bool = Value; + return ret; +} + +UCVarValue FBoolCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromBool (DefaultValue, type); +} + +UCVarValue FBoolCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Bool; + ret.Bool = DefaultValue; + return ret; +} + +void FBoolCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + DefaultValue = ToBool (value, type); + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } +} + +void FBoolCVar::DoSet (UCVarValue value, ECVarType type) +{ + Value = ToBool (value, type); +} + +// +// Integer cvar implementation +// + +FIntCVar::FIntCVar (const char *name, int def, DWORD flags, void (*callback)(FIntCVar &)) +: FBaseCVar (name, flags, reinterpret_cast(callback)) +{ + DefaultValue = def; + if (Flags & CVAR_ISDEFAULT) + Value = def; +} + +ECVarType FIntCVar::GetRealType () const +{ + return CVAR_Int; +} + +UCVarValue FIntCVar::GetGenericRep (ECVarType type) const +{ + return FromInt (Value, type); +} + +UCVarValue FIntCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Int; + ret.Int = Value; + return ret; +} + +UCVarValue FIntCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromInt (DefaultValue, type); +} + +UCVarValue FIntCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Int; + ret.Int = DefaultValue; + return ret; +} + +void FIntCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + DefaultValue = ToInt (value, type); + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } +} + +void FIntCVar::DoSet (UCVarValue value, ECVarType type) +{ + Value = ToInt (value, type); +} + +// +// Floating point cvar implementation +// + +FFloatCVar::FFloatCVar (const char *name, float def, DWORD flags, void (*callback)(FFloatCVar &)) +: FBaseCVar (name, flags, reinterpret_cast(callback)) +{ + DefaultValue = def; + if (Flags & CVAR_ISDEFAULT) + Value = def; +} + +ECVarType FFloatCVar::GetRealType () const +{ + return CVAR_Float; +} + +UCVarValue FFloatCVar::GetGenericRep (ECVarType type) const +{ + return FromFloat (Value, type); +} + +UCVarValue FFloatCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Float; + ret.Float = Value; + return ret; +} + +UCVarValue FFloatCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromFloat (DefaultValue, type); +} + +UCVarValue FFloatCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Float; + ret.Float = DefaultValue; + return ret; +} + +void FFloatCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + DefaultValue = ToFloat (value, type); + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } +} + +void FFloatCVar::DoSet (UCVarValue value, ECVarType type) +{ + Value = ToFloat (value, type); +} + +// +// String cvar implementation +// + +FStringCVar::FStringCVar (const char *name, const char *def, DWORD flags, void (*callback)(FStringCVar &)) +: FBaseCVar (name, flags, reinterpret_cast(callback)) +{ + DefaultValue = copystring (def); + if (Flags & CVAR_ISDEFAULT) + Value = copystring (def); + else + Value = NULL; +} + +FStringCVar::~FStringCVar () +{ + if (Value != NULL) + { + delete[] Value; + } + delete[] DefaultValue; +} + +ECVarType FStringCVar::GetRealType () const +{ + return CVAR_String; +} + +UCVarValue FStringCVar::GetGenericRep (ECVarType type) const +{ + return FromString (Value, type); +} + +UCVarValue FStringCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_String; + ret.String = Value; + return ret; +} + +UCVarValue FStringCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromString (DefaultValue, type); +} + +UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_String; + ret.String = DefaultValue; + return ret; +} + +void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + if (DefaultValue) + delete[] DefaultValue; + DefaultValue = ToString (value, type); + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } +} + +void FStringCVar::DoSet (UCVarValue value, ECVarType type) +{ + ReplaceString (&Value, ToString (value, type)); +} + +// +// Color cvar implementation +// + +FColorCVar::FColorCVar (const char *name, int def, DWORD flags, void (*callback)(FColorCVar &)) +: FIntCVar (name, def, flags, reinterpret_cast(callback)) +{ +} + +ECVarType FColorCVar::GetRealType () const +{ + return CVAR_Color; +} + +UCVarValue FColorCVar::GetGenericRep (ECVarType type) const +{ + return FromInt2 (Value, type); +} + +UCVarValue FColorCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromInt2 (DefaultValue, type); +} + +void FColorCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + DefaultValue = ToInt2 (value, type); + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } +} + +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) +{ + if (type == CVAR_String) + { + UCVarValue ret; + sprintf (cstrbuf, "%02x %02x %02x", + RPART(value), GPART(value), BPART(value)); + ret.String = cstrbuf; + return ret; + } + return FromInt (value, type); +} + +int FColorCVar::ToInt2 (UCVarValue value, ECVarType type) +{ + int ret; + + if (type == CVAR_String) + { + FString string; + // Only allow named colors after the screen exists (i.e. after + // we've got some lumps loaded, so X11R6RGB can be read). Since + // the only time this might be called before that is when loading + // zdoom.ini, this shouldn't be a problem. + if (screen && !(string = V_GetColorStringByName (value.String)).IsEmpty() ) + { + ret = V_GetColorFromString (NULL, string); + } + else + { + ret = V_GetColorFromString (NULL, value.String); + } + } + else + { + ret = ToInt (value, type); + } + return ret; +} + +// +// GUID cvar implementation +// + +FGUIDCVar::FGUIDCVar (const char *name, const GUID *def, DWORD flags, void (*callback)(FGUIDCVar &)) +: FBaseCVar (name, flags, reinterpret_cast(callback)) +{ + if (def != NULL) + { + DefaultValue = *def; + if (Flags & CVAR_ISDEFAULT) + Value = *def; + } + else + { + memset (&Value, 0, sizeof(DefaultValue)); + memset (&DefaultValue, 0, sizeof(DefaultValue)); + } +} + +ECVarType FGUIDCVar::GetRealType () const +{ + return CVAR_GUID; +} + +UCVarValue FGUIDCVar::GetGenericRep (ECVarType type) const +{ + return FromGUID (Value, type); +} + +UCVarValue FGUIDCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_GUID; + ret.pGUID = &Value; + return ret; +} + +UCVarValue FGUIDCVar::GetGenericRepDefault (ECVarType type) const +{ + return FromGUID (DefaultValue, type); +} + +UCVarValue FGUIDCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_GUID; + ret.pGUID = &DefaultValue; + return ret; +} + +void FGUIDCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + const GUID *guid = ToGUID (value, type); + if (guid != NULL) + { + Value = *guid; + if (Flags & CVAR_ISDEFAULT) + { + SetGenericRep (value, type); + Flags |= CVAR_ISDEFAULT; + } + } +} + +void FGUIDCVar::DoSet (UCVarValue value, ECVarType type) +{ + const GUID *guid = ToGUID (value, type); + if (guid != NULL) + { + Value = *guid; + } +} + +// +// More base cvar stuff +// + +void FBaseCVar::ResetColors () +{ + FBaseCVar *var = CVars; + + while (var) + { + if (var->GetRealType () == CVAR_Color) + { + var->DoSet (var->GetGenericRep (CVAR_Int), CVAR_Int); + } + var = var->m_Next; + } +} + +void FBaseCVar::ResetToDefault () +{ + if (!(Flags & CVAR_ISDEFAULT)) + { + UCVarValue val; + ECVarType type; + + val = GetFavoriteRepDefault (&type); + SetGenericRep (val, type); + Flags |= CVAR_ISDEFAULT; + } +} + +// +// Flag cvar implementation +// +// This type of cvar is not a "real" cvar. Instead, it gets and sets +// the value of a FIntCVar, modifying it bit-by-bit. As such, it has +// no default, and is not written to the .cfg or transferred around +// the network. The "host" cvar is responsible for that. +// + +FFlagCVar::FFlagCVar (const char *name, FIntCVar &realvar, DWORD bitval) +: FBaseCVar (name, 0, NULL), +ValueVar (realvar), +BitVal (bitval) +{ + int bit; + + Flags &= ~CVAR_ISDEFAULT; + + assert (bitval != 0); + + bit = 0; + while ((bitval >>= 1) != 0) + { + ++bit; + } + BitNum = bit; + + assert ((1u << BitNum) == BitVal); +} + +ECVarType FFlagCVar::GetRealType () const +{ + return CVAR_Dummy; +} + +UCVarValue FFlagCVar::GetGenericRep (ECVarType type) const +{ + return FromBool ((ValueVar & BitVal) != 0, type); +} + +UCVarValue FFlagCVar::GetFavoriteRep (ECVarType *type) const +{ + UCVarValue ret; + *type = CVAR_Bool; + ret.Bool = (ValueVar & BitVal) != 0; + return ret; +} + +UCVarValue FFlagCVar::GetGenericRepDefault (ECVarType type) const +{ + ECVarType dummy; + UCVarValue def; + def = ValueVar.GetFavoriteRepDefault (&dummy); + return FromBool ((def.Int & BitVal) != 0, type); +} + +UCVarValue FFlagCVar::GetFavoriteRepDefault (ECVarType *type) const +{ + ECVarType dummy; + UCVarValue def; + def = ValueVar.GetFavoriteRepDefault (&dummy); + def.Bool = (def.Int & BitVal) != 0; + *type = CVAR_Bool; + return def; +} + +void FFlagCVar::SetGenericRepDefault (UCVarValue value, ECVarType type) +{ + bool newdef = ToBool (value, type); + ECVarType dummy; + UCVarValue def; + def = ValueVar.GetFavoriteRepDefault (&dummy); + if (newdef) + def.Int |= BitVal; + else + def.Int &= ~BitVal; + ValueVar.SetGenericRepDefault (def, CVAR_Int); +} + +void FFlagCVar::DoSet (UCVarValue value, ECVarType type) +{ + bool newval = ToBool (value, type); + + // Server cvars that get changed by this need to use a special message, because + // changes are not processed until the next net update. This is a problem with + // 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.Flags & CVAR_SERVERINFO) && gamestate != GS_STARTUP && !demoplayback) + { + if (netgame && !players[consoleplayer].settings_controller) + { + Printf ("Only setting controllers can change %s\n", Name); + return; + } + D_SendServerFlagChange (&ValueVar, BitNum, newval); + } + else + { + int val = *ValueVar; + if (newval) + val |= BitVal; + else + val &= ~BitVal; + ValueVar = val; + } +} + +//////////////////////////////////////////////////////////////////////// +static int STACK_ARGS sortcvars (const void *a, const void *b) +{ + return strcmp (((*(FBaseCVar **)a))->GetName(), ((*(FBaseCVar **)b))->GetName()); +} + +void FilterCompactCVars (TArray &cvars, DWORD filter) +{ + FBaseCVar *cvar = CVars; + while (cvar) + { + if (cvar->Flags & filter) + cvars.Push (cvar); + cvar = cvar->m_Next; + } + if (cvars.Size () > 0) + { + cvars.ShrinkToFit (); + qsort (&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars); + } +} + +void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact) +{ + FBaseCVar *cvar = CVars; + BYTE *ptr = *demo_p; + + if (compact) + { + TArray cvars; + ptr += sprintf ((char *)ptr, "\\\\%ux", filter); + FilterCompactCVars (cvars, filter); + while (cvars.Pop (cvar)) + { + UCVarValue val = cvar->GetGenericRep (CVAR_String); + ptr += sprintf ((char *)ptr, "\\%s", val.String); + } + } + else + { + cvar = CVars; + while (cvar) + { + if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_NOSAVE)) + { + UCVarValue val = cvar->GetGenericRep (CVAR_String); + ptr += sprintf ((char *)ptr, "\\%s\\%s", + cvar->GetName (), val.String); + } + cvar = cvar->m_Next; + } + } + + *demo_p = ptr + 1; +} + +void C_ReadCVars (BYTE **demo_p) +{ + char *ptr = *((char **)demo_p); + char *breakpt; + + if (*ptr++ != '\\') + return; + + if (*ptr == '\\') + { // compact mode + TArray cvars; + FBaseCVar *cvar; + DWORD filter; + + ptr++; + breakpt = strchr (ptr, '\\'); + *breakpt = 0; + filter = strtoul (ptr, NULL, 16); + *breakpt = '\\'; + ptr = breakpt + 1; + + FilterCompactCVars (cvars, filter); + + while (cvars.Pop (cvar)) + { + UCVarValue val; + breakpt = strchr (ptr, '\\'); + if (breakpt) + *breakpt = 0; + val.String = ptr; + cvar->ForceSet (val, CVAR_String); + if (breakpt) + { + *breakpt = '\\'; + ptr = breakpt + 1; + } + else + break; + } + } + else + { + char *value; + + while ( (breakpt = strchr (ptr, '\\')) ) + { + *breakpt = 0; + value = breakpt + 1; + if ( (breakpt = strchr (value, '\\')) ) + *breakpt = 0; + + cvar_set (ptr, value); + + *(value - 1) = '\\'; + if (breakpt) + { + *breakpt = '\\'; + ptr = breakpt + 1; + } + else + { + break; + } + } + } + *demo_p += strlen (*((char **)demo_p)) + 1; +} + +static struct backup_s +{ + char *name, *string; +} CVarBackups[MAX_DEMOCVARS]; + +static int numbackedup = 0; + +void C_BackupCVars (void) +{ + struct backup_s *backup = CVarBackups; + FBaseCVar *cvar = CVars; + + while (cvar) + { + if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) + && !(cvar->Flags & CVAR_LATCH)) + { + if (backup == &CVarBackups[MAX_DEMOCVARS]) + I_Error ("C_BackupDemoCVars: Too many cvars to save (%d)", MAX_DEMOCVARS); + backup->name = copystring (cvar->GetName()); + backup->string = copystring (cvar->GetGenericRep (CVAR_String).String); + backup++; + } + cvar = cvar->m_Next; + } + numbackedup = backup - CVarBackups; +} + +void C_RestoreCVars (void) +{ + struct backup_s *backup = CVarBackups; + int i; + + for (i = numbackedup; i; i--, backup++) + { + cvar_set (backup->name, backup->string); + delete[] backup->name; + delete[] backup->string; + backup->name = backup->string = NULL; + } + numbackedup = 0; +} + +FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev) +{ + FBaseCVar *var; + FBaseCVar *dummy; + + if (var_name == NULL) + return NULL; + + if (prev == NULL) + prev = &dummy; + + var = CVars; + *prev = NULL; + while (var) + { + if (stricmp (var->GetName (), var_name) == 0) + break; + *prev = var; + var = var->m_Next; + } + return var; +} + +FBaseCVar *FindCVarSub (const char *var_name, int namelen) +{ + FBaseCVar *var; + + if (var_name == NULL) + return NULL; + + var = CVars; + while (var) + { + const char *probename = var->GetName (); + + if (strnicmp (probename, var_name, namelen) == 0 && + probename[namelen] == 0) + { + break; + } + var = var->m_Next; + } + return var; +} + +void UnlatchCVars (void) +{ + FLatchedValue var; + + while (LatchedValues.Pop (var)) + { + DWORD oldflags = var.Variable->Flags; + var.Variable->Flags &= ~(CVAR_LATCH | CVAR_SERVERINFO); + var.Variable->SetGenericRep (var.Value, var.Type); + if (var.Type == CVAR_String) + delete[] var.Value.String; + var.Variable->Flags = oldflags; + } +} + +void C_SetCVarsToDefaults (void) +{ + FBaseCVar *cvar = CVars; + + while (cvar) + { + // Only default save-able cvars + if (cvar->Flags & CVAR_ARCHIVE) + { + UCVarValue val; + ECVarType type; + val = cvar->GetFavoriteRepDefault (&type); + cvar->SetGenericRep (val, type); + } + cvar = cvar->m_Next; + } +} + +void C_ArchiveCVars (FConfigFile *f, int type) +{ + // type 0: Game-specific cvars + // type 1: Global cvars + // type 2: Unknown cvars + // type 3: Unknown global cvars + // type 4: User info cvars + // type 5: Server info cvars + static const DWORD filters[6] = + { + CVAR_ARCHIVE, + CVAR_ARCHIVE|CVAR_GLOBALCONFIG, + CVAR_ARCHIVE|CVAR_AUTO, + CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_AUTO, + CVAR_ARCHIVE|CVAR_USERINFO, + CVAR_ARCHIVE|CVAR_SERVERINFO + }; + + FBaseCVar *cvar = CVars; + DWORD filter; + + filter = filters[type]; + + while (cvar) + { + if ((cvar->Flags & + (CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE)) + == filter) + { + UCVarValue val; + val = cvar->GetGenericRep (CVAR_String); + f->SetValueForKey (cvar->GetName (), val.String); + } + cvar = cvar->m_Next; + } +} + +void FBaseCVar::CmdSet (const char *newval) +{ + UCVarValue val; + + // Casting away the const is safe in this case. + val.String = const_cast(newval); + SetGenericRep (val, CVAR_String); + + if (GetFlags() & CVAR_NOSET) + Printf ("%s is write protected.\n", GetName()); + else if (GetFlags() & CVAR_LATCH) + Printf ("%s will be changed for next game.\n", GetName()); +} + +CCMD (set) +{ + if (argv.argc() != 3) + { + Printf ("usage: set \n"); + } + else + { + FBaseCVar *var; + + var = FindCVar (argv[1], NULL); + if (var == NULL) + var = new FStringCVar (argv[1], NULL, CVAR_AUTO | CVAR_UNSETTABLE | cvar_defflags); + + var->CmdSet (argv[2]); + } +} + +CCMD (unset) +{ + if (argv.argc() != 2) + { + Printf ("usage: unset \n"); + } + else + { + FBaseCVar *var = FindCVar (argv[1], NULL); + if (var != NULL) + { + if (var->GetFlags() & CVAR_UNSETTABLE) + { + delete var; + } + else + { + Printf ("Cannot unset %s\n", argv[1]); + } + } + } +} + +CCMD (get) +{ + FBaseCVar *var, *prev; + + if (argv.argc() >= 2) + { + if ( (var = FindCVar (argv[1], &prev)) ) + { + UCVarValue val; + val = var->GetGenericRep (CVAR_String); + Printf ("\"%s\" is \"%s\"\n", var->GetName(), val.String); + } + else + { + Printf ("\"%s\" is unset\n", argv[1]); + } + } + else + { + Printf ("get: need variable name\n"); + } +} + +CCMD (toggle) +{ + FBaseCVar *var, *prev; + UCVarValue val; + + if (argv.argc() > 1) + { + if ( (var = FindCVar (argv[1], &prev)) ) + { + val = var->GetGenericRep (CVAR_Bool); + val.Bool = !val.Bool; + var->SetGenericRep (val, CVAR_Bool); + Printf ("\"%s\" is \"%s\"\n", var->GetName(), + val.Bool ? "true" : "false"); + } + } +} + +void FBaseCVar::ListVars (const char *filter, bool plain) +{ + FBaseCVar *var = CVars; + int count = 0; + + while (var) + { + if (CheckWildcards (filter, var->GetName())) + { + DWORD flags = var->GetFlags(); + UCVarValue val; + + val = var->GetGenericRep (CVAR_String); + if (plain) + { // plain formatting does not include user-defined cvars + if (!(flags & CVAR_UNSETTABLE)) + { + ++count; + Printf ("%s : %s\n", var->GetName(), var->GetGenericRep(CVAR_String).String); + } + } + else + { + ++count; + Printf ("%c%c%c %s : :%s\n", + flags & CVAR_ARCHIVE ? 'A' : ' ', + flags & CVAR_USERINFO ? 'U' : + flags & CVAR_SERVERINFO ? 'S' : + flags & CVAR_AUTO ? 'C' : ' ', + flags & CVAR_NOSET ? '-' : + flags & CVAR_LATCH ? 'L' : + flags & CVAR_UNSETTABLE ? '*' : ' ', + var->GetName(), + var->GetGenericRep (CVAR_String).String); + } + } + var = var->m_Next; + } + Printf ("%d cvars\n", count); +} + +CCMD (cvarlist) +{ + if (argv.argc() == 1) + { + FBaseCVar::ListVars (NULL, false); + } + else + { + FBaseCVar::ListVars (argv[1], false); + } +} + +CCMD (cvarlistplain) +{ + FBaseCVar::ListVars (NULL, true); +} + +CCMD (archivecvar) +{ + + if (argv.argc() == 1) + { + Printf ("Usage: archivecvar \n"); + } + else + { + FBaseCVar *var = FindCVar (argv[1], NULL); + + if (var != NULL && (var->GetFlags() & CVAR_AUTO)) + { + var->SetArchiveBit (); + } + } +} diff --git a/src/c_expr.cpp b/src/c_expr.cpp index fa8e4081..82d972bd 100644 --- a/src/c_expr.cpp +++ b/src/c_expr.cpp @@ -233,8 +233,8 @@ missing: Printf ("Missing argument to %s\n", token); done: - if (prod2 != NULL) free (prod2); - if (prod1 != NULL) free (prod1); + if (prod2 != NULL) M_Free (prod2); + if (prod1 != NULL) M_Free (prod1); return prod3; } @@ -353,7 +353,7 @@ static FStringProd *DoubleToString (FProduction *prod) sprintf (buf, "%g", static_cast(prod)->Value); newprod = NewStringProd (buf); - free (prod); + M_Free (prod); return newprod; } @@ -368,7 +368,7 @@ static FDoubleProd *StringToDouble (FProduction *prod) FDoubleProd *newprod; newprod = NewDoubleProd (atof (static_cast(prod)->Value)); - free (prod); + M_Free (prod); return newprod; } @@ -746,7 +746,7 @@ CCMD (test) } if (prod != NULL) { - free (prod); + M_Free (prod); } } @@ -802,7 +802,7 @@ CCMD (eval) Printf ("%s\n", static_cast(prod)->Value); } } - free (prod); + M_Free (prod); return; } } diff --git a/src/d_net.cpp b/src/d_net.cpp index 9fbcb615..896b974c 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -197,7 +197,7 @@ static struct TicSpecial { if (streams[i]) { - free (streams[i]); + M_Free (streams[i]); streams[i] = NULL; used[i] = 0; } @@ -649,6 +649,7 @@ void PlayerIsGone (int netnode, int netconsole) if (playeringame[i] && !players[i].isbot) { Net_Arbitrator = i; + players[i].settings_controller = true; Printf ("%s is the new arbitrator\n", players[i].userinfo.netname); break; } @@ -1580,6 +1581,8 @@ void D_CheckNetGame (void) I_InitNetwork (); if (doomcom.id != DOOMCOM_ID) I_FatalError ("Doomcom buffer invalid!"); + + players[0].settings_controller = true; consoleplayer = doomcom.consoleplayer; @@ -2313,6 +2316,26 @@ void Net_DoCommand (int type, BYTE **stream, int player) playerswiping &= ~(1 << player); break; + case DEM_ADDCONTROLLER: + { + BYTE playernum = ReadByte (stream); + players[playernum].settings_controller = true; + + if (consoleplayer == playernum || consoleplayer == Net_Arbitrator) + Printf ("%s has been added to the controller list.\n", players[playernum].userinfo.netname); + } + break; + + case DEM_DELCONTROLLER: + { + BYTE playernum = ReadByte (stream); + players[playernum].settings_controller = false; + + if (consoleplayer == playernum || consoleplayer == Net_Arbitrator) + Printf ("%s has been removed from the controller list.\n", players[playernum].userinfo.netname); + } + break; + default: I_Error ("Unknown net command: %d", type); break; @@ -2362,6 +2385,8 @@ void Net_SkipCommand (int type, BYTE **stream) case DEM_DROPPLAYER: case DEM_FOV: case DEM_MYFOV: + case DEM_ADDCONTROLLER: + case DEM_DELCONTROLLER: skip = 1; break; @@ -2417,3 +2442,132 @@ CCMD (pings) Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i], players[i].userinfo.netname); } + +//========================================================================== +// +// Network_Controller +// +// Implement players who have the ability to change settings in a network +// game. +// +//========================================================================== + +static void Network_Controller (int playernum, bool add) +{ + if (consoleplayer != Net_Arbitrator) + { + Printf ("This command is only accessible to the net arbitrator.\n"); + return; + } + + if (players[playernum].settings_controller && add) + { + Printf ("%s is already on the setting controller list.\n", players[playernum].userinfo.netname); + return; + } + + if (!players[playernum].settings_controller && !add) + { + Printf ("%s is not on the setting controller list.\n", players[playernum].userinfo.netname); + return; + } + + if (!playeringame[playernum]) + { + Printf ("Player (%d) not found!\n"); + return; + } + + if (players[playernum].isbot) + { + Printf ("Bots cannot be added to the controller list.\n"); + return; + } + + if (playernum == Net_Arbitrator) + { + Printf ("The net arbitrator cannot have their status changed on this list.\n"); + return; + } + + if (add) + Net_WriteByte (DEM_ADDCONTROLLER); + else + Net_WriteByte (DEM_DELCONTROLLER); + + Net_WriteByte (playernum); +} + +//========================================================================== +// +// CCMD net_addcontroller +// +//========================================================================== + +CCMD (net_addcontroller) +{ + if (!netgame) + { + Printf ("This command can only be used when playing a net game.\n"); + return; + } + + if (argv.argc () < 2) + { + Printf ("Usage: net_addcontroller \n"); + return; + } + + Network_Controller (atoi (argv[1]), true); +} + +//========================================================================== +// +// CCMD net_removecontroller +// +//========================================================================== + +CCMD (net_removecontroller) +{ + if (!netgame) + { + Printf ("This command can only be used when playing a net game.\n"); + return; + } + + if (argv.argc () < 2) + { + Printf ("Usage: net_removecontroller \n"); + return; + } + + Network_Controller (atoi (argv[1]), false); +} + +//========================================================================== +// +// CCMD net_listcontrollers +// +//========================================================================== + +CCMD (net_listcontrollers) +{ + if (!netgame) + { + Printf ("This command can only be used when playing a net game.\n"); + return; + } + + Printf ("The following players can change the game settings:\n"); + + for (int i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].settings_controller) + { + Printf ("- %s\n", players[i].userinfo.netname); + } + } +} diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index db91e781..b2a21a58 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -823,15 +823,18 @@ CCMD (playerinfo) else { int i = atoi (argv[1]); - Printf ("Name: %s\n", players[i].userinfo.netname); - Printf ("Team: %d\n", players[i].userinfo.team); - Printf ("Aimdist: %d\n", players[i].userinfo.aimdist); - Printf ("Color: %06x\n", players[i].userinfo.color); - Printf ("Skin: %d\n", players[i].userinfo.skin); - Printf ("Gender: %d\n", players[i].userinfo.gender); - Printf ("NeverSwitch: %d\n", players[i].userinfo.neverswitch); - Printf ("MoveBob: %g\n", players[i].userinfo.MoveBob/65536.f); - Printf ("StillBob: %g\n", players[i].userinfo.StillBob/65536.f); - Printf ("PlayerClass: %d\n", players[i].userinfo.PlayerClass); + userinfo_t *ui = &players[i].userinfo; + Printf ("Name: %s\n", ui->netname); + Printf ("Team: %s (%d)\n", ui->team == TEAM_None ? "None" : teams[ui->team].name, ui->team); + Printf ("Aimdist: %d\n", ui->aimdist); + Printf ("Color: %06x\n", ui->color); + Printf ("Skin: %s (%d)\n", skins[ui->skin].name, ui->skin); + Printf ("Gender: %s (%d)\n", GenderNames[ui->gender], ui->gender); + Printf ("NeverSwitch: %d\n", ui->neverswitch); + Printf ("MoveBob: %g\n", ui->MoveBob/65536.f); + Printf ("StillBob: %g\n", ui->StillBob/65536.f); + Printf ("PlayerClass: %s (%d)\n", + ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName), + ui->PlayerClass); } } diff --git a/src/d_player.h b/src/d_player.h index 8e6ee612..2ac7f2a5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -280,6 +280,8 @@ public: // pointed to by this. Allows bot to roam to it if // necessary. + bool settings_controller; // Player can control game settings. + //Skills struct botskill_t skill; diff --git a/src/d_protocol.h b/src/d_protocol.h index dde9a6c6..104d307e 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -147,6 +147,8 @@ enum EDemoCommand DEM_WIPEON, // 45 Player started a screen wipe DEM_WIPEOFF, // 46 Player finished a screen wipe DEM_TAKECHEAT, // 47 String: item to take, Word: quantity + DEM_ADDCONTROLLER, // 48 Player to add to the controller list. + DEM_DELCONTROLLER, // 49 Player to remove from the controller list. }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/dobject.h b/src/dobject.h index f06f43dd..f18f1e03 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -283,7 +283,7 @@ public: void operator delete (void *mem) { - free (mem); + M_Free(mem); } protected: diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dbcda05c..070429c1 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -305,7 +305,7 @@ void PClass::FreeStateList () if (ActorInfo != NULL && ActorInfo->StateList != NULL) { ActorInfo->StateList->Destroy(); - free (ActorInfo->StateList); + M_Free (ActorInfo->StateList); ActorInfo->StateList = NULL; } } diff --git a/src/farchive.cpp b/src/farchive.cpp index 574b9f7d..7d17c8d4 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -229,7 +229,10 @@ void FCompressedFile::Close () m_File = NULL; } if (m_Buffer) - free (m_Buffer); + { + M_Free (m_Buffer); + m_Buffer = NULL; + } BeEmpty (); } @@ -372,7 +375,7 @@ void FCompressedFile::Implode () memcpy (m_Buffer + 8, compressed, outlen); if (compressed) delete[] compressed; - free (oldbuf); + M_Free (oldbuf); } void FCompressedFile::Explode () @@ -396,7 +399,7 @@ void FCompressedFile::Explode () r = uncompress (expand, &newlen, m_Buffer + 8, cprlen); if (r != Z_OK || newlen != expandsize) { - free (expand); + M_Free (expand); I_Error ("Could not decompress cfile"); } } @@ -405,7 +408,7 @@ void FCompressedFile::Explode () memcpy (expand, m_Buffer + 8, expandsize); } if (FreeOnExplode ()) - free (m_Buffer); + M_Free (m_Buffer); m_Buffer = expand; m_BufferSize = expandsize; } @@ -430,7 +433,7 @@ FCompressedMemFile::~FCompressedMemFile () { if (m_ImplodedBuffer != NULL) { - free (m_ImplodedBuffer); + M_Free (m_ImplodedBuffer); } } @@ -672,7 +675,7 @@ FArchive::~FArchive () if (m_TypeMap) delete[] m_TypeMap; if (m_ObjectMap) - free (m_ObjectMap); + M_Free (m_ObjectMap); if (m_SpriteMap) delete[] m_SpriteMap; } diff --git a/src/g_game.cpp b/src/g_game.cpp index f0573093..a0d3ec1c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -102,6 +102,7 @@ FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH); CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH); CVAR (Bool, chasedemo, false, 0); CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR (Bool, longsavemessages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) gameaction_t gameaction; gamestate_t gamestate = GS_STARTUP; @@ -2065,7 +2066,11 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio } fclose(stdfile); } - if (success) Printf ("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars()); + if (success) + { + if (longsavemessages) Printf ("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars()); + else Printf ("%s\n", GStrings("GGSAVED")); + } else Printf(PRINT_HIGH, "Save failed\n"); BackupSaveName = filename; @@ -2431,7 +2436,7 @@ bool G_ProcessIFFDemo (char *mapname) delete[] uncompressed; return true; } - delete[] demobuffer; + M_Free (demobuffer); zdembodyend = uncompressed + uncompSize; demobuffer = demo_p = uncompressed; } @@ -2451,7 +2456,7 @@ void G_DoPlayDemo (void) if (demolump >= 0) { int demolen = Wads.LumpLength (demolump); - demobuffer = new BYTE[demolen]; + demobuffer = (BYTE *)M_Malloc(demolen); Wads.ReadLump (demolump, demobuffer); } else @@ -2542,7 +2547,7 @@ bool G_CheckDemoStatus (void) C_RestoreCVars (); // [RH] Restore cvars demo might have changed - delete[] demobuffer; + M_Free (demobuffer); demoplayback = false; netdemo = false; netgame = false; @@ -2615,7 +2620,7 @@ bool G_CheckDemoStatus (void) WriteLong (demo_p - demobuffer - 8, &formlen); M_WriteFile (demoname, demobuffer, demo_p - demobuffer); - free (demobuffer); + M_Free (demobuffer); demorecording = false; stoprecording = false; Printf ("Demo %s recorded\n", demoname); diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 2f51d0f1..4463ea01 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -24,7 +24,7 @@ IMPLEMENT_ACTOR (AArtiTomeOfPower, Heretic, 86, 134) PROP_Flags (MF_SPECIAL|MF_COUNTITEM) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) - PROP_Inventory_FlagsSet (IF_PICKUPFLASH) + PROP_Inventory_PickupFlash (1) PROP_Inventory_Icon ("ARTIPWBK") PROP_PowerupGiver_Powerup ("PowerWeaponLevel2") PROP_Inventory_PickupMessage("$TXT_ARTITOMEOFPOWER") @@ -106,7 +106,8 @@ IMPLEMENT_ACTOR (AArtiTimeBomb, Heretic, 34, 72) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIFBMB") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTIFIREBOMB") diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp index 234f2db0..1d77d195 100644 --- a/src/g_hexen/a_blastradius.cpp +++ b/src/g_hexen/a_blastradius.cpp @@ -37,7 +37,8 @@ IMPLEMENT_ACTOR (AArtiBlastRadius, Hexen, 10110, 74) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIBLST") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTIBLASTRADIUS") diff --git a/src/g_hexen/a_boostarmor.cpp b/src/g_hexen/a_boostarmor.cpp index 4142845c..ae18363c 100644 --- a/src/g_hexen/a_boostarmor.cpp +++ b/src/g_hexen/a_boostarmor.cpp @@ -33,7 +33,8 @@ IMPLEMENT_ACTOR (AArtiBoostArmor, Hexen, 8041, 22) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIBRAC") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTIBOOSTARMOR") diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp index 8e91dc4e..2f27da13 100644 --- a/src/g_hexen/a_flechette.cpp +++ b/src/g_hexen/a_flechette.cpp @@ -159,7 +159,8 @@ IMPLEMENT_ACTOR (AArtiPoisonBag, Hexen, 8000, 72) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIPSBG") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTIPOISONBAG") diff --git a/src/g_hexen/a_healingradius.cpp b/src/g_hexen/a_healingradius.cpp index 3f777650..fbbe6bf5 100644 --- a/src/g_hexen/a_healingradius.cpp +++ b/src/g_hexen/a_healingradius.cpp @@ -48,7 +48,8 @@ IMPLEMENT_ACTOR (AArtiHealingRadius, Hexen, 10120, 0) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIHRAD") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTIHEALINGRADIUS") diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp index a51fc472..61b69757 100644 --- a/src/g_hexen/a_summon.cpp +++ b/src/g_hexen/a_summon.cpp @@ -30,7 +30,8 @@ IMPLEMENT_ACTOR (AArtiDarkServant, Hexen, 86, 16) PROP_SpawnState (S_ARTI_SUMMON) PROP_Inventory_RespawnTics (30+4200) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTISUMN") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTISUMMON") diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 2940c347..75610b3b 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -44,7 +44,8 @@ IMPLEMENT_ACTOR (AArtiTeleportOther, Hexen, 10040, 17) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (S_ARTI_TELOTHER1) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTITELO") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTITELEPORTOTHER") diff --git a/src/g_level.cpp b/src/g_level.cpp index 6a24dfe4..965e1d4f 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2620,11 +2620,11 @@ void G_MakeEpisodes () static const char *hepinames[5] = { - "MNU_COTD", - "MNU_HELLSMAW", - "MNU_DOME", - "MNU_OSSUARY", - "MNU_DEMESNE", + "$MNU_COTD", + "$MNU_HELLSMAW", + "$MNU_DOME", + "$MNU_OSSUARY", + "$MNU_DEMESNE", }; static const char hepikeys[5] = { 'c', 'h', 'd', 'o', 's' }; diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 410bb62d..4b2ee066 100644 --- a/src/g_raven/a_artitele.cpp +++ b/src/g_raven/a_artitele.cpp @@ -31,7 +31,8 @@ IMPLEMENT_ACTOR (AArtiTeleport, Raven, 36, 18) PROP_Flags2 (MF2_FLOATBOB) PROP_SpawnState (0) PROP_Inventory_DefMaxAmount - PROP_Inventory_FlagsSet (IF_INVBAR|IF_PICKUPFLASH|IF_FANCYPICKUPSOUND) + PROP_Inventory_PickupFlash (1) + PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND) PROP_Inventory_Icon ("ARTIATLP") PROP_Inventory_PickupSound ("misc/p_pkup") PROP_Inventory_PickupMessage("$TXT_ARTITELEPORT") diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index f2a7b8eb..9618c095 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -587,18 +587,18 @@ bool AInventory::GoAway () // Dropped items never stick around if (flags & MF_DROPPED) { - if (ItemFlags & IF_PICKUPFLASH) + if (PickupFlash != NULL) { - Spawn (x, y, z, ALLOW_REPLACE); + Spawn(PickupFlash, x, y, z, ALLOW_REPLACE); } return false; } if (!ShouldStay ()) { - if (ItemFlags & IF_PICKUPFLASH) + if (PickupFlash != NULL) { - Spawn (x, y, z, ALLOW_REPLACE); + Spawn(PickupFlash, x, y, z, ALLOW_REPLACE); } Hide (); if (ShouldRespawn ()) @@ -857,7 +857,7 @@ void AInventory::Hide () { SetState (&States[S_HIDESPECIAL]); tics = 1400; - if (ItemFlags & IF_PICKUPFLASH) tics += 30; + if (PickupFlash != NULL) tics += 30; } else { diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 3f58cfcd..0acf9017 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -90,7 +90,7 @@ enum IF_INVBAR = 1<<6, // Item appears in the inventory bar IF_HUBPOWER = 1<<7, // Powerup is kept when moving in a hub IF_INTERHUBSTRIP = 1<<8, // Item is removed when travelling between hubs - IF_PICKUPFLASH = 1<<9, // Item "flashes" when picked up + //IF_PICKUPFLASH = 1<<9, // superseded by 'PickupFlash' property. IF_ALWAYSPICKUP = 1<<10, // For IF_AUTOACTIVATE, MaxAmount=0 items: Always "pick up", even if it doesn't do anything IF_FANCYPICKUPSOUND = 1<<11, // Play pickup sound in "surround" mode IF_BIGPOWERUP = 1<<12, // Affected by RESPAWN_SUPER dmflag @@ -136,6 +136,7 @@ public: int DropTime; // Countdown after dropping DWORD ItemFlags; + const PClass *PickupFlash; // actor to spawn as pickup flash WORD PickupSound; diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index d79b73f2..ee2dfe20 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -78,6 +78,7 @@ enum //drawnumber flags DRAWNUMBER_TOTALITEMS = 2048, DRAWNUMBER_SECRETS = 4096, DRAWNUMBER_TOTALSECRETS = 8192, + DRAWNUMBER_ARMORCLASS = 16384, }; enum //drawbar flags (will go into special2) @@ -106,6 +107,8 @@ enum //drawgem flags { DRAWGEM_WIGGLE = 1, DRAWGEM_TRANSLATABLE = 2, + DRAWGEM_ARMOR = 4, + DRAWGEM_REVERSE = 8, }; enum //drawshader flags @@ -137,6 +140,7 @@ static const char *SBarInfoTopLevel[] = "base", "height", "interpolatehealth", + "interpolatearmor", "completeborder", "statusbar", NULL @@ -146,6 +150,7 @@ enum SBARINFO_BASE, SBARINFO_HEIGHT, SBARINFO_INTERPOLATEHEALTH, + SBARINFO_INTERPOLATEARMOR, SBARINFO_COMPLETEBORDER, SBARINFO_STATUSBAR, }; @@ -215,7 +220,7 @@ void FreeSBarInfoScript() } } -//Laz Bar Script Reader +//SBarInfo Script Reader void SBarInfo::ParseSBarInfo(int lump) { FScanner sc(lump, Wads.GetLumpFullName(lump)); @@ -276,6 +281,23 @@ void SBarInfo::ParseSBarInfo(int lump) } sc.MustGetToken(';'); break; + case SBARINFO_INTERPOLATEARMOR: //Since interpolatehealth is such a popular command + if(sc.CheckToken(TK_True)) + { + interpolateArmor = true; + } + else + { + sc.MustGetToken(TK_False); + interpolateArmor = false; + } + if(sc.CheckToken(',')) //speed + { + sc.MustGetToken(TK_IntConst); + this->armorInterpolationSpeed = sc.Number; + } + sc.MustGetToken(';'); + break; case SBARINFO_COMPLETEBORDER: //draws the border instead of an HOM if(sc.CheckToken(TK_True)) { @@ -492,6 +514,8 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) cmd.flags += DRAWNUMBER_SECRETS; else if(sc.Compare("totalsecrets")) cmd.flags += DRAWNUMBER_TOTALSECRETS; + else if(sc.Compare("armorclass")) + cmd.flags += DRAWNUMBER_ARMORCLASS; else { cmd.flags = DRAWNUMBER_INVENTORY; @@ -796,9 +820,14 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) cmd.flags += DRAWGEM_WIGGLE; else if(sc.Compare("translatable")) cmd.flags += DRAWGEM_TRANSLATABLE; + else if(sc.Compare("armor")) + cmd.flags += DRAWGEM_ARMOR; + else if(sc.Compare("reverse")) + cmd.flags += DRAWGEM_REVERSE; else sc.ScriptError("Unknown drawgem flag '%s'.", sc.String); - sc.MustGetToken(','); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); } sc.MustGetToken(TK_StringConst); //chain cmd.special = newImage(sc.String); @@ -994,10 +1023,6 @@ int SBarInfo::newImage(const char* patchname) { return -1; } -// if(strlen(patchname) > 8) -// { -// sc.ScriptError("Graphic names can not be greater then 8 characters long."); -// } for(unsigned int i = 0;i < this->Images.Size();i++) //did we already load it? { if(stricmp(this->Images[i], patchname) == 0) @@ -1038,8 +1063,10 @@ void SBarInfo::Init() { automapbar = false; interpolateHealth = false; + interpolateArmor = false; completeBorder = false; interpolationSpeed = 8; + armorInterpolationSpeed = 8; height = 0; } @@ -1243,10 +1270,8 @@ public: faceTimer = ST_FACETIME; rampageTimer = 0; faceIndex = 0; - if(SBarInfoScript->interpolateHealth) - { - oldHealth = 0; - } + oldHealth = 0; + oldArmor = 0; mugshotHealth = -1; lastPrefix = ""; weaponGrin = false; @@ -1337,11 +1362,34 @@ public: { if(oldHealth > CPlayer->health) { - oldHealth -= clamp((oldHealth - CPlayer->health) >> 2, 1, 8); + oldHealth -= clamp((oldHealth - CPlayer->health) >> 2, 1, SBarInfoScript->interpolationSpeed); } else if(oldHealth < CPlayer->health) { - oldHealth += clamp((CPlayer->health - oldHealth) >> 2, 1, 8); + oldHealth += clamp((CPlayer->health - oldHealth) >> 2, 1, SBarInfoScript->interpolationSpeed); + } + } + AInventory *armor = CPlayer->mo->FindInventory(); + if(armor == NULL) + { + oldArmor = 0; + } + else + { + if(!SBarInfoScript->interpolateArmor) + { + oldArmor = armor->Amount; + } + else + { + if(oldArmor > armor->Amount) + { + oldArmor -= clamp((oldArmor - armor->Amount) >> 2, 1, SBarInfoScript->armorInterpolationSpeed); + } + else if(oldArmor < armor->Amount) + { + oldArmor += clamp((armor->Amount - oldArmor) >> 2, 1, SBarInfoScript->armorInterpolationSpeed); + } } } if(artiflash) @@ -1437,11 +1485,17 @@ private: AAmmo *ammo1, *ammo2; int ammocount1, ammocount2; GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2); + ABasicArmor *armor = CPlayer->mo->FindInventory(); int health = CPlayer->mo->health; + int armorAmount = armor != NULL ? armor->Amount : 0; if(SBarInfoScript->interpolateHealth) { health = oldHealth; } + if(SBarInfoScript->interpolateArmor) + { + armorAmount = oldArmor; + } for(unsigned int i = 0;i < block.commands.Size();i++) { SBarInfoCommand& cmd = block.commands[i]; @@ -1522,7 +1576,6 @@ private: } else if((cmd.flags & DRAWIMAGE_ARMOR)) { - ABasicArmor *armor = CPlayer->mo->FindInventory(); if(armor != NULL && armor->Amount != 0) DrawGraphic(TexMan(armor->Icon), cmd.x, cmd.y, cmd.flags); } @@ -1558,8 +1611,7 @@ private: } else if(cmd.flags == DRAWNUMBER_ARMOR) { - AInventory *armor = CPlayer->mo->FindInventory(); - cmd.value = armor != NULL ? armor->Amount : 0; + cmd.value = armorAmount; } else if(cmd.flags == DRAWNUMBER_AMMO1) { @@ -1617,6 +1669,21 @@ private: cmd.value = level.found_secrets; else if(cmd.flags == DRAWNUMBER_TOTALSECRETS) cmd.value = level.total_secrets; + else if(cmd.flags == DRAWNUMBER_ARMORCLASS) + { + AHexenArmor *harmor = CPlayer->mo->FindInventory(); + if(harmor != NULL) + { + cmd.value = harmor->Slots[0] + harmor->Slots[1] + + harmor->Slots[2] + harmor->Slots[3] + harmor->Slots[4]; + } + //Hexen counts basic armor also so we should too. + if(armor != NULL) + { + cmd.value += armor->SavePercent; + } + cmd.value /= (5*FRACUNIT); + } else if(cmd.flags == DRAWNUMBER_INVENTORY) { AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); @@ -1728,8 +1795,7 @@ private: } else if(cmd.flags == DRAWNUMBER_ARMOR) { - AInventory *armor = CPlayer->mo->FindInventory(); - value = armor != NULL ? armor->Amount : 0; + value = armorAmount; if(!((cmd.special2 & DRAWBAR_COMPAREDEFAULTS) == DRAWBAR_COMPAREDEFAULTS)) { AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0])); //max comparer @@ -1816,12 +1882,17 @@ private: value = 0; } } + value = max - value; //invert since the new drawing method requires drawing the bg on the fg. if(max != 0 && value > 0) { value = (value << FRACBITS) / max; if(value > FRACUNIT) value = FRACUNIT; } + else if(max == 0 && value <= 0) + { + value = FRACUNIT; + } else { value = 0; @@ -1843,20 +1914,13 @@ private: screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); } - // Draw background - if (bg != NULL && bg->GetWidth() == fg->GetWidth() && bg->GetHeight() == fg->GetHeight()) - { - screen->DrawTexture(bg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - TAG_DONE); - } - else - { - screen->Clear(x, y, x + w, y + h, GPalette.BlackIndex, 0); - } + //Draw the whole foreground + screen->DrawTexture(fg, x, y, + DTA_DestWidth, w, + DTA_DestHeight, h, + TAG_DONE); - // Calc clipping rect for foreground + // Calc clipping rect for background cx = cmd.x + ST_X + cmd.special3; cy = cmd.y + ST_Y + cmd.special3; cw = fg->GetWidth() - cmd.special3 * 2; @@ -1867,7 +1931,7 @@ private: } if (horizontal) { - if (!reverse) + if (reverse) { // left to right cr = cx + FixedMul(cw, value); } @@ -1880,7 +1944,7 @@ private: } else { - if (!reverse) + if (reverse) { // bottom to top cb = cy + ch; cy += FixedMul(ch, FRACUNIT - value); @@ -1892,20 +1956,27 @@ private: cr = cx + cw; } - // Draw foreground - screen->DrawTexture(fg, x, y, - DTA_DestWidth, w, - DTA_DestHeight, h, - DTA_ClipLeft, cx, - DTA_ClipTop, cy, - DTA_ClipRight, cr, - DTA_ClipBottom, cb, - TAG_DONE); + // Draw background + if (bg != NULL && bg->GetWidth() == fg->GetWidth() && bg->GetHeight() == fg->GetHeight()) + { + screen->DrawTexture(bg, x, y, + DTA_DestWidth, w, + DTA_DestHeight, h, + DTA_ClipLeft, cx, + DTA_ClipTop, cy, + DTA_ClipRight, cr, + DTA_ClipBottom, cb, + TAG_DONE); + } + else + { + screen->Clear(cx, cy, cr, cb, GPalette.BlackIndex, 0); + } break; } case SBARINFO_DRAWGEM: { - int value = health; + int value = (cmd.flags & DRAWGEM_ARMOR) ? armorAmount : health; int max = 100; bool wiggle = false; bool translate = !!(cmd.flags & DRAWGEM_TRANSLATABLE); @@ -1919,6 +1990,7 @@ private: { value = 0; } + value = (cmd.flags & DRAWGEM_REVERSE) ? 100 - value : value; if(health != CPlayer->health) { wiggle = !!(cmd.flags & DRAWGEM_WIGGLE); @@ -2325,6 +2397,7 @@ private: int rampageTimer; int faceIndex; int oldHealth; + int oldArmor; int mugshotHealth; int chainWiggle; int artiflash; diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index f9fc6f86..f93ed725 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -46,8 +46,10 @@ struct SBarInfo SBarInfoBlock huds[6]; bool automapbar; bool interpolateHealth; + bool interpolateArmor; bool completeBorder; int interpolationSpeed; + int armorInterpolationSpeed; int height; int gameType; diff --git a/src/gl/gl_menu.cpp b/src/gl/gl_menu.cpp index 128619fd..c462a064 100644 --- a/src/gl/gl_menu.cpp +++ b/src/gl/gl_menu.cpp @@ -127,7 +127,7 @@ menuitem_t OpenGLItems[] = { { discrete, "Sprite billboard", {&gl_billboard_mode}, {2.0}, {0.0}, {0.0}, {BillboardModes} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { discrete, "Vertical Sync", {&vid_vsync}, {2.0}, {0.0}, {0.0}, {OnOff} }, -// { discrete, "Refresh rate", {&gl_vid_refreshHz}, {7.0}, {0.0}, {0.0}, {Hz} }, +// { discrete, "Refresh rate", {&vid_refreshrate}, {7.0}, {0.0}, {0.0}, {Hz} }, // { more, "Apply Refresh rate setting",{NULL+}, {7.0}, {0.0}, {0.0}, {(value_t *)ApplyRefresh} }, { discrete, "Rendering quality", {&gl_render_precise}, {2.0}, {0.0}, {0.0}, {Precision} }, { discrete, "Environment map on mirrors",{&gl_mirror_envmap}, {2.0}, {0.0}, {0.0}, {OnOff} }, diff --git a/src/gl/gl_scene.cpp b/src/gl/gl_scene.cpp index 2c5853cb..e6f375b1 100644 --- a/src/gl/gl_scene.cpp +++ b/src/gl/gl_scene.cpp @@ -908,7 +908,7 @@ void OpenGLFrameBuffer::WriteSavePic (player_t *player, FILE *file, int width, i byte * scr = (byte *)M_Malloc(width * height * 3); gl.ReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr); M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width*3); - free(scr); + M_Free(scr); } //----------------------------------------------------------------------------- diff --git a/src/info.h b/src/info.h index 60d3670d..13c6c4da 100644 --- a/src/info.h +++ b/src/info.h @@ -317,6 +317,7 @@ enum ADEF_Inventory_RespawnTics, ADEF_Inventory_FlagsSet, ADEF_Inventory_FlagsClear, + ADEF_Inventory_PickupFlash, ADEF_PuzzleItem_Number, // Identifies the puzzle item for UsePuzzleItem diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp index eb8ca256..93be7753 100644 --- a/src/infodefaults.cpp +++ b/src/infodefaults.cpp @@ -255,6 +255,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint) case ADEF_Inventory_FlagsSet: item->ItemFlags |= dataint; break; case ADEF_Inventory_FlagsClear: item->ItemFlags &= ~dataint; break; + case ADEF_Inventory_PickupFlash:if(dataint) { item->PickupFlash = fuglyname("PickupFlash"); } else { item->PickupFlash = NULL; } break; case ADEF_Inventory_Amount: item->Amount = dataint; break; case ADEF_Inventory_RespawnTics:item->RespawnTics = dataint; break; case ADEF_Inventory_MaxAmount: item->MaxAmount = dataint; break; diff --git a/src/infomacros.h b/src/infomacros.h index c103e8f8..1c7c2de1 100644 --- a/src/infomacros.h +++ b/src/infomacros.h @@ -297,6 +297,7 @@ public: #define PROP_Inventory_RespawnTics(x) ADD_WORD_PROP(ADEF_Inventory_RespawnTics,x) #define PROP_Inventory_FlagsSet(x) ADD_LONG_PROP(ADEF_Inventory_FlagsSet,x) #define PROP_Inventory_FlagsClear(x) ADD_LONG_PROP(ADEF_Inventory_FlagsClear,x) +#define PROP_Inventory_PickupFlash(x) ADD_BYTE_PROP(ADEF_Inventory_PickupFlash, x) #define PROP_PuzzleItem_Number(x) ADD_BYTE_PROP(ADEF_PuzzleItem_Number,x) diff --git a/src/m_alloc.cpp b/src/m_alloc.cpp index f448c9d9..897f2e54 100644 --- a/src/m_alloc.cpp +++ b/src/m_alloc.cpp @@ -1,9 +1,9 @@ /* ** m_alloc.cpp -** Wrappers for the malloc family of functions +** Wrappers for the malloc family of functions that count used bytes. ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -32,39 +32,91 @@ ** */ -#if !defined(_DEBUG) || !defined(_MSC_VER) - #include "i_system.h" -#include "m_alloc.h" +#include "stats.h" +#include -void *M_Malloc (size_t size) +ADD_STAT(mem) { - void *zone = malloc (size); - - if (!zone) - I_FatalError ("Could not malloc %u bytes", size); - - return zone; + FString out; + out.Format("Alloc: %uKB", (AllocBytes + 1023) >> 10); + return out; } -void *M_Calloc (size_t num, size_t size) -{ - void *zone = calloc (num, size); - - if (!zone) - I_FatalError ("Could not calloc %u bytes", num * size); - - return zone; -} - -void *M_Realloc (void *memblock, size_t size) -{ - void *zone = realloc (memblock, size); - - if (!zone) - I_FatalError ("Could not realloc %u bytes", size); - - return zone; -} +size_t AllocBytes; +#ifndef _MSC_VER +#define _NORMAL_BLOCK 0 +#define _malloc_dbg(s,b,f,l) malloc(s) +#define _realloc_dbg(p,s,b,f,l) realloc(p,s) #endif +#ifndef _WIN32 +#define _msize(p) malloc_usable_size(p) // from glibc/FreeBSD +#endif + +#ifndef _DEBUG +void *M_Malloc(size_t size) +{ + void *block = malloc(size); + + if (block == NULL) + I_FatalError("Could not malloc %u bytes", size); + + AllocBytes += _msize(block); + return block; +} + +void *M_Realloc(void *memblock, size_t size) +{ + if (memblock != NULL) + { + AllocBytes -= _msize(memblock); + } + void *block = realloc(memblock, size); + if (block == NULL) + { + I_FatalError("Could not realloc %u bytes", size); + } + AllocBytes += _msize(block); + return block; +} +#else +#ifdef _MSC_VER +#include +#endif + +void *M_Malloc_Dbg(size_t size, const char *file, int lineno) +{ + void *block = _malloc_dbg(size, _NORMAL_BLOCK, file, lineno); + + if (block == NULL) + I_FatalError("Could not malloc %u bytes", size); + + AllocBytes += _msize(block); + return block; +} + +void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) +{ + if (memblock != NULL) + { + AllocBytes -= _msize(memblock); + } + void *block = _realloc_dbg(memblock, size, _NORMAL_BLOCK, file, lineno); + if (block == NULL) + { + I_FatalError("Could not realloc %u bytes", size); + } + AllocBytes += _msize(block); + return block; +} +#endif + +void M_Free (void *block) +{ + if (block != NULL) + { + AllocBytes -= _msize(block); + free(block); + } +} diff --git a/src/m_alloc.h b/src/m_alloc.h index 2b18c7c3..8d7866a7 100644 --- a/src/m_alloc.h +++ b/src/m_alloc.h @@ -2,7 +2,7 @@ ** m_alloc.h ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -34,26 +34,26 @@ #ifndef __M_ALLOC_H__ #define __M_ALLOC_H__ -#if !defined(_DEBUG) || !defined(_MSC_VER) #include // These are the same as the same stdlib functions, -// except they bomb out with an error requester +// except they bomb out with a fatal error // when they can't get the memory. -void *M_Malloc (size_t size); -void *M_Calloc (size_t num, size_t size); -void *M_Realloc (void *memblock, size_t size); +#if defined(_DEBUG) +#define M_Malloc(s) M_Malloc_Dbg(s, __FILE__, __LINE__) +#define M_Realloc(p,s) M_Realloc_Dbg(p, s, __FILE__, __LINE__) +void *M_Malloc_Dbg (size_t size, const char *file, int lineno); +void *M_Realloc_Dbg (void *memblock, size_t size, const char *file, int lineno); #else - -#include -#include - -#define M_Malloc(size) malloc(size) -#define M_Calloc(num, size) calloc(num, size) -#define M_Realloc(memblock, size) realloc(memblock, size) - +void *M_Malloc (size_t size); +void *M_Realloc (void *memblock, size_t size); #endif +void M_Free (void *memblock); + +// Number of bytes currently allocated through M_Malloc/M_Realloc +extern size_t AllocBytes; + #endif //__M_ALLOC_H__ diff --git a/src/m_menu.cpp b/src/m_menu.cpp index aedd0978..6c1574f6 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -291,11 +291,11 @@ static oldmenu_t MainDef = // static oldmenuitem_t HereticMainMenu[] = { - {1,1,'n',"MNU_NEWGAME",M_NewGame, CR_UNTRANSLATED}, - {1,1,'o',"MNU_OPTIONS",M_Options, CR_UNTRANSLATED}, - {1,1,'f',"MNU_GAMEFILES",M_GameFiles, CR_UNTRANSLATED}, - {1,1,'i',"MNU_INFO",M_ReadThis, CR_UNTRANSLATED}, - {1,1,'q',"MNU_QUITGAME",M_QuitGame, CR_UNTRANSLATED} + {1,1,'n',"$MNU_NEWGAME",M_NewGame, CR_UNTRANSLATED}, + {1,1,'o',"$MNU_OPTIONS",M_Options, CR_UNTRANSLATED}, + {1,1,'f',"$MNU_GAMEFILES",M_GameFiles, CR_UNTRANSLATED}, + {1,1,'i',"$MNU_INFO",M_ReadThis, CR_UNTRANSLATED}, + {1,1,'q',"$MNU_QUITGAME",M_QuitGame, CR_UNTRANSLATED} }; static oldmenu_t HereticMainDef = @@ -312,10 +312,10 @@ static oldmenu_t HereticMainDef = // static oldmenuitem_t ClassItems[] = { - { 1,1, 'f', "MNU_FIGHTER", SCClass, CR_UNTRANSLATED }, - { 1,1, 'c', "MNU_CLERIC", SCClass, CR_UNTRANSLATED }, - { 1,1, 'm', "MNU_MAGE", SCClass, CR_UNTRANSLATED }, - { 1,1, 'r', "MNU_RANDOM", SCClass, CR_UNTRANSLATED } // [RH] + { 1,1, 'f', "$MNU_FIGHTER", SCClass, CR_UNTRANSLATED }, + { 1,1, 'c', "$MNU_CLERIC", SCClass, CR_UNTRANSLATED }, + { 1,1, 'm', "$MNU_MAGE", SCClass, CR_UNTRANSLATED }, + { 1,1, 'r', "$MNU_RANDOM", SCClass, CR_UNTRANSLATED } // [RH] }; static oldmenu_t ClassMenu = @@ -382,8 +382,8 @@ oldmenu_t EpiDef = // static oldmenuitem_t FilesItems[] = { - {1,1,'l',"MNU_LOADGAME",M_LoadGame, CR_UNTRANSLATED}, - {1,1,'s',"MNU_SAVEGAME",M_SaveGame, CR_UNTRANSLATED} + {1,1,'l',"$MNU_LOADGAME",M_LoadGame, CR_UNTRANSLATED}, + {1,1,'s',"$MNU_SAVEGAME",M_SaveGame, CR_UNTRANSLATED} }; static oldmenu_t FilesMenu = @@ -3208,8 +3208,9 @@ void M_Drawer () color = CR_RED; } } - screen->DrawText (color, x, y, - GStrings(currentMenu->menuitems[i].name), + const char *text = currentMenu->menuitems[i].name; + if (*text == '$') text = GStrings(text+1); + screen->DrawText (color, x, y, text, DTA_Clean, true, TAG_DONE); } else diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 7c432827..3909d32e 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -81,6 +81,7 @@ FGameConfigFile *GameConfig; CVAR(Bool, screenshot_quiet, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); CVAR(String, screenshot_type, "png", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); CVAR(String, screenshot_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); +EXTERN_CVAR(Bool, longsavemessages); extern void FreeKeySections(); @@ -721,7 +722,9 @@ void M_ScreenShot (const char *filename) if (!screenshot_quiet) { - Printf ("Captured %s\n", autoname.GetChars()); + int slash = -1; + if (!longsavemessages) slash = autoname.LastIndexOfAny(":/\\"); + Printf ("Captured %s\n", autoname.GetChars()+slash+1); } } else diff --git a/src/m_options.cpp b/src/m_options.cpp index bae1ab52..a765dec0 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -104,6 +104,8 @@ CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // Show messages has default, 0 = off, 1 = on CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, show_obituaries, true, CVAR_ARCHIVE) +EXTERN_CVAR (Bool, longsavemessages) +EXTERN_CVAR (Bool, screenshot_quiet) extern int skullAnimCounter; @@ -146,6 +148,11 @@ value_t OnOff[2] = { { 1.0, "On" } }; +value_t OffOn[2] = { + { 0.0, "On" }, + { 1.0, "Off" } +}; + menu_t *CurrentMenu; int CurrentItem; static const char *OldMessage; @@ -809,7 +816,10 @@ static menuitem_t MessagesItems[] = { { cdiscrete, "Critical Messages", {&msg2color}, {21.0}, {0.0}, {0.0}, {TextColors} }, { cdiscrete, "Chat Messages", {&msg3color}, {21.0}, {0.0}, {0.0}, {TextColors} }, { cdiscrete, "Team Messages", {&msg4color}, {21.0}, {0.0}, {0.0}, {TextColors} }, - { cdiscrete, "Centered Messages", {&msgmidcolor}, {21.0}, {0.0}, {0.0}, {TextColors} } + { cdiscrete, "Centered Messages", {&msgmidcolor}, {21.0}, {0.0}, {0.0}, {TextColors} }, + { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, + { discrete, "Screenshot messages", {&screenshot_quiet}, {2.0}, {0.0}, {0.0}, {OffOn} }, + { discrete, "Detailed save messages",{&longsavemessages}, {2.0}, {0.0}, {0.0}, {OnOff} }, }; menu_t MessagesMenu = diff --git a/src/name.cpp b/src/name.cpp index b8a7d123..eeb30420 100644 --- a/src/name.cpp +++ b/src/name.cpp @@ -270,13 +270,13 @@ FName::NameManager::~NameManager() for (block = Blocks; block != NULL; block = next) { next = block->NextBlock; - free (block); + M_Free (block); } Blocks = NULL; if (NameArray != NULL) { - free (NameArray); + M_Free (NameArray); NameArray = NULL; } NumNames = MaxNames = 0; diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index f4687c4a..1f7a5bd1 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -720,7 +720,7 @@ void P_CleanExtSectors() // destroy embedded objects (TArrays) extsectordata[i].extsector_t::~extsector_t(); } - free(extsectordata); + M_Free(extsectordata); extsectordata = NULL; } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f6c14f7d..a4256226 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3738,7 +3738,7 @@ void P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer) { // Give all cards in death match mode. p->mo->GiveDeathmatchInventory (); } - else if (multiplayer && state == PST_REBORN && oldactor != NULL) + else if ((multiplayer || (level.flags & LEVEL_ALLOWRESPAWN)) && state == PST_REBORN && oldactor != NULL) { // Special inventory handling for respawning in coop p->mo->FilterCoopRespawnInventory (oldactor); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index adc38def..d29d145b 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3434,7 +3434,7 @@ void P_FreeExtraLevelData() while (node != NULL) { msecnode_t *next = node->m_snext; - free (node); + M_Free (node); node = next; } headsecnode = NULL; diff --git a/src/p_switch.cpp b/src/p_switch.cpp index e6f4aea5..238b3dc9 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -121,8 +121,11 @@ public: { for(unsigned i=0;iIsDescendantOf (RUNTIME_CLASS (APlayerPawn))) { - Printf ("Invalid player class '%s'", argv[1]); + Printf ("Invalid player class '%s'\n", argv[1]); } else if (ti->Meta.GetMetaString (APMETA_DisplayName) == NULL) { - Printf ("Missing displayname for player class '%s'", argv[1]); + Printf ("Missing displayname for player class '%s'\n", argv[1]); } else { @@ -175,7 +175,7 @@ CCMD (addplayerclass) } else { - Printf ("Unknown flag '%s' for player class '%s'", argv[arg], argv[1]); + Printf ("Unknown flag '%s' for player class '%s'\n", argv[arg], argv[1]); } arg++; diff --git a/src/r_anim.cpp b/src/r_anim.cpp index f0786ed6..37b80fab 100644 --- a/src/r_anim.cpp +++ b/src/r_anim.cpp @@ -620,7 +620,7 @@ AnimArray::~AnimArray() { if ((*this)[i] != NULL) { - free ((*this)[i]); + M_Free ((*this)[i]); (*this)[i] = NULL; } } diff --git a/src/r_data.cpp b/src/r_data.cpp index 75a68205..e8d119a1 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -388,14 +388,14 @@ void R_DeinitData () // Free openings if (openings != NULL) { - free (openings); + M_Free (openings); openings = NULL; } // Free drawsegs if (drawsegs != NULL) { - free (drawsegs); + M_Free (drawsegs); drawsegs = NULL; } } diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 7e7c28e5..86b445b2 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -491,7 +491,8 @@ static visplane_t *new_visplane (unsigned hash) if (check == NULL) { - check = (visplane_t *)M_Calloc (1, sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); + check = (visplane_t *)M_Malloc (sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); + memset(check, 0, sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); check->bottom = &check->top[MAXWIDTH+2]; } else if (NULL == (freetail = freetail->next)) @@ -1637,7 +1638,7 @@ bool R_PlaneInitData () while (pl) { visplane_t *next = pl->next; - free (pl); + M_Free (pl); pl = next; } freetail = NULL; @@ -1650,7 +1651,7 @@ bool R_PlaneInitData () while (pl) { visplane_t *next = pl->next; - free (pl); + M_Free (pl); pl = next; } } diff --git a/src/r_translate.cpp b/src/r_translate.cpp index 2ea65daa..4c6f9771 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -78,7 +78,7 @@ void FRemapTable::Free() KillNative(); if (Remap != NULL) { - free(Remap); + M_Free(Remap); Remap = NULL; Palette = NULL; NumEntries = 0; diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 8527d25a..110d5b42 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -778,7 +778,7 @@ static void S_ClearSoundData() { FMusicVolume *me = MusicVolumes; MusicVolumes = me->Next; - delete me; + M_Free(me); } S_rnd.Clear(); diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 9de65367..8a1c8e60 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -154,7 +154,7 @@ struct FSoundSequencePtrArray : public TArray { for (unsigned int i = 0; i < Size(); ++i) { - free ((*this)[i]); + M_Free ((*this)[i]); } } }; @@ -463,7 +463,7 @@ void S_ParseSndSeq (int levellump) { if (Sequences[i]) { - free(Sequences[i]); + M_Free(Sequences[i]); } } Sequences.Clear(); @@ -496,7 +496,7 @@ void S_ParseSndSeq (int levellump) { if (Sequences[curseq]->SeqName == seqname) { - free (Sequences[curseq]); + M_Free (Sequences[curseq]); Sequences[curseq] = NULL; break; } diff --git a/src/sdl/sdlglvideo.cpp b/src/sdl/sdlglvideo.cpp index 49ff9e54..12eb4010 100644 --- a/src/sdl/sdlglvideo.cpp +++ b/src/sdl/sdlglvideo.cpp @@ -377,3 +377,7 @@ bool SDLGLFB::IsValid () return DFrameBuffer::IsValid() && Screen != NULL; } +void SDLGLFB::NewRefreshRate () +{ +} + diff --git a/src/sdl/sdlglvideo.h b/src/sdl/sdlglvideo.h index d0c32910..4f4fc13b 100644 --- a/src/sdl/sdlglvideo.h +++ b/src/sdl/sdlglvideo.h @@ -48,6 +48,8 @@ public: bool IsValid (); bool IsFullscreen (); + void NewRefreshRate (); + friend class SDLGLVideo; //[C] diff --git a/src/stringtable.cpp b/src/stringtable.cpp index 6968357f..f4108a5b 100644 --- a/src/stringtable.cpp +++ b/src/stringtable.cpp @@ -80,7 +80,7 @@ void FStringTable::FreeData () while (entry != NULL) { next = entry->Next; - free (entry); + M_Free (entry); entry = next; } } @@ -98,7 +98,7 @@ void FStringTable::FreeNonDehackedStrings () if (entry->PassNum != 0) { *pentry = next; - free (entry); + M_Free (entry); } else { @@ -254,7 +254,7 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p if (cmpval == 0 && entry->PassNum >= passnum) { *pentry = entry->Next; - free (entry); + M_Free (entry); entry = NULL; } if (entry == NULL || cmpval > 0) @@ -396,6 +396,6 @@ void FStringTable::SetString (const char *name, const char *newString) { *pentry = entry; entry->Next = oentry->Next; - free (oentry); + M_Free (oentry); } } diff --git a/src/svnrevision.h b/src/svnrevision.h index f59f6c27..ae381053 100644 --- a/src/svnrevision.h +++ b/src/svnrevision.h @@ -3,5 +3,5 @@ // This file was automatically generated by the // updaterevision tool. Do not edit by hand. -#define SVN_REVISION_STRING "748" -#define SVN_REVISION_NUMBER 748 +#define SVN_REVISION_STRING "755" +#define SVN_REVISION_NUMBER 755 diff --git a/src/tarray.h b/src/tarray.h index d34e0533..44ea0537 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -89,7 +89,7 @@ public: { DoDelete (0, Count-1); } - free (Array); + M_Free (Array); } DoCopy (other); } @@ -103,7 +103,7 @@ public: { DoDelete (0, Count-1); } - free (Array); + M_Free (Array); Array = NULL; Count = 0; Most = 0; @@ -178,7 +178,7 @@ public: { if (Array != NULL) { - free (Array); + M_Free (Array); Array = NULL; } } @@ -604,7 +604,7 @@ protected: Nodes[i].~Node(); } } - free(Nodes); + M_Free(Nodes); Nodes = NULL; Size = 0; LastFree = NULL; @@ -628,7 +628,7 @@ protected: nold[i].~Node(); } } - free(nold); + M_Free(nold); } void Rehash() diff --git a/src/textures/rawpagetexture.cpp b/src/textures/rawpagetexture.cpp index 4cb80f63..5ff6f69f 100644 --- a/src/textures/rawpagetexture.cpp +++ b/src/textures/rawpagetexture.cpp @@ -99,15 +99,15 @@ bool FRawPageTexture::Check(FileReader & data) } if (gapAtStart || (x != width)) { - free (foo); + M_Free (foo); return true; } - free(foo); + M_Free(foo); return false; } else { - free (foo); + M_Free (foo); return true; } } diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 2799d46f..9889e0dd 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -266,7 +266,7 @@ FTexture::Span **FTexture::CreateSpans (const BYTE *pixels) const void FTexture::FreeSpans (Span **spans) const { - free (spans); + M_Free (spans); } void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int ypos, const BYTE *translation) diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 47f2f629..8246b1cd 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -492,10 +492,12 @@ void ParseActor(FScanner &sc) // fields in the weapons // //========================================================================== + void FinishThingdef() { unsigned int i; bool isRuntimeActor=false; + int errorcount=0; for (i = 0;i < PClass::m_Types.Size(); i++) { @@ -517,6 +519,26 @@ void FinishThingdef() GetDefaultByType(ti)->flags &=~MF_COUNTKILL; } + if (ti->IsDescendantOf(RUNTIME_CLASS(AInventory))) + { + AInventory * defaults=(AInventory *)ti->Defaults; + fuglyname v; + + v = defaults->PickupFlash; + if (v != NAME_None && v.IsValidName()) + { + defaults->PickupFlash = PClass::FindClass(v); + if (isRuntimeActor) + { + if (!defaults->PickupFlash) + { + Printf("Unknown pickup flash '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; + } + } + } + } + // the typeinfo properties of weapons have to be fixed here after all actors have been declared if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { @@ -531,11 +553,13 @@ void FinishThingdef() { if (!defaults->AmmoType1) { - I_Error("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } else if (defaults->AmmoType1->ParentClass != RUNTIME_CLASS(AAmmo)) { - I_Error("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } } } @@ -548,11 +572,13 @@ void FinishThingdef() { if (!defaults->AmmoType2) { - I_Error("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } else if (defaults->AmmoType2->ParentClass != RUNTIME_CLASS(AAmmo)) { - I_Error("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } } } @@ -565,11 +591,13 @@ void FinishThingdef() { if (!defaults->SisterWeaponType) { - I_Error("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } else if (!defaults->SisterWeaponType->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { - I_Error("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } } } @@ -586,10 +614,26 @@ void FinishThingdef() if (ready || select || deselect || fire) { // Do some consistency checks. If these states are undefined the weapon cannot work! - if (!ready) I_Error("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars()); - if (!select) I_Error("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars()); - if (!deselect) I_Error("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars()); - if (!fire) I_Error("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars()); + if (!ready) + { + Printf("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars()); + errorcount++; + } + if (!select) + { + Printf("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars()); + errorcount++; + } + if (!deselect) + { + Printf("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars()); + errorcount++; + } + if (!fire) + { + Printf("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars()); + errorcount++; + } } } @@ -606,15 +650,21 @@ void FinishThingdef() defaults->WeaponClass = PClass::FindClass(v); if (!defaults->WeaponClass) { - I_Error("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } else if (!defaults->WeaponClass->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { - I_Error("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + Printf("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars()); + errorcount++; } } } } + if (errorcount > 0) + { + I_Error("%d errors during actor postprocessing", errorcount); + } // Since these are defined in DECORATE now the table has to be initialized here. for(int i=0;i<31;i++) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 22e5f0b9..874ed1dd 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -247,12 +247,14 @@ static flagdef InventoryFlags[] = DEFINE_FLAG(IF, INVBAR, AInventory, ItemFlags), DEFINE_FLAG(IF, HUBPOWER, AInventory, ItemFlags), DEFINE_FLAG(IF, INTERHUBSTRIP, AInventory, ItemFlags), - DEFINE_FLAG(IF, PICKUPFLASH, AInventory, ItemFlags), DEFINE_FLAG(IF, ALWAYSPICKUP, AInventory, ItemFlags), DEFINE_FLAG(IF, FANCYPICKUPSOUND, AInventory, ItemFlags), DEFINE_FLAG(IF, BIGPOWERUP, AInventory, ItemFlags), DEFINE_FLAG(IF, KEEPDEPLETED, AInventory, ItemFlags), DEFINE_FLAG(IF, IGNORESKILL, AInventory, ItemFlags), + + DEFINE_DEPRECATED_FLAG(PICKUPFLASH, AInventory, 5), + }; static flagdef WeaponFlags[] = @@ -398,6 +400,16 @@ static void HandleDeprecatedFlags(AActor *defaults, bool set, int index) case 4: // LONGMELEERANGE defaults->meleethreshold = set? 196*FRACUNIT : 0; break; + case 5: // INVENTORY.PICKUPFLASH + if (set) + { + static_cast(defaults)->PickupFlash = fuglyname("PickupFlash"); + } + else + { + static_cast(defaults)->PickupFlash = NULL; + } + break; default: break; // silence GCC } @@ -1816,6 +1828,15 @@ static void InventoryDefMaxAmount (FScanner &sc, AInventory *defaults, Baggage & } +//========================================================================== +// +//========================================================================== +static void InventoryPickupflash (FScanner &sc, AInventory *defaults, Baggage &bag) +{ + sc.MustGetString(); + defaults->PickupFlash = fuglyname(sc.String); +} + //========================================================================== // //========================================================================== @@ -2500,6 +2521,7 @@ static const ActorProps props[] = { "inventory.givequest", (apf)InventoryGiveQuest, RUNTIME_CLASS(AInventory) }, { "inventory.icon", (apf)InventoryIcon, RUNTIME_CLASS(AInventory) }, { "inventory.maxamount", (apf)InventoryMaxAmount, RUNTIME_CLASS(AInventory) }, + { "inventory.pickupflash", (apf)InventoryPickupflash, RUNTIME_CLASS(AInventory) }, { "inventory.pickupmessage", (apf)InventoryPickupmsg, RUNTIME_CLASS(AInventory) }, { "inventory.pickupsound", (apf)InventoryPickupsound, RUNTIME_CLASS(AInventory) }, { "inventory.respawntics", (apf)InventoryRespawntics, RUNTIME_CLASS(AInventory) }, diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 169fc2ea..56127a93 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -331,7 +331,7 @@ void InstallStates(FActorInfo *info, AActor *defaults) if (info->StateList != NULL) { info->StateList->Destroy(); - free(info->StateList); + M_Free(info->StateList); } info->StateList = CreateStateLabelList(StateLabels); diff --git a/src/v_video.cpp b/src/v_video.cpp index 34d7e03b..00d40c1d 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -150,6 +150,7 @@ CVAR (Int, vid_defbits, 8, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, vid_fps, false, 0) CVAR (Bool, ticker, false, 0) CVAR (Int, vid_showpalette, 0, 0) + CUSTOM_CVAR (Bool, vid_vsync, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (screen != NULL) @@ -158,6 +159,14 @@ CUSTOM_CVAR (Bool, vid_vsync, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) } } +CUSTOM_CVAR (Int, vid_refreshrate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + if (screen != NULL) + { + screen->NewRefreshRate(); + } +} + CUSTOM_CVAR (Float, dimamount, 0.2f, CVAR_ARCHIVE) { if (self < 0.f) @@ -1075,6 +1084,19 @@ void DFrameBuffer::SetVSync (bool vsync) { } +//========================================================================== +// +// DFrameBuffer :: NewRefreshRate +// +// Sets the fullscreen display to the new refresh rate in vid_refreshrate, +// if possible. +// +//========================================================================== + +void DFrameBuffer::NewRefreshRate () +{ +} + //========================================================================== // // DFrameBuffer :: SetBlendingRect diff --git a/src/v_video.h b/src/v_video.h index 3eaff383..8f38f15d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -344,6 +344,9 @@ public: // Changes the vsync setting, if supported by the device. virtual void SetVSync (bool vsync); + // Tells the device to recreate itself with the new setting from vid_refreshrate. + virtual void NewRefreshRate (); + // Set the rect defining the area effected by blending. virtual void SetBlendingRect (int x1, int y1, int x2, int y2); diff --git a/src/version.h b/src/version.h index 8282c58b..45536382 100644 --- a/src/version.h +++ b/src/version.h @@ -64,7 +64,7 @@ // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x209 +#define DEMOGAMEVERSION 0x20A // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. diff --git a/src/w_wad.cpp b/src/w_wad.cpp index fc4b5d42..4f431ef4 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -228,7 +228,7 @@ void FWadCollection::InitMultipleFiles (wadlist_t **filenames) DefaultExtension (name, ".wad"); AddFile (name); - free (*filenames); + M_Free (*filenames); *filenames = next; // The first two files are always zdoom.wad and the IWAD, which @@ -305,7 +305,7 @@ static DWORD Zip_FindCentralDir(FileReader * fin) FileSize = fin->Tell(); uMaxBack = MIN(0xffff, FileSize); - buf = (unsigned char*)M_Malloc(BUFREADCOMMENT+4); + buf = (unsigned char*)malloc(BUFREADCOMMENT+4); if (buf == NULL) return 0; uBackRead = 4; diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 4dd813dd..b2c8a65c 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -197,6 +197,7 @@ EXTERN_CVAR (Bool, fullscreen) EXTERN_CVAR (Float, Gamma) EXTERN_CVAR (Bool, vid_vsync) EXTERN_CVAR (Float, transsouls) +EXTERN_CVAR (Int, vid_refreshrate) extern IDirect3D9 *D3D; @@ -304,7 +305,19 @@ D3DFB::D3DFB (int width, int height, bool fullscreen) if (FAILED(D3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &d3dpp, &D3DDevice))) { - D3DDevice = NULL; + if (d3dpp.FullScreen_RefreshRateInHz != 0) + { + d3dpp.FullScreen_RefreshRateInHz = 0; + if (FAILED(hr = D3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, + D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &d3dpp, &D3DDevice))) + { + if (FAILED(D3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &d3dpp, &D3DDevice))) + { + D3DDevice = NULL; + } + } + } } } if (D3DDevice != NULL) @@ -386,6 +399,10 @@ void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, b pp->BackBufferFormat = fullscreen ? D3DFMT_A8R8G8B8 : D3DFMT_UNKNOWN; pp->hDeviceWindow = Window; pp->PresentationInterval = vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + if (fullscreen) + { + pp->FullScreen_RefreshRateInHz = vid_refreshrate; + } } bool D3DFB::CreateResources () @@ -531,7 +548,18 @@ bool D3DFB::Reset () FillPresentParameters (&d3dpp, !Windowed, VSync); if (!SUCCEEDED(D3DDevice->Reset (&d3dpp))) { - return false; + if (d3dpp.FullScreen_RefreshRateInHz != 0) + { + d3dpp.FullScreen_RefreshRateInHz = 0; + if (!SUCCEEDED(D3DDevice->Reset (&d3dpp))) + { + return false; + } + } + else + { + return false; + } } LOG("Device was reset\n"); if (!CreateFBTexture() || !CreateVertexes()) @@ -1090,6 +1118,14 @@ void D3DFB::SetVSync (bool vsync) } } +void D3DFB::NewRefreshRate () +{ + if (!Windowed) + { + Reset(); + } +} + void D3DFB::Blank () { // Only used by movie player, which isn't working with D3D9 yet. diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index c362173a..a1738cc1 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -80,6 +80,7 @@ extern bool VidResizing; EXTERN_CVAR (Bool, fullscreen) EXTERN_CVAR (Float, Gamma) +EXTERN_CVAR (Int, vid_refreshrate) extern IDirectDraw2 *DDraw; @@ -224,6 +225,7 @@ bool DDrawFB::CreateResources () DDSURFACEDESC ddsd = { sizeof(ddsd), }; HRESULT hr; int bits; + int refresh; BufferCount = 1; @@ -241,13 +243,18 @@ bool DDrawFB::CreateResources () break; } } - hr = DDraw->SetDisplayMode (Width, TrueHeight, bits = vid_displaybits, 0, 0); + hr = DDraw->SetDisplayMode (Width, TrueHeight, bits = vid_displaybits, vid_refreshrate, 0); if (FAILED(hr)) { + hr = DDraw->SetDisplayMode (Width, TrueHeight, bits = vid_displaybits, 0, 0); bits = 32; while (FAILED(hr) && bits >= 8) { - hr = DDraw->SetDisplayMode (Width, Height, bits, 0, 0); + hr = DDraw->SetDisplayMode (Width, Height, bits, vid_refreshrate, 0); + if (FAILED(hr)) + { + hr = DDraw->SetDisplayMode (Width, Height, bits, 0, 0); + } bits -= 8; } if (FAILED(hr)) @@ -1270,6 +1277,13 @@ void DDrawFB::SetVSync (bool vsync) FlipFlags = vsync ? DDFLIP_WAIT : DDFLIP_WAIT|DDFLIP_NOVSYNC; } +void DDrawFB::NewRefreshRate() +{ + if (!Windowed) + { + NeedResRecreate = true; + } +} void DDrawFB::Blank () { diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 43511136..10a832fc 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -1437,7 +1437,7 @@ BYTE *ST_Util_BitsForBitmap (BITMAPINFO *bitmap_info) void ST_Util_FreeBitmap (BITMAPINFO *bitmap_info) { - free (bitmap_info); + M_Free (bitmap_info); } //========================================================================== diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index 231898e1..036e3016 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -27,7 +27,6 @@ RenderContext gl; CVAR(Bool, gl_vid_allowsoftware, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); EXTERN_CVAR(Bool, gl_vid_compatibility) -CVAR(Int, gl_vid_refreshHz, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); Win32GLVideo::Win32GLVideo(int parm) : m_Modes(NULL), m_IsFullscreen(false) { @@ -192,7 +191,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool fs, DF m_DisplayBits = gl_vid_compatibility? 16:32; m_DisplayHz = 60; - if (gl_vid_refreshHz == 0) + if (vid_refreshrate == 0) { for (ModeInfo *mode = m_Modes; mode != NULL; mode = mode->next) { @@ -204,7 +203,7 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool fs, DF } else { - m_DisplayHz = gl_vid_refreshHz; + m_DisplayHz = vid_refreshrate; } if (old != NULL) @@ -390,3 +389,11 @@ void Win32GLFrameBuffer::SetVSync (bool vsync) if (gl.SetVSync!=NULL) gl.SetVSync(vsync); } +void Win32GLFRameBuffer::NewRefreshRate () +{ + if (m_Fullscreen) + { + setmodeneeded = true; + } +} + diff --git a/src/win32/win32gliface.h b/src/win32/win32gliface.h index 25b14797..07939899 100644 --- a/src/win32/win32gliface.h +++ b/src/win32/win32gliface.h @@ -28,7 +28,6 @@ EXTERN_CVAR(Int, vid_defheight); EXTERN_CVAR(Int, vid_renderer); EXTERN_CVAR(Bool, gl_vid_allowsoftware); -EXTERN_CVAR(Int, gl_vid_refreshHz); extern HINSTANCE g_hInst; extern HWND Window; @@ -101,6 +100,8 @@ public: virtual void ReleaseResources (); void SetVSync (bool vsync); + void NewRefreshRate (); + int GetTrueHeight() { return static_cast(Video)->GetTrueHeight(); } diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 7468e072..c54e4d40 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -159,6 +159,7 @@ public: int QueryNewPalette (); void PaletteChanged (); void SetVSync (bool vsync); + void NewRefreshRate(); HRESULT GetHR (); void Blank (); @@ -240,6 +241,7 @@ public: void Blank (); bool PaintToWindow (); void SetVSync (bool vsync); + void NewRefreshRate(); void GetScreenshotBuffer(const BYTE *&buffer, int &pitch, ESSType &color_type); void ReleaseScreenshotBuffer(); void SetBlendingRect (int x1, int y1, int x2, int y2); diff --git a/wadsrc/invgeml1.png b/wadsrc/invgeml1.png index 65e1a2f7..37d71eb3 100644 Binary files a/wadsrc/invgeml1.png and b/wadsrc/invgeml1.png differ diff --git a/wadsrc/invgeml2.png b/wadsrc/invgeml2.png index 0b274050..3617d58b 100644 Binary files a/wadsrc/invgeml2.png and b/wadsrc/invgeml2.png differ diff --git a/wadsrc/invgemr1.png b/wadsrc/invgemr1.png index e0c2c693..f66b8383 100644 Binary files a/wadsrc/invgemr1.png and b/wadsrc/invgemr1.png differ diff --git a/wadsrc/invgemr2.png b/wadsrc/invgemr2.png index b1ac0c21..9b229459 100644 Binary files a/wadsrc/invgemr2.png and b/wadsrc/invgemr2.png differ