Merged heads.
This commit is contained in:
		
							
								
								
									
										70
									
								
								cstrike/addons/sourcemod/configs/zr/hitgroups.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								cstrike/addons/sourcemod/configs/zr/hitgroups.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
// Hitgroups
 | 
			
		||||
//
 | 
			
		||||
// Format
 | 
			
		||||
//
 | 
			
		||||
// "hitgroup index" // Index of the hitgroup (listed below)
 | 
			
		||||
// {
 | 
			
		||||
//	"name"			"name of hitgroup" // Redundant as of now, used for readability.
 | 
			
		||||
//	"knockback"		"1.0" (default) // The knockback multiplier for the hitgroup
 | 
			
		||||
// }
 | 
			
		||||
//
 | 
			
		||||
// Notes:
 | 
			
		||||
//
 | 
			
		||||
// A missing config setting will be assumed to be its default value (documented above).
 | 
			
		||||
 | 
			
		||||
"hitgroups" // Counter-Strike: Source hitgroups
 | 
			
		||||
{
 | 
			
		||||
	"0"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Generic"
 | 
			
		||||
		"knockback"	"1.0"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"1"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Head"
 | 
			
		||||
		"knockback"	"2.0"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"2"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Chest"
 | 
			
		||||
		"knockback"	"1.3"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"3"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Stomach"
 | 
			
		||||
		"knockback"	"1.2"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"4"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Left Arm"
 | 
			
		||||
		"knockback"	"1.0"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"5"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Right Arm"
 | 
			
		||||
		"knockback"	"1.0"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"6"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Left Leg"
 | 
			
		||||
		"knockback"	"0.9"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"7"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Right Leg"
 | 
			
		||||
		"knockback"	"0.9"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"10"
 | 
			
		||||
	{
 | 
			
		||||
		"name"		"Gear"
 | 
			
		||||
		"knockback"	"1.0"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,12 @@
 | 
			
		||||
"Games"
 | 
			
		||||
{
 | 
			
		||||
	"cstrike"
 | 
			
		||||
	"#default"
 | 
			
		||||
	{
 | 
			
		||||
		"#supported"
 | 
			
		||||
		{
 | 
			
		||||
			"game"		"cstrike"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		"Offsets"
 | 
			
		||||
		{
 | 
			
		||||
			"RemoveAllItems"
 | 
			
		||||
@@ -9,17 +14,20 @@
 | 
			
		||||
				"windows"	"283"
 | 
			
		||||
				"linux"		"284"
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			"EyePosition"
 | 
			
		||||
			{
 | 
			
		||||
				"windows"	"117"
 | 
			
		||||
				"linux"		"118"
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			"EyeAngles"
 | 
			
		||||
			{
 | 
			
		||||
				"windows"	"206"
 | 
			
		||||
				"linux"		"207"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		"Signatures"
 | 
			
		||||
		{
 | 
			
		||||
			"TerminateRound"
 | 
			
		||||
@@ -28,6 +36,13 @@
 | 
			
		||||
				"windows"	"\x83\xEC\x18\x53\x55\x8B\xD9\x8B\x4C\x24\x28\x56\x57\x33\xF6\x8D"
 | 
			
		||||
				"linux"		"@_ZN12CCSGameRules14TerminateRoundEfi"
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			"CSWeaponDrop"
 | 
			
		||||
			{
 | 
			
		||||
				"library"	"server"
 | 
			
		||||
				"windows"	"\x2A\x2A\x2A\x2A\x2A\x2A\x53\x55\x56\x57\x8B\xBC\x24\x40\x01\x00\x00\x32\xDB\x85\xFF\x8B\xF1\x0F"
 | 
			
		||||
				"linux"		"@_ZN9CCSPlayer12CSWeaponDropEP17CBaseCombatWeaponbb"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -36,9 +36,15 @@
 | 
			
		||||
// Weapons
 | 
			
		||||
#include "zr/weapons/weapons"
 | 
			
		||||
 | 
			
		||||
// Hitgroups
 | 
			
		||||
#include "zr/hitgroups"
 | 
			
		||||
 | 
			
		||||
// Knockback
 | 
			
		||||
#include "zr/knockback"
 | 
			
		||||
 | 
			
		||||
// Spawn protect
 | 
			
		||||
#include "zr/spawnprotect"
 | 
			
		||||
 | 
			
		||||
#include "zr/zadmin"
 | 
			
		||||
#include "zr/damagecontrol"
 | 
			
		||||
#include "zr/commands"
 | 
			
		||||
@@ -126,7 +132,8 @@ public OnMapStart()
 | 
			
		||||
    
 | 
			
		||||
    // Forward event to modules.
 | 
			
		||||
    ClassLoad();
 | 
			
		||||
    WeaponsOnMapStart();
 | 
			
		||||
    WeaponsLoad();
 | 
			
		||||
    HitgroupsLoad();
 | 
			
		||||
    Anticamp_Startup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handle to keep track of AntiStickTimer 
 | 
			
		||||
 * Handle to keep track of AntiStickTimer.
 | 
			
		||||
*/
 | 
			
		||||
new Handle:tAntiStick = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +48,7 @@ AntiStickReset()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if a player is currently stuck within another player
 | 
			
		||||
 * Checks if a player is currently stuck within another player.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 * @return          The client index of the other stuck player, -1 when
 | 
			
		||||
@@ -61,11 +61,11 @@ AntiStickIsStuck(client)
 | 
			
		||||
    
 | 
			
		||||
    GetClientAbsOrigin(client, clientloc);
 | 
			
		||||
    
 | 
			
		||||
    // x = client index
 | 
			
		||||
    // x = client index.
 | 
			
		||||
    new maxplayers = GetMaxClients();
 | 
			
		||||
    for (new x = 1; x <= maxplayers; x++)
 | 
			
		||||
    {
 | 
			
		||||
        // Validate player is in-game, alive, and isn't the player being checked ('client')
 | 
			
		||||
        // Validate player is in-game, alive, and isn't the player being checked. ('client')
 | 
			
		||||
        if (!IsClientInGame(x) || !IsPlayerAlive(x) || x == client)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
@@ -82,7 +82,7 @@ AntiStickIsStuck(client)
 | 
			
		||||
                new Float:eyeloc[3];
 | 
			
		||||
                GetPlayerEyePosition(client, eyeloc);
 | 
			
		||||
                
 | 
			
		||||
                // Get the distance between the eyes and feet and subtract the stack "view crush"
 | 
			
		||||
                // Get the distance between the eyes and feet and subtract the stack "view crush."
 | 
			
		||||
                new Float:eyedistance = FloatAbs(eyeloc[2] - clientloc[2]) - PLAYER_HULL_STACK_OFFSET;
 | 
			
		||||
                new Float:zdistance = FloatAbs(stuckloc[2] - clientloc[2]);
 | 
			
		||||
                
 | 
			
		||||
@@ -107,13 +107,13 @@ public Action:AntiStickTimer(Handle:timer)
 | 
			
		||||
    new maxplayers = GetMaxClients();
 | 
			
		||||
    for (new x = 1; x <= maxplayers; x++)
 | 
			
		||||
    {
 | 
			
		||||
        // Validate player is in-game and alive
 | 
			
		||||
        // Validate player is in-game and alive.
 | 
			
		||||
        if (!IsClientInGame(x) || !IsPlayerAlive(x))
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Stop if the player isn't stuck
 | 
			
		||||
        // Stop if the player isn't stuck.
 | 
			
		||||
        new stuckindex = AntiStickIsStuck(x);
 | 
			
		||||
        if (stuckindex == -1)
 | 
			
		||||
        {
 | 
			
		||||
@@ -138,23 +138,24 @@ public Action:AntiStickTimer(Handle:timer)
 | 
			
		||||
 * Repeated timer function.
 | 
			
		||||
 * Re-solidifies a player being unstuck.
 | 
			
		||||
 *
 | 
			
		||||
 * @param index     The client index.
 | 
			
		||||
 * @param timer     The timer handle. 
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
*/
 | 
			
		||||
public Action:AntiStickSolidify(Handle:timer, any:index)
 | 
			
		||||
public Action:AntiStickSolidify(Handle:timer, any:client)
 | 
			
		||||
{
 | 
			
		||||
    // Validate player is in-game, alive, and is being unstuck
 | 
			
		||||
    if (!IsClientInGame(index) || !IsPlayerAlive(index) || CanCollide(index))
 | 
			
		||||
    // Validate player is in-game, alive, and is being unstuck.
 | 
			
		||||
    if (!IsClientInGame(client) || !IsPlayerAlive(client) || CanCollide(client))
 | 
			
		||||
    {
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Stop if the player is still stuck
 | 
			
		||||
    if (AntiStickIsStuck(index) > -1)
 | 
			
		||||
    // Stop if the player is still stuck.
 | 
			
		||||
    if (AntiStickIsStuck(client) > -1)
 | 
			
		||||
    {
 | 
			
		||||
        return Plugin_Continue;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    NoCollide(index, false);
 | 
			
		||||
    NoCollide(client, false);
 | 
			
		||||
    
 | 
			
		||||
    return Plugin_Stop;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -169,6 +169,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
 | 
			
		||||
    SetPlayerFOV(index, 90);
 | 
			
		||||
    ClientCommand(index, "r_screenoverlay \"\"");
 | 
			
		||||
    
 | 
			
		||||
    // Stop here if client isn't on a team.
 | 
			
		||||
    new team = GetClientTeam(index);
 | 
			
		||||
    if (team != CS_TEAM_T && team != CS_TEAM_CT)
 | 
			
		||||
    {
 | 
			
		||||
@@ -186,7 +187,6 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
 | 
			
		||||
    NightVisionOn(index, false);
 | 
			
		||||
    NightVision(index, false);
 | 
			
		||||
    
 | 
			
		||||
    pProtect[index] = false;
 | 
			
		||||
    if (zombieSpawned)
 | 
			
		||||
    {
 | 
			
		||||
        if (team == CS_TEAM_T)
 | 
			
		||||
@@ -194,34 +194,6 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
 | 
			
		||||
            CS_SwitchTeam(index, CS_TEAM_CT);
 | 
			
		||||
            CS_RespawnPlayer(index);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        new protect = GetConVarInt(gCvars[CVAR_PROTECT]);
 | 
			
		||||
        if (protect > 0)
 | 
			
		||||
        {
 | 
			
		||||
            decl String:respawnteam[32];
 | 
			
		||||
            GetConVarString(gCvars[CVAR_RESPAWN_TEAM], respawnteam, sizeof(respawnteam));
 | 
			
		||||
            
 | 
			
		||||
            if (!StrEqual(respawnteam, "zombie", false) && !(GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && gKilledByWorld[index]))
 | 
			
		||||
            {
 | 
			
		||||
                SetPlayerAlpha(index, 0);
 | 
			
		||||
                SetPlayerSpeed(index, 600.0);
 | 
			
		||||
                pProtect[index] = true;
 | 
			
		||||
                
 | 
			
		||||
                ZR_PrintToChat(index, "Spawn protection begin", protect);
 | 
			
		||||
                ZR_PrintCenterText(index, "Spawn protection begin", protect);
 | 
			
		||||
                
 | 
			
		||||
                if (tHandles[index][TPROTECT] != INVALID_HANDLE)
 | 
			
		||||
                {
 | 
			
		||||
                    KillTimer(tHandles[index][TPROTECT]);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                pTimeLeft[index] = protect;
 | 
			
		||||
                
 | 
			
		||||
                PrintHintText(index, "%d", pTimeLeft[index]);
 | 
			
		||||
 | 
			
		||||
                tHandles[index][TPROTECT] = CreateTimer(1.0, ProtectTimer, index, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
@@ -230,6 +202,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
 | 
			
		||||
    
 | 
			
		||||
    // Forward event to modules.
 | 
			
		||||
    ClassOnClientSpawn(index);
 | 
			
		||||
    SpawnProtectPlayerSpawn(index);
 | 
			
		||||
    ZTeleClientSpawned(index);
 | 
			
		||||
    
 | 
			
		||||
    ZR_PrintToChat(index, "!zmenu reminder");
 | 
			
		||||
@@ -240,13 +213,15 @@ public Action:PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
 | 
			
		||||
    new index = GetClientOfUserId(GetEventInt(event, "userid"));
 | 
			
		||||
    new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
 | 
			
		||||
    
 | 
			
		||||
    new hitgroup = GetEventInt(event, "hitgroup");
 | 
			
		||||
    
 | 
			
		||||
    new dmg_health = GetEventInt(event, "dmg_health");
 | 
			
		||||
    
 | 
			
		||||
    decl String:weapon[32];
 | 
			
		||||
    GetEventString(event, "weapon", weapon, sizeof(weapon));
 | 
			
		||||
    
 | 
			
		||||
    // Forward event to modules.
 | 
			
		||||
    KnockbackPlayerHurt(index, attacker, weapon, dmg_health);
 | 
			
		||||
    KnockbackPlayerHurt(index, attacker, weapon, hitgroup, dmg_health);
 | 
			
		||||
    
 | 
			
		||||
    // Check if the attacker is a player.
 | 
			
		||||
    if (attacker != 0)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								src/zr/hitgroups.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/zr/hitgroups.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ============================================================================
 | 
			
		||||
 *
 | 
			
		||||
 *   Zombie:Reloaded
 | 
			
		||||
 *
 | 
			
		||||
 *   File:        hitgroup.inc
 | 
			
		||||
 *   Description: API for loading hitgroup specific settings.
 | 
			
		||||
 *   Author:      Greyscale, Richard Helgeby
 | 
			
		||||
 *
 | 
			
		||||
 * ============================================================================
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array to store keyvalue data.
 | 
			
		||||
 */
 | 
			
		||||
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_LEFTARM    4
 | 
			
		||||
#define HITGROUP_RIGHTARM   5
 | 
			
		||||
#define HITGROUP_LEFTLEG    6
 | 
			
		||||
#define HITGROUP_RIGHTLEG   7
 | 
			
		||||
#define HITGROUP_GEAR       10
 | 
			
		||||
/**
 | 
			
		||||
 * @endsection
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears hitgroup data.
 | 
			
		||||
 */ 
 | 
			
		||||
HitgroupsClearData()
 | 
			
		||||
{
 | 
			
		||||
    // Load hitgroup data.
 | 
			
		||||
    if (kvHitgroups != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(kvHitgroups);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    kvHitgroups = CreateKeyValues("hitgroups");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads hitgroup data from file.
 | 
			
		||||
 */ 
 | 
			
		||||
HitgroupsLoad()
 | 
			
		||||
{
 | 
			
		||||
    // Clear hitgroup data
 | 
			
		||||
    HitgroupsClearData();
 | 
			
		||||
    
 | 
			
		||||
    decl String:path[PLATFORM_MAX_PATH];
 | 
			
		||||
    BuildPath(Path_SM, path, sizeof(path), "configs/zr/hitgroups.txt");
 | 
			
		||||
    
 | 
			
		||||
    // If file isn't found, stop plugin.
 | 
			
		||||
    if (!FileToKeyValues(kvHitgroups, path))
 | 
			
		||||
    {
 | 
			
		||||
        if (LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_HITGROUPS))
 | 
			
		||||
        {
 | 
			
		||||
            ZR_LogMessageFormatted(-1, "Hitgroups", "Config Validation", "Missing file hitgroups.txt, disabling hitgroup-based modules.", LOG_FORMAT_TYPE_FULL);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Validate hitgroups config.
 | 
			
		||||
    HitgroupsValidateConfig();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Validate hitgroup config file and settings.
 | 
			
		||||
 */ 
 | 
			
		||||
HitgroupsValidateConfig()
 | 
			
		||||
{
 | 
			
		||||
    // If log flag check fails, don't log.
 | 
			
		||||
    if (!LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_HITGROUPS))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    KvRewind(kvHitgroups);
 | 
			
		||||
    if (!KvGotoFirstSubKey(kvHitgroups))
 | 
			
		||||
    {
 | 
			
		||||
        ZR_LogMessageFormatted(-1, "Hitgroups", "Config Validation", "No hitgroups listed in hitgroups.txt, disabling hitgroup-based modules.", LOG_FORMAT_TYPE_FULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Retrieve hitgroup knockback value.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param hitgroup  The hitgroup index.
 | 
			
		||||
 */   
 | 
			
		||||
Float:HitgroupsGetHitgroupKnockback(hitgroup)
 | 
			
		||||
{
 | 
			
		||||
    // Reset keyvalue's traversal stack.
 | 
			
		||||
    KvRewind(kvHitgroups);
 | 
			
		||||
    if (KvGotoFirstSubKey(kvHitgroups))
 | 
			
		||||
    {
 | 
			
		||||
        decl String:sHitgroup[4];
 | 
			
		||||
        
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvHitgroups, sHitgroup, sizeof(sHitgroup));
 | 
			
		||||
            
 | 
			
		||||
            // If this is the right hitgroup, then return knockback for it.
 | 
			
		||||
            if (hitgroup == StringToInt(sHitgroup))
 | 
			
		||||
            {
 | 
			
		||||
                return KvGetFloat(kvHitgroups, "knockback", 1.0);
 | 
			
		||||
            }
 | 
			
		||||
        } while (KvGotoNextKey(kvHitgroups));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return 1.0;
 | 
			
		||||
}
 | 
			
		||||
@@ -6,29 +6,15 @@
 | 
			
		||||
 * ==================== 
 | 
			
		||||
 */
 | 
			
		||||
  
 | 
			
		||||
/**
 | 
			
		||||
 * @section Player hitgroup values.
 | 
			
		||||
 */
 | 
			
		||||
#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
 | 
			
		||||
#define HITGROUP_RIGHTLEG   7
 | 
			
		||||
#define HITGROUP_GEAR       10
 | 
			
		||||
/**
 | 
			
		||||
 * @endsection
 | 
			
		||||
 */
 | 
			
		||||
  
 | 
			
		||||
/** Player hurt event
 | 
			
		||||
/** Player hurt event.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client        The victim index. (zombie)
 | 
			
		||||
 * @param attacker      The attacker index. (human)
 | 
			
		||||
 * @param weapon        The weapon used.
 | 
			
		||||
 * @param hitgroup      Hitgroup attacker has damaged. 
 | 
			
		||||
 * @param dmg_health    Damage done.
 | 
			
		||||
 */ 
 | 
			
		||||
KnockbackPlayerHurt(client, attacker, const String:weapon[], dmg_health)
 | 
			
		||||
KnockbackPlayerHurt(client, attacker, const String:weapon[], hitgroup, dmg_health)
 | 
			
		||||
{
 | 
			
		||||
    // Check if the attacker is a player.
 | 
			
		||||
    if (attacker != 0)
 | 
			
		||||
@@ -68,14 +54,14 @@ KnockbackPlayerHurt(client, attacker, const String:weapon[], dmg_health)
 | 
			
		||||
                TR_GetEndPosition(clientloc);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // Apply damage knockback multiplier
 | 
			
		||||
            knockback *= float(dmg_health);
 | 
			
		||||
            
 | 
			
		||||
            // Retrieve weapon knockback boost.
 | 
			
		||||
            new Float:boostWeapon = WeaponGetWeaponKnockback(weapon);
 | 
			
		||||
            
 | 
			
		||||
            // Apply weapon knockback multiplier.
 | 
			
		||||
            knockback *= boostWeapon;
 | 
			
		||||
            // Retrieve hitgroup knockback boost.
 | 
			
		||||
            new Float:boostHitgroup = HitgroupsGetHitgroupKnockback(hitgroup);
 | 
			
		||||
            
 | 
			
		||||
            // Apply all knockback multipliers.
 | 
			
		||||
            knockback *= float(dmg_health) * boostWeapon * boostHitgroup;
 | 
			
		||||
            
 | 
			
		||||
            // Apply knockback.
 | 
			
		||||
            KnockbackSetVelocity(client, attackerloc, clientloc, knockback);
 | 
			
		||||
@@ -85,6 +71,7 @@ KnockbackPlayerHurt(client, attacker, const String:weapon[], dmg_health)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sets velocity on a player.
 | 
			
		||||
 *  
 | 
			
		||||
 * @param client        The client index.
 | 
			
		||||
 * @param startpoint    The starting coordinate to push from.
 | 
			
		||||
 * @param endpoint      The ending coordinate to push towards.
 | 
			
		||||
@@ -108,6 +95,7 @@ KnockbackSetVelocity(client, const Float:startpoint[3], const Float:endpoint[3],
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Trace Ray forward, used as a filter to continue tracing if told so. (See sdktools_trace.inc)
 | 
			
		||||
 *  
 | 
			
		||||
 * @param entity        The entity index.
 | 
			
		||||
 * @param contentsMask  The contents mask.
 | 
			
		||||
 * @return              True to allow hit, false to continue tracing. 
 | 
			
		||||
@@ -126,6 +114,7 @@ public bool:KnockbackTRFilter(entity, contentsMask)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Find the location of an exploding grenade (currently inflicting damage in player_hurt).
 | 
			
		||||
 *  
 | 
			
		||||
 * @param heLoc     The location of the exploding grenade.
 | 
			
		||||
 * @return          The entity index of the grenade. 
 | 
			
		||||
 */  
 | 
			
		||||
 
 | 
			
		||||
@@ -115,25 +115,3 @@ LoadDownloadData()
 | 
			
		||||
    CloseHandle(fileDownloads);
 | 
			
		||||
    CloseHandle(arrayDownloads);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*ApplyZombieModel(client)
 | 
			
		||||
{
 | 
			
		||||
    decl String:modelpath[256];
 | 
			
		||||
    
 | 
			
		||||
    new bool:classes = GetConVarBool(gCvars[CVAR_CLASSES]);
 | 
			
		||||
    if (classes)
 | 
			
		||||
    {
 | 
			
		||||
        GetClassModel(pClass[client], modelpath, sizeof(modelpath));
 | 
			
		||||
        if (!StrEqual(modelpath, "default", false))
 | 
			
		||||
        {
 | 
			
		||||
            SetPlayerModel(client, modelpath);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    new randmodel = GetRandomInt(0, GetArraySize(arrayModels) - 1);
 | 
			
		||||
    GetArrayString(arrayModels, randmodel, modelpath, sizeof(modelpath));
 | 
			
		||||
    Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
 | 
			
		||||
    
 | 
			
		||||
    SetPlayerModel(client, modelpath);
 | 
			
		||||
}*/
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,10 @@ new offsRender;
 | 
			
		||||
 | 
			
		||||
new Handle:g_hGameConf = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hRemoveAllItems = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hTerminateRound = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hEyePosition = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hEyeAngles = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hTerminateRound = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_hCSWeaponDrop = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
FindOffsets()
 | 
			
		||||
{
 | 
			
		||||
@@ -100,27 +101,61 @@ FindOffsets()
 | 
			
		||||
 | 
			
		||||
SetupGameData()
 | 
			
		||||
{
 | 
			
		||||
    // Load game config file.
 | 
			
		||||
    g_hGameConf = LoadGameConfigFile("plugin.zombiereloaded");
 | 
			
		||||
    
 | 
			
		||||
    // 
 | 
			
		||||
    StartPrepSDKCall(SDKCall_Player);
 | 
			
		||||
    PrepSDKCall_SetFromConf(g_hGameConf, SDKConf_Virtual, "RemoveAllItems");
 | 
			
		||||
    g_hRemoveAllItems = EndPrepSDKCall();
 | 
			
		||||
    
 | 
			
		||||
    if(g_hRemoveAllItems == INVALID_HANDLE)
 | 
			
		||||
	{
 | 
			
		||||
		SetFailState("Couldn't find offset \"RemoveAllItems\"!");
 | 
			
		||||
	}
 | 
			
		||||
    
 | 
			
		||||
    StartPrepSDKCall(SDKCall_Player);
 | 
			
		||||
    PrepSDKCall_SetFromConf(g_hGameConf, SDKConf_Virtual, "EyePosition");
 | 
			
		||||
    PrepSDKCall_SetReturnInfo(SDKType_QAngle, SDKPass_ByValue);
 | 
			
		||||
    g_hEyePosition = EndPrepSDKCall();
 | 
			
		||||
    
 | 
			
		||||
    if(g_hEyePosition == INVALID_HANDLE)
 | 
			
		||||
	{
 | 
			
		||||
		SetFailState("Couldn't find offset \"EyePosition\"!");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    StartPrepSDKCall(SDKCall_Player);
 | 
			
		||||
    PrepSDKCall_SetFromConf(g_hGameConf, SDKConf_Virtual, "EyeAngles");
 | 
			
		||||
    PrepSDKCall_SetReturnInfo(SDKType_QAngle, SDKPass_ByValue);
 | 
			
		||||
    g_hEyeAngles = EndPrepSDKCall();
 | 
			
		||||
    
 | 
			
		||||
    if(g_hEyeAngles == INVALID_HANDLE)
 | 
			
		||||
	{
 | 
			
		||||
		SetFailState("Couldn't find offset \"EyeAngles\"!");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    StartPrepSDKCall(SDKCall_GameRules);
 | 
			
		||||
    PrepSDKCall_SetFromConf(g_hGameConf, SDKConf_Signature, "TerminateRound");
 | 
			
		||||
    PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain);
 | 
			
		||||
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
 | 
			
		||||
    g_hTerminateRound = EndPrepSDKCall();
 | 
			
		||||
    
 | 
			
		||||
    if(g_hTerminateRound == INVALID_HANDLE)
 | 
			
		||||
	{
 | 
			
		||||
		SetFailState("Couldn't find signature \"CGameRules::TerminateRound\"!");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    StartPrepSDKCall(SDKCall_Player);
 | 
			
		||||
    PrepSDKCall_SetFromConf(g_hGameConf, SDKConf_Signature, "CSWeaponDrop");
 | 
			
		||||
    PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer);
 | 
			
		||||
    PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain);
 | 
			
		||||
    PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain);
 | 
			
		||||
    g_hCSWeaponDrop = EndPrepSDKCall();
 | 
			
		||||
    
 | 
			
		||||
    if(g_hCSWeaponDrop == INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        SetFailState("Couldn't find signature \"CBasePlayer::CSWeaponDrop\"!");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SetPlayerVelocity(client, const Float:vec[3], bool:reset)
 | 
			
		||||
@@ -231,13 +266,12 @@ GetPlayerEyeAngles(client, Float:ang[3])
 | 
			
		||||
 | 
			
		||||
TerminateRound(Float:delay, reason)
 | 
			
		||||
{
 | 
			
		||||
    if (g_hTerminateRound == INVALID_HANDLE) return;
 | 
			
		||||
    SDKCall(g_hTerminateRound, delay, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SetPlayerModel(client, const String:model[])
 | 
			
		||||
CSDropWeapon(client, weapon)
 | 
			
		||||
{
 | 
			
		||||
    SetEntityModel(client, model);
 | 
			
		||||
    SDKCall(g_hCSWeaponDrop, client, weapon, true, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SetPlayerAlpha(client, alpha)
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
 | 
			
		||||
    
 | 
			
		||||
    // TODO: Add support for keeping the default cs model ("default").
 | 
			
		||||
    
 | 
			
		||||
    SetPlayerModel(client, modelpath);
 | 
			
		||||
    SetEntityModel(client, modelpath);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										145
									
								
								src/zr/spawnprotect.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/zr/spawnprotect.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ============================================================================
 | 
			
		||||
 *
 | 
			
		||||
 *   Zombie:Reloaded
 | 
			
		||||
 *
 | 
			
		||||
 *   File:        spawnprotect.inc
 | 
			
		||||
 *   Description: Protects late-joining players from zombies for x seconds.
 | 
			
		||||
 *
 | 
			
		||||
 * ============================================================================
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array for storing spawn protect timer handles per client.
 | 
			
		||||
 */
 | 
			
		||||
new Handle:tSpawnProtect[MAXPLAYERS + 1];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array for flagging client to be protected.
 | 
			
		||||
 */ 
 | 
			
		||||
new bool:pSpawnProtect[MAXPLAYERS + 1];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array for storing time left for spawn protection per client.
 | 
			
		||||
 */
 | 
			
		||||
new pSpawnProtectTime[MAXPLAYERS + 1];
 | 
			
		||||
 
 | 
			
		||||
/**
 | 
			
		||||
 * Client is joining the server.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 */ 
 | 
			
		||||
SpawnProtectClientInit(client)
 | 
			
		||||
{
 | 
			
		||||
    tSpawnProtect[client] = INVALID_HANDLE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Player is spawning into the game.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 */   
 | 
			
		||||
SpawnProtectPlayerSpawn(client)
 | 
			
		||||
{
 | 
			
		||||
    // Disable spawn protection on client.
 | 
			
		||||
    pSpawnProtect[client] = false;
 | 
			
		||||
    
 | 
			
		||||
    // If zombie hasn't spawned, then stop.
 | 
			
		||||
    if (!zombieSpawned)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If protect cvar is invalid or 0, then stop.
 | 
			
		||||
    new protect = GetConVarInt(gCvars[CVAR_PROTECT]);
 | 
			
		||||
    if (protect <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Get respawn team.
 | 
			
		||||
    decl String:respawnteam[32];
 | 
			
		||||
    GetConVarString(gCvars[CVAR_RESPAWN_TEAM], respawnteam, sizeof(respawnteam));
 | 
			
		||||
    
 | 
			
		||||
    // If the respawn team is not set to zombie, and either cvar zr_suicide_world_damage or the client
 | 
			
		||||
    // wasn't killed by world is false, then continue to protect client.
 | 
			
		||||
    if (!StrEqual(respawnteam, "zombie", false) && !(GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && gKilledByWorld[client]))
 | 
			
		||||
    {
 | 
			
		||||
        // Set spawn protect flag on client.
 | 
			
		||||
        pSpawnProtect[client] = true;
 | 
			
		||||
        
 | 
			
		||||
        // Set improved attributes
 | 
			
		||||
        // (Move to cvar?)
 | 
			
		||||
        SetPlayerAlpha(client, 0);
 | 
			
		||||
        SetPlayerSpeed(client, 600.0);
 | 
			
		||||
        
 | 
			
		||||
        // Set time left to zr_protect's value.
 | 
			
		||||
        pSpawnProtectTime[client] = protect;
 | 
			
		||||
        
 | 
			
		||||
        // Tell client they are being protected.
 | 
			
		||||
        ZR_PrintToChat(client, "Spawn protection begin", protect);
 | 
			
		||||
        
 | 
			
		||||
        // Send time left in a hud message.
 | 
			
		||||
        ZR_HudHint(client, "Spawn Protect", pSpawnProtectTime[client]);
 | 
			
		||||
        
 | 
			
		||||
        // If timer is currently running, kill it.
 | 
			
		||||
        if (tSpawnProtect[client] != INVALID_HANDLE)
 | 
			
		||||
        {
 | 
			
		||||
            KillTimer(tSpawnProtect[client]);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Start repeating timer.
 | 
			
		||||
        tSpawnProtect[client] = CreateTimer(1.0, SpawnProtectTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Timer callback function, countdown for spawn protection.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param timer     The timer handle.
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 */    
 | 
			
		||||
public Action:SpawnProtectTimer(Handle:timer, any:client)
 | 
			
		||||
{
 | 
			
		||||
    // If client leaves, then stop timer.
 | 
			
		||||
    if (!IsClientInGame(client))
 | 
			
		||||
    {
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If client has become a zombie, then stop timer.
 | 
			
		||||
    if (!IsPlayerHuman(client))
 | 
			
		||||
    {
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Decrement time left.
 | 
			
		||||
    pSpawnProtectTime[client]--;
 | 
			
		||||
    
 | 
			
		||||
    // Print time left to client.
 | 
			
		||||
    ZR_HudHint(client, "Spawn Protect", pSpawnProtectTime[client]);
 | 
			
		||||
    
 | 
			
		||||
    // Time has expired.
 | 
			
		||||
    if (pSpawnProtectTime[client] <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        // Remove protect flag.
 | 
			
		||||
        pSpawnProtect[client] = false;
 | 
			
		||||
        
 | 
			
		||||
        // Tell client spawn protection is over.
 | 
			
		||||
        ZR_HudHint(client, "Spawn protection end");
 | 
			
		||||
        
 | 
			
		||||
        // Fix attributes.
 | 
			
		||||
        // TODO: Set class attributes.
 | 
			
		||||
        SetPlayerAlpha(client, 255);
 | 
			
		||||
        SetPlayerSpeed(client, 300.0);
 | 
			
		||||
        
 | 
			
		||||
        // Clear timer handle.
 | 
			
		||||
        tSpawnProtect[client] = INVALID_HANDLE;
 | 
			
		||||
        
 | 
			
		||||
        // Stop timer.
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Allow timer to continue repeating.
 | 
			
		||||
    return Plugin_Continue;
 | 
			
		||||
}
 | 
			
		||||
@@ -15,13 +15,13 @@
 | 
			
		||||
 */
 | 
			
		||||
public bool:Market_OnWeaponSelected(client, String:weaponid[])
 | 
			
		||||
{
 | 
			
		||||
    // If player is dead or weaponid is invalid, then stop
 | 
			
		||||
    // If player is dead or weaponid is invalid, then stop.
 | 
			
		||||
    if (!weaponid[0] || !IsPlayerAlive(client))
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If player is a zombie, then stop
 | 
			
		||||
    // If player is a zombie, then stop.
 | 
			
		||||
    if (IsPlayerZombie(client))
 | 
			
		||||
    {
 | 
			
		||||
        ZR_PrintToChat(client, "Zombie cant use weapon");
 | 
			
		||||
@@ -29,7 +29,7 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[])
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If player is using the rebuy option then allow
 | 
			
		||||
    // If player is using the rebuy option then allow.
 | 
			
		||||
    if (StrEqual(weaponid, "rebuy"))
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -39,16 +39,16 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[])
 | 
			
		||||
    decl String:weapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
    new price;
 | 
			
		||||
    
 | 
			
		||||
    // If the market plugin can't find info about the weapon, then stop
 | 
			
		||||
    // If the market plugin can't find info about the weapon, then stop.
 | 
			
		||||
    if (!Market_GetWeaponIDInfo(weaponid, display, weapon, price))
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Strip "weapon_" from entity name
 | 
			
		||||
    // Strip "weapon_" from entity name.
 | 
			
		||||
    ReplaceString(weapon, sizeof(weapon), "weapon_", "");
 | 
			
		||||
    
 | 
			
		||||
    // If the weapon is restricted, then stop
 | 
			
		||||
    // If the weapon is restricted, then stop.
 | 
			
		||||
    if (RestrictIsWeaponRestricted(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        ZR_PrintToChat(client, "Weapon is restricted", weapon);
 | 
			
		||||
@@ -56,7 +56,7 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[])
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Check if buyzone cvar is enabled, and if the client is in a buyzone
 | 
			
		||||
    // Check if buyzone cvar is enabled, and if the client is in a buyzone.
 | 
			
		||||
    new bool:buyzone = GetConVarBool(gCvars[CVAR_ZMARKET_BUYZONE]); 
 | 
			
		||||
    if (!IsClientInBuyZone(client) && buyzone)
 | 
			
		||||
    {
 | 
			
		||||
@@ -76,12 +76,12 @@ public bool:Market_OnWeaponSelected(client, String:weaponid[])
 | 
			
		||||
 */
 | 
			
		||||
public Market_PostOnWeaponSelected(client, &bool:allowed)
 | 
			
		||||
{
 | 
			
		||||
    // If the purchase wasn't allowed, then stop
 | 
			
		||||
    // If the purchase wasn't allowed, then stop.
 | 
			
		||||
    if (!allowed)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Resend market menu
 | 
			
		||||
    // Resend market menu.
 | 
			
		||||
    ZMarket(client);
 | 
			
		||||
}
 | 
			
		||||
@@ -16,12 +16,12 @@ enum WeaponsMenu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array to store the client's current weapon menu
 | 
			
		||||
 * Array to store the client's current weapon menu.
 | 
			
		||||
 */
 | 
			
		||||
new WeaponsMenu:curMenuWeapons[MAXPLAYERS + 1];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Array to store the client's current weapon group menu
 | 
			
		||||
 * Array to store the client's current weapon group menu.
 | 
			
		||||
 */ 
 | 
			
		||||
new String:curMenuGroup[WEAPONS_MAX_LENGTH][MAXPLAYERS + 1];
 | 
			
		||||
 | 
			
		||||
@@ -31,7 +31,7 @@ new String:curMenuGroup[WEAPONS_MAX_LENGTH][MAXPLAYERS + 1];
 | 
			
		||||
 */  
 | 
			
		||||
WeaponsMenuMain(client)
 | 
			
		||||
{
 | 
			
		||||
    // Create menu handle
 | 
			
		||||
    // Create menu handle.
 | 
			
		||||
    new Handle:menu_weapons_main = CreateMenu(WeaponsMenuMainHandle);
 | 
			
		||||
    
 | 
			
		||||
    SetGlobalTransTarget(client);
 | 
			
		||||
@@ -49,7 +49,7 @@ WeaponsMenuMain(client)
 | 
			
		||||
    AddMenuItem(menu_weapons_main, "toggleweaponrestriction", toggleweaponrestriction);
 | 
			
		||||
    AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction);
 | 
			
		||||
    
 | 
			
		||||
    // Disable market option if market isn't installed
 | 
			
		||||
    // Disable market option if market isn't installed.
 | 
			
		||||
    if (market)
 | 
			
		||||
    {
 | 
			
		||||
        AddMenuItem(menu_weapons_main, "zmarket", zmarket);
 | 
			
		||||
@@ -59,10 +59,10 @@ WeaponsMenuMain(client)
 | 
			
		||||
        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);
 | 
			
		||||
    
 | 
			
		||||
    // Send menu
 | 
			
		||||
    // Send menu.
 | 
			
		||||
    DisplayMenu(menu_weapons_main, client, MENU_TIME_FOREVER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -75,7 +75,7 @@ WeaponsMenuMain(client)
 | 
			
		||||
 */ 
 | 
			
		||||
public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client, slot)
 | 
			
		||||
{
 | 
			
		||||
    // Client selected an option
 | 
			
		||||
    // Client selected an option.
 | 
			
		||||
    if (action == MenuAction_Select)
 | 
			
		||||
    {
 | 
			
		||||
        switch(slot)
 | 
			
		||||
@@ -94,16 +94,16 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client closed the menu
 | 
			
		||||
    // Client closed the menu.
 | 
			
		||||
    if (action == MenuAction_Cancel)
 | 
			
		||||
    {
 | 
			
		||||
        // Client hit "Back" button
 | 
			
		||||
        // Client hit "Back" button.
 | 
			
		||||
        if (slot == MenuCancel_ExitBack)
 | 
			
		||||
        {
 | 
			
		||||
            ZRAdminMenu(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client hit "Exit" button
 | 
			
		||||
    // Client hit "Exit" button.
 | 
			
		||||
    else if (action == MenuAction_End)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(menu_weapons_main);
 | 
			
		||||
@@ -116,15 +116,15 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
 | 
			
		||||
 */ 
 | 
			
		||||
WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
{
 | 
			
		||||
    // Set the current action client is performing on a weapon (see enum WeaponsMenu)
 | 
			
		||||
    // Set the current action client is performing on a weapon. (see enum WeaponsMenu)
 | 
			
		||||
    curMenuWeapons[client] = type;
 | 
			
		||||
    
 | 
			
		||||
    // Create menu handle
 | 
			
		||||
    // Create menu handle.
 | 
			
		||||
    new Handle:menu_weapons_weapons = CreateMenu(WeaponsMenuWeaponsHandle);
 | 
			
		||||
    
 | 
			
		||||
    SetGlobalTransTarget(client);
 | 
			
		||||
    
 | 
			
		||||
    // If client wants to perform an action on a single weapon, show weapon list
 | 
			
		||||
    // If client wants to perform an action on a single weapon, show weapon list.
 | 
			
		||||
    switch(curMenuWeapons[client])
 | 
			
		||||
    {
 | 
			
		||||
        case Weapon:
 | 
			
		||||
@@ -136,7 +136,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
            new Handle:arrayWeapons = INVALID_HANDLE;
 | 
			
		||||
            new size = WeaponsCreateWeaponArray(arrayWeapons);
 | 
			
		||||
            
 | 
			
		||||
            // x = Array index
 | 
			
		||||
            // x = Array index.
 | 
			
		||||
            for (new x = 0; x < size; x++)
 | 
			
		||||
            {
 | 
			
		||||
                GetArrayString(arrayWeapons, x, weapon, sizeof(weapon));
 | 
			
		||||
@@ -148,7 +148,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
                    Format(display, sizeof(display), "%s*", weapon);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // If weapon restriction is blocked for the menu, disable option
 | 
			
		||||
                // If weapon restriction is blocked for the menu, disable option.
 | 
			
		||||
                new bool:menu = WeaponsIsWeaponMenu(weapon);
 | 
			
		||||
                
 | 
			
		||||
                if (menu)
 | 
			
		||||
@@ -161,7 +161,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // If there are no weapons, add an "(Empty)" line
 | 
			
		||||
            // If there are no weapons, add an "(Empty)" line.
 | 
			
		||||
            if (size == 0)
 | 
			
		||||
            {
 | 
			
		||||
                decl String:empty[64];
 | 
			
		||||
@@ -170,10 +170,10 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
                AddMenuItem(menu_weapons_weapons, "empty", empty, ITEMDRAW_DISABLED);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // Kill the array handle
 | 
			
		||||
            // Kill the array handle.
 | 
			
		||||
            CloseHandle(arrayWeapons);
 | 
			
		||||
        }
 | 
			
		||||
        // If client wants to perform an action on a weapon group, show custom group list
 | 
			
		||||
        // If client wants to perform an action on a weapon group, show custom group list.
 | 
			
		||||
        case WeaponGroup:
 | 
			
		||||
        {
 | 
			
		||||
            SetMenuTitle(menu_weapons_weapons, "%t\n ", "Weapons menu weapons group title");
 | 
			
		||||
@@ -183,7 +183,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
            new Handle:arrayWeaponGroups = INVALID_HANDLE;
 | 
			
		||||
            new size = RestrictCreateGroupArray(arrayWeaponGroups);
 | 
			
		||||
            
 | 
			
		||||
            // x = Array index
 | 
			
		||||
            // x = Array index.
 | 
			
		||||
            for (new x = 0; x < size; x++)
 | 
			
		||||
            {
 | 
			
		||||
                GetArrayString(arrayWeaponGroups, x, weapongroup, sizeof(weapongroup));
 | 
			
		||||
@@ -202,7 +202,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
                AddMenuItem(menu_weapons_weapons, weapongroup, display);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // If there are no weapons, add an "(Empty)" line
 | 
			
		||||
            // If there are no weapons, add an "(Empty)" line.
 | 
			
		||||
            if (size == 0)
 | 
			
		||||
            {
 | 
			
		||||
                decl String:empty[64];
 | 
			
		||||
@@ -230,7 +230,7 @@ WeaponsMenuWeapons(client, WeaponsMenu:type)
 | 
			
		||||
 */ 
 | 
			
		||||
public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action, client, slot)
 | 
			
		||||
{
 | 
			
		||||
    // Client selected an option
 | 
			
		||||
    // Client selected an option.
 | 
			
		||||
    if (action == MenuAction_Select)
 | 
			
		||||
    {
 | 
			
		||||
        decl String:weapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
@@ -238,7 +238,7 @@ public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action,
 | 
			
		||||
        
 | 
			
		||||
        switch(curMenuWeapons[client])
 | 
			
		||||
        {
 | 
			
		||||
            // Client is restricting a single weapon
 | 
			
		||||
            // Client is restricting a single weapon.
 | 
			
		||||
            case Weapon:
 | 
			
		||||
            {
 | 
			
		||||
                new WpnRestrictQuery:output;
 | 
			
		||||
@@ -254,27 +254,27 @@ public WeaponsMenuWeaponsHandle(Handle:menu_weapons_weapons, MenuAction:action,
 | 
			
		||||
                    RestrictPrintUnrestrictOutput(client, output, weapon, false);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Resend menu
 | 
			
		||||
                // Resend menu.
 | 
			
		||||
                WeaponsMenuWeapons(client, curMenuWeapons[client]);
 | 
			
		||||
            }
 | 
			
		||||
            // Client is accessing a weapon group
 | 
			
		||||
            // Client is accessing a weapon group.
 | 
			
		||||
            case WeaponGroup:
 | 
			
		||||
            {
 | 
			
		||||
                // Send weapon group menu
 | 
			
		||||
                // Send weapon group menu.
 | 
			
		||||
                WeaponsMenuWeaponGroup(client, weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client closed the menu
 | 
			
		||||
    // Client closed the menu.
 | 
			
		||||
    if (action == MenuAction_Cancel)
 | 
			
		||||
    {
 | 
			
		||||
        // Client hit "Back" button
 | 
			
		||||
        // Client hit "Back" button.
 | 
			
		||||
        if (slot == MenuCancel_ExitBack)
 | 
			
		||||
        {
 | 
			
		||||
            WeaponsMenuMain(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client hit "Exit" button
 | 
			
		||||
    // Client hit "Exit" button.
 | 
			
		||||
    else if (action == MenuAction_End)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(menu_weapons_weapons);
 | 
			
		||||
@@ -285,7 +285,7 @@ WeaponsMenuWeaponGroup(client, const String:weapongroup[])
 | 
			
		||||
{
 | 
			
		||||
    strcopy(curMenuGroup[client], WEAPONS_MAX_LENGTH, weapongroup);
 | 
			
		||||
    
 | 
			
		||||
    // Create menu handle
 | 
			
		||||
    // Create menu handle.
 | 
			
		||||
    new Handle:menu_weapons_groupweapon = CreateMenu(WeaponsMenuWeaponGroupHandle);
 | 
			
		||||
    
 | 
			
		||||
    SetMenuTitle(menu_weapons_groupweapon, "%t\n ", "Weapons menu weapon group title", weapongroup);
 | 
			
		||||
@@ -319,7 +319,7 @@ WeaponsMenuWeaponGroup(client, const String:weapongroup[])
 | 
			
		||||
    new Handle:arrayGroupWeapons = INVALID_HANDLE;
 | 
			
		||||
    new size = RestrictCreateGroupWeaponsArray(arrayGroupWeapons, weapongroup);
 | 
			
		||||
    
 | 
			
		||||
    // x = Array index
 | 
			
		||||
    // x = Array index.
 | 
			
		||||
    for (new x = 0; x < size; x++)
 | 
			
		||||
    {
 | 
			
		||||
        GetArrayString(arrayGroupWeapons, x, groupweapon, sizeof(groupweapon));
 | 
			
		||||
@@ -334,7 +334,7 @@ WeaponsMenuWeaponGroup(client, const String:weapongroup[])
 | 
			
		||||
        AddMenuItem(menu_weapons_groupweapon, groupweapon, display);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Kill the array handle
 | 
			
		||||
    // Kill the array handle.
 | 
			
		||||
    CloseHandle(arrayGroupWeapons);
 | 
			
		||||
    
 | 
			
		||||
    SetMenuExitBackButton(menu_weapons_groupweapon, true);
 | 
			
		||||
@@ -351,7 +351,7 @@ WeaponsMenuWeaponGroup(client, const String:weapongroup[])
 | 
			
		||||
 */ 
 | 
			
		||||
public WeaponsMenuWeaponGroupHandle(Handle:menu_weapons_groupweapon, MenuAction:action, client, slot)
 | 
			
		||||
{
 | 
			
		||||
    // Client selected an option
 | 
			
		||||
    // Client selected an option.
 | 
			
		||||
    if (action == MenuAction_Select)
 | 
			
		||||
    {
 | 
			
		||||
        switch(slot)
 | 
			
		||||
@@ -387,19 +387,19 @@ public WeaponsMenuWeaponGroupHandle(Handle:menu_weapons_groupweapon, MenuAction:
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Resend menu
 | 
			
		||||
        // Resend menu.
 | 
			
		||||
        WeaponsMenuWeaponGroup(client, curMenuGroup[client]);
 | 
			
		||||
    }
 | 
			
		||||
    // Client closed the menu
 | 
			
		||||
    // Client closed the menu.
 | 
			
		||||
    if (action == MenuAction_Cancel)
 | 
			
		||||
    {
 | 
			
		||||
        // Client hit "Back" button
 | 
			
		||||
        // Client hit "Back" button.
 | 
			
		||||
        if (slot == MenuCancel_ExitBack)
 | 
			
		||||
        {
 | 
			
		||||
            WeaponsMenuWeapons(client, curMenuWeapons[client]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client hit "Exit" button
 | 
			
		||||
    // Client hit "Exit" button.
 | 
			
		||||
    else if (action == MenuAction_End)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(menu_weapons_groupweapon);
 | 
			
		||||
@@ -412,7 +412,7 @@ public WeaponsMenuWeaponGroupHandle(Handle:menu_weapons_groupweapon, MenuAction:
 | 
			
		||||
 */  
 | 
			
		||||
WeaponsMenuMarket(client)
 | 
			
		||||
{
 | 
			
		||||
    // Create menu handle
 | 
			
		||||
    // Create menu handle.
 | 
			
		||||
    new Handle:menu_weapons_market = CreateMenu(WeaponsMenuMarketHandle);
 | 
			
		||||
    
 | 
			
		||||
    SetGlobalTransTarget(client);
 | 
			
		||||
@@ -428,7 +428,7 @@ WeaponsMenuMarket(client)
 | 
			
		||||
    
 | 
			
		||||
    AddMenuItem(menu_weapons_market, "togglebuyzone", togglebuyzone);
 | 
			
		||||
    
 | 
			
		||||
    // Create a "Back" button to the weapons main menu
 | 
			
		||||
    // Create a "Back" button to the weapons main menu.
 | 
			
		||||
    SetMenuExitBackButton(menu_weapons_market, true);
 | 
			
		||||
    
 | 
			
		||||
    // Send menu
 | 
			
		||||
@@ -444,7 +444,7 @@ WeaponsMenuMarket(client)
 | 
			
		||||
 */ 
 | 
			
		||||
public WeaponsMenuMarketHandle(Handle:menu_weapons_market, MenuAction:action, client, slot)
 | 
			
		||||
{
 | 
			
		||||
    // Client selected an option
 | 
			
		||||
    // Client selected an option.
 | 
			
		||||
    if (action == MenuAction_Select)
 | 
			
		||||
    {
 | 
			
		||||
        switch(slot)
 | 
			
		||||
@@ -462,19 +462,19 @@ public WeaponsMenuMarketHandle(Handle:menu_weapons_market, MenuAction:action, cl
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Resend menu
 | 
			
		||||
        // Resend menu.
 | 
			
		||||
        WeaponsMenuMarket(client);
 | 
			
		||||
    }
 | 
			
		||||
    // Client closed the menu
 | 
			
		||||
    // Client closed the menu.
 | 
			
		||||
    if (action == MenuAction_Cancel)
 | 
			
		||||
    {
 | 
			
		||||
        // Client hit "Back" button
 | 
			
		||||
        // Client hit "Back" button.
 | 
			
		||||
        if (slot == MenuCancel_ExitBack)
 | 
			
		||||
        {
 | 
			
		||||
            WeaponsMenuMain(client);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Client hit "Exit" button
 | 
			
		||||
    // Client hit "Exit" button.
 | 
			
		||||
    else if (action == MenuAction_End)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(menu_weapons_market);
 | 
			
		||||
 
 | 
			
		||||
@@ -38,22 +38,22 @@ enum WpnRestrictQuery
 | 
			
		||||
 */
 | 
			
		||||
RestrictInit()
 | 
			
		||||
{
 | 
			
		||||
    // Initialize weapon restrict array
 | 
			
		||||
    // Initialize weapon restrict array.
 | 
			
		||||
    gRestrictedWeapons = CreateArray(32, 0);
 | 
			
		||||
    
 | 
			
		||||
    // Hook buy command
 | 
			
		||||
    // Hook buy command.
 | 
			
		||||
    RegConsoleCmd("buy", RestrictBuyHook);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears weapon restrict data
 | 
			
		||||
 * Clears weapon restrict data.
 | 
			
		||||
 */ 
 | 
			
		||||
RestrictClearData()
 | 
			
		||||
{
 | 
			
		||||
    // Clear restricted weapons
 | 
			
		||||
    // Clear restricted weapons.
 | 
			
		||||
    RestrictWeaponUnrestrictAll();
 | 
			
		||||
    
 | 
			
		||||
    // Load weapon group data
 | 
			
		||||
    // Load weapon group data.
 | 
			
		||||
    if (kvWeaponGroups != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(kvWeaponGroups);
 | 
			
		||||
@@ -67,13 +67,13 @@ RestrictClearData()
 | 
			
		||||
 */
 | 
			
		||||
RestrictOnMapStart()
 | 
			
		||||
{
 | 
			
		||||
    // Restrict default restrictions (set in weapons.txt)
 | 
			
		||||
    // 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");
 | 
			
		||||
    
 | 
			
		||||
    // If file isn't found, stop plugin
 | 
			
		||||
    // If file isn't found, stop plugin.
 | 
			
		||||
    if (!FileToKeyValues(kvWeaponGroups, path))
 | 
			
		||||
    {
 | 
			
		||||
        if (LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
 | 
			
		||||
@@ -88,7 +88,7 @@ RestrictOnMapStart()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Restrict default restrictions (set in weapons.txt)
 | 
			
		||||
 * Restrict default restrictions. (set in weapons.txt)
 | 
			
		||||
 */
 | 
			
		||||
RestrictDefaultRestrictions()
 | 
			
		||||
{
 | 
			
		||||
@@ -103,7 +103,7 @@ RestrictDefaultRestrictions()
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeapons, weapon, sizeof(weapon));
 | 
			
		||||
            
 | 
			
		||||
            // If weapon is defaulted to restricted, then restrict weapon
 | 
			
		||||
            // If weapon is defaulted to restricted, then restrict weapon.
 | 
			
		||||
            decl String:restrict[8];
 | 
			
		||||
            KvGetString(kvWeapons, "restrict", restrict, sizeof(restrict), "no");
 | 
			
		||||
            
 | 
			
		||||
@@ -113,7 +113,7 @@ RestrictDefaultRestrictions()
 | 
			
		||||
                RestrictPrintRestrictOutput(0, output, display, true);
 | 
			
		||||
                
 | 
			
		||||
                // Function calls above screwed with the keyvalue stack, so we have to set it back
 | 
			
		||||
                // to where it was before those calls
 | 
			
		||||
                // to where it was before those calls.
 | 
			
		||||
                KvRewind(kvWeapons);
 | 
			
		||||
                KvJumpToKey(kvWeapons, weapon);
 | 
			
		||||
            }
 | 
			
		||||
@@ -126,14 +126,16 @@ RestrictDefaultRestrictions()
 | 
			
		||||
 */ 
 | 
			
		||||
RestrictValidateWeaponGroups()
 | 
			
		||||
{
 | 
			
		||||
    // If log flag check fails, don't log
 | 
			
		||||
    // If log flag check fails, don't log.
 | 
			
		||||
    if (!LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Reset keygroup's traversal stack.
 | 
			
		||||
    KvRewind(kvWeaponGroups);
 | 
			
		||||
    
 | 
			
		||||
    // Traverse into the keygroup. (weapon groups level)
 | 
			
		||||
    if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
    {
 | 
			
		||||
        decl String:weapongroup[WEAPONS_MAX_LENGTH];
 | 
			
		||||
@@ -143,12 +145,14 @@ RestrictValidateWeaponGroups()
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeaponGroups, weapongroup, sizeof(weapongroup));
 | 
			
		||||
            
 | 
			
		||||
            // Traverse into the keygroup. (weapons level)
 | 
			
		||||
            if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
            {
 | 
			
		||||
                do
 | 
			
		||||
                {
 | 
			
		||||
                    KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon));
 | 
			
		||||
                    
 | 
			
		||||
                    // If weapon is invalid, then log it.
 | 
			
		||||
                    if (!WeaponsIsValidWeapon(groupweapon))
 | 
			
		||||
                    {
 | 
			
		||||
                        ZR_LogMessageFormatted(-1, "Weapon Restrict", "Config Validation", "Invalid weapon \"%s\" in group \"%s\" configured in weapongroups.txt.", LOG_FORMAT_TYPE_ERROR, groupweapon, weapongroup);
 | 
			
		||||
@@ -157,6 +161,7 @@ RestrictValidateWeaponGroups()
 | 
			
		||||
                
 | 
			
		||||
                KvGoBack(kvWeaponGroups);
 | 
			
		||||
            }
 | 
			
		||||
            // If it couldn't traverse to the weapons, then log no weapons within group.
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                ZR_LogMessageFormatted(-1, "Weapon Restrict", "Config Validation", "No weapons listed in weapon group \"%s\" in weapongroups.txt.", LOG_FORMAT_TYPE_ERROR, weapongroup);
 | 
			
		||||
@@ -174,7 +179,7 @@ RestrictWeaponUnrestrictAll()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook Weapon_CanUse function on a client.
 | 
			
		||||
 * Client is joining the server.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 */
 | 
			
		||||
@@ -202,15 +207,15 @@ RestrictOnClientDisconnect(client)
 | 
			
		||||
 */
 | 
			
		||||
public Action:RestrictBuyHook(client, argc)
 | 
			
		||||
{
 | 
			
		||||
    // If plugin is disabled then stop
 | 
			
		||||
    // If plugin is disabled then stop.
 | 
			
		||||
    new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]);
 | 
			
		||||
    if (!enabled)
 | 
			
		||||
    {
 | 
			
		||||
        // Allow command
 | 
			
		||||
        // Allow command.
 | 
			
		||||
        return Plugin_Continue;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If player is a zombie then block command
 | 
			
		||||
    // If player is a zombie then block command.
 | 
			
		||||
    if (IsPlayerZombie(client))
 | 
			
		||||
    {
 | 
			
		||||
        ZR_PrintToChat(client, "Zombie cant use weapon");
 | 
			
		||||
@@ -224,16 +229,16 @@ public Action:RestrictBuyHook(client, argc)
 | 
			
		||||
    
 | 
			
		||||
    ReplaceString(weapon, sizeof(weapon), "weapon_", "");
 | 
			
		||||
    
 | 
			
		||||
    // Check if the weapon is restricted, if so then block command
 | 
			
		||||
    // Check if the weapon is restricted, if so then block command.
 | 
			
		||||
    if (RestrictIsWeaponRestricted(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        ZR_PrintToChat(client, "Weapon is restricted", weapon);
 | 
			
		||||
        
 | 
			
		||||
        // Block command
 | 
			
		||||
        // Block command.
 | 
			
		||||
        return Plugin_Handled;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Allow command
 | 
			
		||||
    // Allow command.
 | 
			
		||||
    return Plugin_Continue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -251,18 +256,23 @@ public Action:RestrictBuyHook(client, argc)
 | 
			
		||||
 */
 | 
			
		||||
WpnRestrictQuery:RestrictRestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
{
 | 
			
		||||
    // Check if weapon is a custom group name.
 | 
			
		||||
    if (RestrictIsWeaponGroup(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        // Return restrict failed if group is already restricted.
 | 
			
		||||
        if (RestrictIsGroupRestricted(weapon))
 | 
			
		||||
        {
 | 
			
		||||
            return Failed_Group;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Jump to weapon group key.
 | 
			
		||||
        KvRewind(kvWeaponGroups);
 | 
			
		||||
        KvJumpToKey(kvWeaponGroups, weapon);
 | 
			
		||||
        
 | 
			
		||||
        // Get display name of the weapon group.
 | 
			
		||||
        KvGetSectionName(kvWeaponGroups, display, WEAPONS_MAX_LENGTH);
 | 
			
		||||
        
 | 
			
		||||
        // Traverse into the group's weapons.
 | 
			
		||||
        if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
        {
 | 
			
		||||
            decl String:groupweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
@@ -271,12 +281,13 @@ WpnRestrictQuery:RestrictRestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
            {
 | 
			
		||||
                KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon));
 | 
			
		||||
                
 | 
			
		||||
                // If weapon is invalid, then skip
 | 
			
		||||
                // If weapon is invalid, then skip.
 | 
			
		||||
                if (!WeaponsIsValidWeapon(groupweapon))
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Add to restricted weapon array if not already restricted.
 | 
			
		||||
                if (!RestrictIsWeaponRestricted(groupweapon))
 | 
			
		||||
                {
 | 
			
		||||
                    PushArrayString(gRestrictedWeapons, groupweapon);
 | 
			
		||||
@@ -284,23 +295,29 @@ WpnRestrictQuery:RestrictRestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
            } while (KvGotoNextKey(kvWeaponGroups));
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Successfully restricted a group
 | 
			
		||||
        return Successful_Group;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If weapon name is invalid then set display to invalid weapon name.
 | 
			
		||||
    if (!WeaponsIsValidWeapon(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        strcopy(display, WEAPONS_MAX_LENGTH, weapon);
 | 
			
		||||
        
 | 
			
		||||
        // Weapon name was invalid.
 | 
			
		||||
        return Invalid;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Get display name of the weapon.
 | 
			
		||||
    WeaponGetDisplayName(weapon, display);
 | 
			
		||||
    
 | 
			
		||||
    // Return restrict failed if weapon is already restricted.
 | 
			
		||||
    if (RestrictIsWeaponRestricted(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        return Failed_Weapon;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Add to restricted weapon array.
 | 
			
		||||
    PushArrayString(gRestrictedWeapons, display);
 | 
			
		||||
    
 | 
			
		||||
    return Successful_Weapon;
 | 
			
		||||
@@ -310,8 +327,8 @@ WpnRestrictQuery:RestrictRestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
 * Unrestricts a weapon.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param weapon    The weapon/group name.
 | 
			
		||||
 * @param display   String set to the name set in weapons.txt
 | 
			
		||||
 *                  Set to the value of 'weapon' if invalid
 | 
			
		||||
 * @param display   String set to the name set in weapons.txt.
 | 
			
		||||
 *                  Set to the value of 'weapon' if invalid.
 | 
			
		||||
 * @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.
 | 
			
		||||
@@ -320,18 +337,23 @@ WpnRestrictQuery:RestrictRestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
 */
 | 
			
		||||
WpnRestrictQuery:RestrictUnrestrict(const String:weapon[], String:display[] = "")
 | 
			
		||||
{
 | 
			
		||||
    // Check if weapon is a custom group name.
 | 
			
		||||
    if (RestrictIsWeaponGroup(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        // Return restrict failed if group isn't restricted.
 | 
			
		||||
        if (RestrictIsGroupUnrestricted(weapon))
 | 
			
		||||
        {
 | 
			
		||||
            return Failed_Group;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Jump to weapon group key.
 | 
			
		||||
        KvRewind(kvWeaponGroups);
 | 
			
		||||
        KvJumpToKey(kvWeaponGroups, weapon);
 | 
			
		||||
        
 | 
			
		||||
        // Get display name of the weapon group.
 | 
			
		||||
        KvGetSectionName(kvWeaponGroups, display, WEAPONS_MAX_LENGTH);
 | 
			
		||||
        
 | 
			
		||||
        // Traverse into the group's weapons.
 | 
			
		||||
        if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
        {
 | 
			
		||||
            decl String:groupweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
@@ -346,8 +368,10 @@ WpnRestrictQuery:RestrictUnrestrict(const String:weapon[], String:display[] = ""
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Remove from restricted weapon array if currently restricted.
 | 
			
		||||
                if (RestrictIsWeaponRestricted(groupweapon))
 | 
			
		||||
                {
 | 
			
		||||
                    // Verify weapon is in the array.
 | 
			
		||||
                    new weaponindex = RestrictGetIndex(groupweapon);
 | 
			
		||||
                    if (weaponindex > -1)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -357,9 +381,11 @@ WpnRestrictQuery:RestrictUnrestrict(const String:weapon[], String:display[] = ""
 | 
			
		||||
            } while (KvGotoNextKey(kvWeaponGroups));
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Successfully unrestricted a group
 | 
			
		||||
        return Successful_Group;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If weapon name is invalid then set display to invalid weapon name.
 | 
			
		||||
    if (!WeaponsIsValidWeapon(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        strcopy(display, WEAPONS_MAX_LENGTH, weapon);
 | 
			
		||||
@@ -367,16 +393,20 @@ WpnRestrictQuery:RestrictUnrestrict(const String:weapon[], String:display[] = ""
 | 
			
		||||
        return Invalid;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Get display name of the weapon.
 | 
			
		||||
    WeaponGetDisplayName(weapon, display);
 | 
			
		||||
    
 | 
			
		||||
    // Return unrestrict failed if weapon isn't restricted.
 | 
			
		||||
    if (!RestrictIsWeaponRestricted(weapon))
 | 
			
		||||
    {
 | 
			
		||||
        return Failed_Weapon;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Verify weapon is in the array.
 | 
			
		||||
    new weaponindex = RestrictGetIndex(display);
 | 
			
		||||
    if (weaponindex > -1)
 | 
			
		||||
    {
 | 
			
		||||
        // Remove from restricted weapon array.
 | 
			
		||||
        RemoveFromArray(gRestrictedWeapons, weaponindex);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
@@ -394,6 +424,7 @@ RestrictPrintRestrictOutput(client, WpnRestrictQuery:output, const String:weapon
 | 
			
		||||
{
 | 
			
		||||
    switch(output)
 | 
			
		||||
    {
 | 
			
		||||
        // Weapon was successfully restricted.
 | 
			
		||||
        case Successful_Weapon:
 | 
			
		||||
        {
 | 
			
		||||
            ZR_PrintToChat(0, "Restrict weapon", weapon);
 | 
			
		||||
@@ -403,6 +434,7 @@ RestrictPrintRestrictOutput(client, WpnRestrictQuery:output, const String:weapon
 | 
			
		||||
                ZR_LogMessageFormatted(client, "Weapon Restrict", "Restrict", "\"%L\" restricted weapon: \"%s\".", LOG_FORMAT_TYPE_FULL, client, weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon group was successfully restricted.
 | 
			
		||||
        case Successful_Group:
 | 
			
		||||
        {
 | 
			
		||||
            decl String:weaponlist[128];
 | 
			
		||||
@@ -415,6 +447,7 @@ RestrictPrintRestrictOutput(client, WpnRestrictQuery:output, const String:weapon
 | 
			
		||||
                ZR_LogMessageFormatted(client, "Weapon Restrict", "Restrict", "\"%L\" restricted weapon group: \"%s\".", LOG_FORMAT_TYPE_FULL, client, weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon was already restricted.
 | 
			
		||||
        case Failed_Weapon:
 | 
			
		||||
        {
 | 
			
		||||
            if (reply)
 | 
			
		||||
@@ -426,6 +459,7 @@ RestrictPrintRestrictOutput(client, WpnRestrictQuery:output, const String:weapon
 | 
			
		||||
                ZR_PrintToChat(client, "Restrict weapon failed", weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon group was already restricted.
 | 
			
		||||
        case Failed_Group:
 | 
			
		||||
        {
 | 
			
		||||
            decl String:weaponlist[128];
 | 
			
		||||
@@ -440,6 +474,7 @@ RestrictPrintRestrictOutput(client, WpnRestrictQuery:output, const String:weapon
 | 
			
		||||
                ZR_PrintToChat(client, "Restrict custom weapon group failed", weapon, weaponlist);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon name was invalid.
 | 
			
		||||
        case Invalid:
 | 
			
		||||
        {
 | 
			
		||||
            if (reply)
 | 
			
		||||
@@ -465,6 +500,7 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
{
 | 
			
		||||
    switch(output)
 | 
			
		||||
    {
 | 
			
		||||
        // Weapon was successfully unrestricted.
 | 
			
		||||
        case Successful_Weapon:
 | 
			
		||||
        {
 | 
			
		||||
            ZR_PrintToChat(0, "Unrestrict weapon", weapon);
 | 
			
		||||
@@ -474,6 +510,7 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
                ZR_LogMessageFormatted(client, "Weapon Restrict", "Unrestrict", "\"%L\" unrestricted weapon: \"%s\".", LOG_FORMAT_TYPE_FULL, client, weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon group was successfully unrestricted.
 | 
			
		||||
        case Successful_Group:
 | 
			
		||||
        {
 | 
			
		||||
            decl String:weaponlist[128];
 | 
			
		||||
@@ -486,6 +523,7 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
                ZR_LogMessageFormatted(client, "Weapon Restrict", "Unrestrict", "\"%L\" unrestricted weapon group: \"%s\".", LOG_FORMAT_TYPE_FULL, client, weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon wasn't restricted.
 | 
			
		||||
        case Failed_Weapon:
 | 
			
		||||
        {
 | 
			
		||||
            if (reply)
 | 
			
		||||
@@ -497,6 +535,7 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
                ZR_PrintToChat(client, "Unrestrict weapon failed", weapon);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon group wasn't restricted.
 | 
			
		||||
        case Failed_Group:
 | 
			
		||||
        {
 | 
			
		||||
            decl String:weaponlist[128];
 | 
			
		||||
@@ -511,6 +550,7 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
                ZR_PrintToChat(client, "Unrestrict custom weapon group failed", weapon, weaponlist);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Weapon name was invalid.
 | 
			
		||||
        case Invalid:
 | 
			
		||||
        {
 | 
			
		||||
            if (reply)
 | 
			
		||||
@@ -529,22 +569,28 @@ RestrictPrintUnrestrictOutput(client, WpnRestrictQuery:output, const String:weap
 | 
			
		||||
 * Checks if a weapon is restricted.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param weapon    The weapon name.
 | 
			
		||||
 * @return          True if weapon is restricted, false if not. 
 | 
			
		||||
 */
 | 
			
		||||
bool:RestrictIsWeaponRestricted(const String:weapon[])
 | 
			
		||||
{
 | 
			
		||||
    decl String:restrictedweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
    
 | 
			
		||||
    new size = GetArraySize(gRestrictedWeapons);
 | 
			
		||||
    
 | 
			
		||||
    // x = restricted weapon index.
 | 
			
		||||
    for (new x = 0; x < size; x++)
 | 
			
		||||
    {
 | 
			
		||||
        GetArrayString(gRestrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon));
 | 
			
		||||
        
 | 
			
		||||
        // Check if weapon matches any weapon names in the restricted weapon array.
 | 
			
		||||
        if (StrEqual(weapon, restrictedweapon, false))
 | 
			
		||||
        {
 | 
			
		||||
            // Weapon is restricted.
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Weapon is not restricted.
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -555,11 +601,15 @@ bool:RestrictIsWeaponRestricted(const String:weapon[])
 | 
			
		||||
 */
 | 
			
		||||
bool:RestrictIsGroupRestricted(const String:weapongroup[])
 | 
			
		||||
{
 | 
			
		||||
    // Reset keygroup's traversal stack.
 | 
			
		||||
    KvRewind(kvWeaponGroups);
 | 
			
		||||
    
 | 
			
		||||
    // Traverse in to the group names.
 | 
			
		||||
    if (KvJumpToKey(kvWeaponGroups, weapongroup))
 | 
			
		||||
    {
 | 
			
		||||
        decl String:groupweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
        
 | 
			
		||||
        // Traverse into the group's weapons.
 | 
			
		||||
        if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
        {
 | 
			
		||||
            do
 | 
			
		||||
@@ -587,11 +637,15 @@ bool:RestrictIsGroupRestricted(const String:weapongroup[])
 | 
			
		||||
 */
 | 
			
		||||
bool:RestrictIsGroupUnrestricted(const String:weapongroup[])
 | 
			
		||||
{
 | 
			
		||||
    // Reset keygroup's traversal stack.
 | 
			
		||||
    KvRewind(kvWeaponGroups);
 | 
			
		||||
    
 | 
			
		||||
    // Traverse in to the group names.
 | 
			
		||||
    if (KvJumpToKey(kvWeaponGroups, weapongroup))
 | 
			
		||||
    {
 | 
			
		||||
        decl String:groupweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
        
 | 
			
		||||
        // Traverse into the group's weapons.
 | 
			
		||||
        if (KvGotoFirstSubKey(kvWeaponGroups))
 | 
			
		||||
        {
 | 
			
		||||
            do
 | 
			
		||||
@@ -632,16 +686,21 @@ RestrictGetIndex(const String:weapon[])
 | 
			
		||||
    decl String:restrictedweapon[WEAPONS_MAX_LENGTH];
 | 
			
		||||
    
 | 
			
		||||
    new size = GetArraySize(gRestrictedWeapons);
 | 
			
		||||
    
 | 
			
		||||
    // x = restricted weapon index.
 | 
			
		||||
    for (new x = 0; x < size; x++)
 | 
			
		||||
    {
 | 
			
		||||
        GetArrayString(gRestrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon));
 | 
			
		||||
        
 | 
			
		||||
        // Check if weapon matches weapon in restricted weapons array.
 | 
			
		||||
        if (StrEqual(weapon, restrictedweapon, false))
 | 
			
		||||
        {
 | 
			
		||||
            // Return restricted weapon's index.
 | 
			
		||||
            return x;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Weapon isn't restricted.
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -653,10 +712,10 @@ RestrictGetIndex(const String:weapon[])
 | 
			
		||||
 */
 | 
			
		||||
bool:RestrictIsWeaponGroup(const String:groupname[])
 | 
			
		||||
{
 | 
			
		||||
    // Reset the traversal stack
 | 
			
		||||
    // Reset keygroup's traversal stack.
 | 
			
		||||
    KvRewind(kvWeaponGroups);
 | 
			
		||||
    
 | 
			
		||||
    // Returns true if groupname is listed in the custom groups file
 | 
			
		||||
    // Returns true if groupname is listed in the custom groups file.
 | 
			
		||||
    return KvJumpToKey(kvWeaponGroups, groupname);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -710,7 +769,7 @@ RestrictCreateGroupWeaponsArray(&Handle:arrayGroupWeapons, const String:weapongr
 | 
			
		||||
            {
 | 
			
		||||
                KvGetSectionName(kvWeaponGroups, groupweapon, maxlen);
 | 
			
		||||
                
 | 
			
		||||
                // If the weapon is invalid, then stop
 | 
			
		||||
                // If the weapon is invalid, then stop.
 | 
			
		||||
                if (!WeaponsIsValidWeapon(groupweapon))
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
@@ -749,7 +808,7 @@ RestrictGetGroupWeapons(const String:groupname[], String:weaponlist[], maxlen, c
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeaponGroups, groupweapon, sizeof(groupweapon));
 | 
			
		||||
            
 | 
			
		||||
            // If weapon is invalid, then skip
 | 
			
		||||
            // If weapon is invalid, then skip.
 | 
			
		||||
            if (!WeaponsIsValidWeapon(groupweapon))
 | 
			
		||||
            {
 | 
			
		||||
                continue;
 | 
			
		||||
@@ -775,7 +834,7 @@ RestrictGetGroupWeapons(const String:groupname[], String:weaponlist[], maxlen, c
 | 
			
		||||
 */
 | 
			
		||||
public RestrictCanUse(client, weapon, dummy1, dummy2, dummy3, dummy4)
 | 
			
		||||
{
 | 
			
		||||
    // If plugin is disabled then stop
 | 
			
		||||
    // If plugin is disabled then stop.
 | 
			
		||||
    new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]);
 | 
			
		||||
    if (!enabled)
 | 
			
		||||
    {
 | 
			
		||||
@@ -785,16 +844,16 @@ public RestrictCanUse(client, weapon, dummy1, dummy2, dummy3, dummy4)
 | 
			
		||||
    new String:weaponname[WEAPONS_MAX_LENGTH];
 | 
			
		||||
    GetEdictClassname(weapon, weaponname, sizeof(weaponname));
 | 
			
		||||
    
 | 
			
		||||
    // Strip "weapon_" from entity name
 | 
			
		||||
    // Strip "weapon_" from entity name.
 | 
			
		||||
    ReplaceString(weaponname, sizeof(weaponname), "weapon_", "");
 | 
			
		||||
    
 | 
			
		||||
    // If the weapon is restricted then prevent pickup
 | 
			
		||||
    // If the weapon is restricted then prevent pickup.
 | 
			
		||||
    if (RestrictIsWeaponRestricted(weaponname))
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // If the player is a zombie and the weapon isn't a knife then prevent pickup
 | 
			
		||||
    // If the player is a zombie and the weapon isn't a knife then prevent pickup.
 | 
			
		||||
    if (IsPlayerZombie(client) && !StrEqual(weaponname, "knife"))
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ new Handle:kvWeapons = INVALID_HANDLE;
 | 
			
		||||
#include "zr/weapons/menu_weapons"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Weapons module init function
 | 
			
		||||
 * Weapons module init function.
 | 
			
		||||
 */ 
 | 
			
		||||
WeaponsInit()
 | 
			
		||||
{
 | 
			
		||||
@@ -34,7 +34,7 @@ WeaponsInit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Clears weapon data
 | 
			
		||||
 * Clears weapon data.
 | 
			
		||||
 */
 | 
			
		||||
WeaponsClearData()
 | 
			
		||||
{
 | 
			
		||||
@@ -50,18 +50,18 @@ WeaponsClearData()
 | 
			
		||||
/**
 | 
			
		||||
 * Loads weapon data from file.
 | 
			
		||||
 */
 | 
			
		||||
WeaponsOnMapStart()
 | 
			
		||||
WeaponsLoad()
 | 
			
		||||
{
 | 
			
		||||
    // Clear weapon data
 | 
			
		||||
    // Clear weapon data.
 | 
			
		||||
    WeaponsClearData();
 | 
			
		||||
    
 | 
			
		||||
    // Clear weapon restrict data
 | 
			
		||||
    // Clear weapon restrict data.
 | 
			
		||||
    RestrictClearData();
 | 
			
		||||
    
 | 
			
		||||
    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 file isn't found, stop plugin.
 | 
			
		||||
    if (!FileToKeyValues(kvWeapons, path))
 | 
			
		||||
    {
 | 
			
		||||
        if (LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
 | 
			
		||||
@@ -72,16 +72,19 @@ WeaponsOnMapStart()
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Validate weapons config
 | 
			
		||||
    WeaponsValidateWeaponsConfig();
 | 
			
		||||
    // Validate weapons config.
 | 
			
		||||
    WeaponsValidateConfig();
 | 
			
		||||
    
 | 
			
		||||
    // Forward event to sub-module
 | 
			
		||||
    // Forward event to sub-module.
 | 
			
		||||
    RestrictOnMapStart();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WeaponsValidateWeaponsConfig()
 | 
			
		||||
/**
 | 
			
		||||
 * Validate weapon config file and settings.
 | 
			
		||||
 */ 
 | 
			
		||||
WeaponsValidateConfig()
 | 
			
		||||
{
 | 
			
		||||
    // If log flag check fails, don't log
 | 
			
		||||
    // If log flag check fails, don't log.
 | 
			
		||||
    if (!LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
@@ -94,15 +97,25 @@ WeaponsValidateWeaponsConfig()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Client is joining the server.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param client    The client index.  
 | 
			
		||||
 */ 
 | 
			
		||||
WeaponsClientInit(client)
 | 
			
		||||
{
 | 
			
		||||
    // Forward event to sub-module
 | 
			
		||||
    // Forward event to sub-module.
 | 
			
		||||
    RestrictClientInit(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Client is leaving the server.
 | 
			
		||||
 * 
 | 
			
		||||
 * @param client    The client index.
 | 
			
		||||
 */   
 | 
			
		||||
WeaponsOnClientDisconnect(client)
 | 
			
		||||
{
 | 
			
		||||
    // Forward event to sub-module
 | 
			
		||||
    // Forward event to sub-module.
 | 
			
		||||
    RestrictOnClientDisconnect(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +141,7 @@ WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH)
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeapons, weapon, maxlen);
 | 
			
		||||
            
 | 
			
		||||
            // Push weapon name into the array
 | 
			
		||||
            // Push weapon name into the array.
 | 
			
		||||
            PushArrayString(arrayWeapons, weapon);
 | 
			
		||||
            
 | 
			
		||||
            // Increment count.
 | 
			
		||||
@@ -141,12 +154,13 @@ WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if a weapon is valid (aka listed in weapons.txt)
 | 
			
		||||
 * 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[])
 | 
			
		||||
{
 | 
			
		||||
    // Reset keyvalue's traversal stack.
 | 
			
		||||
    KvRewind(kvWeapons);
 | 
			
		||||
    if (KvGotoFirstSubKey(kvWeapons))
 | 
			
		||||
    {
 | 
			
		||||
@@ -156,6 +170,7 @@ bool:WeaponsIsValidWeapon(const String:weapon[])
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
 | 
			
		||||
            
 | 
			
		||||
            // If weaponname matches a valid weapon, then return true.
 | 
			
		||||
            if (StrEqual(validweapon, weapon, false))
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
@@ -164,16 +179,18 @@ bool:WeaponsIsValidWeapon(const String:weapon[])
 | 
			
		||||
        } while (KvGotoNextKey(kvWeapons));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Weapon is invalid.
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Looks up a weapon in weapons.txt and returns exact display name
 | 
			
		||||
 * Looks up a weapon in weapons.txt and returns exact display name.
 | 
			
		||||
 * @param weapon    The weapon name.
 | 
			
		||||
 * @param display   Returns with the display name, is not changed if weapon is invalid. 
 | 
			
		||||
 */
 | 
			
		||||
WeaponGetDisplayName(const String:weapon[], String:display[])
 | 
			
		||||
{
 | 
			
		||||
    // Reset keyvalue's traversal stack.
 | 
			
		||||
    KvRewind(kvWeapons);
 | 
			
		||||
    if (KvGotoFirstSubKey(kvWeapons))
 | 
			
		||||
    {
 | 
			
		||||
@@ -183,6 +200,7 @@ WeaponGetDisplayName(const String:weapon[], String:display[])
 | 
			
		||||
        {
 | 
			
		||||
            KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
 | 
			
		||||
            
 | 
			
		||||
            // If weapon matches a valid weapon (case-insensitive), then return display name.
 | 
			
		||||
            if (StrEqual(validweapon, weapon, false))
 | 
			
		||||
            {
 | 
			
		||||
                strcopy(display, WEAPONS_MAX_LENGTH, validweapon);
 | 
			
		||||
@@ -225,7 +243,7 @@ bool:WeaponsIsWeaponMenu(const String:weapon[])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns knockback multiplier of the weapon
 | 
			
		||||
 * Returns knockback multiplier of the weapon.
 | 
			
		||||
 * @param weapon    The weapon name.
 | 
			
		||||
 * @return          The float value of the knockback multiplier, 1.0 if not found.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -519,6 +519,7 @@ ZRLogFlagsMenu(client)
 | 
			
		||||
    decl String:z_log_module_teleport[64];
 | 
			
		||||
    decl String:z_log_module_classes[64];
 | 
			
		||||
    decl String:z_log_module_weapons[64];
 | 
			
		||||
    decl String:z_log_module_hitgroups[64];
 | 
			
		||||
    decl String:z_log_module_commands[64];
 | 
			
		||||
    decl String:z_log_module_anticamp[64];
 | 
			
		||||
    decl String:z_log_module_damagecontrol[64];
 | 
			
		||||
@@ -541,6 +542,7 @@ ZRLogFlagsMenu(client)
 | 
			
		||||
    Format(z_log_module_teleport, sizeof(z_log_module_teleport), "Teleporter (%d)", LogHasFlag(LOG_MODULE_TELEPORT));
 | 
			
		||||
    Format(z_log_module_classes, sizeof(z_log_module_classes), "Classes (%d)", LogHasFlag(LOG_MODULE_CLASSES));
 | 
			
		||||
    Format(z_log_module_weapons, sizeof(z_log_module_weapons), "Weapons (%d)", LogHasFlag(LOG_MODULE_WEAPONS));
 | 
			
		||||
    Format(z_log_module_hitgroups, sizeof(z_log_module_hitgroups), "Hitgroups (%d)", LogHasFlag(LOG_MODULE_HITGROUPS));
 | 
			
		||||
    Format(z_log_module_commands, sizeof(z_log_module_commands), "Admin commands (%d)", LogHasFlag(LOG_MODULE_COMMANDS));
 | 
			
		||||
    Format(z_log_module_anticamp, sizeof(z_log_module_anticamp), "Anticamp (%d)", LogHasFlag(LOG_MODULE_ANTICAMP));
 | 
			
		||||
    Format(z_log_module_damagecontrol, sizeof(z_log_module_damagecontrol), "Damage control (suicides) (%d)", LogHasFlag(LOG_MODULE_DAMAGECONTROL));
 | 
			
		||||
@@ -572,7 +574,7 @@ ZRLogFlagsMenu(client)
 | 
			
		||||
    DisplayMenu(menu_log_flags, client, MENU_TIME_FOREVER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public ZRLogFlagsMenuHandle(Handle:menu_log_flags , MenuAction:action, client, slot)
 | 
			
		||||
public ZRLogFlagsMenuHandle(Handle:menu_log_flags, MenuAction:action, client, slot)
 | 
			
		||||
{
 | 
			
		||||
    if (action == MenuAction_Select)
 | 
			
		||||
    {
 | 
			
		||||
@@ -665,20 +667,25 @@ public ZRLogFlagsMenuHandle(Handle:menu_log_flags , MenuAction:action, client, s
 | 
			
		||||
            }
 | 
			
		||||
            case 17:
 | 
			
		||||
            {
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_COMMANDS);
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_HITGROUPS);
 | 
			
		||||
                ZRLogFlagsMenu(client);
 | 
			
		||||
            }
 | 
			
		||||
            case 18:
 | 
			
		||||
            {
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_ANTICAMP);
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_COMMANDS);
 | 
			
		||||
                ZRLogFlagsMenu(client);
 | 
			
		||||
            }
 | 
			
		||||
            case 19:
 | 
			
		||||
            {
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_DAMAGECONTROL);
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_ANTICAMP);
 | 
			
		||||
                ZRLogFlagsMenu(client);
 | 
			
		||||
            }
 | 
			
		||||
            case 20:
 | 
			
		||||
            {
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_DAMAGECONTROL);
 | 
			
		||||
                ZRLogFlagsMenu(client);
 | 
			
		||||
            }
 | 
			
		||||
            case 21:
 | 
			
		||||
            {
 | 
			
		||||
                ToggleLogFlag(LOG_MODULE_OFFSETS);
 | 
			
		||||
                ZRLogFlagsMenu(client);
 | 
			
		||||
@@ -694,7 +701,7 @@ public ZRLogFlagsMenuHandle(Handle:menu_log_flags , MenuAction:action, client, s
 | 
			
		||||
    }
 | 
			
		||||
    if (action == MenuAction_End)
 | 
			
		||||
    {
 | 
			
		||||
        CloseHandle(menu_log_flags );
 | 
			
		||||
        CloseHandle(menu_log_flags);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -194,14 +194,6 @@ Zombify_Mother(client)
 | 
			
		||||
        tHandles[client][TMOAN] = CreateTimer(interval, ZombieMoanTimer, client, TIMER_REPEAT);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tHandles[client][TPROTECT] != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        pProtect[client] = false;
 | 
			
		||||
        
 | 
			
		||||
        KillTimer(tHandles[client][TPROTECT]);
 | 
			
		||||
        tHandles[client][TPROTECT] = INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tHandles[client][TZHP] != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        KillTimer(tHandles[client][TZHP]);
 | 
			
		||||
@@ -270,15 +262,6 @@ Zombify(client, attacker = -1, bool:motherinfect = false)
 | 
			
		||||
        tHandles[client][TMOAN] = CreateTimer(interval, ZombieMoanTimer, client, TIMER_REPEAT);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Kill spawn protection timer.
 | 
			
		||||
    if (tHandles[client][TPROTECT] != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        pProtect[client] = false;
 | 
			
		||||
        
 | 
			
		||||
        KillTimer(tHandles[client][TPROTECT]);
 | 
			
		||||
        tHandles[client][TPROTECT] = INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Kill HP display timer.
 | 
			
		||||
    if (tHandles[client][TZHP] != INVALID_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
@@ -635,36 +618,6 @@ public Action:ZHPTimer(Handle:timer, any:index)
 | 
			
		||||
    return Plugin_Continue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Action:ProtectTimer(Handle:timer, any:index)
 | 
			
		||||
{
 | 
			
		||||
    if (!IsClientInGame(index))
 | 
			
		||||
    {
 | 
			
		||||
        tHandles[index][TPROTECT] = INVALID_HANDLE;
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    pTimeLeft[index]--;
 | 
			
		||||
    ZR_HudHint(index, "Spawn Protect", pTimeLeft[index]);
 | 
			
		||||
    
 | 
			
		||||
    if (pTimeLeft[index] <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        pProtect[index] = false;
 | 
			
		||||
    
 | 
			
		||||
        if (IsPlayerHuman(index))
 | 
			
		||||
        {
 | 
			
		||||
            ZR_HudHint(index, "Spawn protection end");
 | 
			
		||||
            SetPlayerAlpha(index, 255);
 | 
			
		||||
            SetPlayerSpeed(index, 300.0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tHandles[index][TPROTECT] = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
        return Plugin_Stop;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return Plugin_Continue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RespawnPlayer(client)
 | 
			
		||||
{
 | 
			
		||||
    if (!IsClientInGame(client))
 | 
			
		||||
 
 | 
			
		||||
@@ -55,9 +55,10 @@ enum ZTeam
 | 
			
		||||
#define LOG_MODULE_OVERLAYS         65536       /** overlays.inc */
 | 
			
		||||
#define LOG_MODULE_TELEPORT         131072      /** teleport.inc */
 | 
			
		||||
#define LOG_MODULE_WEAPONS          262144      /** Weapons module - weapons/ *.inc */
 | 
			
		||||
#define LOG_MODULE_ANTICAMP         524288      /** anticamp.inc */
 | 
			
		||||
#define LOG_MODULE_DAMAGECONTROL    1048576     /** damagecontrol.inc */
 | 
			
		||||
#define LOG_MODULE_OFFSETS          2097152     /** offsets.inc */
 | 
			
		||||
#define LOG_MODULE_HITGROUPS        524288      /** hitgroups.inc */
 | 
			
		||||
#define LOG_MODULE_ANTICAMP         1048576     /** anticamp.inc */
 | 
			
		||||
#define LOG_MODULE_DAMAGECONTROL    2097152     /** damagecontrol.inc */
 | 
			
		||||
#define LOG_MODULE_OFFSETS          4194304     /** offsets.inc */
 | 
			
		||||
/*
 | 
			
		||||
 * @endsection
 | 
			
		||||
 */
 | 
			
		||||
@@ -76,8 +77,6 @@ new bool:dispHP[MAXPLAYERS + 1];
 | 
			
		||||
new bool:pProtect[MAXPLAYERS + 1];
 | 
			
		||||
new bool:gKilledByWorld[MAXPLAYERS + 1] = {false, ...};
 | 
			
		||||
 | 
			
		||||
new pTimeLeft[MAXPLAYERS + 1];
 | 
			
		||||
 | 
			
		||||
new Float:spawnLoc[MAXPLAYERS + 1][3];
 | 
			
		||||
new Float:bufferLoc[MAXPLAYERS + 1][3];
 | 
			
		||||
new bool:ztele_spawned[MAXPLAYERS + 1] = {false, ...};
 | 
			
		||||
@@ -96,15 +95,14 @@ new Handle:tInfect = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
new Handle:pList = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
#define MAXTIMERS 7
 | 
			
		||||
#define MAXTIMERS 6
 | 
			
		||||
 | 
			
		||||
#define TMOAN 0
 | 
			
		||||
#define TREGEN 1
 | 
			
		||||
#define TTELE 2
 | 
			
		||||
#define TZHP 3
 | 
			
		||||
#define TPROTECT 4
 | 
			
		||||
#define TRESPAWN 5
 | 
			
		||||
#define TZVISION 6
 | 
			
		||||
#define TRESPAWN 4
 | 
			
		||||
#define TZVISION 5
 | 
			
		||||
 | 
			
		||||
new Handle:tHandles[MAXPLAYERS + 1][MAXTIMERS];
 | 
			
		||||
 | 
			
		||||
@@ -243,10 +241,8 @@ bool:IsClientPlayer(client)
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    
 | 
			
		||||
    return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -261,8 +257,6 @@ bool:IsClientAdmin(client)
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    
 | 
			
		||||
    return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user