diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 36e3d576b..c8f1ee4c6 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1488,6 +1488,44 @@ FBaseCVar *FindCVarSub (const char *var_name, int namelen) return var; } +FBaseCVar *GetCVar(AActor *activator, const char *cvarname) +{ + FBaseCVar *cvar = FindCVar(cvarname, nullptr); + // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return nullptr. + if (cvar == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + else + { + // For userinfo cvars, redirect to GetUserCVar + if (cvar->GetFlags() & CVAR_USERINFO) + { + if (activator == nullptr || activator->player == nullptr) + { + return nullptr; + } + return GetUserCVar(int(activator->player - players), cvarname); + } + return cvar; + } +} + +FBaseCVar *GetUserCVar(int playernum, const char *cvarname) +{ + if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) + { + return nullptr; + } + FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); + FBaseCVar *cvar; + if (cvar_p == nullptr || (cvar = *cvar_p) == nullptr || (cvar->GetFlags() & CVAR_IGNORE)) + { + return nullptr; + } + return cvar; +} + //=========================================================================== // // C_CreateCVar diff --git a/src/c_cvars.h b/src/c_cvars.h index 59a3208d1..be7676e89 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -186,6 +186,10 @@ void C_BackupCVars (void); FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); FBaseCVar *FindCVarSub (const char *var_name, int namelen); +// Used for ACS and DECORATE. +FBaseCVar *GetCVar(AActor *activator, const char *cvarname); +FBaseCVar *GetUserCVar(int playernum, const char *cvarname); + // Create a new cvar with the specified name and type FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, DWORD flags); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index ca5e41757..29c9fe8fe 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4657,7 +4657,11 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) { UCVarValue val; - if (is_string) + if (cvar == nullptr) + { + return 0; + } + else if (is_string) { val = cvar->GetGenericRep(CVAR_String); return GlobalACSStrings.AddString(val.String); @@ -4674,44 +4678,6 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) } } -static int GetUserCVar(int playernum, const char *cvarname, bool is_string) -{ - if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) - { - return 0; - } - FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); - FBaseCVar *cvar; - if (cvar_p == NULL || (cvar = *cvar_p) == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - return DoGetCVar(cvar, is_string); -} - -static int GetCVar(AActor *activator, const char *cvarname, bool is_string) -{ - FBaseCVar *cvar = FindCVar(cvarname, NULL); - // Either the cvar doesn't exist, or it's for a mod that isn't loaded, so return 0. - if (cvar == NULL || (cvar->GetFlags() & CVAR_IGNORE)) - { - return 0; - } - else - { - // For userinfo cvars, redirect to GetUserCVar - if (cvar->GetFlags() & CVAR_USERINFO) - { - if (activator == NULL || activator->player == NULL) - { - return 0; - } - return GetUserCVar(int(activator->player - players), cvarname, is_string); - } - return DoGetCVar(cvar, is_string); - } -} - static int SetUserCVar(int playernum, const char *cvarname, int value, bool is_string) { if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) @@ -5396,7 +5362,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetCVarString: if (argCount == 1) { - return GetCVar(activator, FBehavior::StaticLookupString(args[0]), true); + return DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(args[0])), true); } break; @@ -5417,14 +5383,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args) case ACSF_GetUserCVar: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), false); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), false); } break; case ACSF_GetUserCVarString: if (argCount == 2) { - return GetUserCVar(args[0], FBehavior::StaticLookupString(args[1]), true); + return DoGetCVar(GetUserCVar(args[0], FBehavior::StaticLookupString(args[1])), true); } break; @@ -9132,7 +9098,7 @@ scriptwait: break; case PCD_GETCVAR: - STACK(1) = GetCVar(activator, FBehavior::StaticLookupString(STACK(1)), false); + STACK(1) = DoGetCVar(GetCVar(activator, FBehavior::StaticLookupString(STACK(1))), false); break; case PCD_SETHUDSIZE: diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 80e8226f6..dbbb12f6a 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -513,6 +513,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCrouchFactor) return 0; } +//========================================================================== +// +// GetCVar +// +// NON-ACTION function that works like ACS's GetCVar. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetCVar) +{ + if (numret > 0) + { + assert(ret != nullptr); + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(cvarname); + + FBaseCVar *cvar = GetCVar(self, cvarname); + if (cvar == nullptr) + { + ret->SetFloat(0); + } + else + { + ret->SetFloat(cvar->GetGenericRep(CVAR_Float).Float); + } + return 1; + } + return 0; +} + //=========================================================================== // // __decorate_internal_state__ diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 6606f8a49..5c46d0d4b 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -47,6 +47,7 @@ ACTOR Actor native //: Thinker native int GetSpawnHealth(); native int GetGibHealth(); native float GetCrouchFactor(int ptr = AAPTR_PLAYER1); + native float GetCVar(string cvar); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support.