diff --git a/cstrike/addons/sourcemod/configs/zr/weapongroups.txt b/cstrike/addons/sourcemod/configs/zr/weapongroups.txt deleted file mode 100644 index 8eec683..0000000 --- a/cstrike/addons/sourcemod/configs/zr/weapongroups.txt +++ /dev/null @@ -1,86 +0,0 @@ -// Weapon Lists -// -// -// Counter-Strike: Source | -// -----------------------| -// glock | -// usp | -// p228 | -// deagle | -// elite | -// fiveseven | -// m3 | -// xm1014 | -// mac10 | -// tmp | -// mp5navy | -// ump45 | -// p90 | -// galil | -// famas | -// ak47 | -// m4a1 | -// sg552 | -// aug | -// scout | -// sg550 | -// g3sg1 | -// awp | -// -----------------------| - - -// Format -// -// -// "weapon group name" -// { -// "weaponname (listed above)" {} <-- To satisfy the standard format of a keyvalues file, -// without these brackets the weapon will be ommitted -// } - - -"weapongroups" -{ - "pistols" - { - "glock" {} - "usp" {} - "p228" {} - "deagle" {} - "elite" {} - "fiveseven" {} - } - - "shotguns" - { - "m3" {} - "xm1014" {} - } - - "smgs" - { - "mac10" {} - "tmp" {} - "mp5navy" {} - "ump45" {} - "p90" {} - } - - "rifles" - { - "galil" {} - "famas" {} - "ak47" {} - "m4a1" {} - "sg552" {} - "aug" {} - } - - "snipers" - { - "scout" {} - "sg550" {} - "g2sg1" {} - "awp" {} - } -} \ No newline at end of file diff --git a/cstrike/addons/sourcemod/configs/zr/weapons/weapongroups.txt b/cstrike/addons/sourcemod/configs/zr/weapons/weapongroups.txt new file mode 100644 index 0000000..9b41133 --- /dev/null +++ b/cstrike/addons/sourcemod/configs/zr/weapons/weapongroups.txt @@ -0,0 +1,58 @@ +// Weapon Groups +// (See list of weapons in weapons.txt) + +// Format +// +// +// "weapon group name" (how it appears in chat messages) +// { +// "weaponname" {} <-- To satisfy the standard format of a keyvalues file, +// without these brackets the weapon will be skipped. +// Invalid weapons are logged and skipped. +// } + +"weapongroups" +{ + "Pistols" + { + "Glock" {} + "USP" {} + "P228" {} + "Deagle" {} + "Elite" {} + "Fiveseven" {} + } + + "Shotguns" + { + "M3" {} + "XM1014" {} + } + + "SMGs" + { + "Mac10" {} + "TMP" {} + "MP5Navy" {} + "UMP45" {} + "P90" {} + } + + "Rifles" + { + "Galil" {} + "Famas" {} + "AK47" {} + "M4A1" {} + "SG552" {} + "AUG" {} + } + + "Snipers" + { + "Scout" {} + "SG550" {} + "G2SG1" {} + "AWP" {} + } +} \ No newline at end of file diff --git a/cstrike/addons/sourcemod/configs/zr/weapons/weapons.txt b/cstrike/addons/sourcemod/configs/zr/weapons/weapons.txt new file mode 100644 index 0000000..4bc8718 --- /dev/null +++ b/cstrike/addons/sourcemod/configs/zr/weapons/weapons.txt @@ -0,0 +1,154 @@ +// Weapons +// +// Format +// +// "weaponname" // Name of the weapon (without weapon_ prefix) +// { +// "restrict" "no" (default) // Restricts the weapon on each map start +// "menu" "yes" (default) // Allows admins to toggle restriction with the menu +// } +// +// Duplicate weapon entries will show up separately in restrict menu, but +// only the first one's options are used. + +"weapons" // Counter-Strike: Source weapons +{ + "Glock" + { + "restrict" "no" + "menu" "yes" + } + + "USP" + { + "restrict" "no" + "menu" "yes" + } + + "P228" + { + "restrict" "no" + "menu" "yes" + } + + "Deagle" + { + "restrict" "no" + "menu" "yes" + } + + "Elite" + { + "restrict" "no" + "menu" "yes" + } + + "Fiveseven" + { + "restrict" "no" + "menu" "yes" + } + + "M3" + { + "restrict" "no" + "menu" "yes" + } + + "XM1014" + { + "restrict" "no" + "menu" "yes" + } + + "Mac10" + { + "restrict" "no" + "menu" "yes" + } + + "TMP" + { + "restrict" "no" + "menu" "yes" + } + + "MP5Navy" + { + "restrict" "no" + "menu" "yes" + } + + "UMP45" + { + "restrict" "no" + "menu" "yes" + } + + "P90" + { + "restrict" "no" + "menu" "yes" + } + + "Galil" + { + "restrict" "no" + "menu" "yes" + } + + "Famas" + { + "restrict" "no" + "menu" "yes" + } + + "AK47" + { + "restrict" "no" + "menu" "no" + } + + "M4A1" + { + "restrict" "no" + "menu" "yes" + } + + "SG552" + { + "restrict" "no" + "menu" "yes" + } + + "AUG" + { + "restrict" "no" + "menu" "yes" + } + + "Scout" + { + "restrict" "no" + "menu" "yes" + } + + "SG550" + { + "restrict" "no" + "menu" "yes" + } + + "GSG1" + { + "restrict" "no" + "menu" "yes" + } + + "AWP" + { + "restrict" "no" + "menu" "yes" + } + +} \ No newline at end of file diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index c7cf987..dcca35d 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -90,12 +90,6 @@ "en" "You are now susceptible to zombie infection." "ru" "Теперь вы восприимчивы к зомби инфекции." } - - "Market out of buyzone" - { - "en" "You are not in a buyzone." - "ru" "Вы вне зоны покупки." - } "!ztele amount" { @@ -171,35 +165,67 @@ } // =========================== - // Weapon Restrict + // Weapons // =========================== + // General + + "Zombie cant use weapon" + { + "en" "Zombies can't use weapons!" + "ru" "Зомби не могут использовать оружие!" + } + + // Market + + "Market out of buyzone" + { + "en" "You are not in a buyzone." + "ru" "Вы вне зоны покупки." + } + + // Restrict + "Restrict weapon" { "#format" "{1:s}" "en" "Weapon @green\"{1}\" @defaulthas been restricted." - "ru" "Оружие @green\"{1}\" было запрещено." } "Unrestrict weapon" { "#format" "{1:s}" "en" "Weapon @green\"{1}\" @defaulthas been unrestricted." - "ru" "Оружие @green\"{1}\" было разрешено." + } + + "Restrict weapon failed" + { + "#format" "{1:s}" + "en" "Weapon @green\"{1}\" @defaultis already restricted." + } + + "Unrestrict weapon failed" + { + "#format" "{1:s}" + "en" "Weapon @green\"{1}\" @default has no restrictions set." } "Restrict custom weapon group" { "#format" "{1:s},{2:s}" "en" "Weapon group @green\"{1}\" ({2}) @defaulthas been restricted." - "ru" "Группа оружия @green\"{1}\" ({2}) была запрещена." } "Unrestrict custom weapon group" { "#format" "{1:s},{2:s}" "en" "Weapon group @green\"{1}\" ({2}) @defaulthas been unrestricted." - "ru" "Группа оружия @green\"{1}\" ({2}) была разрешена." + } + + "Weapon invalid" + { + "#format" "{1:s}" + "en" "Weapon @green\"{1}\" @defaultis an invalid weapon name." } "Weapon is restricted" @@ -209,19 +235,42 @@ "ru" "Оружие @green{1} @default запрещено." } - "Weapon invalid" + // Menu + + "Weapons menu main title" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaultis not currently restricted." + "en" "Weapons Management" } - "Zombie cant use weapon" + "Weapons menu main restrict weapon" { - "en" "Zombies can't use weapons!" - "ru" "Зомби не могут использовать оружие!" + "en" "Restrict a Weapon" } + "Weapons menu main unrestrict weapon" + { + "en" "Unrestrict a Weapon" + } + "Weapons menu main restrict weapon group" + { + "en" "Restrict a Weapon Group" + } + + "Weapons menu main unrestrict weapon group" + { + "en" "Unrestrict a Weapon Group" + } + + "Weapons menu main market" // Option disabled if ZMarket isn't installed + { + "en" "ZMarket Options" + } + + "Weapons menu weapons title" + { + "en" "Toggle Restrictions:" + } "Suicide text" { @@ -344,27 +393,22 @@ { "en" "Infect a Player" } - + "!zadmin main spawn" { "en" "Spawn All Players" } - + "!zadmin main tele" { "en" "ZTele Commands" } - - "!zadmin main restrict" + + "!zadmin main weapons" { - "en" "Restrict Weapon" + "en" "Weapon Management" } - - "!zadmin main unrestrict" - { - "en" "Unrestrict Weapon" - } - + "!zadmin main logflags" { "en" "Logging Flags" diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 3741a90..b9d6816 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -33,12 +33,11 @@ #include "zr/zombie" #include "zr/menu" #include "zr/sayhooks" -#include "zr/zadmin" // Weapons -#include "zr/weapons/restrict" -#include "zr/weapons/markethandler" +#include "zr/weapons/weapons" +#include "zr/zadmin" #include "zr/damagecontrol" #include "zr/commands" #include "zr/event" @@ -120,8 +119,16 @@ public OnMapStart() LoadModelData(); LoadDownloadData(); - // Forward event to modules. - WeaponRestrictMapStart(); + // Weapons + WeaponsOnMapStart(); + + new i; + new classindex = GetDefaultClassIndex(); + for (i = 1; i <= MAXPLAYERS; i++) + { + pClass[i] = classindex; + } + Anticamp_Startup(); } @@ -132,6 +139,11 @@ public OnMapEnd() public OnConfigsExecuted() { + FindMapSky(); + + LoadClassData(); + LoadAmbienceData(); + decl String:mapconfig[PLATFORM_MAX_PATH]; GetCurrentMap(mapconfig, sizeof(mapconfig)); @@ -143,17 +155,8 @@ public OnConfigsExecuted() if (FileExists(path)) { ServerCommand("exec %s", mapconfig); - if (LogFlagCheck(LOG_CORE_EVENTS)) - { - LogMessage("Executed map config file: %s", mapconfig); - } + LogMessage("Executed map config file: %s", mapconfig); } - - FindMapSky(); - - ClassLoad(); - LoadClassData(); - LoadAmbienceData(); } public OnClientPutInServer(client) @@ -167,9 +170,8 @@ public OnClientPutInServer(client) new bool:zhp = GetConVarBool(gCvars[CVAR_ZHP_DEFAULT]); dispHP[client] = zhp; - // Forward event to modules. + // Weapon restrict WeaponRestrictClientInit(client); - ClassClientInit(client); ClientHookAttack(client); @@ -186,12 +188,12 @@ public OnClientPutInServer(client) public OnClientDisconnect(client) { - ClientUnHookAttack(client); - PlayerLeft(client); - - // Forward event to modules. + // Weapon restrict WeaponRestrictClientDisconnect(client); - ClassOnClientDisconnect(client); + + ClientUnHookAttack(client); + + PlayerLeft(client); ZTeleResetClient(client); AmbienceStop(client); @@ -233,8 +235,6 @@ ZREnd() UnhookCvars(); UnhookEvents(); - // TODO: Disable all modules! Teleport, ambience, overlays, antistick, etc. - new maxplayers = GetMaxClients(); for (new x = 1; x <= maxplayers; x++) { diff --git a/src/zr/commands.inc b/src/zr/commands.inc index 8380f34..b2b5f5c 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -169,6 +169,12 @@ public Action:Command_Restrict(client, argc) ZR_PrintToChat(0, "Restrict custom weapon group", arg1, weaponlist); } + case Failed_Weapon: + { + ZR_ReplyToCommand(client, "Restrict weapon failed", arg1); + + return Plugin_Handled; + } case Invalid: { ZR_ReplyToCommand(client, "Weapon invalid", arg1); @@ -226,6 +232,12 @@ public Action:Command_Unrestrict(client, argc) ZR_PrintToChat(0, "Unrestrict custom weapon group", arg1, weaponlist); } + case Failed_Weapon: + { + ZR_ReplyToCommand(client, "Unrestrict weapon failed", arg1); + + return Plugin_Handled; + } case Invalid: { ZR_ReplyToCommand(client, "Weapon invalid", arg1); diff --git a/src/zr/weapons/markethandler.inc b/src/zr/weapons/markethandler.inc index 544883c..712f57c 100644 --- a/src/zr/weapons/markethandler.inc +++ b/src/zr/weapons/markethandler.inc @@ -12,7 +12,7 @@ * @param client The client index. * @param weaponid The unique weapon ID used for market natives. * @return True to allow market to take over, false to block purchase. -*/ + */ public bool:Market_OnWeaponSelected(client, String:weaponid[]) { // If player is dead or weaponid is invalid, then stop @@ -36,7 +36,7 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[]) } decl String:display[64]; - decl String:weapon[32]; + decl String:weapon[WEAPONS_MAX_LENGTH]; new price; // If the market plugin can't find info about the weapon, then stop @@ -73,7 +73,7 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[]) * * @param client The client index. * @param allowed True when the weapon was purchased successfully, false otherwise. -*/ + */ public Market_PostOnWeaponSelected(client, &bool:allowed) { // If the purchase wasn't allowed, then stop diff --git a/src/zr/weapons/menu_weapons.inc b/src/zr/weapons/menu_weapons.inc new file mode 100644 index 0000000..a529a6e --- /dev/null +++ b/src/zr/weapons/menu_weapons.inc @@ -0,0 +1,283 @@ +/** + * ==================== + * Zombie:Reloaded + * File: menu_weapons.inc + * Author: Greyscale + * ==================== + */ + +/** + * Weapons Menus + */ +enum WeaponsMenu +{ + Restrict_Weapon, + Unrestrict_Weapon, + Restrict_Group, + Unrestrict_Group, +} + +/** + * Array to store the client's current weapon menu + */ +new WeaponsMenu:curMenuWeapons[MAXPLAYERS+1]; + +/** + * Sends main weapon menu to client. + * @param client The client index. + */ +WeaponsMenuMain(client) +{ + // Create menu handle + new Handle:menu_weapons_main = CreateMenu(WeaponsMenuMainHandle); + + SetGlobalTransTarget(client); + + SetMenuTitle(menu_weapons_main, "%t\n ", "Weapons menu main title"); + + decl String:restrictweapon[64]; + decl String:unrestrictweapon[64]; + decl String:restrictwgroup[64]; + decl String:unrestrictwgroup[64]; + decl String:zmarket[64]; + + Format(restrictweapon, sizeof(restrictweapon), "%t", "Weapons menu main restrict weapon"); + Format(unrestrictweapon, sizeof(unrestrictweapon), "%t", "Weapons menu main unrestrict weapon"); + Format(restrictwgroup, sizeof(restrictwgroup), "%t", "Weapons menu main restrict weapon group"); + Format(unrestrictwgroup, sizeof(unrestrictwgroup), "%t", "Weapons menu main unrestrict weapon group"); + Format(zmarket, sizeof(zmarket), "%t", "Weapons menu main market"); + + AddMenuItem(menu_weapons_main, "restrictweapon", restrictweapon); + AddMenuItem(menu_weapons_main, "unrestrictweapon", unrestrictweapon); + AddMenuItem(menu_weapons_main, "restrictwgroup", restrictwgroup); + AddMenuItem(menu_weapons_main, "unrestrictwgroup", unrestrictwgroup); + + // Disable market option if market isn't installed + if (market) + { + AddMenuItem(menu_weapons_main, "zmarket", zmarket); + } + else + { + AddMenuItem(menu_weapons_main, "zmarket", zmarket, ITEMDRAW_DISABLED); + } + + // Create a "Back" button to the weapons main menu + SetMenuExitBackButton(menu_weapons_main, true); + + // Send menu + DisplayMenu(menu_weapons_main, client, MENU_TIME_FOREVER); +} + +/** + * Called when client selects option in the weapons main menu, and handles it. + * @param menu_weapons_main Handle of the menu being used. + * @param action The action done on the menu (see menus.inc, enum MenuAction). + * @param client The client index. + * @param slot The slot index selected (starting from 0). + */ +public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client, slot) +{ + // Client selected an option + if (action == MenuAction_Select) + { + switch(slot) + { + case 0: + { + WeaponsMenuWeapons(client, Restrict_Weapon); + } + case 1: + { + WeaponsMenuWeapons(client, Unrestrict_Weapon); + } + case 2: + { + WeaponsMenuWeapons(client, Restrict_Group); + } + case 3: + { + WeaponsMenuWeapons(client, Unrestrict_Group); + } + case 4: + { + // WeaponsMenuMarket(client); + } + } + } + // Client closed the menu + if (action == MenuAction_Cancel) + { + // Client hit "Back" button + if (slot == MenuCancel_ExitBack) + { + ZRAdminMenu(client); + } + } + // Client hit "Exit" button + else if (action == MenuAction_End) + { + CloseHandle(menu_weapons_main); + } +} + +/** + * Sends weapon list menu to client. + * @param client The client index. + */ +WeaponsMenuWeapons(client, WeaponsMenu:type) +{ + // Set the current action client is performing on a weapon (see enum WeaponsMenu) + curMenuWeapons[client] = type; + + // Create menu handle + new Handle:menu_weapons_weapons = CreateMenu(WeaponsMenuWeaponsHandle); + + SetGlobalTransTarget(client); + + SetMenuTitle(menu_weapons_weapons, "%t\n ", "Weapons menu weapons title"); + + // If client wants to perform an action on a single weapon, show weapon list + if (curMenuWeapons[client] == Restrict_Weapon || curMenuWeapons[client] == Unrestrict_Weapon) + { + decl String:weapon[WEAPONS_MAX_LENGTH]; + new Handle:arrayWeapons = INVALID_HANDLE; + new size = WeaponsCreateWeaponArray(arrayWeapons); + + // x = Array index + for (new x = 0; x < size; x++) + { + GetArrayString(arrayWeapons, x, weapon, sizeof(weapon)); + + new bool:menu = WeaponsIsWeaponMenu(weapon); + + // If weapon restriction is blocked for the menu, disable option + if (menu) + { + AddMenuItem(menu_weapons_weapons, weapon, weapon); + } + else + { + AddMenuItem(menu_weapons_weapons, weapon, weapon, ITEMDRAW_DISABLED); + } + } + + // Kill the array handle + CloseHandle(arrayWeapons); + } + // If client wants to perform an action on a weapon group, show custom group list + else if (curMenuWeapons[client] == Restrict_Group || curMenuWeapons[client] == Unrestrict_Group) + { + decl String:weapongroup[WEAPONS_MAX_LENGTH]; + new Handle:arrayWeaponGroups = INVALID_HANDLE; + new size = WeaponsCreateWeaponGroupArray(arrayWeaponGroups); + + // x = Array index + for (new x = 0; x < size; x++) + { + GetArrayString(arrayWeaponGroups, x, weapongroup, sizeof(weapongroup)); + + AddMenuItem(menu_weapons_weapons, weapongroup, weapongroup); + } + + // Kill the array handle + CloseHandle(arrayWeaponGroups); + } + + SetMenuExitBackButton(menu_weapons_weapons, true); + + DisplayMenu(menu_weapons_weapons, client, MENU_TIME_FOREVER); +} + +/** + * Called when client selects option in the weapons list menu, and handles it. + * @param menu_weapons_main Handle of the menu being used. + * @param action The action done on the menu (see menus.inc, enum MenuAction). + * @param client The client index. + * @param slot The slot index selected (starting from 0). + */ +public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action, client, slot) +{ + // Client selected an option + if (action == MenuAction_Select) + { + decl String:weapon[WEAPONS_MAX_LENGTH]; + GetMenuItem(menu_weapons_weapons, slot, weapon, sizeof(weapon)); + + new WpnRestrictQuery:output; + + // If client is restricting a weapon or group, then call the restrict function + if (curMenuWeapons[client] == Restrict_Weapon || curMenuWeapons[client] == Restrict_Group) + { + output = WeaponRestrictRestrict(weapon); + + switch(output) + { + case Successful_Weapon: + { + ZR_PrintToChat(0, "Restrict weapon", weapon); + } + case Successful_Group: + { + decl String:weaponlist[128]; + WeaponRestrictGetWeaponList(weapon, weaponlist, sizeof(weaponlist), ", "); + + ZR_PrintToChat(0, "Restrict custom weapon group", weapon, weaponlist); + } + case Failed_Weapon: + { + ZR_PrintToChat(client, "Restrict weapon failed", weapon); + } + case Invalid: + { + ZR_PrintToChat(client, "Weapon invalid", weapon); + } + } + } + // If client is unrestricting a weapon or group, then call the unrestrict function + else if (curMenuWeapons[client] == Unrestrict_Weapon || curMenuWeapons[client] == Unrestrict_Group) + { + output = WeaponRestrictUnrestrict(weapon); + + switch(output) + { + case Successful_Weapon: + { + ZR_PrintToChat(0, "Unrestrict weapon", weapon); + } + case Successful_Group: + { + decl String:weaponlist[128]; + WeaponRestrictGetWeaponList(weapon, weaponlist, sizeof(weaponlist), ", "); + + ZR_PrintToChat(0, "Unrestrict custom weapon group", weapon, weaponlist); + } + case Failed_Weapon: + { + ZR_PrintToChat(client, "Unrestrict weapon failed", weapon); + } + case Invalid: + { + ZR_PrintToChat(client, "Weapon invalid", weapon); + } + } + } + + // Resend menu + WeaponsMenuWeapons(client, curMenuWeapons[client]); + } + // Client closed the menu + if (action == MenuAction_Cancel) + { + // Client hit "Back" button + if (slot == MenuCancel_ExitBack) + { + WeaponsMenuMain(client); + } + } + // Client hit "Exit" button + else if (action == MenuAction_End) + { + CloseHandle(menu_weapons_weapons); + } +} \ No newline at end of file diff --git a/src/zr/weapons/restrict.inc b/src/zr/weapons/restrict.inc index c8e53b9..23240da 100644 --- a/src/zr/weapons/restrict.inc +++ b/src/zr/weapons/restrict.inc @@ -8,32 +8,34 @@ /** * Array to store restricted weapon names. -*/ + */ new Handle:gRestrictedWeapons = INVALID_HANDLE; /** * Array to store keyvalue data. -*/ + */ new Handle:kvWeaponGroups = INVALID_HANDLE; /** * Array that stores the "HookID" to be later unhooked on player disconnect. -*/ + */ new gCanUseHookID[MAXPLAYERS+1]; /** * Query results returned when (un)restricting a weapon. -*/ + */ enum WpnRestrictQuery { Successful_Weapon, /** Weapon (un)restrict query was successful. */ Successful_Group, /** Group (un)restrict query was successful. */ + Failed_Weapon, /** Weapon (un)restrict was unsuccessful */ + Failed_Group, /** Group (un)restrict was unsuccessful */ Invalid, /** Weapon/Group invalid */ } /** * Initialize data and hook commands. -*/ + */ WeaponRestrictInit() { // Initialize weapon restrict array @@ -45,8 +47,8 @@ WeaponRestrictInit() /** * Loads weapon data from file. -*/ -WeaponRestrictMapStart() + */ +WeaponRestrictOnMapStart() { // Clear restricted weapons RestrictWeaponUnrestrictAll(); @@ -60,17 +62,44 @@ WeaponRestrictMapStart() kvWeaponGroups = CreateKeyValues("weapongroups"); decl String:path[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapongroups.txt"); + BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapongroups.txt"); + // If file isn't found, stop plugin if (!FileToKeyValues(kvWeaponGroups, path)) { SetFailState("\"%s\" missing from server", path); } + + KvRewind(kvWeaponGroups); + + if (KvGotoFirstSubKey(kvWeaponGroups)) + { + do + { + if (KvGotoFirstSubKey(kvWeaponGroups)) + { + decl String:groupweapon[32]; + + do + { + + KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon)); + + if (!WeaponsIsValidWeapon(groupweapon)) + { + // TODO: LOG INVALID WEAPON + } + } while (KvGotoNextKey(kvWeaponGroups)); + + KvGoBack(kvWeaponGroups); + } + } while (KvGotoNextKey(kvWeaponGroups)); + } } /** * Clears restricted weapon array. -*/ + */ RestrictWeaponUnrestrictAll() { ClearArray(gRestrictedWeapons); @@ -80,7 +109,7 @@ RestrictWeaponUnrestrictAll() * Hook Weapon_CanUse function on a client. * * @param client The client index. -*/ + */ WeaponRestrictClientInit(client) { gCanUseHookID[client] = Hacks_Hook(client, HACKS_HTYPE_WEAPON_CANUSE, WeaponRestrictCanUse, false); @@ -90,7 +119,7 @@ WeaponRestrictClientInit(client) * Unhook Weapon_CanUse function on a client. * * @param client The client index. -*/ + */ WeaponRestrictClientDisconnect(client) { Hacks_Unhook(gCanUseHookID[client]); @@ -102,7 +131,7 @@ WeaponRestrictClientDisconnect(client) * * @param client The client index. * @param argc Argument count. -*/ + */ public Action:WeaponRestrictBuyHook(client, argc) { // If plugin is disabled then stop @@ -146,8 +175,10 @@ public Action:WeaponRestrictBuyHook(client, argc) * @param weapon The weapon/group name. * @return Successful_Weapon: The call successfully restricted a weapon. * Successful_Group: The call successfully restricted a weapon group. + * Failed_Weapon: The call failed to restrict a weapon. + * Failed_Group: The call failed to restrict a weapon group. * Invalid: The call was unsuccessful due to invalid weapon. -*/ + */ WpnRestrictQuery:WeaponRestrictRestrict(const String:weapon[]) { if (WeaponRestrictIsCustomGroup(weapon)) @@ -164,6 +195,12 @@ WpnRestrictQuery:WeaponRestrictRestrict(const String:weapon[]) KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon)); + // If weapon is invalid, then skip + if (!WeaponsIsValidWeapon(groupweapon)) + { + continue; + } + if (!WeaponRestrictIsRestricted(groupweapon)) { PushArrayString(gRestrictedWeapons, groupweapon); @@ -174,11 +211,18 @@ WpnRestrictQuery:WeaponRestrictRestrict(const String:weapon[]) return Successful_Group; } - if (!WeaponRestrictIsRestricted(weapon)) + if (!WeaponsIsValidWeapon(weapon)) { - PushArrayString(gRestrictedWeapons, weapon); + return Invalid; } + if (WeaponRestrictIsRestricted(weapon)) + { + return Failed_Weapon; + } + + PushArrayString(gRestrictedWeapons, weapon); + return Successful_Weapon; } @@ -188,8 +232,10 @@ WpnRestrictQuery:WeaponRestrictRestrict(const String:weapon[]) * @param weapon The weapon/group name. * @return Successful_Weapon: The call successfully restricted a weapon. * Successful_Group: The call successfully restricted a weapon group. - * Invalid: The call was unsuccessful due to invalid weapon. -*/ + * Failed_Weapon: The call failed to restrict a weapon. + * Failed_Group: The call failed to restrict a weapon group. + * Invalid: The call was unsuccessful due to invalid weapon. + */ WpnRestrictQuery:WeaponRestrictUnrestrict(const String:weapon[]) { if (WeaponRestrictIsCustomGroup(weapon)) @@ -199,12 +245,18 @@ WpnRestrictQuery:WeaponRestrictUnrestrict(const String:weapon[]) if (KvGotoFirstSubKey(kvWeaponGroups)) { - decl String:groupweapon[32]; + decl String:groupweapon[WEAPONS_MAX_LENGTH]; do { KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon)); + // If weapon is invalid, then skip + if (!WeaponsIsValidWeapon(groupweapon)) + { + continue; + } + if (WeaponRestrictIsRestricted(groupweapon)) { new weaponindex = WeaponRestrictGetIndex(groupweapon); @@ -219,31 +271,36 @@ WpnRestrictQuery:WeaponRestrictUnrestrict(const String:weapon[]) return Successful_Group; } - if (WeaponRestrictIsRestricted(weapon)) + if (!WeaponsIsValidWeapon(weapon)) { - new weaponindex = WeaponRestrictGetIndex(weapon); - if (weaponindex > -1) - { - RemoveFromArray(gRestrictedWeapons, weaponindex); - - return Successful_Weapon; - } + return Invalid; } - return Invalid; + if (!WeaponRestrictIsRestricted(weapon)) + { + return Failed_Weapon; + } + + new weaponindex = WeaponRestrictGetIndex(weapon); + if (weaponindex > -1) + { + RemoveFromArray(gRestrictedWeapons, weaponindex); + } + + return Successful_Weapon; } /** * Checks if a weapon is restricted. * * @param weapon The weapon name. -*/ + */ bool:WeaponRestrictIsRestricted(const String:weapon[]) { new size = GetArraySize(gRestrictedWeapons); for (new x = 0; x < size; x++) { - decl String:restrictedweapon[32]; + decl String:restrictedweapon[WEAPONS_MAX_LENGTH]; GetArrayString(gRestrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon)); if (StrEqual(weapon, restrictedweapon, false)) @@ -259,13 +316,13 @@ bool:WeaponRestrictIsRestricted(const String:weapon[]) * Returns the array index of the restricted weapon. * * @param weapon The weapon name. -*/ + */ WeaponRestrictGetIndex(const String:weapon[]) { new size = GetArraySize(gRestrictedWeapons); for (new x = 0; x < size; x++) { - decl String:restrictedweapon[32]; + decl String:restrictedweapon[WEAPONS_MAX_LENGTH]; GetArrayString(gRestrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon)); if (StrEqual(weapon, restrictedweapon, false)) @@ -282,7 +339,7 @@ WeaponRestrictGetIndex(const String:weapon[]) * * @param groupname Name of the group to check. * @return True if it's a group, false if not. -*/ + */ bool:WeaponRestrictIsCustomGroup(const String:groupname[]) { // Reset the traversal stack @@ -300,7 +357,7 @@ bool:WeaponRestrictIsCustomGroup(const String:groupname[]) * @param weaponlist Variable to store weapon list string in. * @param maxlen Maximum length of the weapon list, the rest is truncated. * @param separator Separator character between weapon names. -*/ + */ WeaponRestrictGetWeaponList(const String:groupname[], String:weaponlist[], maxlen, const String:separator[]) { KvRewind(kvWeaponGroups); @@ -308,7 +365,7 @@ WeaponRestrictGetWeaponList(const String:groupname[], String:weaponlist[], maxle if (KvGotoFirstSubKey(kvWeaponGroups)) { - decl String:groupweapon[32]; + decl String:groupweapon[WEAPONS_MAX_LENGTH]; strcopy(weaponlist, maxlen, ""); @@ -316,6 +373,12 @@ WeaponRestrictGetWeaponList(const String:groupname[], String:weaponlist[], maxle { KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon)); + // If weapon is invalid, then skip + if (!WeaponsIsValidWeapon(groupweapon)) + { + continue; + } + if (!weaponlist[0]) { strcopy(weaponlist, maxlen, groupweapon); @@ -333,7 +396,7 @@ WeaponRestrictGetWeaponList(const String:groupname[], String:weaponlist[], maxle * @param client The client index. * @param weapon The weapon index. * @return 0 to block weapon pickup, Hacks_Continue to allow. -*/ + */ public WeaponRestrictCanUse(client, weapon, dummy1, dummy2, dummy3, dummy4) { // If plugin is disabled then stop @@ -343,7 +406,7 @@ public WeaponRestrictCanUse(client, weapon, dummy1, dummy2, dummy3, dummy4) return Hacks_Continue; } - new String:weaponname[32]; + new String:weaponname[WEAPONS_MAX_LENGTH]; GetEdictClassname(weapon, weaponname, sizeof(weaponname)); // Strip "weapon_" from entity name diff --git a/src/zr/weapons/weapons.inc b/src/zr/weapons/weapons.inc new file mode 100644 index 0000000..39afb52 --- /dev/null +++ b/src/zr/weapons/weapons.inc @@ -0,0 +1,186 @@ +/** + * ==================== + * Zombie:Reloaded + * File: weapons.inc + * Author: Greyscale + * ==================== + */ + +/** + * Handle to store trie weapon data + */ +new Handle:trieWeapons = INVALID_HANDLE; + +/** + * Maximum length of a weapon name string + */ +#define WEAPONS_MAX_LENGTH 32 + +/** + * @section Config array indexes. + */ +#define WEAPON_RESTRICT 0 +#define WEAPON_MENU 1 +/** + * @endsection + */ + +/** + * Array to store keyvalue data. + */ +new Handle:kvWeapons = INVALID_HANDLE; + +#include "zr/weapons/restrict" +#include "zr/weapons/markethandler" +#include "zr/weapons/menu_weapons" + +/** + * Loads weapon data from file. + */ +WeaponsOnMapStart() +{ + // Destroy trie data if populated + if (trieWeapons != INVALID_HANDLE) + { + CloseHandle(trieWeapons); + } + + // Create trie to store weapon data + trieWeapons = CreateTrie(); + + // Load weapon data + if (kvWeapons != INVALID_HANDLE) + { + CloseHandle(kvWeapons); + } + + kvWeapons = CreateKeyValues("weapons"); + + decl String:path[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapons.txt"); + + // If file isn't found, stop plugin + if (!FileToKeyValues(kvWeapons, path)) + { + SetFailState("\"%s\" missing from server", path); + } + + KvRewind(kvWeapons); + if (KvGotoFirstSubKey(kvWeapons)) + { + decl String:weapon[WEAPONS_MAX_LENGTH]; + decl String:restrict[8]; + decl String:menu[8]; + + do + { + KvGetSectionName(kvWeapons, weapon, sizeof(weapon)); + KvGetString(kvWeapons, "restrict", restrict, sizeof(restrict), "no"); + KvGetString(kvWeapons, "menu", menu, sizeof(menu), "yes"); + + new bool:config[2]; + config[WEAPON_RESTRICT] = ConfigOptionToBool(restrict); + config[WEAPON_MENU] = ConfigOptionToBool(menu); + + SetTrieArray(trieWeapons, weapon, config, sizeof(config), false); + + } while (KvGotoNextKey(kvWeapons)); + } + + // Weapon restrict + WeaponRestrictOnMapStart(); +} + +/** + * Creates an array of all listed weapons in weapons.txt. + * @param arrayWeapons The handle of the array, don't forget to call CloseHandle + * on it when finished! + * @return The size of the array. + */ +WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH) +{ + arrayWeapons = CreateArray(maxlen); + new count = 0; + + KvRewind(kvWeapons); + if (KvGotoFirstSubKey(kvWeapons)) + { + decl String:weapon[maxlen]; + + do + { + KvGetSectionName(kvWeapons, weapon, maxlen); + + PushArrayString(arrayWeapons, weapon); + count++; + } while (KvGotoNextKey(kvWeapons)); + } + + return count; +} + +/** + * Creates an array of all listed weapon groups in weapongroups.txt. + * @param arrayWeaponGroups The handle of the array, don't forget to call CloseHandle + * on it when finished! + * @return The size of the array. + */ +WeaponsCreateWeaponGroupArray(&Handle:arrayWeaponGroups, maxlen = WEAPONS_MAX_LENGTH) +{ + arrayWeaponGroups = CreateArray(maxlen); + new count = 0; + + KvRewind(kvWeaponGroups); + if (KvGotoFirstSubKey(kvWeaponGroups)) + { + decl String:weapongroup[maxlen]; + + do + { + KvGetSectionName(kvWeaponGroups, weapongroup, maxlen); + + PushArrayString(arrayWeaponGroups, weapongroup); + count++; + } while (KvGotoNextKey(kvWeaponGroups)); + } + + return count; +} + +/** + * Checks if a weapon is valid (aka listed in weapons.txt) + * @param weapon The weapon name. + * @return Returns true if valid, false it not. + */ +bool:WeaponsIsValidWeapon(const String:weapon[]) +{ + new bool:config[2]; + + return GetTrieArray(trieWeapons, weapon, config, sizeof(config)); +} + +/** + * Checks if a weapon is restricted by default. + * @param weapon The weapon name. + * @return Returns true if restricted, false it not. + */ +bool:WeaponsIsWeaponRestrict(const String:weapon[]) +{ + new bool:config[2]; + GetTrieArray(trieWeapons, weapon, config, sizeof(config)); + + return config[WEAPON_RESTRICT]; +} + +/** + * Checks if a weapon restriction can be toggled by the admin menu. + * @param weapon The weapon name. + * @return Returns true if restricted, false it not. + */ +bool:WeaponsIsWeaponMenu(const String:weapon[]) +{ + new bool:config[2]; + GetTrieArray(trieWeapons, weapon, config, sizeof(config)); + + return config[WEAPON_MENU]; +} \ No newline at end of file diff --git a/src/zr/zadmin.inc b/src/zr/zadmin.inc index cb5f8f7..a87ea25 100644 --- a/src/zr/zadmin.inc +++ b/src/zr/zadmin.inc @@ -18,11 +18,11 @@ bool:ZRAdminMenu(client) return false; } - new Handle:menu_admin = CreateMenu(ZRAdminMenuHandle); + new Handle:menu_zadmin = CreateMenu(ZRAdminMenuHandle); SetGlobalTransTarget(client); - SetMenuTitle(menu_admin, "%t\n ", "!zadmin main title"); + SetMenuTitle(menu_zadmin, "%t\n ", "!zadmin main title"); decl String:knockbackm[64]; decl String:knockback[64]; @@ -30,8 +30,7 @@ bool:ZRAdminMenu(client) decl String:infect[64]; decl String:zspawn[64]; decl String:ztele[64]; - decl String:restrict[64]; - decl String:unrestrict[64]; + decl String:weapons[64]; decl String:logflags[64]; Format(knockbackm, sizeof(knockbackm), "%t", "!zadmin main knockbackm"); @@ -40,23 +39,21 @@ bool:ZRAdminMenu(client) Format(infect, sizeof(infect), "%t", "!zadmin main infect"); Format(zspawn, sizeof(zspawn), "%t", "!zadmin main spawn"); Format(ztele, sizeof(ztele), "%t", "!zadmin main tele"); - Format(restrict, sizeof(restrict), "%t", "!zadmin main restrict"); - Format(unrestrict, sizeof(unrestrict), "%t", "!zadmin main unrestrict"); + Format(weapons, sizeof(weapons), "%t", "!zadmin main weapons"); Format(logflags, sizeof(logflags), "%t", "!zadmin main logflags"); - AddMenuItem(menu_admin, "knockbackm", knockbackm); - AddMenuItem(menu_admin, "knockback", knockback); - AddMenuItem(menu_admin, "nvgs", nvgs); - AddMenuItem(menu_admin, "infect", infect); - AddMenuItem(menu_admin, "zspawn", zspawn); - AddMenuItem(menu_admin, "ztele", ztele); - AddMenuItem(menu_admin, "restrict", restrict, ITEMDRAW_DISABLED); - AddMenuItem(menu_admin, "unrestrict", unrestrict, ITEMDRAW_DISABLED); - AddMenuItem(menu_admin, "logflags", logflags); + AddMenuItem(menu_zadmin, "knockbackm", knockbackm); + AddMenuItem(menu_zadmin, "knockback", knockback); + AddMenuItem(menu_zadmin, "nvgs", nvgs); + AddMenuItem(menu_zadmin, "infect", infect); + AddMenuItem(menu_zadmin, "zspawn", zspawn); + AddMenuItem(menu_zadmin, "ztele", ztele); + AddMenuItem(menu_zadmin, "weapons", weapons); + AddMenuItem(menu_zadmin, "logflags", logflags); - SetMenuExitBackButton(menu_admin, true); + SetMenuExitBackButton(menu_zadmin, true); - DisplayMenu(menu_admin, client, MENU_TIME_FOREVER); + DisplayMenu(menu_zadmin, client, MENU_TIME_FOREVER); return true; } @@ -93,13 +90,9 @@ public ZRAdminMenuHandle(Handle:menu_admin, MenuAction:action, client, slot) } case 6: { - // restrict + WeaponsMenuMain(client); } case 7: - { - // unrestrict - } - case 8: { ZRLogFlagsMenu(client); } diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 5acce55..54a9fd7 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -63,8 +63,8 @@ new bool:motherZombie[MAXPLAYERS+1]; new bool:gZombie[MAXPLAYERS+1]; new bool:gBlockMotherInfect[MAXPLAYERS+1]; new bool:bZVision[MAXPLAYERS+1]; -//new bool:bZVisionOn[MAXPLAYERS+1]; -//new String:ZVisionOverlay[MAXPLAYERS+1][PLATFORM_MAX_PATH]; +new bool:bZVisionOn[MAXPLAYERS+1]; +new String:ZVisionOverlay[MAXPLAYERS+1][PLATFORM_MAX_PATH]; new bool:dispHP[MAXPLAYERS+1]; new bool:pProtect[MAXPLAYERS+1]; new bool:gKilledByWorld[MAXPLAYERS+1] = {false, ...}; @@ -106,6 +106,16 @@ new Handle:tHandles[MAXPLAYERS+1][MAXTIMERS]; new QueryCookie:mat_dxlevel; +bool:ConfigOptionToBool(const String:option[]) +{ + if (StrEqual(option, "yes", false)) + { + return true; + } + + return false; +} + FindClientDXLevel(client) { if (IsFakeClient(client)) @@ -211,6 +221,18 @@ bool:IsPlayerInList(client) return false; } +bool:IntToBool(intval) +{ + if (intval == 0) + { + return false; + } + else + { + return true; + } +} + bool:IsClientPlayer(client) { if (client > 0 && client <= maxclients)