Made config module, recoded models.inc and added validations, added a cvar to flag any sayhook as quiet to hide from chat, hooked mp_limitteams, fixed menu handle function, moved file paths into cvars and updated all modules but classes to use it
This commit is contained in:
parent
1a638cfbac
commit
8da309e4f4
@ -13,7 +13,7 @@
|
||||
"EyeAngles"
|
||||
{
|
||||
"windows" "206"
|
||||
"osx" "207"
|
||||
"linux" "207"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "zr/zombiereloaded"
|
||||
#include "zr/log"
|
||||
#include "zr/cvars"
|
||||
#include "zr/config"
|
||||
#include "zr/translation"
|
||||
#include "zr/tools"
|
||||
#include "zr/models"
|
||||
@ -166,9 +167,6 @@ public OnLibraryAdded(const String:name[])
|
||||
*/
|
||||
public OnMapStart()
|
||||
{
|
||||
LoadModelData();
|
||||
LoadDownloadData();
|
||||
|
||||
// Forward event to modules.
|
||||
RoundEndOnMapStart();
|
||||
InfectOnMapStart();
|
||||
@ -191,26 +189,9 @@ public OnMapEnd()
|
||||
*/
|
||||
public OnConfigsExecuted()
|
||||
{
|
||||
// TODO: move to config module when made.
|
||||
decl String:mapconfig[PLATFORM_MAX_PATH];
|
||||
|
||||
GetCurrentMap(mapconfig, sizeof(mapconfig));
|
||||
Format(mapconfig, sizeof(mapconfig), "sourcemod/zombiereloaded/%s.cfg", mapconfig);
|
||||
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
Format(path, sizeof(path), "cfg/%s", mapconfig);
|
||||
|
||||
if (FileExists(path))
|
||||
{
|
||||
ServerCommand("exec %s", mapconfig);
|
||||
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS))
|
||||
{
|
||||
LogMessageFormatted(-1, "", "", "Executed map config file: %s.", LOG_FORMAT_TYPE_SIMPLE, mapconfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward event to modules.
|
||||
ConfigLoad();
|
||||
ModelsLoad();
|
||||
WeaponsLoad();
|
||||
HitgroupsLoad();
|
||||
InfectLoad();
|
||||
|
@ -24,6 +24,12 @@
|
||||
enum CvarsList
|
||||
{
|
||||
Handle:CVAR_ENABLE,
|
||||
Handle:CVAR_CONFIG_PATH_MODELS,
|
||||
Handle:CVAR_CONFIG_PATH_DOWNLOADS,
|
||||
Handle:CVAR_CONFIG_PATH_PLAYERCLASSES,
|
||||
Handle:CVAR_CONFIG_PATH_WEAPONS,
|
||||
Handle:CVAR_CONFIG_PATH_WEAPONGROUPS,
|
||||
Handle:CVAR_CONFIG_PATH_HITGROUPS,
|
||||
Handle:CVAR_CLASSES_SPAWN,
|
||||
Handle:CVAR_CLASSES_RANDOM,
|
||||
Handle:CVAR_CLASSES_DEFAULT_ZOMBIE,
|
||||
@ -40,6 +46,8 @@ enum CvarsList
|
||||
Handle:CVAR_DAMAGE_SUICIDE_ZOMBIE,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_HUMAN,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_CMDS,
|
||||
Handle:CVAR_SAYHOOKS_QUIET,
|
||||
Handle:CVAR_SAYHOOKS_QUIET_FLAGS,
|
||||
Handle:CVAR_ROUNDEND_OVERLAY,
|
||||
Handle:CVAR_ROUNDEND_OVERLAY_ZOMBIE,
|
||||
Handle:CVAR_ROUNDEND_OVERLAY_HUMAN,
|
||||
@ -177,6 +185,17 @@ CvarsCreate()
|
||||
|
||||
// (None)
|
||||
|
||||
// ===========================
|
||||
// Config (core)
|
||||
// ===========================
|
||||
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_MODELS] = CreateConVar("zr_config_path_models", "configs/zr/models.txt", "");
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_DOWNLOADS] = CreateConVar("zr_config_path_downloads", "configs/zr/downloads.txt");
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_PLAYERCLASSES] = CreateConVar("zr_config_path_playerclasses", "configs/zr/playerclasses.txt");
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_WEAPONS] = CreateConVar("zr_config_path_weapons", "configs/zr/weapons/weapons.txt");
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_WEAPONGROUPS] = CreateConVar("zr_config_path_weapongroups", "configs/zr/weapons/weapongroups.txt");
|
||||
g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt");
|
||||
|
||||
// ===========================
|
||||
// Tools (core)
|
||||
// ===========================
|
||||
@ -290,6 +309,22 @@ CvarsCreate()
|
||||
g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS] = CreateConVar("zr_damage_suicide_cmds", "kill, spectate, jointeam", "");
|
||||
// Old Desc: List of suicide commands to intercept. (Delimited by \", \"
|
||||
|
||||
// ===========================
|
||||
// Say Hooks (core)
|
||||
// ===========================
|
||||
|
||||
g_hCvarsList[CVAR_SAYHOOKS_QUIET] = CreateConVar("zr_sayhooks_quiet", "1", "");
|
||||
g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS] = CreateConVar("zr_sayhooks_quiet_flags", "58", "");
|
||||
// Flags (default: 2 + 8 + 16 + 32)
|
||||
// 0 Allow all.
|
||||
// 1 Quiet "!zmenu" say hook.
|
||||
// 2 Quiet "!zadmin" say hook.
|
||||
// 4 Quiet "!zclass" say hook.
|
||||
// 8 Quiet "!zspawn" say hook.
|
||||
// 16 Quiet "!ztele" say hook.
|
||||
// 32 Quiet "!zhp" say hook.
|
||||
// 64 Quiet "!zmarket" say hook.
|
||||
|
||||
// ===========================
|
||||
// Account (module)
|
||||
// ===========================
|
||||
@ -465,7 +500,7 @@ CvarsHook(bool:unhook = false)
|
||||
|
||||
// Hook cvar to prevent it from changing.
|
||||
HookConVarChange(g_hAutoTeamBalance, CvarsHookLocked);
|
||||
//HookConVarChange(hLimitTeams, CvarsHookLocked);
|
||||
HookConVarChange(g_hLimitTeams, CvarsHookLocked);
|
||||
HookConVarChange(g_hRestartGame, CvarsHookRestartGame);
|
||||
|
||||
// Anticamp shtuff. (needs to be moved to anticamp if these hooks are necessary)
|
||||
@ -486,6 +521,12 @@ public CvarsHookLocked(Handle:cvar, const String:oldvalue[], const String:newval
|
||||
// If cvar is mp_autoteambalance, then continue.
|
||||
if (cvar == g_hAutoTeamBalance)
|
||||
{
|
||||
// If plugin is reverting value, then stop.
|
||||
if (StringToInt(newvalue) == CVARS_AUTOTEAMBALANCE_LOCKED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Revert to locked value.
|
||||
SetConVarInt(g_hAutoTeamBalance, CVARS_AUTOTEAMBALANCE_LOCKED);
|
||||
|
||||
@ -498,6 +539,12 @@ public CvarsHookLocked(Handle:cvar, const String:oldvalue[], const String:newval
|
||||
// If cvar is mp_limitteams, then continue.
|
||||
else if (cvar == g_hLimitTeams)
|
||||
{
|
||||
// If plugin is reverting value, then stop.
|
||||
if (StringToInt(newvalue) == CVARS_LIMITTEAMS_LOCKED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Revert to locked value.
|
||||
SetConVarInt(g_hLimitTeams, CVARS_LIMITTEAMS_LOCKED);
|
||||
|
||||
|
@ -174,6 +174,7 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad
|
||||
// Forward event to modules.
|
||||
InfectOnClientSpawn(index);
|
||||
ClassOnClientSpawn(index); // Module event depends on infect module.
|
||||
RestrictOnClientSpawn(index);
|
||||
SEffectsOnClientSpawn(index);
|
||||
AccountOnClientSpawn(index);
|
||||
SpawnProtectOnClientSpawn(index);
|
||||
|
@ -17,10 +17,10 @@ new Handle:kvHitgroups = INVALID_HANDLE;
|
||||
/**
|
||||
* @section Player hitgroup values.
|
||||
*/
|
||||
#define HITGROUP_GENERIC 0
|
||||
#define HITGROUP_HEAD 1
|
||||
#define HITGROUP_CHEST 2
|
||||
#define HITGROUP_STOMACH 3
|
||||
#define HITGROUP_GENERIC 0
|
||||
#define HITGROUP_HEAD 1
|
||||
#define HITGROUP_CHEST 2
|
||||
#define HITGROUP_STOMACH 3
|
||||
#define HITGROUP_LEFTARM 4
|
||||
#define HITGROUP_RIGHTARM 5
|
||||
#define HITGROUP_LEFTLEG 6
|
||||
@ -59,20 +59,25 @@ HitgroupsLoad()
|
||||
return;
|
||||
}
|
||||
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/zr/hitgroups.txt");
|
||||
// Get hitgroups config path.
|
||||
decl String:pathhitgroups[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_HITGROUPS, pathhitgroups);
|
||||
|
||||
// If file isn't found, stop plugin.
|
||||
if (!FileToKeyValues(kvHitgroups, path))
|
||||
// If file doesn't exist, then log and stop.
|
||||
if (!exists)
|
||||
{
|
||||
// Log failure.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_HITGROUPS))
|
||||
{
|
||||
LogMessageFormatted(-1, "Hitgroups", "Config Validation", "Missing file hitgroups.txt, disabling hitgroup-based modules.", LOG_FORMAT_TYPE_FULL);
|
||||
LogMessageFormatted(-1, "Hitgroups", "Config Validation", "Missing hitgroups config file: %s", LOG_FORMAT_TYPE_ERROR, pathhitgroups);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Put file data into memory.
|
||||
FileToKeyValues(kvHitgroups, pathhitgroups);
|
||||
|
||||
// Validate hitgroups config.
|
||||
HitgroupsValidateConfig();
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ public MenuMainHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
// Copy return to resend variable.
|
||||
resend = !ZRAdminMenu(client);
|
||||
}
|
||||
// Select zclass.
|
||||
case 1:
|
||||
{
|
||||
// Send class menu
|
||||
@ -90,26 +91,30 @@ public MenuMainHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
// Don't resend this menu.
|
||||
resend = false;
|
||||
}
|
||||
// Select zspawn.
|
||||
case 2:
|
||||
{
|
||||
// Copy return to resend variable.
|
||||
resend = !ZMarketSend(client);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// Send zspawn command from client.
|
||||
ZSpawnClient(client);
|
||||
}
|
||||
case 4:
|
||||
// Select ztele.
|
||||
case 3:
|
||||
{
|
||||
// Copy return to resend variable.
|
||||
resend = !ZTele(client);
|
||||
}
|
||||
case 5:
|
||||
// Select zhp.
|
||||
case 4:
|
||||
{
|
||||
// Toggle ZHP.
|
||||
ZHPToggle(client);
|
||||
}
|
||||
// Select zmarket.
|
||||
case 5:
|
||||
{
|
||||
// Copy return to resend variable.
|
||||
resend = !ZMarketMenu(client);
|
||||
}
|
||||
}
|
||||
|
||||
// Resend is still true, then resend menu.
|
||||
|
@ -1,117 +1,250 @@
|
||||
/**
|
||||
* ====================
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
* File: models.inc
|
||||
* Author: Greyscale
|
||||
* ====================
|
||||
*
|
||||
* File: models.inc
|
||||
* Description: Model validation and API
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
new String:modelSuffix[8][16] = {".dx80.vtx", ".dx90.vtx", ".mdl", ".phy", ".sw.vtx", ".vvd", ".xbox", ".xbox.vtx"};
|
||||
/**
|
||||
* Maximum folder depth a model file can be located.
|
||||
*/
|
||||
#define MODELS_PATH_MAX_DEPTH 8
|
||||
|
||||
new Handle:arrayModels = INVALID_HANDLE;
|
||||
/**
|
||||
* Maximum string length of a folder a model file is located under.
|
||||
*/
|
||||
#define MODELS_PATH_DIR_MAX_LENGTH 32
|
||||
|
||||
FileLinesToArray(Handle:array, const Handle:file)
|
||||
/**
|
||||
* Array that stores a list of validated models.
|
||||
*/
|
||||
new Handle:arrayModelsList = INVALID_HANDLE;
|
||||
|
||||
ModelsLoad()
|
||||
{
|
||||
ClearArray(array);
|
||||
// Add models to downloads table and validate.
|
||||
ModelsPrepModels();
|
||||
|
||||
decl String:line[128];
|
||||
// Add download entries to downloads table and validate.
|
||||
ModelsPrepDownloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate model paths and add to downloads table.
|
||||
*/
|
||||
ModelsPrepModels()
|
||||
{
|
||||
// Get models file path.
|
||||
decl String:pathmodels[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_MODELS, pathmodels);
|
||||
|
||||
while(!IsEndOfFile(file) && ReadFileLine(file, line, sizeof(line)))
|
||||
// If file doesn't exist, then log and stop.
|
||||
if (!exists)
|
||||
{
|
||||
if (StrContains(line, ";") == -1)
|
||||
// Log failure and stop plugin.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
if (StrContains(line, "//") > -1)
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Missing models file: %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
}
|
||||
|
||||
// If model array exists, then destroy it.
|
||||
if (arrayModelsList != INVALID_HANDLE)
|
||||
{
|
||||
CloseHandle(arrayModelsList);
|
||||
}
|
||||
|
||||
arrayModelsList = ConfigLinesToArray(pathmodels);
|
||||
|
||||
// If array couldn't be created, then fail.
|
||||
if (arrayModelsList == INVALID_HANDLE)
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Error parsing %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
|
||||
new modelcount;
|
||||
new modelvalidcount;
|
||||
new modelfilecount;
|
||||
|
||||
decl String:modelbase[PLATFORM_MAX_PATH];
|
||||
decl String:modelpath[PLATFORM_MAX_PATH];
|
||||
decl String:modelname[MODELS_PATH_DIR_MAX_LENGTH];
|
||||
decl String:modelfile[MODELS_PATH_DIR_MAX_LENGTH];
|
||||
decl String:modeldiskname[MODELS_PATH_DIR_MAX_LENGTH];
|
||||
decl String:modelfullpath[PLATFORM_MAX_PATH];
|
||||
|
||||
new String:baseexploded[MODELS_PATH_MAX_DEPTH][MODELS_PATH_DIR_MAX_LENGTH];
|
||||
|
||||
new FileType:type;
|
||||
|
||||
new models = modelcount = GetArraySize(arrayModelsList);
|
||||
|
||||
// x = model array index.
|
||||
for (new x = 0; x < models; x++)
|
||||
{
|
||||
// Get base model path (rawline in models.txt)
|
||||
GetArrayString(arrayModelsList, x, modelbase, sizeof(modelbase));
|
||||
|
||||
// Explode path into pieces. (separated by "/")
|
||||
new strings = ExplodeString(modelbase, "/", baseexploded, MODELS_PATH_MAX_DEPTH, MODELS_PATH_DIR_MAX_LENGTH);
|
||||
|
||||
// Get model file name.
|
||||
strcopy(modelname, sizeof(modelname), baseexploded[strings - 1]);
|
||||
|
||||
// Get the path to the file.
|
||||
// Works by truncating original path by the length of the file name.
|
||||
strcopy(modelpath, strlen(modelbase) - strlen(modelname), modelbase);
|
||||
|
||||
// Open dir containing model files.
|
||||
new Handle:modeldir = OpenDirectory(modelpath);
|
||||
|
||||
// Reset model file count.
|
||||
modelfilecount = 0;
|
||||
|
||||
while (ReadDirEntry(modeldir, modelfile, sizeof(modelfile), type))
|
||||
{
|
||||
// If entry isn't a file, then stop.
|
||||
if (type != FileType_File)
|
||||
{
|
||||
SplitString(line, "//", line, sizeof(line));
|
||||
continue;
|
||||
}
|
||||
TrimString(line);
|
||||
|
||||
if (!StrEqual(line, "", false))
|
||||
// Find break point index in the string to get model name.
|
||||
// Add one because it seems to break on the character before.
|
||||
new breakpoint = FindCharInString(modelfile, '.') + 1;
|
||||
strcopy(modeldiskname, breakpoint, modelfile);
|
||||
|
||||
// If this file doesn't match, then stop.
|
||||
if (!StrEqual(modelname, modeldiskname, false))
|
||||
{
|
||||
PushArrayString(array, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Format a full path string.
|
||||
strcopy(modelfullpath, sizeof(modelfullpath), modelpath);
|
||||
Format(modelfullpath, sizeof(modelfullpath), "%s/%s", modelfullpath, modelfile);
|
||||
|
||||
// Precache model file and add to downloads table.
|
||||
PrecacheModel(modelfullpath);
|
||||
AddFileToDownloadsTable(modelfullpath);
|
||||
|
||||
// Increment modelfilecount
|
||||
modelfilecount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadModelData()
|
||||
{
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/zr/models.txt");
|
||||
|
||||
if (arrayModels != INVALID_HANDLE)
|
||||
{
|
||||
CloseHandle(arrayModels);
|
||||
}
|
||||
|
||||
arrayModels = CreateArray(256, 0);
|
||||
|
||||
new Handle:fileModels = OpenFile(path, "r");
|
||||
if (fileModels == INVALID_HANDLE)
|
||||
{
|
||||
SetFailState("\"%s\" missing from server", path);
|
||||
}
|
||||
|
||||
FileLinesToArray(arrayModels, fileModels);
|
||||
|
||||
if (!GetArraySize(arrayModels))
|
||||
{
|
||||
SetFailState("No models listed in models.txt, please add some models then restart");
|
||||
}
|
||||
|
||||
decl String:model[256];
|
||||
decl String:modelpath[256];
|
||||
|
||||
new modelsize = GetArraySize(arrayModels);
|
||||
for (new x = 0; x < modelsize; x++)
|
||||
{
|
||||
for (new y = 0; y < 8; y++)
|
||||
|
||||
// Increment modelvalidcount if model files are valid.
|
||||
if (modelfilecount)
|
||||
{
|
||||
GetArrayString(arrayModels, x, model, sizeof(model));
|
||||
Format(modelpath, sizeof(modelpath), "%s%s", model, modelSuffix[y]);
|
||||
if (FileExists(modelpath))
|
||||
{
|
||||
PrecacheModel(modelpath);
|
||||
AddFileToDownloadsTable(modelpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(fileModels);
|
||||
}
|
||||
|
||||
LoadDownloadData()
|
||||
{
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/zr/downloads.txt");
|
||||
|
||||
new Handle:fileDownloads = OpenFile(path, "r");
|
||||
|
||||
if (fileDownloads == INVALID_HANDLE)
|
||||
{
|
||||
SetFailState("\"%s\" missing from server", path);
|
||||
}
|
||||
|
||||
new Handle:arrayDownloads = CreateArray(256, 0);
|
||||
|
||||
FileLinesToArray(arrayDownloads, fileDownloads);
|
||||
|
||||
decl String:file[256];
|
||||
|
||||
new downloadsize = GetArraySize(arrayDownloads);
|
||||
for (new x = 0; x < downloadsize; x++)
|
||||
{
|
||||
GetArrayString(arrayDownloads, x, file, sizeof(file));
|
||||
if (FileExists(file))
|
||||
{
|
||||
AddFileToDownloadsTable(file);
|
||||
modelvalidcount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZR_LogMessage("File load failed", file);
|
||||
// Remove client from array.
|
||||
RemoveFromArray(arrayModelsList, x);
|
||||
|
||||
// Subtract one from count.
|
||||
models--;
|
||||
|
||||
// Backtrack one index, because we deleted it out from under the loop.
|
||||
x--;
|
||||
|
||||
// Log missing model files.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Missing model files on server (%s)", LOG_FORMAT_TYPE_ERROR, modelbase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log model validation info.
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, modelcount, modelvalidcount, modelcount - modelvalidcount);
|
||||
|
||||
// If none of the model paths are valid, then log and fail.
|
||||
if (!modelvalidcount)
|
||||
{
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "No usable model paths in %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(fileDownloads);
|
||||
CloseHandle(arrayDownloads);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate custom download paths and add to downloads table.
|
||||
*/
|
||||
ModelsPrepDownloads()
|
||||
{
|
||||
// Get downloads file path.
|
||||
decl String:pathdownloads[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_DOWNLOADS, pathdownloads);
|
||||
|
||||
// If file doesn't exist, then log.
|
||||
if (!exists)
|
||||
{
|
||||
// Log error, then stop.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing downloads file: %s", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
new Handle:arrayDownloadsList = ConfigLinesToArray(pathdownloads);
|
||||
|
||||
// If array couldn't be created, then fail.
|
||||
if (arrayModelsList == INVALID_HANDLE)
|
||||
{
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Error parsing %s", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
}
|
||||
}
|
||||
|
||||
new downloadcount;
|
||||
new downloadvalidcount;
|
||||
|
||||
decl String:downloadpath[PLATFORM_MAX_PATH];
|
||||
|
||||
new downloads = downloadcount = GetArraySize(arrayDownloadsList);
|
||||
|
||||
// x = download array index.
|
||||
for (new x = 0; x < downloads; x++)
|
||||
{
|
||||
// Get base model path (rawline in models.txt)
|
||||
GetArrayString(arrayDownloadsList, x, downloadpath, sizeof(downloadpath));
|
||||
|
||||
// If file doesn't exist, then remove, log, and stop.
|
||||
if (!FileExists(downloadpath))
|
||||
{
|
||||
// Remove client from array.
|
||||
RemoveFromArray(arrayDownloadsList, x);
|
||||
|
||||
// Subtract one from count.
|
||||
downloads--;
|
||||
|
||||
// Backtrack one index, because we deleted it out from under the loop.
|
||||
x--;
|
||||
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing file (%s)", LOG_FORMAT_TYPE_ERROR, downloadpath);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Increment downloadvalidcount
|
||||
downloadvalidcount++;
|
||||
|
||||
// Precache model file and add to downloads table.
|
||||
AddFileToDownloadsTable(downloadpath);
|
||||
}
|
||||
|
||||
// Log model validation info.
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, downloadcount, downloadvalidcount, downloadcount - downloadvalidcount);
|
||||
}
|
@ -70,8 +70,8 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
||||
if (strcmp(modelpath, "random", false) == 0)
|
||||
{
|
||||
// TODO: Make a function that gets a random model from the specified team.
|
||||
new randmodel = GetRandomInt(0, GetArraySize(arrayModels) - 1);
|
||||
GetArrayString(arrayModels, randmodel, modelpath, sizeof(modelpath));
|
||||
new randmodel = GetRandomInt(0, GetArraySize(arrayModelsList) - 1);
|
||||
GetArrayString(arrayModelsList, randmodel, modelpath, sizeof(modelpath));
|
||||
Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
|
||||
}
|
||||
|
||||
|
@ -261,6 +261,9 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
{
|
||||
ClassMenuMain(client);
|
||||
}
|
||||
|
||||
// Stop so menu doesn't reopen.
|
||||
return;
|
||||
}
|
||||
case MenuAction_End:
|
||||
{
|
||||
|
@ -251,6 +251,12 @@ RoundEndOutcome:RoundEndReasonToOutcome(reason)
|
||||
*/
|
||||
public Action:RoundEndTimer(Handle:timer)
|
||||
{
|
||||
// If there aren't clients on both teams, then stop.
|
||||
if (ZRTeamHasClients())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Terminate the round with humans as the winner.
|
||||
RoundEndTerminateRound(ROUNDEND_DELAY, HumansWin);
|
||||
}
|
||||
|
@ -28,6 +28,20 @@
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Say hook quiet flags.
|
||||
*/
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZMENU 1
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZADMIN 2
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZCLASS 4
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZSPAWN 8
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZTELE 16
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZHP 32
|
||||
#define SAYHOOKS_KEYWORD_FLAG_ZMARKET 64
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Say hooks module init function.
|
||||
*/
|
||||
@ -55,50 +69,114 @@ public Action:SayHooksCmdSay(client, argc)
|
||||
// Strip away the quotes.
|
||||
ReplaceString(args, sizeof(args), "\"", "");
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
if (StrEqual(args, SAYHOOKS_KEYWORD_ZMENU, false))
|
||||
new chatflag = SayHooksChatToFlag(args);
|
||||
|
||||
// If chatflag is invalid, then continue.
|
||||
if (!chatflag)
|
||||
{
|
||||
MenuMain(client);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZADMIN, false))
|
||||
switch(chatflag)
|
||||
{
|
||||
ZRAdminMenu(client);
|
||||
// Client triggered ZMenu flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZMENU:
|
||||
{
|
||||
// Send main menu.
|
||||
MenuMain(client);
|
||||
}
|
||||
// Client triggered ZAdmin flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZADMIN:
|
||||
{
|
||||
ZRAdminMenu(client);
|
||||
}
|
||||
// Client triggered ZClass flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZCLASS:
|
||||
{
|
||||
// Send class menu.
|
||||
ClassMenuMain(client);
|
||||
}
|
||||
// Client triggered ZSpawn flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZSPAWN:
|
||||
{
|
||||
// Spawns a late-joining client into the game.
|
||||
ZSpawnClient(client);
|
||||
}
|
||||
// Client triggered ZTele flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZTELE:
|
||||
{
|
||||
ZTele(client);
|
||||
}
|
||||
// Client triggered ZHP flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZHP:
|
||||
{
|
||||
// Toggle ZHP.
|
||||
ZHPToggle(client);
|
||||
}
|
||||
// Client triggered ZMarket flag.
|
||||
case SAYHOOKS_KEYWORD_FLAG_ZMARKET:
|
||||
{
|
||||
// Send market menu.
|
||||
ZMarketMenu(client);
|
||||
}
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZCLASS, false))
|
||||
// If quiet cvar is disabled, then continue.
|
||||
new bool:quiet = GetConVarBool(g_hCvarsList[CVAR_SAYHOOKS_QUIET]);
|
||||
if (!quiet)
|
||||
{
|
||||
ClassMenuMain(client);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZSPAWN, false))
|
||||
// If word is flagged to be quieted, then stop.
|
||||
new quietflags = GetConVarInt(g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS]);
|
||||
if (quietflags & chatflag)
|
||||
{
|
||||
// Spawns a late-joining client into the game.
|
||||
ZSpawnClient(client);
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZTELE, false))
|
||||
{
|
||||
ZTele(client);
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZHP, false))
|
||||
{
|
||||
// Toggle ZHP.
|
||||
ZHPToggle(client);
|
||||
}
|
||||
|
||||
// If client triggered the zmenu keyword, then send menu.
|
||||
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZMARKET, false))
|
||||
{
|
||||
// Send market menu.
|
||||
ZMarketSend(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert chat text into a defined flag.
|
||||
*
|
||||
* @param chat The chat text to convert.
|
||||
* @return Returns flag for word given, returns 0 if matches none.
|
||||
*/
|
||||
SayHooksChatToFlag(const String:chat[])
|
||||
{
|
||||
// Return flag for chatstring.
|
||||
|
||||
if (StrEqual(chat, SAYHOOKS_KEYWORD_ZMENU, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZMENU;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZADMIN, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZADMIN;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZCLASS, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZCLASS;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZSPAWN, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZSPAWN;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZTELE, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZTELE;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZHP, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZHP;
|
||||
}
|
||||
else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZMARKET, false))
|
||||
{
|
||||
return SAYHOOKS_KEYWORD_FLAG_ZMARKET;
|
||||
}
|
||||
|
||||
// Return 0.
|
||||
return 0;
|
||||
}
|
@ -19,7 +19,7 @@ new bool:g_bMarket;
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
bool:ZMarketSend(client)
|
||||
bool:ZMarketMenu(client)
|
||||
{
|
||||
// If market is disabled, then stop.
|
||||
if (!g_bMarket)
|
||||
@ -151,5 +151,5 @@ public Market_PostOnWeaponSelected(client, &bool:allowed)
|
||||
}
|
||||
|
||||
// Resend market menu.
|
||||
ZMarketSend(client);
|
||||
ZMarketMenu(client);
|
||||
}
|
@ -48,16 +48,7 @@ WeaponsMenuMain(client)
|
||||
|
||||
AddMenuItem(menu_weapons_main, "toggleweaponrestriction", toggleweaponrestriction);
|
||||
AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction);
|
||||
|
||||
// Disable market option if market isn't installed.
|
||||
if (g_bMarket)
|
||||
{
|
||||
AddMenuItem(menu_weapons_main, "zmarket", zmarket);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMenuItem(menu_weapons_main, "zmarket", zmarket, ITEMDRAW_DISABLED);
|
||||
}
|
||||
AddMenuItem(menu_weapons_main, "zmarket", zmarket, MenuGetItemDraw(g_bMarket));
|
||||
|
||||
// Create a "Back" button to the weapons main menu.
|
||||
SetMenuExitBackButton(menu_weapons_main, true);
|
||||
|
@ -82,20 +82,26 @@ RestrictOnMapStart()
|
||||
// Restrict default restrictions. (set in weapons.txt)
|
||||
RestrictDefaultRestrictions();
|
||||
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapongroups.txt");
|
||||
// Get weapon groups config path.
|
||||
decl String:pathweapongroups[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_WEAPONGROUPS, pathweapongroups);
|
||||
|
||||
// If file isn't found, stop plugin.
|
||||
if (!FileToKeyValues(kvWeaponGroups, path))
|
||||
// If file doesn't exist, then log and stop.
|
||||
if (!exists)
|
||||
{
|
||||
// Log failure.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
|
||||
{
|
||||
LogMessageFormatted(-1, "Weapons", "Config Validation", "Missing file weapongroups.txt.", LOG_FORMAT_TYPE_ERROR);
|
||||
LogMessageFormatted(-1, "Weapons", "Config Validation", "Missing weapon groups config file: %s", LOG_FORMAT_TYPE_ERROR, pathweapongroups);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Put file data into memory.
|
||||
FileToKeyValues(kvWeaponGroups, pathweapongroups);
|
||||
|
||||
// Validate weapon groups config.
|
||||
RestrictValidateWeaponGroups();
|
||||
}
|
||||
|
||||
@ -197,6 +203,7 @@ RestrictWeaponUnrestrictAll()
|
||||
*/
|
||||
RestrictClientInit(client)
|
||||
{
|
||||
// Hook "canuse" on client.
|
||||
gCanUseHookID[client] = Hacks_Hook(client, HACKS_HTYPE_WEAPON_CANUSE, RestrictCanUse, false);
|
||||
}
|
||||
|
||||
@ -207,9 +214,22 @@ RestrictClientInit(client)
|
||||
*/
|
||||
RestrictOnClientDisconnect(client)
|
||||
{
|
||||
// Unhook "canuse" on client.
|
||||
Hacks_Unhook(gCanUseHookID[client]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Client is spawning into the game.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
RestrictOnClientSpawn(client)
|
||||
{
|
||||
// Re-hook "canuse" on client.
|
||||
Hacks_Unhook(gCanUseHookID[client]);
|
||||
gCanUseHookID[client] = Hacks_Hook(client, HACKS_HTYPE_WEAPON_CANUSE, RestrictCanUse, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback function for the "buy" command
|
||||
* Used to block use of this command under certain conditions.
|
||||
|
@ -82,20 +82,25 @@ WeaponsLoad()
|
||||
return;
|
||||
}
|
||||
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapons.txt");
|
||||
// Get weapons config path.
|
||||
decl String:pathweapons[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_WEAPONS, pathweapons);
|
||||
|
||||
// If file isn't found, stop plugin.
|
||||
if (!FileToKeyValues(kvWeapons, path))
|
||||
// If file doesn't exist, then log and stop.
|
||||
if (!exists)
|
||||
{
|
||||
// Log failure.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
|
||||
{
|
||||
LogMessageFormatted(-1, "Weapons", "Config Validation", "Missing file weapons.txt.", LOG_FORMAT_TYPE_ERROR);
|
||||
LogMessageFormatted(-1, "Weapons", "Config Validation", "Missing weapons config file: %s", LOG_FORMAT_TYPE_ERROR, pathweapons);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Put file data into memory.
|
||||
FileToKeyValues(kvWeapons, pathweapons);
|
||||
|
||||
// Validate weapons config.
|
||||
WeaponsValidateConfig();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user