#pragma semicolon 1
#pragma newdecls required
#include sdktools_stringtables
static const char SIDE[][] = {"ft", "bk", "up", "dn", "lf", "rt"};
KeyValues
kvSettings;
ConVar
convarNow,
convarSky;
bool
bTimer,
bChangeMap,
bGO,
bNow;
char
szSky[128],
szSkyDefault[128],
szLog[PLATFORM_MAX_PATH],
szMap[128];
public Plugin myinfo =
{
name = "Change Sky",
author = "Paranoiiik",
version = "0.1 [Test Version]",
description = "Change sky by time and maps",
url = "vk.com/oldfreelance"
}
public void OnPluginStart()
{
bGO = GetEngineVersion() == Engine_CSGO;
convarNow = CreateConVar("change_sky_now", "0", "1 - Менять небо прямо во время игры, 0 - После окончания раунда\nПригодится для случаев, когда на сервере не происходит конец раунда", _, true, _, true, 1.0);
convarNow.AddChangeHook(cvarNow);
bNow = convarNow.BoolValue;
convarSky = FindConVar("sv_skyname");
AutoExecConfig(true, "ChangeSky");
HookEvent("round_end", eventRoundEnd);
}
public void cvarNow(ConVar cvar, const char[] oldValue, const char[] newValue)
{
bNow = cvar.BoolValue;
}
public void OnMapStart()
{
GetCurrentMap(szMap, sizeof szMap);
GetMapDisplayName(szMap, szMap, sizeof szMap);
// Чтобы было стандартное небо, если в определённое время никакое небо в конфиге не установлено
if(convarSky) convarSky.GetString(szSkyDefault, sizeof szSkyDefault);
// Настройки карт, времени и неба | Если там есть небо в определённое время, оно перебьёт стандартное
loadSettings();
// Ставим небо в зависимости от условий выше
convarSky.SetString(!szSky[0] ? szSkyDefault : szSky, true);
// Проверяем текущее время. Если совпадает, решаем, менять ли небо сразу и менять ли карту для его смены
CreateTimer(60.0, timerCheckTime, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
timerCheckTime(null);
}
stock void loadSettings()
{
delete kvSettings;
kvSettings = new KeyValues("change_sky");
char szBuffer[PLATFORM_MAX_PATH];
BuildPath(Path_SM, szBuffer, sizeof szBuffer, "configs/change_sky.ini");
if(!kvSettings.ImportFromFile(szBuffer))
{
skyLog(szBuffer);
return;
}
bChangeMap = view_as<bool>(kvSettings.GetNum("change_map", 1));
FormatTime(szBuffer, sizeof szBuffer, "%H:%M", GetTime());
int iTime = StringToInt(szBuffer);
kvSettings.Rewind();
if(kvSettings.GotoFirstSubKey())
{
char szStart[16], szEnd[16], szName[32];
do
{
// Время начала и конца неба
kvSettings.GetString("start", szStart, sizeof szStart);
kvSettings.GetString("end", szEnd, sizeof szEnd);
if(iTime >= StringToInt(szStart) && iTime < StringToInt(szEnd))
{
szSky[0] = 0;
// Есть ли небо для всех карт
kvSettings.GetString("sky", szName, sizeof szName);
if(szName[0]) FormatEx(szSky, sizeof(szSky), szName);
else
{
// Есть ли небо по префиксам карт
if(kvSettings.JumpToKey("maps_prefix", false))
{
if(SplitString(szMap, "_", szMap, sizeof szMap) != -1)
{
kvSettings.GetString(szMap, szName, sizeof szName);
if(szName[0]) szSky = szName;
}
kvSettings.GoBack();
}
// Есть ли небо по определённым картам
if(kvSettings.JumpToKey("maps", false))
{
kvSettings.GetString(szMap, szName, sizeof szName);
if(szName[0]) szSky = szName;
kvSettings.GoBack();
}
}
// Загружаем нужное небо игроку
if(szSky[0]) skyDownload(szSky);
}
}
while(kvSettings.GotoNextKey());
}
}
public Action eventRoundEnd(Event event, const char[] name, bool dontBroadcast)
{
if(bTimer) CreateTimer(3.0, timerChangeMap, _, TIMER_FLAG_NO_MAPCHANGE);
}
public Action timerCheckTime(Handle timer)
{
char szTime[16];
FormatTime(szTime, sizeof szTime, "%H:%M", GetTime());
kvSettings.Rewind();
if(kvSettings.GotoFirstSubKey())
{
do
{
// Время начала и конца неба
char szStart[16], szEnd[16];
kvSettings.GetString("start", szStart, sizeof szStart);
if(!strcmp(szTime, szStart))
{
// В CS:GO небо можно менять "на лету"
// В CS:S изменения sv_skyname применятся лишь при старте карты | "на лету" останется старое небо, даже если значение поменялось
// Выбор, менять ли карту, я оставил больше для CS:GO, по сути, чтоб у владельца сервера было больше свободы
if(bGO) convarSky.SetString(szSky, true);
if(bChangeMap)
{
// Меняем небо либо через 3 секунды после окончания раунда, либо сразу
if(!bNow) bTimer = true;
else
{
bTimer = false;
ForceChangeLevel(szMap, "change_sky plugin");
}
}
}
kvSettings.GetString("end", szEnd, sizeof szEnd);
if(!strcmp(szTime, szEnd))
{
// В CS:GO небо можно менять "на лету"
// В CS:S изменения sv_skyname применятся лишь при старте карты | "на лету" останется старое небо, даже если значение поменялось
// Выбор, менять ли карту, я оставил больше для CS:GO, по сути, чтоб у владельца сервера было больше свободы
if(bGO) convarSky.SetString(szSkyDefault, true);
if(bChangeMap)
{
// Меняем небо либо через 3 секунды после окончания раунда, либо сразу
if(!bNow) bTimer = true;
else
{
bTimer = false;
ForceChangeLevel(szMap, "change_sky plugin");
}
}
}
}
while(kvSettings.GotoNextKey());
}
}
public Action timerChangeMap(Handle timer)
{
bTimer = false;
ForceChangeLevel(szMap, "change_sky plugin");
}
// Функция позволит нам скачать небо клиенту без сторонних файлов
// Админ должен будет указать в конфиге лишь название, плагин сам отыщет пути и добавит файлы в загрузку
stock void skyDownload(char[] szName)
{
// Если небо находится по нестандартному пути "materials/my_folder/sky" - sv_skyname "../my_folder/sky"
// Убираем лишние символы из названия, чтобы адеквато скачать небо клиенту, используя название неба в поиске пути
char szPath[256];
if(StrContains(szName, "../", true) != -1)
{
ReplaceString(szName, sizeof szName, "../", "");
FormatEx(szPath, sizeof szPath, "materials/");
}
else if(StrContains(szName, "./", true) != -1)
{
ReplaceString(szName, sizeof szName, "./", "");
FormatEx(szPath, sizeof szPath, "materials/");
}
else FormatEx(szPath, sizeof szPath, "materials/skybox/");
// Собственно, загрузка и прекэш файлов неба игроку
// Я думал, над тем, как укоротить эту часть кода, но не хватило мозгов. Может, позже что-то придумаю
char szBuffer[256];
for(int i; i < sizeof(SIDE); i++)
{
FormatEx(szBuffer, sizeof(szBuffer), "%s%s%s.vmt", szPath, szName, SIDE);
if(!FileExists(szBuffer)) skyLog(szBuffer);
else
{
AddFileToDownloadsTable(szBuffer);
if(!IsModelPrecached(szBuffer)) PrecacheModel(szBuffer, true);
}
FormatEx(szBuffer, sizeof(szBuffer), "%s%s%s.vtf", szPath, szName, SIDE);
if(!FileExists(szBuffer)) skyLog(szBuffer);
else AddFileToDownloadsTable(szBuffer);
}
}
stock void skyLog(char[] fileName)
{
BuildPath(Path_SM, szLog, sizeof szLog, "logs/ChangeSky.log");
LogToFileEx(szLog, "Missing file: \"%s\"", fileName);
}