Recoded weapon restrictions, and made new way of storing data. (Arrays)

* Removed ZMarket as an external plugin (to be integrated next commit)
* Updated weapon configs, removed weapongroups.txt and moved weapons.txt to root zr config folder.
* Moved offset finding to respective module, made new forward *OnOffsetsFound.
* Updated weapons&hitgroups config file format to match playerclass.txt
* Updated translations.
* Recoded weapon restrict menu, commented out all zadmin options that don't quite work.
* Added weaponammo module (not finished but existent)
* Started zmarket module.
This commit is contained in:
Greyscale
2009-05-28 23:43:15 -07:00
parent b1f8de9526
commit 0f8206596a
34 changed files with 2565 additions and 2673 deletions

View File

@ -22,23 +22,31 @@
#define CONFIG_FILE_ALIAS_DOWNLOADS "downloads"
#define CONFIG_FILE_ALIAS_CLASSES "classes"
#define CONFIG_FILE_ALIAS_WEAPONS "weapons"
#define CONFIG_FILE_ALIAS_WEAPONGROUPS "weapongroups"
#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
{
ConfigInvalid = -1, /** Invalid config file. */
ConfigModels, /** <sourcemod root>/configs/zr/models.txt (default) */
ConfigDownloads, /** <sourcemod root>/configs/zr/downloads.txt (default) */
ConfigClasses, /** <sourcemod root>/configs/zr/playerclasses.txt (default) */
ConfigWeapons, /** <sourcemod root>/configs/zr/weapons/weapons.txt/weapongroups.txt (default) */
ConfigHitgroups, /** <sourcemod root>/configs/zr/hitgroups.txt (default) */
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) */
}
/**
@ -46,11 +54,12 @@ enum ConfigFile
*/
enum ConfigData
{
bool:ConfigLoaded, /** True if config is loaded, false if not. */
Function:ConfigReloadFunc, /** Function to call to reload config. */
Handle:ConfigHandle, /** Handle of the config file. */
String:ConfigPath[PLATFORM_MAX_PATH], /** Full path to config file. */
String:ConfigAlias[CONFIG_MAX_LENGTH], /** Config file alias, used for client interaction. */
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. */
}
/**
@ -61,24 +70,14 @@ new g_ConfigData[ConfigFile][ConfigData];
/**
* Actions to use when working on key/values.
*/
enum ConfigKeyvalueAction
enum ConfigKvAction
{
ConfigKVCreate, /** Create a key. */
ConfigKVDelete, /** Delete a key. */
ConfigKVSet, /** Modify setting of a key. */
ConfigKVGet, /** Get setting of a key. */
KvAction_Create, /** Create a key. */
KvAction_KVDelete, /** Delete a key. */
KvAction_KVSet, /** Modify setting of a key. */
KvAction_KVGet, /** Get setting of a key. */
}
/**
* @section Global data handle initializations.
*/
new Handle:arrayModelsList = INVALID_HANDLE;
new Handle:arrayDownloadsList = INVALID_HANDLE;
new Handle:kvClassData = INVALID_HANDLE;
new Handle:kvWeapons = INVALID_HANDLE;
new Handle:kvWeaponGroups = INVALID_HANDLE;
new Handle:kvHitgroups = INVALID_HANDLE;
/**
* Create commands related to config here.
*/
@ -157,20 +156,20 @@ ConfigOnModulesLoaded()
/**
* 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 loaded True if the config should be loaded, false if not.
* @param path (Optional) Full path to config file.
* @param alias (Optional) Config file alias, used for client interaction.
* @param alias Config file alias, used for client interaction.
*/
stock ConfigRegisterConfig(ConfigFile:file, bool:loaded, Function:reloadfunc, Handle:filehandle = INVALID_HANDLE, const String:path[] = "", const String:alias[] = "")
stock ConfigRegisterConfig(ConfigFile:file, ConfigStructure:structure, const String:alias[] = "")
{
// Copy file info to data container.
g_ConfigData[file][ConfigLoaded] = loaded;
g_ConfigData[file][ConfigHandle] = filehandle;
g_ConfigData[file][ConfigReloadFunc] = reloadfunc;
strcopy(g_ConfigData[file][ConfigPath], PLATFORM_MAX_PATH, path);
strcopy(g_ConfigData[file][ConfigAlias], CONFIG_MAX_LENGTH, alias);
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);
}
/**
@ -182,7 +181,19 @@ stock ConfigRegisterConfig(ConfigFile:file, bool:loaded, Function:reloadfunc, Ha
stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded)
{
// Set load state.
g_ConfigData[config][ConfigLoaded] = loaded;
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;
}
/**
@ -194,7 +205,7 @@ stock ConfigSetConfigLoaded(ConfigFile:config, bool:loaded)
stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc)
{
// Set reload function.
g_ConfigData[config][ConfigReloadFunc] = reloadfunc;
g_ConfigData[config][Data_ReloadFunc] = reloadfunc;
}
/**
@ -206,7 +217,7 @@ stock ConfigSetConfigReloadFunc(ConfigFile:config, Function:reloadfunc)
stock ConfigSetConfigHandle(ConfigFile:config, Handle:file)
{
// Set file handle.
g_ConfigData[config][ConfigHandle] = file;
g_ConfigData[config][Data_Handle] = file;
}
/**
@ -218,7 +229,7 @@ stock ConfigSetConfigHandle(ConfigFile:config, Handle:file)
stock ConfigSetConfigPath(ConfigFile:config, const String:path[])
{
// Set config file path.
strcopy(g_ConfigData[config][ConfigPath], PLATFORM_MAX_PATH, path);
strcopy(g_ConfigData[config][Data_Path], PLATFORM_MAX_PATH, path);
}
/**
@ -230,7 +241,7 @@ stock ConfigSetConfigPath(ConfigFile:config, const String:path[])
stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[])
{
// Set config alias.
strcopy(g_ConfigData[config][ConfigAlias], CONFIG_MAX_LENGTH, alias);
strcopy(g_ConfigData[config][Data_Alias], CONFIG_MAX_LENGTH, alias);
}
/**
@ -242,7 +253,19 @@ stock ConfigSetConfigAlias(ConfigFile:config, const String:alias[])
stock bool:ConfigIsConfigLoaded(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][ConfigLoaded];
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];
}
/**
@ -254,7 +277,7 @@ stock bool:ConfigIsConfigLoaded(ConfigFile:config)
stock Function:ConfigGetConfigReloadFunc(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][ConfigReloadFunc];
return g_ConfigData[config][Data_ReloadFunc];
}
/**
@ -266,7 +289,7 @@ stock Function:ConfigGetConfigReloadFunc(ConfigFile:config)
stock Handle:ConfigGetConfigHandle(ConfigFile:config)
{
// Return load status.
return g_ConfigData[config][ConfigHandle];
return g_ConfigData[config][Data_Handle];
}
/**
@ -277,7 +300,7 @@ stock Handle:ConfigGetConfigHandle(ConfigFile:config)
stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen)
{
// Copy path to return string.
strcopy(path, maxlen, g_ConfigData[config][ConfigPath]);
strcopy(path, maxlen, g_ConfigData[config][Data_Path]);
}
/**
@ -288,7 +311,133 @@ stock ConfigGetConfigPath(ConfigFile:config, String:path[], maxlen)
stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
{
// Copy alias to return string.
strcopy(alias, maxlen, g_ConfigData[config][ConfigAlias]);
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.
* @return True if file was loaded successfuly, false otherwise.
*/
stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
{
// 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 handle is still open, then close it before creating a new one.
if (arrayConfig != INVALID_HANDLE)
{
CloseHandle(arrayConfig);
}
// Create array in handle.
arrayConfig = CreateArray(CONFIG_MAX_LENGTH);
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(!IsEndOfFile(hFile))
{
// Get current line text.
ReadFileLine(hFile, line, sizeof(line));
// If line contains a ";", then stop.
if (StrContains(line, ";") > -1)
{
continue;
}
// 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(CONFIG_MAX_LENGTH);
// 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;
}
/**
@ -297,7 +446,7 @@ stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
* @param config The config file entry to reload.
* @return True if the config is loaded, false if not.
*/
stock bool:ConfigReloadFile(ConfigFile:config)
stock bool:ConfigReloadConfig(ConfigFile:config)
{
// If file isn't loaded, then stop.
new bool:loaded = ConfigIsConfigLoaded(config);
@ -309,6 +458,7 @@ stock bool:ConfigReloadFile(ConfigFile:config)
// 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.
@ -323,12 +473,169 @@ stock bool:ConfigReloadFile(ConfigFile:config)
// Call reload function.
Call_StartFunction(GetMyHandle(), reloadfunc);
Call_PushCell(config);
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.
*
@ -374,94 +681,11 @@ stock ConfigFile:ConfigAliasToConfigFile(const String:alias[])
}
// Invalid config file.
return ConfigInvalid;
return File_Invalid;
}
/**
* 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 index of config to modify. (see CONFIG_FILE_* defines)
* @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 gotten value.
* @return True if the change was made successfully, false otherwise.
*/
stock bool:ConfigKeyvalueTreeSetting(config, ConfigKeyvalueAction:action = ConfigKVCreate, const String:keys[][], keysMax, const String:setting[] = "", String:value[] = "", maxlen = 0)
{
// Retrieve handle of the keyvalue tree.
new Handle:hConfig = ConfigGetConfigHandle(config);
// If handle is invalid, then stop.
if (hConfig == INVALID_HANDLE)
{
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 == Create));
// If exists is false, then stop.
if (!exists)
{
// Key doesn't exist.
return false;
}
}
switch(action)
{
case ConfigKVCreate:
{
if (!setting[0] || !value[0])
{
// We created the key already, so return true.
return true;
}
// Set new value.
KvSetString(hConfig, setting, value);
}
case ConfigKVDelete:
{
// Return deletion result.
return KvDeleteKey(hConfig, setting);
}
case ConfigKVSet:
{
// Set new value.
KvSetString(hConfig, setting, value);
}
case ConfigKVGet:
{
// Get current value.
KvGetString(hConfig, setting, value, maxlen);
}
}
// We successfully set or got the value.
return true;
}
/**
* Command callback (zr_reloadconfig)
* Command callback (zr_config_reload)
* Reloads a config file and forwards event to modules.
*
* @param client The client index.
@ -472,7 +696,7 @@ public Action:ConfigReloadCommand(client, argc)
// If not enough arguments given, then stop.
if (argc < 1)
{
TranslationReplyToCommand(client, "Config command reload syntax", CONFIG_FILE_ALIAS_MODELS, CONFIG_FILE_ALIAS_DOWNLOADS, CONFIG_FILE_ALIAS_CLASSES, CONFIG_FILE_ALIAS_WEAPONS, CONFIG_FILE_ALIAS_WEAPONGROUPS, CONFIG_FILE_ALIAS_HITGROUPS);
TranslationReplyToCommand(client, "Config command reload syntax", CONFIG_FILE_ALIAS_MODELS, CONFIG_FILE_ALIAS_DOWNLOADS, CONFIG_FILE_ALIAS_CLASSES, CONFIG_FILE_ALIAS_WEAPONS, CONFIG_FILE_ALIAS_HITGROUPS);
return Plugin_Handled;
}
@ -482,14 +706,14 @@ public Action:ConfigReloadCommand(client, argc)
// If alias is invalid, then stop.
new ConfigFile:config = ConfigAliasToConfigFile(arg1);
if (config == ConfigInvalid)
if (config == File_Invalid)
{
TranslationReplyToCommand(client, "Config command reload invalid", arg1);
return Plugin_Handled;
}
// Reload config file.
new bool:loaded = ConfigReloadFile(config);
new bool:loaded = ConfigReloadConfig(config);
// Get config file path.
decl String:path[PLATFORM_MAX_PATH];
@ -506,7 +730,7 @@ public Action:ConfigReloadCommand(client, argc)
}
/**
* Command callback (zr_reloadconfigall)
* Command callback (zr_config_reloadall)
* Reloads all config files and forwards event to all modules.
*
* @param client The client index.
@ -523,7 +747,7 @@ public Action:ConfigReloadAllCommand(client, argc)
for (new x = 0; x < sizeof(g_ConfigData); x++)
{
// Reload config file.
new bool:successful = ConfigReloadFile(ConfigFile:x);
new bool:successful = ConfigReloadConfig(ConfigFile:x);
// Get config's alias.
ConfigGetConfigAlias(ConfigFile:x, configalias, sizeof(configalias));
@ -539,71 +763,13 @@ public Action:ConfigReloadAllCommand(client, argc)
}
}
/**
* Iterate through a file and store each line in an array.
*
* @param path Path to the file to iterate through.
* @return The handle of the array, don't forget to call CloseHandle
* on it when finished!
*/
Handle:ConfigLinesToArray(const String:path[])
{
new Handle:arrayLines = CreateArray(PLATFORM_MAX_PATH);
decl String:line[PLATFORM_MAX_PATH];
// Open file.
new Handle:hFile = OpenFile(path, "r");
// If file couldn't be opened, then stop.
if (hFile == INVALID_HANDLE)
{
return INVALID_HANDLE;
}
while(!IsEndOfFile(hFile))
{
// Get current line text.
ReadFileLine(hFile, line, sizeof(line));
// If line contains a ";", then stop.
if (StrContains(line, ";") > -1)
{
continue;
}
// 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(arrayLines, line);
}
// Close file handle.
CloseHandle(hFile);
// Return array handle.
return arrayLines;
}
/**
* Converts string of "yes" or "no" to a boolean value.
*
* @param option "yes" or "no" string to be converted.
* @return True if string is "yes", false otherwise.
*/
bool:ConfigSettingToBool(const String:option[])
stock bool:ConfigSettingToBool(const String:option[])
{
// If option is equal to "yes," then return true.
if (StrEqual(option, "yes", false))
@ -620,9 +786,9 @@ bool:ConfigSettingToBool(const String:option[])
*
* @param bOption True/false value to be converted to "yes"/"no", respectively.
* @param option Destination string buffer to store "yes" or "no" in.
* @param maxlen Length of destination string buffer (can't be more than 4).
* @param maxlen Length of destination string buffer (wont't be more than 4).
*/
ConfigBoolToSetting(bool:bOption, String:option[], maxlen)
stock ConfigBoolToSetting(bool:bOption, String:option[], maxlen)
{
// If option is true, then copy "yes" to return string.
if (bOption)
@ -635,3 +801,11 @@ ConfigBoolToSetting(bool:bOption, String:option[], maxlen)
strcopy(option, maxlen, "no");
}
}
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);
}