+- Allied Modders en español (https://amxmodx-es.com)
+-- Foro: AMX Mod X - Scripting (https://amxmodx-es.com/Forum-AMX-Mod-X-Scripting)
+--- Foro: Aportes (https://amxmodx-es.com/Forum-Aportes)
+--- Tema: [API] Settings System (/Thread-API-Settings-System)
Buenas noches, hacia mucho tiempo que no pasaba por aqui.
Queria compartir con ustedes esta API que diseñe hacia unas semanas ya.
• ¿EN QUE CONSISTE?
Basicamente esta API nos permite interactuar con archivos de configuracion de una manera mas sencilla.
Los "archivos de configuracion" son aquellos utilizados por la mayoria de los MODs para customizar sus modos de juego de manera "exterior", sin necesidad de re-compilar el MOD (en conclusion = archivos INI, aunque puede ser usado con cualquier archivo permitido).
No esta demas decir que la idea de esta API esta fundamentada en base a esto: Settings API (load/save data to INI files). Sin embargo la manera en como lo hace es muy diferente, optando por cargar los archivos en memoria, en lugar de leerlos cada vez que se requiere cargar un dato (para mayor informacion, leer el codigo fuente).
• ¿COMO SE UTILIZA?
Actualmente cuenta con 7 natives, las cuales son las siguientes:
params: - szFileName[]: name of file that will be open
return: int - -1: file can't be open (the reason will be shown) - 0+: file's id (it is not the same that fopen() returns) ================================================== */ native settings_open_file(const szFileName[]);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &bValueOut: variable to store result (bool-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_bool(const iFileId, const szSection[], const szKey[], &bool:bValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &iValueOut: variable to store result (int-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_int(const iFileId, const szSection[], const szKey[], &iValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &fValueOut: variable to store result (float-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_float(const iFileId, const szSection[], const szKey[], &Float:fValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - szValueOut: buffer to store result - iValueOut: max buffer's length
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_string(const iFileId, const szSection[], const szKey[], szValueOut[], const iValueOutLen);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &aValueOut: dyn-array to store result (dynamic array)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_darray(const iFileId, const iDynamicArrayType, const szKey[], const szSection[], &Array:aValueOut);
return: bool - true: file has been closed successfully - false: file can't be closed (the reason will be shown) ================================================== */ native bool:settings_close_file(const iFileId);
Creo que las mismas son auto-explicables.
De igual manera, cualquier duda no teman en postearla.
• CODIGO
Código PHP:
/*=============================================================================================== SETTINGS API SYSTEM ===============================================================================================*/
// this will close (free) all files data // keep in mind that when you used this // you will need to RE-ALLOCATE files data again // I mean: // ALLOCATE_FILES_LIST() // ALLOCATE_FILES_FAST_LIT() const CLOSE_ALL_FILES = -(1<<30);
enum file_s { bool:em_bFileClosed, em_iFileSectionsCount, em_szFileName[MAX_FILE_NAME_LEN], Array:em_aFileSectionsList, Trie:em_tFileSectionsFastList // same of above, but for sections ids (fast-lookup) };
enum section_s { em_iSectionKeysCount, em_szSectionName[MAX_SECTION_NAME_LEN], Array:em_aSectionKeysList, Trie:em_tSectionKeysFastList // same as the sections uses, but for keys };
enum key_s { em_szKeyName[MAX_KEY_NAME_LEN], Trie:em_tKeyValues // values are stored in a hash-map for fast-lookup searchs };
// "DARR" stands for dynamic array // the same as used on ArrayCreate native VALUE_TYPE_DARR_BOOL, // array of bools VALUE_TYPE_DARR_INT, // array of ints VALUE_TYPE_DARR_FLOAT, // array of floats VALUE_TYPE_DARR_STRING // array of strings };
new g_iFilesCount; new g_iCurrentFile;
new g_szLine[MAX_LINE_LEN]; new g_szValue[MAX_KEY_VALUE_LEN];
new g_CurrentFileData[file_s];
new Array:g_aFilesList;
new Trie:g_tFilesFastList; // same as above, but for files ids (fast lookup)
/*======================================= API =======================================*/
/*=============================================================================== API ===============================================================================*/
public bool:API_LoadString(const iPluginId, const iParams) { new iExpected = c_ExportedNatives[NATIVE_LOAD_STRING][em_iNativeParams]; if (iParams != iExpected) { log_amx("API_LoadString(): invalid params-count (expected: %d | got: %d)", iExpected, iParams); return false; }
new iId = get_param(1); if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1)) { log_amx("API_LoadString(): invalid file-id (%d)", iId); return false; }
new szSection[MAX_SECTION_NAME_LEN]; get_string(2, szSection, charsmax(szSection)); if (!szSection[0] || strlen(szSection) <= 1) { log_amx("API_LoadString(): invalid section-name (^"%s^")", szSection); return false; }
new szKey[MAX_SECTION_NAME_LEN]; get_string(3, szKey, charsmax(szKey)); if (!szKey[0] || strlen(szKey) <= 1) { log_amx("API_LoadString(): invalid key-name (^"%s^")", szKey); return false; }
new iLenOut = get_param(5);
// single-strings are handle on a different way if (LoadFileValueString(iId, szSection, szKey)) { set_string(4, g_szValue, iLenOut); return true; } return false; }
public bool:API_LoadFloat(const iPluginId, const iParams) { new iExpected = c_ExportedNatives[NATIVE_LOAD_FLOAT][em_iNativeParams]; if (iParams != iExpected) { log_amx("API_LoadInt(): invalid params-count (expected: %d | got: %d)", iExpected, iParams); return false; }
new iId = get_param(1); if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1)) { log_amx("API_LoadFloat(): invalid file-id (%d)", iId); return false; }
new szSection[MAX_SECTION_NAME_LEN]; get_string(2, szSection, charsmax(szSection)); if (!szSection[0] || strlen(szSection) <= 1) { log_amx("API_LoadFloat(): invalid section-name (^"%s^")", szSection); return false; }
new szKey[MAX_SECTION_NAME_LEN]; get_string(3, szKey, charsmax(szKey)); if (!szKey[0] || strlen(szKey) <= 1) { log_amx("API_LoadFloat(): invalid key-name (^"%s^")", szKey); return false; }
new Float:fValueOut; if (LoadFileValue(iId, VALUE_TYPE_FLOAT, szSection, szKey, fValueOut)) { set_float_byref(4, fValueOut); return true; } return false; }
public bool:API_LoadInt(const iPluginId, const iParams) { new iExpected = c_ExportedNatives[NATIVE_LOAD_INT][em_iNativeParams]; if (iParams != iExpected) { log_amx("API_LoadInt(): invalid params-count (expected: %d | got: %d)", iExpected, iParams); return false; }
new iId = get_param(1); if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1)) { log_amx("API_LoadInt(): invalid file-id (%d)", iId); return false; }
new szSection[MAX_SECTION_NAME_LEN]; get_string(2, szSection, charsmax(szSection)); if (!szSection[0] || strlen(szSection) <= 1) { log_amx("API_LoadInt(): invalid section-name (^"%s^")", szSection); return false; }
new szKey[MAX_SECTION_NAME_LEN]; get_string(3, szKey, charsmax(szKey)); if (!szKey[0] || strlen(szKey) <= 1) { log_amx("API_LoadInt(): invalid key-name (^"%s^")", szKey); return false; }
new iValueOut; if (LoadFileValue(iId, VALUE_TYPE_INT, szSection, szKey, iValueOut)) { set_param_byref(4, iValueOut); return true; } return false; }
public bool:API_LoadBool(const iPluginId, const iParams) { new iExpected = c_ExportedNatives[NATIVE_LOAD_BOOL][em_iNativeParams]; if (iParams != iExpected) { log_amx("API_LoadBool(): invalid params-count (expected: %d | got: %d)", iExpected, iParams); return false; }
new iId = get_param(1); if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1)) { log_amx("API_LoadBool(): invalid file-id (%d)", iId); return false; }
new szSection[MAX_SECTION_NAME_LEN]; get_string(2, szSection, charsmax(szSection)); if (!szSection[0] || strlen(szSection) <= 1) { log_amx("API_LoadBool(): invalid section-name (^"%s^")", szSection); return false; }
new szKey[MAX_SECTION_NAME_LEN]; get_string(3, szKey, charsmax(szKey)); if (!szKey[0] || strlen(szKey) <= 1) { log_amx("API_LoadBool(): invalid key-name (^"%s^")", szKey); return false; }
new bool:bValueOut; if (LoadFileValue(iId, VALUE_TYPE_BOOL, szSection, szKey, bValueOut)) { set_param_byref(4, bValueOut); return true; } return false; }
public API_OpenFile(const iPluginId, const iParams) { new iExpected = c_ExportedNatives[NATIVE_OPEN_FILE][em_iNativeParams]; if (iParams != iExpected) { log_amx("API_OpenFile(): invalid params-count (expected: %d | got: %d)", iExpected, iParams); return -1; }
new szFile[MAX_FILE_NAME_LEN]; get_string(1, szFile, charsmax(szFile));
return OpenFile(szFile); }
/*================================================================================ MAIN ================================================================================*/
================================================== */ CloseFile(const iFileId) { // close all files? if (iFileId == CLOSE_ALL_FILES) { new SectionData[section_s]; new KeyData[key_s];
for (new iFile; iFile < FILES_COUNT(); iFile++) { LOAD_FILE_DATA(iFile);
for (new iSection; iSection < SECTIONS_COUNT(); iSection++) { LOAD_SECTION_DATA(iSection, SectionData);
for (new iKey; iKey < KEYS_COUNT(SectionData); iKey++) { LOAD_KEY_DATA(SectionData, iKey, KeyData); CLEAR_KEY_DATA(KeyData); }
new bool:bSaveSection; // are inside a section? then need to be saved
// only used for search the "]" character // this is the section's name-end character new iPos;
// read next line while (KEEP_LOOPING) { // we have reach file's end if (!ReadFileLine(iFile)) { // check for some section to be saved if (bSaveSection) { // save section ADD_SECTION_TO_LIST(SectionData); ADD_SECTION_TO_FAST_LIST(SectionData[em_szSectionName]);
bSaveSection = false; } break; }
// comment line? if (IsCommentLine()) continue;
// section line? if (IsSectionLine()) { // check for some section to be saved if (bSaveSection) { // save section ADD_SECTION_TO_LIST(SectionData); ADD_SECTION_TO_FAST_LIST(SectionData[em_szSectionName]);
bSaveSection = false; }
// clear previous section data arrayset(SectionData, 0, section_s);
iPos = contain(g_szLine, "]"); // find "]" character
// check if section name-lenght is greather than size assigned to it if (iPos > MAX_SECTION_NAME_LEN) { // copy only the assigned size copy(SectionData[em_szSectionName], MAX_SECTION_NAME_LEN - 1, g_szLine[1]); } else { // copy full-name, but ignore the "]" character copy(SectionData[em_szSectionName], iPos - 1, g_szLine[1]); }
// check if a section with same name has been registered previously if (SECTION_EXISTS(SectionData[em_szSectionName])) { SetFailState("LoadFile(): there can't be two sections with the same name (section named ^"%s^" already exists)", SectionData[em_szSectionName]); return false; }
// check if file was previously loaded if (IS_FILE_LOADED(szFileName)) { new iFileId = -1; GET_FILE_ID(szFileName, iFileId);
// can re-open file? if (CanReOpenFile(iFileId)) { // do it, and return it's id ReOpenFile(iFileId); return iFileId; }
// file is attempt to be opened twice log_amx("OpenFile:() file ^"%s^" already loaded", szPath); return -1; }
new iFile = fopen(szPath, "rt"); if (!iFile) { log_amx("OpenFile(): can't read file ^"%s^"", szPath); return -1; }
// go to load file's data if (LoadFile(iFile)) { // file loaded successfully, so add it to the both: normal & fast-lookup lists ADD_FILE_TO_LIST(); ADD_FILE_TO_FAST_LIST(szFileName); return FILES_COUNT() - 1; } return -1; // should never reach here }
================================================== */ public plugin_natives() { new szNative[MAX_NATIVE_NAME]; new szFunc[MAX_FUNCTION_NAME];
for (new i; i < sizeof c_ExportedNatives; i++) { copy(szNative, charsmax(szNative), c_ExportedNatives[i][em_szNativeName]); copy(szFunc, charsmax(szFunc), c_ExportedNatives[i][em_szNativeFunc]);
if (szNative[0] && szFunc[0]) register_native(szNative, szFunc); } }
• CREDITOS
Principalmente los creditos van para MeRcyLeZZ debido a lo anteriormente mencionado, sin contar porciones de codigo de su Zombie Plague Mod
No duden en postear cualquier inconveniente que presenten.
Adios.
(27/07/2020, 11:35 PM)Hypnotize escribió: buen aporte, aunque quizá deberías dejar unos ejemplos para la gente que no sepa demasiado y desee usar el api.
TEST:
- test.ini:
Código PHP:
; los comentarios pueden ser añadidos tanto utilizando el caracter ";" // como tambien dos barras invertidas '//'
public plugin_precache() { new iFile = settings_open_file(config_file) // file's path = addons/amxmodx/configs/test.ini
if (iFile == -1) { set_fail_state("there was an error open file ^"%s^"", config_file); return; }
new iIntValue; if (!settings_load_int(iFile, "TEST SECTION 1", "INT KEY", iIntValue)) log_amx("can't load value for ^"iIntValue^""); else log_amx("iIntValue = %d", iIntValue);
new bool:bBoolValue; if (!settings_load_bool(iFile, "TEST SECTION 1", "BOOL KEY", bBoolValue)) log_amx("can't load value for ^"bBoolValue^""); else log_amx("bBoolValue = %s", bBoolValue ? "true" : "false");
new Float:fFloatValue if (!settings_load_float(iFile, "TEST SECTION 1", "FLOAT KEY", fFloatValue)) log_amx("can't load value for ^"fFloatValue^""); else log_amx("fFloatValue = %.4f", fFloatValue);
new szStringValue[10]; if (!settings_load_string(iFile, "TEST SECTION 2", "STRING KEY", szStringValue, charsmax(szStringValue))) log_amx("can't load value for ^"szStringValue^""); else log_amx("szStringValue = %s", szStringValue);
new Array:aIntsArray = ArrayCreate(); if (!settings_load_darray(iFile, VALUE_TYPE_DARR_INT, "TEST SECTION 3", "INT-ARRAY", aIntsArray)) log_amx("can't lod value for ^"aIntsArray^""); else { new iSize = ArraySize(aIntsArray); log_amx("elements = %d", iSize);
for (new i; i < iSize; i++) log_amx("value #%d = %d", i+1, ArrayGetCell(aIntsArray, i)); }
new Array:aFloatsArray = ArrayCreate(); if (!settings_load_darray(iFile, VALUE_TYPE_DARR_FLOAT, "TEST SECTION 3", "FLOAT-ARRAY", aFloatsArray)) log_amx("can't lod value for ^"aFloatsArray^""); else { new iSize = ArraySize(aFloatsArray); log_amx("elements = %d", iSize);
for (new i; i < iSize; i++) log_amx("value #%.4f = %d", i+1, ArrayGetCell(aFloatsArray, i)); }
new Array:aBoolsArray = ArrayCreate(); if (!settings_load_darray(iFile, VALUE_TYPE_DARR_BOOL, "TEST SECTION 3", "BOOL-ARRAY", aBoolsArray)) log_amx("can't lod value for ^"aBoolsArray^""); else { new iSize = ArraySize(aBoolsArray); log_amx("elements = %d", iSize);
for (new i; i < iSize; i++) log_amx("value #%d = %s", i+1, ArrayGetCell(aBoolsArray, i) ? "true" : "false"); }
new Array:aStringsArray = ArrayCreate(10); if (!settings_load_darray(iFile, VALUE_TYPE_DARR_STRING, "TEST SECTION 3", "STRING-ARRAY", aStringsArray)) log_amx("can't lod value for ^"aStringsArray^""); else { new iSize = ArraySize(aStringsArray); log_amx("elements = %d", iSize);
new szBuff[10]; for (new i; i < iSize; i++) { ArrayGetString(aStringsArray, i, szBuff, charsmax(szBuff)); log_amx("value #%d = %s", i+1, szBuff); } }
// bad key case (key doesn't exists on section) new iBadKeyValue; if (!settings_load_int(iFile, "TEST SECTION 1", "INT KEY BAD", iBadKeyValue)) log_amx("can't load value for ^"iBadKeyValue^""); else log_amx("iBadKeyValue; = %d", iBadKeyValue);
// bad section case (section doesn't exists on file) new iBadSectionValue; if (!settings_load_int(iFile, "TEST SECTION 4", "INT KEY", iBadSectionValue)) log_amx("can't load value for ^"iBadSectionValue^""); else log_amx("iBadSectionValue; = %d", iBadSectionValue);
settings_close_file(iFile); }
GAMEPLAY:
- gameplay.ini:
Código PHP:
[ROUND] INFINITE = true
[MONEY] ON GAME-START = 5000 ON KILL = 500 ON PLANT-BOMB = 750
new g_iMoneyOnGameStart; new g_iMoneyOnKill; new g_iMoneyOnPlantBomb;
new g_szWelcomeMsg[30];
public plugin_precache() { new iFile = settings_open_file(config_file)
if (iFile == -1) { set_fail_state("there was an error open file ^"%s^"", config_file); return; }
if (!settings_load_bool(iFile, "ROUND", "INFINITE", g_bInfiniteRound)) log_amx("can't load value for ^"g_bInfiniteRound^""); else log_amx("infinitie round is %s", g_bInfiniteRound ? "enabled" : "diseabled");
if (!settings_load_int(iFile, "MONEY", "ON GAME-START", g_iMoneyOnGameStart)) log_amx("can't load value for ^"g_iMoneyOnGameStart^""); else log_amx("money at game-start: %d", g_iMoneyOnGameStart);
if (!settings_load_int(iFile, "MONEY", "ON KILL", g_iMoneyOnKill)) log_amx("can't load value for ^"g_iMoneyOnKill^""); else log_amx("money per each kill: %d", g_iMoneyOnKill);
if (!settings_load_int(iFile, "MONEY", "ON PLANT-BOMB", g_iMoneyOnPlantBomb)) log_amx("can't load value for ^"g_iMoneyOnPlantBomb^""); else log_amx("money when plant bomb: %d", g_iMoneyOnPlantBomb);
if (!settings_load_string(iFile, "MESSAGES", "CONNECT", g_szWelcomeMsg, charsmax(g_szWelcomeMsg))) log_amx("can't load value for ^"g_szWelcomeMsg^""); else log_amx("message when somebody connects: %s", g_szWelcomeMsg);
settings_close_file(iFile); }
Y el qué no podia faltar (solo mostrare algunos ejemplos):
ZOMBIEPLAGUE:
- zombieplague.ini:
Código PHP:
; ----------------------------------------- ; Zombie Plague 4.3 Fix5 Customization File ; ----------------------------------------- ; Any changes you make here will be ; automatically loaded at map start
; Note: No error parsing is done for this. ; Make sure you don't mistype anything.
[Access Flags] ENABLE/DISABLE MOD = l ADMIN MENU = d START MODE INFECTION = d START MODE NEMESIS = d START MODE SURVIVOR = d START MODE SWARM = d START MODE MULTI = d START MODE PLAGUE = d MAKE ZOMBIE = d MAKE HUMAN = d MAKE NEMESIS = d MAKE SURVIVOR = d RESPAWN PLAYERS = d ADMIN MODELS = d
[Player Models] (randomly chosen if more than one) HUMAN = arctic , guerilla , leet , terror , gign , gsg9 , sas , urban NEMESIS = zombie_source SURVIVOR = leet , sas ADMIN ZOMBIE = zombie_source ADMIN HUMAN = vip
; If you don't want people using altered player models, enable the following. ; 1 = Bounds Check (model's geometry must fit in the same bbox) ; 2 = CRC Check (file on client must exactly match server's file) FORCE CONSISTENCY = 0
; By default, zombie models are class specific. You can edit them separately in your zp_zombieclasses.ini ; If, however, you want all zombies to use the same models regardless of class, you can enable this ; setting and add your global zombie models to the "ZOMBIE" line. SAME MODELS FOR ALL = 0 ZOMBIE = zombie_source
[Objective Entities] (and anything that would affect gameplay that needs to be removed) CLASSNAMES = func_bomb_target , info_bomb_target , info_vip_start , func_vip_safetyzone , func_escapezone , hostage_entity , monster_scientist , func_hostage_rescue , info_hostage_rescue , env_fog , env_rain , env_snow , item_longjump , func_vehicle , func_buyzone
[SVC_BAD Prevention] (if you experience *many* SVC_BAD kicks, try one of the following) ; A. Increase the delay between model changes here (in 0.1 increments until the kicks are gone) MODELCHANGE DELAY = 0.2 ; B. If you still get recurring kicks, try enabling this setting: (experimental!) HANDLE MODELS ON SEPARATE ENT = 0
; If you want your models to have accurate hitboxes, try enabling this. ; Note: make sure your models don't have messed up hitboxes, otherwise ; this setting might cause your server insane cpu usage and lag! SET MODELINDEX OFFSET = 0
/*=============================================================================================== SETTINGS API SYSTEM ===============================================================================================*/
#if defined SETTINGS_API_INC #endinput #endif #define SETTINGS_API_INC
// value-types for iDynamicArrayType (settings_load_darray) enum _:ValueTypes { VALUE_TYPE_DARR_BOOL = 3, // array of bools VALUE_TYPE_DARR_INT, // array of ints VALUE_TYPE_DARR_FLOAT, // array of floats VALUE_TYPE_DARR_STRING // array of strings };
params: - szFileName[]: name of file that will be open
return: int - -1: file can't be open (the reason will be shown) - 0+: file's id (it is not the same that fopen() returns) ================================================== */ native settings_open_file(const szFileName[]);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &bValueOut: variable to store result (bool-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_bool(const iFileId, const szSection[], const szKey[], &bool:bValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &iValueOut: variable to store result (int-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_int(const iFileId, const szSection[], const szKey[], &iValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &fValueOut: variable to store result (float-type)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_float(const iFileId, const szSection[], const szKey[], &Float:fValueOut);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - szValueOut: buffer to store result - iValueOut: max buffer's length
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_string(const iFileId, const szSection[], const szKey[], szValueOut[], const iValueOutLen);
params: - iFileId: the file-id - szSectionName[]: the section where value is located - szKey[]: the key that holds the value - &aValueOut: dyn-array to store result (dynamic array)
return: bool - true: value has been loaded successfully - false: value can't be loaded (the reason will be shown) ================================================== */ native bool:settings_load_darray(const iFileId, const iDynamicArrayType, const szKey[], const szSection[], &Array:aValueOut);
return: bool - true: file has been closed successfully - false: file can't be closed (the reason will be shown) ================================================== */ native bool:settings_close_file(const iFileId);