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:
Greyscale 2009-04-30 07:36:57 +02:00
parent 1a638cfbac
commit 8da309e4f4
15 changed files with 466 additions and 191 deletions

View File

@ -13,7 +13,7 @@
"EyeAngles" "EyeAngles"
{ {
"windows" "206" "windows" "206"
"osx" "207" "linux" "207"
} }
} }

View File

@ -24,6 +24,7 @@
#include "zr/zombiereloaded" #include "zr/zombiereloaded"
#include "zr/log" #include "zr/log"
#include "zr/cvars" #include "zr/cvars"
#include "zr/config"
#include "zr/translation" #include "zr/translation"
#include "zr/tools" #include "zr/tools"
#include "zr/models" #include "zr/models"
@ -166,9 +167,6 @@ public OnLibraryAdded(const String:name[])
*/ */
public OnMapStart() public OnMapStart()
{ {
LoadModelData();
LoadDownloadData();
// Forward event to modules. // Forward event to modules.
RoundEndOnMapStart(); RoundEndOnMapStart();
InfectOnMapStart(); InfectOnMapStart();
@ -191,26 +189,9 @@ public OnMapEnd()
*/ */
public OnConfigsExecuted() 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. // Forward event to modules.
ConfigLoad();
ModelsLoad();
WeaponsLoad(); WeaponsLoad();
HitgroupsLoad(); HitgroupsLoad();
InfectLoad(); InfectLoad();

View File

@ -24,6 +24,12 @@
enum CvarsList enum CvarsList
{ {
Handle:CVAR_ENABLE, 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_SPAWN,
Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_RANDOM,
Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, Handle:CVAR_CLASSES_DEFAULT_ZOMBIE,
@ -40,6 +46,8 @@ enum CvarsList
Handle:CVAR_DAMAGE_SUICIDE_ZOMBIE, Handle:CVAR_DAMAGE_SUICIDE_ZOMBIE,
Handle:CVAR_DAMAGE_SUICIDE_HUMAN, Handle:CVAR_DAMAGE_SUICIDE_HUMAN,
Handle:CVAR_DAMAGE_SUICIDE_CMDS, Handle:CVAR_DAMAGE_SUICIDE_CMDS,
Handle:CVAR_SAYHOOKS_QUIET,
Handle:CVAR_SAYHOOKS_QUIET_FLAGS,
Handle:CVAR_ROUNDEND_OVERLAY, Handle:CVAR_ROUNDEND_OVERLAY,
Handle:CVAR_ROUNDEND_OVERLAY_ZOMBIE, Handle:CVAR_ROUNDEND_OVERLAY_ZOMBIE,
Handle:CVAR_ROUNDEND_OVERLAY_HUMAN, Handle:CVAR_ROUNDEND_OVERLAY_HUMAN,
@ -177,6 +185,17 @@ CvarsCreate()
// (None) // (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) // Tools (core)
// =========================== // ===========================
@ -290,6 +309,22 @@ CvarsCreate()
g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS] = CreateConVar("zr_damage_suicide_cmds", "kill, spectate, jointeam", ""); g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS] = CreateConVar("zr_damage_suicide_cmds", "kill, spectate, jointeam", "");
// Old Desc: List of suicide commands to intercept. (Delimited by \", \" // 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) // Account (module)
// =========================== // ===========================
@ -465,7 +500,7 @@ CvarsHook(bool:unhook = false)
// Hook cvar to prevent it from changing. // Hook cvar to prevent it from changing.
HookConVarChange(g_hAutoTeamBalance, CvarsHookLocked); HookConVarChange(g_hAutoTeamBalance, CvarsHookLocked);
//HookConVarChange(hLimitTeams, CvarsHookLocked); HookConVarChange(g_hLimitTeams, CvarsHookLocked);
HookConVarChange(g_hRestartGame, CvarsHookRestartGame); HookConVarChange(g_hRestartGame, CvarsHookRestartGame);
// Anticamp shtuff. (needs to be moved to anticamp if these hooks are necessary) // 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 is mp_autoteambalance, then continue.
if (cvar == g_hAutoTeamBalance) if (cvar == g_hAutoTeamBalance)
{ {
// If plugin is reverting value, then stop.
if (StringToInt(newvalue) == CVARS_AUTOTEAMBALANCE_LOCKED)
{
return;
}
// Revert to locked value. // Revert to locked value.
SetConVarInt(g_hAutoTeamBalance, CVARS_AUTOTEAMBALANCE_LOCKED); 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. // If cvar is mp_limitteams, then continue.
else if (cvar == g_hLimitTeams) else if (cvar == g_hLimitTeams)
{ {
// If plugin is reverting value, then stop.
if (StringToInt(newvalue) == CVARS_LIMITTEAMS_LOCKED)
{
return;
}
// Revert to locked value. // Revert to locked value.
SetConVarInt(g_hLimitTeams, CVARS_LIMITTEAMS_LOCKED); SetConVarInt(g_hLimitTeams, CVARS_LIMITTEAMS_LOCKED);

View File

@ -174,6 +174,7 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad
// Forward event to modules. // Forward event to modules.
InfectOnClientSpawn(index); InfectOnClientSpawn(index);
ClassOnClientSpawn(index); // Module event depends on infect module. ClassOnClientSpawn(index); // Module event depends on infect module.
RestrictOnClientSpawn(index);
SEffectsOnClientSpawn(index); SEffectsOnClientSpawn(index);
AccountOnClientSpawn(index); AccountOnClientSpawn(index);
SpawnProtectOnClientSpawn(index); SpawnProtectOnClientSpawn(index);

View File

@ -59,20 +59,25 @@ HitgroupsLoad()
return; return;
} }
decl String:path[PLATFORM_MAX_PATH]; // Get hitgroups config path.
BuildPath(Path_SM, path, sizeof(path), "configs/zr/hitgroups.txt"); decl String:pathhitgroups[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_HITGROUPS, pathhitgroups);
// If file isn't found, stop plugin. // If file doesn't exist, then log and stop.
if (!FileToKeyValues(kvHitgroups, path)) if (!exists)
{ {
// Log failure.
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_HITGROUPS)) 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; return;
} }
// Put file data into memory.
FileToKeyValues(kvHitgroups, pathhitgroups);
// Validate hitgroups config. // Validate hitgroups config.
HitgroupsValidateConfig(); HitgroupsValidateConfig();
} }

View File

@ -82,6 +82,7 @@ public MenuMainHandle(Handle:menu, MenuAction:action, client, slot)
// Copy return to resend variable. // Copy return to resend variable.
resend = !ZRAdminMenu(client); resend = !ZRAdminMenu(client);
} }
// Select zclass.
case 1: case 1:
{ {
// Send class menu // Send class menu
@ -90,26 +91,30 @@ public MenuMainHandle(Handle:menu, MenuAction:action, client, slot)
// Don't resend this menu. // Don't resend this menu.
resend = false; resend = false;
} }
// Select zspawn.
case 2: case 2:
{
// Copy return to resend variable.
resend = !ZMarketSend(client);
}
case 3:
{ {
// Send zspawn command from client. // Send zspawn command from client.
ZSpawnClient(client); ZSpawnClient(client);
} }
case 4: // Select ztele.
case 3:
{ {
// Copy return to resend variable. // Copy return to resend variable.
resend = !ZTele(client); resend = !ZTele(client);
} }
case 5: // Select zhp.
case 4:
{ {
// Toggle ZHP. // Toggle ZHP.
ZHPToggle(client); ZHPToggle(client);
} }
// Select zmarket.
case 5:
{
// Copy return to resend variable.
resend = !ZMarketMenu(client);
}
} }
// Resend is still true, then resend menu. // Resend is still true, then resend menu.

View File

@ -1,117 +1,250 @@
/** /*
* ==================== * ============================================================================
*
* Zombie:Reloaded * Zombie:Reloaded
*
* File: models.inc * File: models.inc
* Author: Greyscale * 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();
while(!IsEndOfFile(file) && ReadFileLine(file, line, sizeof(line)))
{
if (StrContains(line, ";") == -1)
{
if (StrContains(line, "//") > -1)
{
SplitString(line, "//", line, sizeof(line));
}
TrimString(line);
if (!StrEqual(line, "", false))
{
PushArrayString(array, line);
}
}
}
} }
LoadModelData() /**
* Validate model paths and add to downloads table.
*/
ModelsPrepModels()
{ {
decl String:path[PLATFORM_MAX_PATH]; // Get models file path.
BuildPath(Path_SM, path, sizeof(path), "configs/zr/models.txt"); decl String:pathmodels[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_MODELS, pathmodels);
if (arrayModels != INVALID_HANDLE) // If file doesn't exist, then log and stop.
if (!exists)
{ {
CloseHandle(arrayModels); // Log failure and stop plugin.
} if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
arrayModels = CreateArray(256, 0);
new Handle:fileModels = OpenFile(path, "r");
if (fileModels == INVALID_HANDLE)
{ {
SetFailState("\"%s\" missing from server", path); LogMessageFormatted(-1, "Models", "Config Validation", "Missing models file: %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
}
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++)
{
GetArrayString(arrayModels, x, model, sizeof(model));
Format(modelpath, sizeof(modelpath), "%s%s", model, modelSuffix[y]);
if (FileExists(modelpath))
{
PrecacheModel(modelpath);
AddFileToDownloadsTable(modelpath);
} }
} }
// If model array exists, then destroy it.
if (arrayModelsList != INVALID_HANDLE)
{
CloseHandle(arrayModelsList);
} }
CloseHandle(fileModels); arrayModelsList = ConfigLinesToArray(pathmodels);
}
LoadDownloadData() // If array couldn't be created, then fail.
{ if (arrayModelsList == INVALID_HANDLE)
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); LogMessageFormatted(-1, "Models", "Config Validation", "Error parsing %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
} }
new Handle:arrayDownloads = CreateArray(256, 0); new modelcount;
new modelvalidcount;
new modelfilecount;
FileLinesToArray(arrayDownloads, fileDownloads); 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];
decl String:file[256]; new String:baseexploded[MODELS_PATH_MAX_DEPTH][MODELS_PATH_DIR_MAX_LENGTH];
new downloadsize = GetArraySize(arrayDownloads); new FileType:type;
for (new x = 0; x < downloadsize; x++)
new models = modelcount = GetArraySize(arrayModelsList);
// x = model array index.
for (new x = 0; x < models; x++)
{ {
GetArrayString(arrayDownloads, x, file, sizeof(file)); // Get base model path (rawline in models.txt)
if (FileExists(file)) 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))
{ {
AddFileToDownloadsTable(file); // If entry isn't a file, then stop.
if (type != FileType_File)
{
continue;
}
// 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))
{
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++;
}
// Increment modelvalidcount if model files are valid.
if (modelfilecount)
{
modelvalidcount++;
} }
else 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);
}
} }
} }
CloseHandle(fileDownloads); // Log model validation info.
CloseHandle(arrayDownloads); 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);
}
}
}
/**
* 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);
} }

View File

@ -70,8 +70,8 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
if (strcmp(modelpath, "random", false) == 0) if (strcmp(modelpath, "random", false) == 0)
{ {
// TODO: Make a function that gets a random model from the specified team. // TODO: Make a function that gets a random model from the specified team.
new randmodel = GetRandomInt(0, GetArraySize(arrayModels) - 1); new randmodel = GetRandomInt(0, GetArraySize(arrayModelsList) - 1);
GetArrayString(arrayModels, randmodel, modelpath, sizeof(modelpath)); GetArrayString(arrayModelsList, randmodel, modelpath, sizeof(modelpath));
Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath); Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
} }

View File

@ -261,6 +261,9 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot)
{ {
ClassMenuMain(client); ClassMenuMain(client);
} }
// Stop so menu doesn't reopen.
return;
} }
case MenuAction_End: case MenuAction_End:
{ {

View File

@ -251,6 +251,12 @@ RoundEndOutcome:RoundEndReasonToOutcome(reason)
*/ */
public Action:RoundEndTimer(Handle:timer) 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. // Terminate the round with humans as the winner.
RoundEndTerminateRound(ROUNDEND_DELAY, HumansWin); RoundEndTerminateRound(ROUNDEND_DELAY, HumansWin);
} }

View File

@ -28,6 +28,20 @@
* @endsection * @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. * Say hooks module init function.
*/ */
@ -55,50 +69,114 @@ public Action:SayHooksCmdSay(client, argc)
// Strip away the quotes. // Strip away the quotes.
ReplaceString(args, sizeof(args), "\"", ""); ReplaceString(args, sizeof(args), "\"", "");
// If client triggered the zmenu keyword, then send menu. new chatflag = SayHooksChatToFlag(args);
if (StrEqual(args, SAYHOOKS_KEYWORD_ZMENU, false))
// If chatflag is invalid, then continue.
if (!chatflag)
{ {
MenuMain(client); return Plugin_Continue;
} }
// If client triggered the zmenu keyword, then send menu. switch(chatflag)
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZADMIN, false)) {
// 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); ZRAdminMenu(client);
} }
// Client triggered ZClass flag.
// If client triggered the zmenu keyword, then send menu. case SAYHOOKS_KEYWORD_FLAG_ZCLASS:
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZCLASS, false))
{ {
// Send class menu.
ClassMenuMain(client); ClassMenuMain(client);
} }
// Client triggered ZSpawn flag.
// If client triggered the zmenu keyword, then send menu. case SAYHOOKS_KEYWORD_FLAG_ZSPAWN:
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZSPAWN, false))
{ {
// Spawns a late-joining client into the game. // Spawns a late-joining client into the game.
ZSpawnClient(client); ZSpawnClient(client);
} }
// Client triggered ZTele flag.
// If client triggered the zmenu keyword, then send menu. case SAYHOOKS_KEYWORD_FLAG_ZTELE:
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZTELE, false))
{ {
ZTele(client); ZTele(client);
} }
// Client triggered ZHP flag.
// If client triggered the zmenu keyword, then send menu. case SAYHOOKS_KEYWORD_FLAG_ZHP:
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZHP, false))
{ {
// Toggle ZHP. // Toggle ZHP.
ZHPToggle(client); ZHPToggle(client);
} }
// Client triggered ZMarket flag.
// If client triggered the zmenu keyword, then send menu. case SAYHOOKS_KEYWORD_FLAG_ZMARKET:
else if (StrEqual(args, SAYHOOKS_KEYWORD_ZMARKET, false))
{ {
// Send market menu. // Send market menu.
ZMarketSend(client); ZMarketMenu(client);
}
}
// If quiet cvar is disabled, then continue.
new bool:quiet = GetConVarBool(g_hCvarsList[CVAR_SAYHOOKS_QUIET]);
if (!quiet)
{
return Plugin_Continue;
}
// If word is flagged to be quieted, then stop.
new quietflags = GetConVarInt(g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS]);
if (quietflags & chatflag)
{
return Plugin_Handled;
} }
return Plugin_Continue; 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;
}

View File

@ -19,7 +19,7 @@ new bool:g_bMarket;
* *
* @param client The client index. * @param client The client index.
*/ */
bool:ZMarketSend(client) bool:ZMarketMenu(client)
{ {
// If market is disabled, then stop. // If market is disabled, then stop.
if (!g_bMarket) if (!g_bMarket)
@ -151,5 +151,5 @@ public Market_PostOnWeaponSelected(client, &bool:allowed)
} }
// Resend market menu. // Resend market menu.
ZMarketSend(client); ZMarketMenu(client);
} }

View File

@ -48,16 +48,7 @@ WeaponsMenuMain(client)
AddMenuItem(menu_weapons_main, "toggleweaponrestriction", toggleweaponrestriction); AddMenuItem(menu_weapons_main, "toggleweaponrestriction", toggleweaponrestriction);
AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction); AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction);
AddMenuItem(menu_weapons_main, "zmarket", zmarket, MenuGetItemDraw(g_bMarket));
// 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);
}
// Create a "Back" button to the weapons main menu. // Create a "Back" button to the weapons main menu.
SetMenuExitBackButton(menu_weapons_main, true); SetMenuExitBackButton(menu_weapons_main, true);

View File

@ -82,20 +82,26 @@ RestrictOnMapStart()
// Restrict default restrictions. (set in weapons.txt) // Restrict default restrictions. (set in weapons.txt)
RestrictDefaultRestrictions(); RestrictDefaultRestrictions();
decl String:path[PLATFORM_MAX_PATH]; // Get weapon groups config path.
BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapongroups.txt"); decl String:pathweapongroups[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_WEAPONGROUPS, pathweapongroups);
// If file isn't found, stop plugin. // If file doesn't exist, then log and stop.
if (!FileToKeyValues(kvWeaponGroups, path)) if (!exists)
{ {
// Log failure.
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS)) 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; return;
} }
// Put file data into memory.
FileToKeyValues(kvWeaponGroups, pathweapongroups);
// Validate weapon groups config.
RestrictValidateWeaponGroups(); RestrictValidateWeaponGroups();
} }
@ -197,6 +203,7 @@ RestrictWeaponUnrestrictAll()
*/ */
RestrictClientInit(client) RestrictClientInit(client)
{ {
// Hook "canuse" on client.
gCanUseHookID[client] = Hacks_Hook(client, HACKS_HTYPE_WEAPON_CANUSE, RestrictCanUse, false); gCanUseHookID[client] = Hacks_Hook(client, HACKS_HTYPE_WEAPON_CANUSE, RestrictCanUse, false);
} }
@ -207,9 +214,22 @@ RestrictClientInit(client)
*/ */
RestrictOnClientDisconnect(client) RestrictOnClientDisconnect(client)
{ {
// Unhook "canuse" on client.
Hacks_Unhook(gCanUseHookID[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 * Command callback function for the "buy" command
* Used to block use of this command under certain conditions. * Used to block use of this command under certain conditions.

View File

@ -82,20 +82,25 @@ WeaponsLoad()
return; return;
} }
decl String:path[PLATFORM_MAX_PATH]; // Get weapons config path.
BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapons.txt"); decl String:pathweapons[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_WEAPONS, pathweapons);
// If file isn't found, stop plugin. // If file doesn't exist, then log and stop.
if (!FileToKeyValues(kvWeapons, path)) if (!exists)
{ {
// Log failure.
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS)) 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; return;
} }
// Put file data into memory.
FileToKeyValues(kvWeapons, pathweapons);
// Validate weapons config. // Validate weapons config.
WeaponsValidateConfig(); WeaponsValidateConfig();