sm-zombiereloaded-3/src/zr/config.inc

958 lines
30 KiB
SourcePawn

/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: config.inc
* Type: Core
* Description: Config API and executing.
*
* Copyright (C) 2009-2013 Greyscale, Richard Helgeby
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================================
*/
/*
Using config API:
-Before any of these helper functions can be used on a config file you must
"register" the module handling the data.
Example:
ConfigRegisterConfig(File_Example, Structure_List, "example");
* The first parameter of this call is the config file we want to register.
this needs to be listed in the "ConfigFile" enum in config.inc.
* The second parameter is the structure of the config file we are loading.
The supported structures are listed in the "ConfigStructure" enum in config.inc
* The last parameter is the file's alias. Or what we use to refer to the
config file from a non-developer's point of view. For example zr_config_reload
requires the file alias to identify the config file the user wants to reload.
-Next we need to define the config file's path. To do this we first need to
retrieve the path file from cvar.
Example:
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_EXAMPLE, pathexample);
* The first parameter is the cvar handle we are looking into.
* The second parameter is the string to store the path in.
* The return value is true if the file exists on the server, false if not.
If the file doesn't exist, handle it. (Print log, stop plugin, etc)
Then store it in the config file data.
Example:
ConfigSetConfigPath(File_Example, pathexample);
* The first parameter is the config file we want to set path to.
* The second parameter is the path we want to set to the config file.
-Next we load config file and prepare its nested array structure.
Example:
new bool:success = ConfigLoadConfig(File_Example, arrayExample);
* The first parameter is the config file we want to load.
* The second parameter is the array handle we want to prepare data structure in.
* The return value is true if the file was successfully loaded, false if the
config file couldn't be loaded. (Invalid data, missing quotes, brackets, etc)
-Next validate the config so far, stopping if no data was found or if ConfigLoadConfig
returned false.
-Then cache the config file data into the arrays (only for Keyvalue structures)
by iterating through the data and pushing the values into the array.
-Validate the values of the data.
-Lastly we need to set specific info to the module now that it has successfully
loaded.
Example:
ConfigSetConfigLoaded(File_Example, true);
ConfigSetConfigReloadFunc(File_Example, GetFunctionByName(GetMyHandle(), "ExampleOnConfigReload"));
ConfigSetConfigHandle(File_Example, arrayExample);
These functions will modify the config file data for other things to use.
(such as zr_config_reload)
* The first function call will set the loaded state of the config file to
true, failing to do this will cause the config module to think your
config file isn't loaded, therefore causing some undesired erroring.
* The second function sets the reload function of the config file. This
function will be called upon its config file being reloaded.
* The third function stores the array handle for use by other parts of the
module.
*/
/**
* The max length of any config string value.
*/
#define CONFIG_MAX_LENGTH 32
/**
* @section Config file reference aliases.
*/
#define CONFIG_FILE_ALIAS_MODELS "models"
#define CONFIG_FILE_ALIAS_DOWNLOADS "downloads"
#define CONFIG_FILE_ALIAS_CLASSES "classes"
#define CONFIG_FILE_ALIAS_WEAPONS "weapons"
#define CONFIG_FILE_ALIAS_HITGROUPS "hitgroups"
/**
* @endsection
*/
/**
* List of config formats used by the plugin.
*/
enum ConfigStructure
{
Structure_List, /** Config is structured as a simple list of strings. */
Structure_Keyvalue, /** Config is a keyvalue structure */
}
/**
* List of config files used by the plugin.
*/
enum ConfigFile
{
File_Invalid = -1, /** Invalid config file. */
File_Models, /** <sourcemod root>/configs/zr/models.txt (default) */
File_Downloads, /** <sourcemod root>/configs/zr/downloads.txt (default) */
File_Classes, /** <sourcemod root>/configs/zr/playerclasses.txt (default) */
File_Weapons, /** <sourcemod root>/configs/zr/weapons.txt (default) */
File_Hitgroups, /** <sourcemod root>/configs/zr/hitgroups.txt (default) */
}
/**
* Data container for each config file.
*/
enum ConfigData
{
bool: Data_Loaded, /** True if config is loaded, false if not. */
ConfigStructure: Data_Structure, /** Format of the config */
Function: Data_ReloadFunc, /** Function to call to reload config. */
Handle: Data_Handle, /** Handle of the config file. */
String: Data_Path[PLATFORM_MAX_PATH], /** Full path to config file. */
String: Data_Alias[CONFIG_MAX_LENGTH], /** Config file alias, used for client interaction. */
}
/**
* Stores all config data.
*/
new g_ConfigData[ConfigFile][ConfigData];
/**
* Actions to use when working on key/values.
*/
enum ConfigKvAction
{
KvAction_Create, /** Create a key. */
KvAction_KVDelete, /** Delete a key. */
KvAction_KVSet, /** Modify setting of a key. */
KvAction_KVGet, /** Get setting of a key. */
}
/**
* Create commands related to config here.
*/
ConfigOnCommandsCreate()
{
// Create config admin commands.
RegConsoleCmd("zr_config_reload", ConfigReloadCommand, "Reloads a config file. Usage: zr_config_reload <file alias>");
RegConsoleCmd("zr_config_reloadall", ConfigReloadAllCommand, "Reloads all config files. Usage: zr_config_reloadall");
}
/**
* Load plugin configs. Executes map configs.
*/
ConfigLoad()
{
decl String:mapconfig[PLATFORM_MAX_PATH];
// Get map name and format into config path.
GetCurrentMap(mapconfig, sizeof(mapconfig));
Format(mapconfig, sizeof(mapconfig), "sourcemod/zombiereloaded/%s.cfg", mapconfig);
// Prepend cfg to path.
decl String:path[PLATFORM_MAX_PATH];
Format(path, sizeof(path), "cfg/%s", mapconfig);
// File doesn't exist, then stop.
if (!FileExists(path))
{
return;
}
// Execute config file.
ServerCommand("exec %s", mapconfig);
// Log action.
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Config, "Map Configs", "Executed map config file: %s", path);
}
/**
* Executed when modules are done loading. After all init calls in
* OnConfigsExecuted.
*
* Executes post map configs if they exist.
*/
ConfigOnModulesLoaded()
{
decl String:mapname[256];
decl String:mapconfig[PLATFORM_MAX_PATH];
decl String:path[PLATFORM_MAX_PATH];
// Get map name and format into config path.
GetCurrentMap(mapname, sizeof(mapname));
Format(mapconfig, sizeof(mapconfig), "sourcemod/zombiereloaded/%s.post.cfg", mapname);
// Prepend cfg to path.
Format(path, sizeof(path), "cfg/%s", mapconfig);
// Workaround for bug 3083 in SourceMod compiler. Having FileExist directly
// in the if in this function makes it crash. Storing the result in a
// boolean first works.
// Check if the file exist.
new bool:cfgexists = FileExists(path);
if (!cfgexists)
{
// File doesn't exist, then stop.
return;
}
// Execute config file.
ServerCommand("exec %s", mapconfig);
// Log action.
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Config, "Post Map Configs", "Executed post map config file: %s", path);
}
/**
* Used by modules that rely on configs to register their config file info.
* (Don't forget to set 'loaded' to 'true' (ConfigSetConfigLoaded) in config load function)
*
* @param file Config file entry to register.
* @param alias Config file alias, used for client interaction.
*/
stock ConfigRegisterConfig(ConfigFile:file, ConfigStructure:structure, const String:alias[] = "")
{
// Copy file info to data container.
g_ConfigData[file][Data_Loaded] = false;
g_ConfigData[file][Data_Structure] = structure;
g_ConfigData[file][Data_Handle] = INVALID_HANDLE;
g_ConfigData[file][Data_ReloadFunc] = INVALID_FUNCTION;
strcopy(g_ConfigData[file][Data_Path], PLATFORM_MAX_PATH, "");
strcopy(g_ConfigData[file][Data_Alias], CONFIG_MAX_LENGTH, alias);
}
/**
* Set the loaded state of a config file entry.
*
* @param config Config file to set load state of.
* @param loaded True to set as loaded, false to set as unloaded.
*/
stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded)
{
// Set load state.
g_ConfigData[config][Data_Loaded] = loaded;
}
/**
* Set the structure type of a config file entry.
*
* @param config Config file to set structure type of.
* @param structure Structure to set as.
*/
stock ConfigSetConfigStructure(ConfigFile:config, ConfigStructure:structure)
{
// Set load state.
g_ConfigData[config][Data_Structure] = structure;
}
/**
* Set the reload function of a config file entry.
*
* @param config Config file to set reload function of.
* @param reloadfunc Reload function.
*/
stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc)
{
// Set reload function.
g_ConfigData[config][Data_ReloadFunc] = reloadfunc;
}
/**
* Set the file handle of a config file entry.
*
* @param config Config file to set handle of.
* @param loaded Config file handle.
*/
stock ConfigSetConfigHandle(ConfigFile:config, Handle:file)
{
// Set file handle.
g_ConfigData[config][Data_Handle] = file;
}
/**
* Set the config file path of a config file entry.
*
* @param config Config file to set file path of.
* @param loaded File path.
*/
stock ConfigSetConfigPath(ConfigFile:config, const String:path[])
{
// Set config file path.
strcopy(g_ConfigData[config][Data_Path], PLATFORM_MAX_PATH, path);
}
/**
* Set the alias of a config file entry.
*
* @param config Config file to set alias of.
* @param loaded Alias of the config file entry.
*/
stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[])
{
// Set config alias.
strcopy(g_ConfigData[config][Data_Alias], CONFIG_MAX_LENGTH, alias);
}
/**
* Returns if a config was successfully loaded.
*
* @param config Config file to check load status of.
* @return True if config is loaded, false otherwise.
*/
stock bool:ConfigIsConfigLoaded(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][Data_Loaded];
}
/**
* Returns config's structure type.
*
* @param config Config file to get structure type of.
* @return Config structure type.
*/
stock ConfigStructure:ConfigGetConfigStructure(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][Data_Structure];
}
/**
* Returns config's reload function.
*
* @param config Config file to get reload function of.
* @return Config reload function.
*/
stock Function:ConfigGetConfigReloadFunc(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][Data_ReloadFunc];
}
/**
* Returns config's file handle.
*
* @param config Config file to get file handle of.
* @return Config file handle.
*/
stock Handle:ConfigGetConfigHandle(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][Data_Handle];
}
/**
* Returns the path for a given config file entry.
*
* @param config Config file to get path of. (see ConfigFile enum)
*/
stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen)
{
// Copy path to return string.
strcopy(path, maxlen, g_ConfigData[config][Data_Path]);
}
/**
* Returns the alias for a given config file entry.
*
* @param config Config file to get alias of. (see ConfigFile enum)
*/
stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
{
// Copy alias to return string.
strcopy(alias, maxlen, g_ConfigData[config][Data_Alias]);
}
/**
* Loads a config file and sets up a nested array type data storage.
*
* @param config The config file to load.
* @param arrayConfig Handle of the main array containing file data.
* @param blocksize The max length of the contained strings.
* @return True if file was loaded successfuly, false otherwise.
*/
stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig, blocksize = CONFIG_MAX_LENGTH)
{
// Get config's structure.
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// Get config's alias
decl String:configalias[CONFIG_MAX_LENGTH];
ConfigGetConfigAlias(config, configalias, sizeof(configalias));
// Get config's file path.
decl String:configpath[PLATFORM_MAX_PATH];
ConfigGetConfigPath(config, configpath, sizeof(configpath));
// If array hasn't been created, then create.
if (arrayConfig == INVALID_HANDLE)
{
// Create array in handle.
arrayConfig = CreateArray(blocksize);
}
switch(structure)
{
case Structure_List:
{
// Open file.
new Handle:hFile;
new success = ConfigOpenConfigFile(config, hFile);
// If config file failed to open, then stop.
if (!success)
{
return false;
}
// Clear out array.
ClearArray(arrayConfig);
decl String:line[PLATFORM_MAX_PATH];
while(ReadFileLine(hFile, line, sizeof(line)))
{
// Cut out comments at the end of a line.
if (StrContains(line, "//") > -1)
{
SplitString(line, "//", line, sizeof(line));
}
// Trim off whitespace.
TrimString(line);
// If line is empty, then stop.
if (!line[0])
{
continue;
}
// Push line into array.
PushArrayString(arrayConfig, line);
}
// We're done this file, so now we can destory it from memory.
CloseHandle(hFile);
return true;
}
case Structure_Keyvalue:
{
// Open file.
new Handle:hKeyvalue;
new success = ConfigOpenConfigFile(config, hKeyvalue);
// If config file failed to open, then stop.
if (!success)
{
return false;
}
// Destroy all old data.
ConfigClearKvArray(arrayConfig);
if (KvGotoFirstSubKey(hKeyvalue))
{
do
{
// Create new array to store information for config entry.
new Handle:arrayConfigEntry = CreateArray(blocksize);
// Push the key name into the config entry's array.
decl String:keyname[CONFIG_MAX_LENGTH];
KvGetSectionName(hKeyvalue, keyname, sizeof(keyname));
PushArrayString(arrayConfigEntry, keyname); // Index: 0
// Store this handle in the main array.
PushArrayCell(arrayConfig, arrayConfigEntry);
} while(KvGotoNextKey(hKeyvalue));
}
// We're done this file for now, so now we can destory it from memory.
CloseHandle(hKeyvalue);
return true;
}
}
return false;
}
/**
* Reload a config file.
*
* @param config The config file entry to reload.
* @return True if the config is loaded, false if not.
*/
stock bool:ConfigReloadConfig(ConfigFile:config)
{
// If file isn't loaded, then stop.
new bool:loaded = ConfigIsConfigLoaded(config);
if (!loaded)
{
return false;
}
// Call reload function
new Function:reloadfunc = ConfigGetConfigReloadFunc(config);
// This should never be true unless someone has tampered with the code.
if (reloadfunc == INVALID_FUNCTION)
{
// Get config alias.
decl String:configalias[CONFIG_MAX_LENGTH];
ConfigGetConfigAlias(config, configalias, sizeof(configalias));
// Print reload failure to logs.
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Config, "Reload Function", "Invalid reload function for config: \"%s\"", configalias);
return true;
}
// Call reload function.
Call_StartFunction(GetMyHandle(), reloadfunc);
Call_Finish();
return true;
}
/**
* Opens a config file with appropriate method.
*
* @param config The config file.
* @param structure The structure of the config file.
* @param hConfig The handle of the opened file.
*/
stock bool:ConfigOpenConfigFile(ConfigFile:config, &Handle:hConfig)
{
// Get config's structure
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// Get config's file path.
decl String:configpath[PLATFORM_MAX_PATH];
ConfigGetConfigPath(config, configpath, sizeof(configpath));
// Get config's alias
decl String:configalias[CONFIG_MAX_LENGTH];
ConfigGetConfigAlias(config, configalias, sizeof(configalias));
switch(structure)
{
case Structure_List:
{
// Open file.
hConfig = OpenFile(configpath, "r");
// If file couldn't be opened, then stop.
if (hConfig == INVALID_HANDLE)
{
return false;
}
return true;
}
case Structure_Keyvalue:
{
hConfig = CreateKeyValues(configalias);
return FileToKeyValues(hConfig, configpath);
}
}
return false;
}
/**
* Creates, deletes, sets, or gets any key/setting of any ZR config keyvalue file in memory.
* Only use when interacting with a command or manipulating single keys/values,
* using this function everywhere would be EXTREMELY inefficient.
*
* @param config Config file to modify.
* @param action Action to perform on keyvalue tree. (see enum ConfigKeyvalueAction)
* @param keys Array containing keys to traverse into.
* @param keysMax The size of the 'keys' array.
* @param setting (Optional) The name of the setting to modify.
* @param value (Optional) The new value to set.
* @param maxlen (Optional) The maxlength of the retrieved value.
* @return True if the change was made successfully, false otherwise.
*/
stock bool:ConfigKeyvalueTreeSetting(ConfigFile:config, ConfigKvAction:action = KvAction_Create, const String:keys[][], keysMax, const String:setting[] = "", String:value[] = "", maxlen = 0)
{
// Get config file's structure.
new ConfigStructure:structure = ConfigGetConfigStructure(config);
// If the config is any other structure beside keyvalue, then stop.
if (structure != Structure_Keyvalue)
{
return false;
}
// Retrieve handle of the keyvalue tree.
new Handle:hConfig;
new bool:success = ConfigOpenConfigFile(config, hConfig);
// If the file couldn't be opened, then stop.
if (!success)
{
return false;
}
// Rewind keyvalue tree.
KvRewind(hConfig);
// x = keys index.
// Traverse into the keygroup, stop if it fails.
for (new x = 0; x < keysMax; x++)
{
// If key is empty, then break the loop.
if (!keys[x][0])
{
break;
}
// Try to jump to next level in the transversal stack, create key if specified.
new bool:exists = KvJumpToKey(hConfig, keys[x], (action == KvAction_Create));
// If exists is false, then stop.
if (!exists)
{
// Key doesn't exist.
return false;
}
}
switch(action)
{
case KvAction_Create:
{
if (!setting[0] || !value[0])
{
// We created the key already, so return true.
return true;
}
// Set new value.
KvSetString(hConfig, setting, value);
}
case KvAction_Delete:
{
// Return deletion result.
return KvDeleteKey(hConfig, setting);
}
case KvAction_Set:
{
// Set new value.
KvSetString(hConfig, setting, value);
}
case KvAction_Get:
{
// Get current value.
KvGetString(hConfig, setting, value, maxlen);
}
}
// We successfully set or got the value.
return true;
}
/**
* Destroy all array handles within an array, and clear main array.
*
* @param arrayKv The array converted from a keyvalue structure.
*/
ConfigClearKvArray(Handle:arrayKv)
{
// x = array index
new size = GetArraySize(arrayKv);
for (new x = 0; x < size; x++)
{
// Destroy nested arrays.
new Handle:arrayKvKey = GetArrayCell(arrayKv, x);
CloseHandle(arrayKvKey);
}
// Now that all data within has been destroyed, we can clear the main array.
ClearArray(arrayKv);
}
/**
* Load config file.
*
* @param file The cvar define of the path to the file.
* @return True if the file exists, false if not.
*/
stock bool:ConfigGetCvarFilePath(CvarsList:cvar, String:path[])
{
// Get cvar's path.
decl String:filepath[PLATFORM_MAX_PATH];
GetConVarString(Handle:g_hCvarsList[cvar], filepath, sizeof(filepath));
// Build full path in return string.
BuildPath(Path_SM, path, PLATFORM_MAX_PATH, filepath);
return FileExists(path);
}
/**
* Finds a config file entry, (see ConfigFile enum) for a given alias.
*
* @param alias The alias to find config file entry of.
* @return Config file entry, ConfigInvalid is returned if alias was not found.
*/
stock ConfigFile:ConfigAliasToConfigFile(const String:alias[])
{
decl String:checkalias[CONFIG_MAX_LENGTH];
// x = config file entry index.
for (new x = 0; x < sizeof(g_ConfigData); x++)
{
// Get config alias.
ConfigGetConfigAlias(ConfigFile:x, checkalias, sizeof(checkalias));
// If alias doesn't match, then stop.
if (!StrEqual(alias, checkalias, false))
{
continue;
}
// Return config file entry.
return ConfigFile:x;
}
// Invalid config file.
return File_Invalid;
}
/**
* Command callback (zr_config_reload)
* Reloads a config file and forwards event to modules.
*
* @param client The client index.
* @param argc Argument count.
*/
public Action:ConfigReloadCommand(client, argc)
{
// Check if privileged.
if (!ZRIsClientPrivileged(client, OperationType_Configuration))
{
TranslationReplyToCommand(client, "No access to command");
return Plugin_Handled;
}
// If not enough arguments given, then stop.
if (argc < 1)
{
TranslationReplyToCommand(client, "Config command reload syntax");
TranslationReplyToCommand(client, "Config command reload related commands");
TranslationPrintToConsole(client, "Config command reload syntax aliases", CONFIG_FILE_ALIAS_MODELS, CONFIG_FILE_ALIAS_DOWNLOADS, CONFIG_FILE_ALIAS_CLASSES, CONFIG_FILE_ALIAS_WEAPONS, CONFIG_FILE_ALIAS_HITGROUPS);
return Plugin_Handled;
}
decl String:filealias[CONFIG_MAX_LENGTH];
decl String:path[PLATFORM_MAX_PATH];
decl String:logmessage[LOG_MAX_LENGTH_FILE];
new args = GetCmdArgs();
for (new x = 1; x <= args; x++)
{
// Get alias to restrict.
GetCmdArg(x, filealias, sizeof(filealias));
// If alias is invalid, then stop.
new ConfigFile:config = ConfigAliasToConfigFile(filealias);
if (config == File_Invalid)
{
TranslationReplyToCommand(client, "Config command reload invalid", filealias);
return Plugin_Handled;
}
// Reload config file.
new bool:loaded = ConfigReloadConfig(config);
// Get config file path.
ConfigGetConfigPath(config, path, sizeof(path));
// Format log message
Format(logmessage, sizeof(logmessage), "Admin \"%L\" reloaded config file \"%s\". (zr_config_reload)", client, path);
// If file isn't loaded then tell client, then stop.
if (!loaded)
{
TranslationReplyToCommand(client, "Config command reload not loaded", filealias);
// Format a failed attempt string to the end of the log message.
Format(logmessage, sizeof(logmessage), "%s -- attempt failed, config file not loaded", logmessage);
}
// Log action to game events.
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_Config, "Reload Config", logmessage);
}
return Plugin_Handled;
}
/**
* Command callback (zr_config_reloadall)
* Reloads all config files and forwards event to all modules.
*
* @param client The client index.
* @param argc Argument count.
*/
public Action:ConfigReloadAllCommand(client, argc)
{
// Check if privileged.
if (!ZRIsClientPrivileged(client, OperationType_Configuration))
{
TranslationReplyToCommand(client, "No access to command");
return Plugin_Handled;
}
// Begin statistics.
TranslationReplyToCommand(client, "Config command reload all stats begin");
decl String:configalias[CONFIG_MAX_LENGTH];
// x = config file entry index.
for (new x = 0; x < sizeof(g_ConfigData); x++)
{
// Reload config file.
new bool:successful = ConfigReloadConfig(ConfigFile:x);
// Get config's alias.
ConfigGetConfigAlias(ConfigFile:x, configalias, sizeof(configalias));
if (successful)
{
TranslationReplyToCommand(client, "Config command reload all stats successful", configalias);
}
else
{
TranslationReplyToCommand(client, "Config command reload all stats failed", configalias);
}
}
// Log action to game events.
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_Config, "Reload All Config", "Admin \"%L\" reloaded all config files.", client);
return Plugin_Handled;
}
/**
* Converts string of "yes/on" or "no/off" to a boolean value. Always uses english as yes/no/on/off language.
*
* @param option "yes/on" or "no/off" string to be converted.
* @return True if string is "yes", false otherwise.
*/
stock bool:ConfigSettingToBool(const String:option[])
{
// If option is equal to "yes," then return true.
if (StrEqual(option, "yes", false) || StrEqual(option, "on", false) || StrEqual(option, "1", false))
{
return true;
}
// Option isn't yes.
return false;
}
/**
* Converts boolean value to "yes" or "no".
*
* @param bOption True/false value to be converted to "yes/on"/"no/off", respectively.
* @param option Destination string buffer to store "yes/on" or "no/off" in.
* @param maxlen Length of destination string buffer.
* @param yesno When true, returns "yes/no", false returns "on/off."
* @param target The target to use as translation language.
*/
stock ConfigBoolToSetting(bool:bOption, String:option[], maxlen, bool:yesno = true, target = LANG_SERVER)
{
decl String:t_yes[16], String:t_on[32];
decl String:t_no[16], String:t_off[32];
SetGlobalTransTarget(target);
// Get the yes/no translations for the target.
Format(t_yes, sizeof(t_yes), "%t", "Yes"); Format(t_on, sizeof(t_on), "%t", "On");
Format(t_no, sizeof(t_no), "%t", "No"); Format(t_off, sizeof(t_off), "%t", "Off");
// If option is true, then copy "yes" to return string.
if (bOption)
{
yesno ? strcopy(option, maxlen, t_yes) : strcopy(option, maxlen, t_on);
}
// If option is false, then copy "no" to return string.
else
{
yesno ? strcopy(option, maxlen, t_no) : strcopy(option, maxlen, t_off);
}
}
/**
* Returns a "yes/no" string from config as a bool.
*
* @param kv The keyvalue handle.
* @param key The keyname the value is under.
* @param defaultvalue (Optional) Value to return if setting is missing.
*/
stock bool:ConfigKvGetStringBool(Handle:kv, const String:key[], const String:defaultvalue[] = "yes")
{
decl String:value[CONFIG_MAX_LENGTH];
KvGetString(kv, key, value, sizeof(value), defaultvalue);
return ConfigSettingToBool(value);
}