Pushistik↯❤
Команда форума
- Регистрация
- 6 Июл 2017
- Сообщения
- 393
- Реакции
- 97
- Баллы
- 28
Консольные переменные в SourceMod (ConVars)
Я думаю что каждый, кто однажды писал плагины для SourceMod, сталкивался с консольными переменнами (ака ConVars).
В "блог" всё сообщение не вместилось, да и русскоязычного перевода я не нашел. Вот так и решил выложить оригинальную статью на родном языке.
Первая часть включает в себя вступление, поиск, создание, изменение значений для переменных, флаги, отслеживание изменений, отправка значений переменных клиентам и полезные советы.
Вторая часть посложнее - ориентирована специально для разработчиков плагинов. В сей раздел входят стили для создания переменных, их возможности и недостатки.
Вступление:
ConVars это консольные переменные. А значения переменных могут быть как string, float так и другие нумерационные значения.
Эти значения можно изменять через консоль или конфиги, и они остаются на протяжении всего времени работы сервера.
Доступ к ConVars можно получить через носители (Handles). Существует два способа контролировать переменные - создать новую или запросить старую.
Заметка: Носители переменных всегда разные и их не нужно "освобождать" вручную. Когда плагин будет отключен, SourceMod, соответственно, всё выполнит за Вас.
Поиск переменных:
Запрос и поиск существующих переменных довольно прост. Допустим, Вы хотите найти mp_startmoney из Counter-Strike: Source.
Заметка: FindConVar() может вернуть нулевое значение (например, когда переменной не существует). Имейте это ввиду, если Вы хотите запрашивать переменные из других плагинов.
Создание ConVars:
Простой переменной достаточно всего лишь задать имя и значение. Однако, неплохо бы еще добавить описание:
Так же Вы можете задать лимиты значений для своей переменной (допустим от 0 до 1, как в bool)
Заметка: Если Вы используете не нумерационное значение для переменной, то и лимиты добавлять не нужно!
Использование/изменение значений:
Вы хотите изменить значение mp_startmoney, но в дальнейшем вернуть значение к оригинальному? Вот пример:
Не забывайте, что типы значений для каждой переменной могут быть разными (float, string и другие). Само собой разумеется, что и значение сохраняется в том же типе.
Заметка: Несмотря на то, что значение mp_startmoney нумерационное (integer), оно может извлекаться как string!
Флаги:
Консольным переменным можно задавать флаги. В отдельных случаях флаги играют важную роль.
Основные флаги:
FCVAR_NOTIFY - Игроки будут оповещены об изменениях. Еще при помощи этого флага можно отслеживать кто пользуется Вашим плагином.
FCVAR_CHEAT - Задает cheat-флаг переменной (т.е. чтобы изменить значение нужно прописать sv_cheats 1 в консоль сервера).
FCVAR_PLUGIN - Флаг, определяющий что эта переменная создана плагином (на самом деле это вообще ни на что не влияет).
FCVAR_DONTRECORD - Если переменная имеет этот флаг, то SM не будет записывать её в конфиг (при использовании AutoExecConfig(true).
Флаги можно не только задавать, но и добавлять/убирать/whatever.
Например, мы хотим изменять значение переменной без изменения sv_cheats.
Заметка: Вся эта мишура с флагами необязательна, так как SourceMod предоставляет возможность менять значения для переменных с любым флагом через sm_cvar "cvar_name" "value".
Список всех флагов можно посмотреть на Developer.Valvesoftware и SM API
Отслеживание изменений:
Очень полезная функция. Тем не менее ею нужно пользоваться с осторожностью!
Нельзя изменять значение переменной внутри хука, иначе цикл будет продолжаться до бесконечности!
Например, Вы хотите чтобы значение bot_quota не было ниже 2:
Заметка: Как уже было сказано ранее, нет необходимости высвобождать переменные и хук, SM всё сделает за Вас.
Отправка переменных.
SM предоставляет отличную функцию - отправлять переменные клиентам.
Таким образом можно отправлять клиентам значение переменной без изменения этой переменной на сервере!
Это тоже вполне легко реализовать:
Полезные советы:
Согласитель, что этот метод намного лучше чем тот, который указан ниже:
Полезные советы:
ConVars это консольные переменные. А значения переменных могут быть как string, float так и другие нумерационные значения.
Эти значения можно изменять через консоль или конфиги, и они остаются на протяжении всего времени работы сервера.
Доступ к ConVars можно получить через носители (Handles). Существует два способа контролировать переменные - создать новую или запросить старую.
Заметка: Носители переменных всегда разные и их не нужно "освобождать" вручную. Когда плагин будет отключен, SourceMod, соответственно, всё выполнит за Вас.
Поиск переменных:
Запрос и поиск существующих переменных довольно прост. Допустим, Вы хотите найти mp_startmoney из Counter-Strike: Source.
PHP:
new Handle:mp_startmoney
public OnPluginStart()
{
mp_startmoney = FindConVar("mp_startmoney")
}
Создание ConVars:
Простой переменной достаточно всего лишь задать имя и значение. Однако, неплохо бы еще добавить описание:
PHP:
new Handle:g_hEnabled
public OnPluginStart()
{
g_hEnabled = CreateConVar("название_переменной", "значение", "описание")
}
PHP:
new Handle:g_hEnabled
public OnPluginStart()
{
g_hEnabled = CreateConVar("название_переменной", "0", "описание",
_, // Флаг (об этом позже)
true, // Зададим минимум
0.0, // И, соответственно, значение
true, // Нужно ли нам задать максимум?
1.0) // Да!
}
Использование/изменение значений:
Вы хотите изменить значение mp_startmoney, но в дальнейшем вернуть значение к оригинальному? Вот пример:
PHP:
new g_oldmoney
SetStartMoney(newmoney)
{
// Сохраним значение mp_startmoney в глобальный g_oldmoney (integer)
g_oldmoney = GetConVarInt(g_hStartMoney)
// А теперь изменим значение mp_startmoney на новое
SetConVarInt(g_hStartMoney, newmoney)
}
RestoreStartMoney()
{
SetConVarInt(g_hStartMoney, g_oldmoney) // Вернем оригинальное значение для mp_startmoney
}
PHP:
GetStartMoney()
{
decl String:buffer[128] // Буффер в который мы "запишем" значение
// Запросим значение mp_startmoney
GetConVarString(g_hStartMoney, buffer, sizeof(buffer))
// Конвертируем string в integer
return StringToInt(buffer)
}
Флаги:
Консольным переменным можно задавать флаги. В отдельных случаях флаги играют важную роль.
Основные флаги:
FCVAR_NOTIFY - Игроки будут оповещены об изменениях. Еще при помощи этого флага можно отслеживать кто пользуется Вашим плагином.
FCVAR_CHEAT - Задает cheat-флаг переменной (т.е. чтобы изменить значение нужно прописать sv_cheats 1 в консоль сервера).
FCVAR_PLUGIN - Флаг, определяющий что эта переменная создана плагином (на самом деле это вообще ни на что не влияет).
FCVAR_DONTRECORD - Если переменная имеет этот флаг, то SM не будет записывать её в конфиг (при использовании AutoExecConfig(true).
Флаги можно не только задавать, но и добавлять/убирать/whatever.
Например, мы хотим изменять значение переменной без изменения sv_cheats.
PHP:
new Handle:MyConVar
public OnPluginStart()
{
MyConVar = FindConVar("mp_mycheatcvar") // Найдем нашу переменную
if (MyConVar != INVALID_HANDLE) // Проверим существует ли она вообще
{
//SetCheatVar(MyConVar) // Добавим чит-флаг
UnsetCheatVar(MyConVar) // Извлечем чит-флаг
}
}
UnsetCheatVar(Handle:hndl)
{
new flags = GetConVarFlags(hndl) // Запросим оригинальные флаги
flags &= ~FCVAR_CHEAT // Извлечем чит-флаг
SetConVarFlags(hndl, flags) // Вернем все предыдущие флаги, но теперь без FCVAR_CHEAT
}
SetCheatVar(Handle:hndl)
{
new flags = GetConVarFlags(hndl)
flags |= FCVAR_CHEAT // То же самое, но добавим FCVAR_CHEAT
SetConVarFlags(hndl, flags)
}
Список всех флагов можно посмотреть на Developer.Valvesoftware и SM API
Отслеживание изменений:
Очень полезная функция. Тем не менее ею нужно пользоваться с осторожностью!
Нельзя изменять значение переменной внутри хука, иначе цикл будет продолжаться до бесконечности!
Например, Вы хотите чтобы значение bot_quota не было ниже 2:
PHP:
new Handle:g_hBotQuota
public OnPluginStart()
{
g_hBotQuota = FindConVar("bot_quota")
if (g_hBotQuota != INVALID_HANDLE)
{
HookConVarChange(g_hBotQuota, OnBotQuotaChange) // Hook all the changes
}
}
public OnBotQuotaChange(Handle:cvar, const String:oldVal[], const String:newVal[])
{
if (StringToInt(newVal) < 2) // Так как значение всегда string ("золотая середина"), его нужно конвертировать в int или float (т.е. просто убрать скобки)
{
SetConVarInt(cvar, 2) // В нашем случае значение изменилось на 0 или 1, но мы не хотим этого допускать! Возвращаем минимально-допустимое значение....
}
}
Отправка переменных.
SM предоставляет отличную функцию - отправлять переменные клиентам.
Таким образом можно отправлять клиентам значение переменной без изменения этой переменной на сервере!
Это тоже вполне легко реализовать:
PHP:
new Handle:g_hMyCvar
public OnPluginStart()
{
g_hMyCvar = FindConVar("sv_cheats") // Найдем необходмую нам переменную
}
public OnClientPutInServer(client)
{
SendConVarValue(client, g_hMyCvar, "1") // И отправим значение 1 когда игрок заходит на сервер
}
- Чаще используйте HookConVarChange!
Если Ваш плагин часто использует значения переменных (например каждый раз когда игрок умирает или получает урон), то можно использовать хук таким образом:
PHP:
new Handle:Enabled
public OnPluginStart()
{
enabled = CreateConVar("mycvar_enable", "1", "shall we work?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
// hoooooooooooooooooooooooooooooook
HookConVarChange(enabled, OnConVarChange);
// Вручную сменим значение с 0 до 1 чтобы загрузить события
OnConVarChange(enabled, "0", "1");
}
public OnConVarChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
switch (StringToInt(newValue))
{
case false:
{
UnhookEvent("player_spawn", Event_Player_Spawn, EventHookMode_Post);
UnhookEvent("player_hurt", Event_Player_Hurt, EventHookMode_Post);
UnhookEvent("dod_stats_weapon_attack", Event_Player_Attack, EventHookMode_Post);
UnhookEvent("dod_point_captured", Event_Point_Captured, EventHookMode_Post);
UnhookEvent("dod_capture_blocked", Event_Capture_Blocked, EventHookMode_Post);
UnhookEvent("dod_bomb_planted", Event_Bomb_Planted, EventHookMode_Post);
UnhookEvent("dod_bomb_defused", Event_Bomb_Defused, EventHookMode_Post);
UnhookEvent("dod_round_win", Event_Round_End, EventHookMode_Post);
UnhookEvent("dod_round_start", Event_Game_Over, EventHookMode_PostNoCopy);
UnhookEvent("dod_game_over", Event_Game_Over, EventHookMode_PostNoCopy);
}
case true:
{
HookEvent("player_spawn", Event_Player_Spawn, EventHookMode_Post);
HookEvent("player_hurt", Event_Player_Hurt, EventHookMode_Post);
HookEvent("dod_stats_weapon_attack", Event_Player_Attack, EventHookMode_Post);
HookEvent("dod_point_captured", Event_Point_Captured, EventHookMode_Post);
HookEvent("dod_capture_blocked", Event_Capture_Blocked, EventHookMode_Post);
HookEvent("dod_bomb_planted", Event_Bomb_Planted, EventHookMode_Post);
HookEvent("dod_bomb_defused", Event_Bomb_Defused, EventHookMode_Post);
HookEvent("dod_round_win", Event_Round_End, EventHookMode_Post);
HookEvent("dod_round_start", Event_Game_Over, EventHookMode_PostNoCopy);
HookEvent("dod_game_over", Event_Game_Over, EventHookMode_PostNoCopy);
}
}
}
PHP:
public Event_Player_Spawn(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarBool(enabled))
{
}
}
public Event_Player_Hurt(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarBool(enabled))
{
}
}
...
- Не использутей FCVAR_REPLICATED для Вашей переменной! Иначе каждый раз, когда игрок будет заходить на сервер, он будет получать ошибку в консоли типа:
"ConVarRef mycvar_version doesn't point to an existing ConVar. SetConVar: No such cvar ( mycvar_version set to XYZ), skipping" - Если переменная использует много значений (1 2 3 4 5 6 7 8 9 10), используйте bit оператор вместо GetConVarInt (ну или в конце-концов switch()).
- Старайтесь избегать одинаковых названий с обычными переменными (типа mp_startmoney), в противном случае плагин откажется работать!
- Однажды созданная переменная сохраняется в кэше сервера, так что если Вы использовали некорректное описание/лимит - лучше перезагрузите сервер - иначе изменения не вступят в силу.
- Если Вам надо найти уже существующую переменную, ищите её в событии OnPluginStart() и сохраните как глобальный Handle. Почему? Да потому что тысячу раз твердили что поиск уже существующих переменных тяжеловат для сервера. Лучше один раз найти и сохранить в памяти! Так то.
У Вас есть плагин, который запрашивает много переменных, но сей процесс требует оптимизации и упрощения? Тогда эта часть статьи для Вас!
Существует некоторое множество стилей для ConVars, о которых многие не знают или просто догадываются.
Существует некоторое множество стилей для ConVars, о которых многие не знают или просто догадываются.
Самый обычный и оригинальный стиль, который используется во множестве плагинов.
Преимущества: простота в использовании.
Недостатки: не лучший способ для работы с крупными плагинами.
Преимущества: простота в использовании.
Недостатки: не лучший способ для работы с крупными плагинами.
PHP:
new Handle:MyConVar
public OnPluginStart()
{
MyConVar = CreateConVar("MyConVar", "1", "Description");
}
public OnMapStart()
{
if (GetConVarBool(MyConVar) == true)
{
// бла бла бла
}
}
Преимущества: Значение сохраняется в переменной (например somevalue) и изменяется при изменении переменной. Полезно при частом использовании значения.
Недостатки:
-не лучший способ для небольших плагинов.
-много (ненужных) переменных типа somevalue.
Недостатки:
-не лучший способ для небольших плагинов.
-много (ненужных) переменных типа somevalue.
PHP:
new Handle:somecvar = INVALID_HANDLE;
new somevalue; // Место хранения значения
public OnPluginStart()
{
somecvar = CreateConVar("sm_somecvar", "6", "some cvar");
HookConVarChange(somecvar, OnConVarChange);
}
public OnConVarChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
somevalue = GetConVarInt(somecvar); // Проделаем тоже самое когда значение изменилось, например, через консоль
}
public OnPlayerSpawn(client)
{
switch (somevalue)
{
case 0: // Когда значение равно 0
case 1: // Или 1
default: // Другое
}
Стиль одного из разработчиков SourceMod. Достоин внимания, так как очень оригинален, интересен и в некой степени оптимизирован.
Преимущества: Глобальные носители (Handle) не используются, что положительно сказывается на производительности сервера.
Недостатки: нужно отслеживать изменения для каждой переменной по отдельности.
Преимущества: Глобальные носители (Handle) не используются, что положительно сказывается на производительности сервера.
Недостатки: нужно отслеживать изменения для каждой переменной по отдельности.
PHP:
new g_iMinPCount = 12;
new bool:g_bEnabled = true;
new g_iCmdRate[2];
public OnPluginStart()
{
new Handle:hRegister; // Локальный handle для регистрации ConVar'ов
// Сразу будем отслеживать изменения и зарегистрируем переменную
HookConVarChange((hRegister = CreateConVar("enabled", "1", "Should I even be running?", _, true, 0.0, true, 1.0)), OnEnabledChange);
g_bEnabled = GetConVarBool(hRegister); // Мгновенно присвоим значение для глобального буля
HookConVarChange((hRegister = CreateConVar("minplayercount", "12", "How many players need to be ingame for any check to occur.")), OnMinPlayChange);
g_iMinPCount = GetConVarInt(hRegister);
// С таким же успехом можно и находить отдельные переменные
if((hRegister = FindConVar("sv_mincmdrate")) != INVALID_HANDLE)
{
g_iCmdRate[0] = GetConVarInt(hRegister);
HookConVarChange(hRegister, OnMinCmdRateChange);
}
if((hRegister = FindConVar("sv_maxcmdrate")) != INVALID_HANDLE)
{
g_iCmdRate[1] = GetConVarInt(hRegister);
HookConVarChange(hRegister, OnMaxCmdRateChange);
}
CloseHandle(hRegister); // Нам ведь не нужны утечки памяти
}
public OnConfigsExecuted()
{
if(g_bEnabled)
{
// бла бла
}
}
public OnEnabledChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
g_bEnabled = GetConVarBool(convar);
}
public OnMinPlayChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
g_iMinPCount = GetConVarInt(convar); // ... для каждой переменной
}
public OnMinCmdRateChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
g_iCmdRate[0] = GetConVarInt(convar);
}
public OnMaxCmdRateChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
g_iCmdRate[1] = GetConVarInt(convar);
}
Автор неизвестен. Но стиль имеет место быть и достоин внимания.
Полезен в том случае когда много однотипных переменных (полезно для плагина статистики).
Ничем особо не отличается от оригинальных стилей.
Полезен в том случае когда много однотипных переменных (полезно для плагина статистики).
Ничем особо не отличается от оригинальных стилей.
PHP:
enum CSWeaponID //взято из cstrike.inc
{
CSWeapon_NONE = 0,
CSWeapon_P228,
CSWeapon_GLOCK,
CSWeapon_SCOUT,
...
}
enum WeaponType // Список носителей для создания ConVar
{
Handle:bomb,
Handle:p228,
Handle:glock,
Handle:scout
};
new Points[WeaponType]; // "Регистратор"
public OnPluginStart()
{
Points[bomb] = CreateConVar("stats_points_bomb", "1", "Points for killing by bomb");
Points[p228] = CreateConVar("stats_points_p228", "5", "Points for killing by p228");
Points[glock] = CreateConVar("stats_points_glock", "5", "Points for killing by glock");
Points[scout] = CreateConVar("stats_points_scout", "7", "Points for killing by scout");
}
public OnPlayerDeath(attacker)
{
GivePoints(attacker, GetConVarInt(Points[GetEventInt(event, "weapon")])); // Дадим убийце Х очков в зависимости от оружия.
}
Придуман одним талантливым шведом.
Преимущества:
Преимущества:
- автоматизация процесса отслеживания переменных (хук).
- безошибочность в извлечении типа значения (float, int или string).
- простота процесса извлечения значения.
- отлично подходит для больших плагинов.
- оптимизированность и оригинальность.
- нельзя мгновенно отслеживать изменения значений типа string
- может показаться сложным
PHP:
enum
{
AllowHealthkit, // Номер переменной
ItemLifeTime,
DeadDrop,
ConfigFile,
ConVar_Size // Максимальное количество переменных
};
enum ValueType
{
ValueType_Bool,
ValueType_Int,
ValueType_Float,
ValueType_String
};
enum ConVar
{
Handle:ConVarHandle, // Носитель консольной переменной
ValueType:Type, // Тип значения (int, bool)
any:Value // Само значение
};
new GetConVar[ConVar_Size][ConVar]; // Функция запроса значения
LoadConVars() // Добавьте это в OnPluginStart()
{
// Номер, тип и оригинальный CreateConVar
AddConVar(AllowHealthkit, ValueType_Bool, CreateConVar("dod_dropmanager_healthkit", "1", "Whether or not allow health kits dropping", FCVAR_PLUGIN, true, 0.0, true, 1.0));
// Значение float/integer/string
AddConVar(ItemLifeTime, ValueType_Float, CreateConVar("dod_dropmanager_lifetime", "45", "Number of seconds a dropped items stays on the ground", FCVAR_PLUGIN, true, 0.0));
AddConVar(DeadDrop, ValueType_Int, CreateConVar("dod_dropmanager_deaddrop", "3", "item to drop after death", FCVAR_PLUGIN, true, 0.0, true, 30.0));
AddConVar(ConfigFile, ValueType_String, CreateConVar("dod_dropmanager_config", "", "Load a custom config for DropManager (without .cfg!)", FCVAR_PLUGIN));
}
// Регистрирует/добавляет ConVar
AddConVar(conVar, ValueType:type, Handle:conVarHandle)
{
GetConVar[conVar][ConVarHandle] = conVarHandle;
GetConVar[conVar][Type] = type;
// String не поддерживается
if (type != ValueType_String)
{
// Обновим значения
UpdateConVarValue(conVar);
// И будем отслеживать
HookConVarChange(conVarHandle, OnConVarChange);
}
}
UpdateConVarValue(conVar)
{
switch (GetConVar[conVar][Type])
{
case ValueType_Bool: GetConVar[conVar][Value] = GetConVarBool (GetConVar[conVar][ConVarHandle]);
case ValueType_Int: GetConVar[conVar][Value] = GetConVarInt (GetConVar[conVar][ConVarHandle]);
case ValueType_Float: GetConVar[conVar][Value] = GetConVarFloat(GetConVar[conVar][ConVarHandle]);
}
}
public OnConVarChange(Handle:conVar, const String:oldValue[], const String:newValue[])
{
// Цикл через все переменные
for (new i = 0; i < ConVar_Size; i++)
{
if (conVar == GetConVar[i][ConVarHandle])
{
UpdateConVarValue(i);
// Еще можно отдельно для каждой переменной указать свои изменения
if (i == ItemLifeTime)
{
// ex. KillTimer
}
}
}
}
public OnConfigsExecuted()
{
// String можно заполучить только так
decl String:cfg[256];
GetConVarString(GetConVar[ConfigFile][ConVarHandle], cfg, sizeof(cfg));
if (cfg[0] != '\0')
{
AutoExecConfig(false, cfg, NULL_STRING);
}
}
public Action:MyFunction()
{
if (GetConVar[AllowHealthkit][Value])
{
// bool
}
// Таймер со значением float
CreateTimer(GetConVar[ItemLifeTime][Value], MyTimer, _, TIMER_FLAG_NO_MAPCHANGE);
switch (GetConVar[DeadDrop][Value])
{
// int
}
}
Схож с предыдущим, но в этом можно запрашивать у одной переменной значения int, float и другие.
Преимущества и недостатки должны быть очевидны.
В пример взят DoD:S ZombieMod
На первый взгляд может показаться, что стиль Andersso сложноват и запутан, но на самом деле это не так!
Достаточно просто всё скопировать и добавить AddConVar(ИМЯ, тип_значения, CreateConVar ("название", "значение", "описание", "флаг", "лимиты") и запрашивать значение через GetConVar[ИМЯ][Value].
Преимущества и недостатки должны быть очевидны.
В пример взят DoD:S ZombieMod
PHP:
enum
{
ConVar_Enabled,
ConVar_Zombie_CritHPRefresh,
ConVar_Size
};
enum ConVar
{
Handle:ConVarHandle,
Value_Int, // Int
bool:Value_Bool, // Bool
Float:Value_Float // Float
};
new g_ConVars[ConVar_Size][ConVar];
InitConVars()
{
CreateConVar("sm_zombiemod_version", PLUGIN_VERSION, PLUGIN_NAME, FCVAR_NOTIFY|FCVAR_DONTRECORD);
AddConVar(ConVar_Enabled, CreateConVar("sm_zombiemod_enabled", "1", "Enable/Disable Zombie Mod."));
AddConVar(ConVar_Zombie_CritHPRefresh, CreateConVar("sm_zombiemod_crit_hp_refresh", "100", "Amount of health a crit zombie will regenerate on kill."));
}
AddConVar(conVar, Handle:conVarHandle)
{
g_ConVars[conVar][ConVarHandle] = conVarHandle;
UpdateConVarValue(conVar);
HookConVarChange(conVarHandle, OnConVarChange);
}
UpdateConVarValue(conVar)
{
g_ConVars[conVar][Value_Int] = GetConVarInt(g_ConVars[conVar][ConVarHandle]);
g_ConVars[conVar][Value_Bool] = GetConVarBool(g_ConVars[conVar][ConVarHandle]);
g_ConVars[conVar][Value_Float] = GetConVarFloat(g_ConVars[conVar][ConVarHandle]);
}
public OnConVarChange(Handle:conVar, const String:oldValue[], const String:newValue[])
{
for (new i = 0; i < ConVar_Size; i++)
{
if (conVar == g_ConVars[i][ConVarHandle])
{
UpdateConVarValue(i);
ConVarChanged(i);
break;
}
}
}
ConVarChanged(conVar)
{
switch (conVar)
{
case ConVar_Enabled: // Что нужно сделать когда изменилось значение первой переменной?
{
// Правильно: бла и бла
}
}
}
public Action:MyFunction()
{
if (g_ConVars[ConVar_Zombie_CritHPRefresh][Value_Float] > 0.0) // FLOAT
{
SetEntityHealth(attacker, g_ConVars[ConVar_Zombie_CritHPRefresh][Value_Int]); // INT
}
}
Достаточно просто всё скопировать и добавить AddConVar(ИМЯ, тип_значения, CreateConVar ("название", "значение", "описание", "флаг", "лимиты") и запрашивать значение через GetConVar[ИМЯ][Value].
Схож с последними двумя, но есть свои недостатки и преимущества.
Преимущества: Поддержка string и простая регистрация ConVar'ов через .inc файл
Недостатки: необходимость своих callback'ов, из-за которых стиль уступает в скорости по отношению к последним двум.
Я, пожалуй, просто приложу библиотеку и напишу как этим ею нужно пользоваться.
Цитирую Zephyrus'а:
Преимущества: Поддержка string и простая регистрация ConVar'ов через .inc файл
Недостатки: необходимость своих callback'ов, из-за которых стиль уступает в скорости по отношению к последним двум.
Я, пожалуй, просто приложу библиотеку и напишу как этим ею нужно пользоваться.
Цитирую Zephyrus'а:
Я сделал эту библиотеку для упрощения и надежности консольных переменных. Чтобы зарегистрировать консольную переменную, достаточно изменить Ваш код на:
PHP:
#include "zephconvars.inc"
new g_cvarPauseAmount;
public OnPluginStart()
{
g_cvarPauseAmount = RegisterConVar("match_pause_amount", "900", "Maximum amount of pause per match", TYPE_INT);
}
Всем спасибо за внимание!
Вложения
-
950 байт Просмотры: 1
-
1,8 KB Просмотры: 1