This commit is contained in:
Greyscale 2009-08-21 12:57:59 -07:00
commit cd25e4e16c
24 changed files with 2024 additions and 895 deletions

View File

@ -10,16 +10,17 @@
//
// Attribute: Values: Description:
// ----------------------------------------------------------------------------
// enabled 0/1 Enables or disables a class.
// enabled yes/no Enables or disables a class.
// team number Specifies what team the class belongs to:
// 0 - Zombies
// 1 - Humans
// 2 - Admin mode classes (incomplete feautre!)
// team_default 0/1 Marks the class as the default class in the team.
// team_default yes/no Marks the class as the default class in the team.
// flags number Special class flags (bit field). To combine multiple flags
// use a sum of the flag values. Available flags:
// 1 - Admins only
// 2 - Mother zombies only
// group text Restrict class to member of this SourceMod group. Leave blank for no restriction.
// name text The class name used in class menu.
// description text The class description used in class menu.
// model_path text Path to model to use. Relative to cstrike folder.
@ -27,13 +28,13 @@
// alpha_damaged number Transparency when damaged.
// alpha_damage number How much damage to do before switching alpha.
// overlay_path text Overlay displayed at the player.
// nvgs 0/1 Give night vision.
// nvgs yes/no Give night vision.
// fov number Field of view value. 90 is default.
// has_napalm 0/1 Allows player to throw napalm grenades. Humans only.
// has_napalm yes/no Allows player to throw napalm grenades. Humans only.
// napalm_time decimal Napalm burn duration. Zombies only.
// immunity_mode number Sets the immunity mode.
// immunity_amount decimal Sets the immunity value.
// no_fall_damage 0/1 Disables fall damage.
// no_fall_damage on/off Disables fall damage.
// health number How many health points to give.
// health_regen_interval decimal Sets the regeneration interval. 0 to disable.
// health_regen_amount number How much HP to give per interval.
@ -54,10 +55,11 @@
"zombie_classic"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "1"
"team_default" "yes"
"flags" "0"
"group" ""
"name" "Classic"
"description" "Need brains!!! Arrrrggghh!"
@ -70,17 +72,17 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "0"
"has_napalm" "no"
"napalm_time" "10.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "2500"
"health_regen_interval" "0.0"
@ -97,10 +99,11 @@
"zombie_fast"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "0"
"team_default" "no"
"flags" "0"
"group" ""
"name" "Fast"
"description" "-HP | +Speed | +Jump | +Knockback"
@ -113,17 +116,17 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "0"
"has_napalm" "no"
"napalm_time" "5.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "2000"
"health_regen_interval" "0.0"
@ -140,10 +143,11 @@
"zombie_mutated"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "0"
"team_default" "no"
"flags" "0"
"group" ""
"name" "Mutated"
"description" "+HP | -Speed | +Jump | +Knockback"
@ -156,17 +160,17 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "0"
"has_napalm" "no"
"napalm_time" "15.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "3500"
"health_regen_interval" "0.0"
@ -183,10 +187,11 @@
"zombie_heavy"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "0"
"team_default" "no"
"flags" "0"
"group" ""
"name" "Heavy"
"description" "+HP | -Speed | -Jump | -Knockback"
@ -199,17 +204,17 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "0"
"has_napalm" "no"
"napalm_time" "20.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "4000"
"health_regen_interval" "0.0"
@ -226,10 +231,11 @@
"mother_zombie"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "0"
"team_default" "no"
"flags" "2"
"group" ""
"name" "Mother zombie"
"description" "+HP regen | +Speed | +Jump | -Knockback"
@ -242,7 +248,7 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "110"
// Effects
@ -252,7 +258,7 @@
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "2500"
"health_regen_interval" "0.25"
@ -269,10 +275,11 @@
"mother_zombie_admin"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "0"
"team_default" "0"
"team_default" "no"
"flags" "3"
"group" ""
"name" "Admin mother zombie"
"description" "+HP regen | +Speed | +Jump | -Knockback"
@ -285,7 +292,7 @@
// Hud
"overlay_path" "overlays/zr/zvision"
"nvgs" "0"
"nvgs" "no"
"fov" "110"
// Effects
@ -295,7 +302,7 @@
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "3500"
"health_regen_interval" "0.25"
@ -318,10 +325,11 @@
"human_normal"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "1"
"team_default" "1"
"team_default" "yes"
"flags" "0"
"group" ""
"name" "Normal Human"
"description" "Default Counter-Strike settings"
@ -334,17 +342,17 @@
// Hud
"overlay_path" ""
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "1"
"has_napalm" "yes"
"napalm_time" "0.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "0"
"no_fall_damage" "no"
"health" "100"
"health_regen_interval" "0.0"
@ -361,10 +369,11 @@
"human_vip"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "1"
"team_default" "0"
"team_default" "yes"
"flags" "0"
"group" ""
"name" "VIP Human"
"description" "Human class for important players"
@ -377,7 +386,7 @@
// Hud
"overlay_path" ""
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
@ -387,7 +396,7 @@
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "0"
"no_fall_damage" "no"
"health" "200"
"health_regen_interval" "1.0"
@ -404,10 +413,11 @@
"human_admin"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "1"
"team_default" "0"
"team_default" "no"
"flags" "1"
"group" ""
"name" "Admin Human"
"description" "Human class for admins"
@ -420,7 +430,7 @@
// Hud
"overlay_path" ""
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
@ -430,7 +440,7 @@
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "1"
"no_fall_damage" "yes"
"health" "200"
"health_regen_interval" "1.0"
@ -447,10 +457,11 @@
"human_speedy"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "1"
"team_default" "0"
"team_default" "no"
"flags" "0"
"group" ""
"name" "Speedy"
"description" "Fast human"
@ -463,11 +474,11 @@
// Hud
"overlay_path" ""
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "0"
"has_napalm" "no"
"napalm_time" "0.0"
// Player behaviour
@ -490,10 +501,11 @@
"human_light"
{
// General
"enabled" "1"
"enabled" "yes"
"team" "1"
"team_default" "0"
"team_default" "no"
"flags" "0"
"group" ""
"name" "Light"
"description" "Regular human with improved jump skills"
@ -506,17 +518,17 @@
// Hud
"overlay_path" ""
"nvgs" "0"
"nvgs" "no"
"fov" "90"
// Effects
"has_napalm" "1"
"has_napalm" "yes"
"napalm_time" "0.0"
// Player behaviour
"immunity_mode" "0"
"immunity_amount" "0.0"
"no_fall_damage" "0"
"no_fall_damage" "no"
"health" "100"
"health_regen_interval" "0.0"

View File

@ -216,49 +216,29 @@
"no" "Klassevalg:"
}
"Classes menu zombie"
"Classes menu active"
{
"no" "Velg zombieklasse:"
"no" "Aktiv: {1}"
}
"Classes menu zombie current"
"Classes menu next"
{
"no" "Velg zombieklasse\n {1}"
"no" "Påfølgende: {1}"
}
"Classes menu zombie next"
"Classes menu select zombie"
{
"no" "Velg zombieklasse\n Aktiv: {1}\n Påfølgende: {2}"
"no" "Velg zombieklasse"
}
"Classes menu human"
"Classes menu select human"
{
"no" "Velg menneskeklasse:"
"no" "Velg menneskeklasse"
}
"Classes menu human current"
"Classes menu select admin"
{
"no" "Velg menneskeklasse\n {1}"
}
"Classes menu human next"
{
"no" "Velg menneskeklasse\n Aktiv: {1}\n Påfølgende: {2}"
}
"Classes menu admin"
{
"no" "Velg administratormodusklasse:"
}
"Classes menu admin current"
{
"no" "Velg administratormodusklasse\n {1}"
}
"Classes menu admin next"
{
"no" "Velg administratormodusklasse\n Active: {1}\n Next spawn: {2}"
"no" "Velg administratormodusklasse"
}
"Classes menu admin mode toggle"
@ -268,7 +248,7 @@
"Classes Menu Team Select Title"
{
"no" "velg lag:"
"no" "Velg lag:"
}
"Classes Menu Zombies"
@ -338,6 +318,11 @@
"no" "Hoppelengde"
}
"Classes Selection Not Allowed"
{
"no" "Endring av klasse er ikke tillatt."
}
// ===========================
// Overlays (core)
// ===========================
@ -372,49 +357,44 @@
"Infect menu clients title"
{
"en" "Zombie Management\nToggle Infection:\n[] = Infected"
"no" "Spillerbehandling\nVeksle mellom zombie og menneske:\n[] = Infisert"
}
// Commands
"Infect command infect syntax"
{
"en" "Infect a client. Usage: zr_infect <filter> [respawn - 1/0]"
"no" "Infiserer en spiller. Syntaks: zr_infect <mål> [teleporter - 1/0]"
}
"Infect command human syntax"
{
"en" "Turn a client into a human. Usage: zr_human <filter> [respawn - 1/0] [protect - 1/0]"
"no" "Gjør en spiller om til et menneske. Syntaks: zr_human <mål> [teleporter - 1/0] [beskyttelse - 1/0]"
}
"Infect command infect successful"
{
"#format" "{1:s}"
"en" "Player @green{1} @defaulthas been successfully infected."
"no" "@green{1}@default ble vellykket infisert."
}
"Infect command infect mother successful"
{
"#format" "{1:s}"
"en" "Player @green{1} @defaulthas been successfully infected as the mother zombie."
"no" "@green{1}@default ble vellykket infisert som moderzombie."
}
"Infect command infect unsuccessful"
{
"#format" "{1:s}"
"en" "Player @green{1} @defaultis already a zombie."
"no" "@green{1}@default er allerede en zombie."
}
"Infect command human successful"
{
"#format" "{1:s}"
"en" "Player @green{1} @defaulthas been successfully brought back as a human."
"no" "@green{1}@default ble vellykket gjort om til et menneske."
}
"Infect command human unsuccessful"
{
"#format" "{1:s}"
"en" "Player @green{1} @defaultis already a human."
"no" "@green{1}@default er allerede et menneske."
}
// ===========================
@ -423,7 +403,7 @@
"Damage suicide intercept"
{
"en" "Suicide attempt intercepted."
"no" "Selvmordsforsøk hindret."
}
// ===========================
@ -434,50 +414,42 @@
"Menu main title"
{
"#format" "{1:s},{2:s}"
"en" "ZR Commands:\nPrefix command with \"{1}\" or \"{2}\" (quiet) when typing in chat."
"no" "ZR-kommandoer:\nStart kommandoen med \"{1}\" or \"{2}\" (skjules) i samtaleområdet."
}
"Menu main zadmin"
{
"#format" "{1:s}"
"en" "ZAdmin - Open admin menu. (Command: {1})"
"no" "ZAdmin - Åpne administrasjonsmeny"
}
"Menu main zclass"
{
"#format" "{1:s}"
"en" "ZClass - Configure class settings. (Command: {1})"
"no" "ZClass - Endre klasseinstillinger"
}
"Menu main zcookies"
{
"#format" "{1:s}"
"en" "ZCookies - Toggle personal ZR settings here. (Command: {1})"
"no" "ZCookies - Endre lagrede instillinger"
}
"Menu main zspawn"
{
"#format" "{1:s}"
"en" "ZSpawn - Join late? Spawn with this. (Command: {1})"
"no" "ZSpawn - Bli med i spillet øyeblikkelig"
}
"Menu main ztele"
{
"#format" "{1:s}"
"en" "ZTele - Stuck? Teleport back to spawn. (Command: {1})"
"no" "ZTele - Teleporter til startområde"
}
"Menu main zhp"
{
"#format" "{1:s}"
"en" "ZHP - Shows real HP as zombie. (Command: {1})"
"no" "ZHP - Vis nåværende helsenivå"
}
"Menu main zmarket"
{
"#format" "{1:s}"
"en" "ZMarket - Customize loadouts here. (Command: {1})"
"no" "ZMarket - Endre våpeninstillinger"
}
// ===========================
@ -488,280 +460,252 @@
"Zombie cant use weapon"
{
"en" "Zombies can't use weapons!"
"ru" "Зомби не могут использовать оружие!"
"no" "Zombier kan ikke bruke våpen."
}
// Restrict
"Restrict weapon"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaulthas been restricted."
"no" "Våpenet @green\"{1}\"@default ble sperret."
}
"Unrestrict weapon"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaulthas been unrestricted."
"no" "Våpenet @green\"{1}\"@default er ikke lenger sperret."
}
"Restrict weapon stopped"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultis already restricted."
"no" "Våpenet @green\"{1}\"@default er allerede sperret."
}
"Unrestrict weapon stopped"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @default has no restrictions set."
"no" "Våpenet @green\"{1}\"@default er ikke sperret."
}
"Restrict weapon type"
{
"#format" "{1:s}"
"en" "Weapons of type @green\"{1}\" @defaulthave been restricted."
"no" "Våpentypen @green\"{1}\"@default er sperret."
}
"Unrestrict weapon type"
{
"#format" "{1:s}"
"en" "Weapons of type @green\"{1}\" @defaulthave been unrestricted."
"no" "Våpentypen @green\"{1}\"@default er ikke lenger sperret."
}
"Restrict weapon type stopped"
{
"#format" "{1:s}"
"en" "Weapons of type @green\"{1}\" @defaultare all already restricted."
"no" "Våpentypen @green\"{1}\"@default er allerede sperret."
}
"Unrestrict weapon type stopped"
{
"#format" "{1:s}"
"en" "Weapons of type @green\"{1}\" @defaulthave no restrictions set."
"no" "Våpentypen @green\"{1}\"@default er ikke sperret."
}
"Restrict weapon untoggleable"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultmay not have its restrictions toggled."
"no" "Våpenet @green\"{1}\"@default kan ikke sperres."
}
"Weapon invalid"
{
"#format" "{1:s}"
"en" "Weapon @green\"{1}\" @defaultis an invalid weapon (type) name."
"no" "Våpenet eller våpentypen @green\"{1}\"@default er ugyldig."
}
"Weapon is restricted"
{
"#format" "{1:s}"
"en" "Weapon @green{1} @defaultis restricted."
"ru" "Оружие @green{1} @default запрещено."
"no" "Våpenet @green{1}@default er sperret."
}
// ZMarket
"Weapons zmarket buyzone"
{
"en" "You must be in a buyzone to use ZMarket."
"no" "Du må være i en kjøpesone for å kunne bruke ZMarket."
}
"Weapons zmarket purchase"
{
"#format" "{1:s}"
"en" "You have purchased weapon @green{1}. @defaultSelect item again to buy ammo if you are low."
"no" "Du har kjøpt våpenet @green{1}@default. Velg gjenstanden igjen for å kjøpe mer ammunisjon."
}
"Weapons zmarket purchase max"
{
"#format" "{1:s},{2:d}"
"en" "Weapon @green{1} @defaulthas a purchase limit of @green{2}@default. Wait until you respawn to try again."
"no" "Våpenet @green{1}@default har en kjøpegrense på @green{2}@default enheter. Vent til neste runde eller gjenoppliving."
}
"Weapons zmarket auto-rebuy toggle on"
{
"en" "Auto-rebuy has been enabled, your loadout will be automatically purchased for you each time you spawn."
"no" "Autokjøp er aktivert, dine valg vil automatisk bli kjøpt hver runde eller hver gjenoppliving."
}
"Weapons zmarket auto-rebuy toggle off"
{
"en" "Auto-rebuy has been disabled."
"no" "Autokjøp er deaktivert."
}
"Weapons zmarket updated loadout"
{
"en" "You are not able to purchase a weapon at this time, but your loadout has been updated with this weapon."
"no" "Du kan ikke kjøpe våpen for øyeblikket, men våpenvalget er blitt lagret."
}
"Weapons zmarket get current loadout"
{
"en" "Updated current loadout, use rebuy option to purchase these weapons again."
"no" "Våpenvalg oppdatert. Bruk gjenkjøpvalget for å kjøpe disse våpnene igjen."
}
// Commands
"Weapons command restrict syntax"
{
"en" "Restricts a weapon or a weapon type. Usage: zr_restrict <weapon|weapon type> [weapon2|weapontype2] ..."
"no" "Sperrer et våpen eller en våpentype. Syntaks: zr_restrict <våpen|våpentype> [våpen|våpentype] ..."
}
"Weapons command unrestrict syntax"
{
"en" "Unrestricts a weapon or a weapon type. Usage: zr_unrestrict <weapon|weapon type> [weapon2|weapontype2] ..."
"no" "Fjerner sperre av et våpen eller en våpentype. Syntaks: zr_unrestrict <våpen|våpentype> [våpen|våpentype] ..."
}
// Menu (Restrict)
"Weapons menu restrict main title"
{
"en" "Weapons Management"
"no" "Våpenbehandling"
}
"Weapons menu restrict main restrict"
{
"en" "Weapon Restrictions"
"no" "Våpensperringer"
}
"Weapons menu restrict main market"
{
"en" "ZMarket"
"no" "ZMarket"
}
"Weapons menu restrict types title"
{
"en" "Weapon Restrictions\nSelect Weapon Type:"
"no" "Våpensperringer\nVelg våpentype:"
}
"Weapons menu restrict types weapon type title"
{
"#format" "{1:s}"
"en" "Weapon Restrictions\nWeapon Type: {1}\n[] = Restricted"
"no" "Våpensperringer\nVåpentype: {1}\n[] = Sperret"
}
"Weapons menu restrict types restrict all"
{
"#format" "{1:s}"
"en" "Restrict weapon type {1}"
"no" "Sperr våpentypen \"{1}\""
}
"Weapons menu restrict types unrestrict all"
{
"#format" "{1:s}"
"en" "Unrestrict weapon type {1}"
"no" "Fjern sperre for våpentypen \"{1}\""
}
"Weapons menu restrict zmarket title"
{
"en" "ZMarket\nSelect Setting:"
"no" "ZMarket\nVelg instilling:"
}
"Weapons menu restrict zmarket buyzone"
{
"#format" "{1:s}"
"en" "Buyzone Only - {1}"
"no" "Kun i kjøpesoner - {1}"
}
// Menu (ZMarket)
"Weapons menu zmarket main title"
{
"en" "ZMarket\nSelect an Option:"
"no" "ZMarket"
}
"Weapons menu zmarket main get loadout"
{
"en" "Get Current Loadout"
"no" "Lagre gjeldende våpenvalg"
}
"Weapons menu zmarket main view loadout"
{
"en" "View My Loadout"
"no" "Vis våpenvalg"
}
"Weapons menu zmarket main rebuy"
{
"en" "Rebuy My Loadout"
"no" "Kjøp gjeldende våpenvalg"
}
"Weapons menu zmarket main auto-rebuy"
{
"#format" "{1:s}"
"en" "Auto-Rebuy: {1}"
"no" "Autokjøp: {1}"
}
"Weapons menu zmarket main weapons list"
{
"en" "View Weapons List"
"no" "Vis våpenliste"
}
"Weapons menu zmarket loadout title"
{
"en" "ZMarket\nMy Current Loadout:\nSelect weapon slot to clear.\nNote: Rebuy refers to these weapons."
"no" "ZMarket\nGjeldende våpenvalg:\nFjern våpen ved å velge det."
}
"Weapons menu zmarket loadout primary"
{
"#format" "{1:s}"
"en" "Primary: {1}"
"no" "Primærvåpen: {1}"
}
"Weapons menu zmarket loadout secondary"
{
"#format" "{1:s}"
"en" "Secondary: {1}"
"no" "sekundærvåpen: {1}"
}
"Weapons menu zmarket loadout melee"
{
"#format" "{1:s}"
"en" "Melee: {1}"
"no" "Nærkamp: {1}"
}
"Weapons menu zmarket loadout projectile"
{
"#format" "{1:s}"
"en" "Projectile: {1}"
"no" "Prosjektiler: {1}"
}
"Weapons menu zmarket loadout explosive"
{
"#format" "{1:s}"
"en" "Explosive: {1}"
"no" "Granater: {1}"
}
"Weapons menu zmarket loadout nvgs"
{
"#format" "{1:s}"
"en" "NVGs: {1}"
"no" "Nattsyn: {1}"
}
"Weapons menu zmarket loadout empty"
{
"en" "(None)"
"no" "(Ingen)"
}
"Weapons menu zmarket types title"
{
"en" "ZMarket\nSelect Weapon Type:"
"no" "ZMarket\nVelg våpentype:"
}
"Weapons menu zmarket types weapon type title"
{
"#format" "{1:s}"
"en" "ZMarket\nWeapon Type: {1}\n[] = Restricted"
"no" "ZMarket\nVåpentype: {1}\n[] = Sperret"
}
"Weapons menu zmarket types weapon info"
{
"#format" "{1:s},{2:d},{3:d}"
"en" "{1} (${2})\nPurchases Left: {3}"
"no" "{1} (${2})\nAntall kjøp igjen: {3}"
}
"Weapons menu zmarket types weapon ammo"
{
"en" "Ammo"
"no" "Ammunisjon"
}
// ===========================
@ -772,62 +716,59 @@
"Hitgroups menu hitgroups title"
{
"en" "Hitgroup Management\nCommands: zr_hitgroup(_enable_all/_headshots_only)\nSelect a Hitgroup to Toggle:"
"no" "Treffgruppebehandling\nKommandoer: zr_hitgroup(_enable_all/_headshots_only)\nVelg en treffgruppe for å aktivere/deaktivere:"
}
"Hitgroups menu hitgroups enable all"
{
"en" "Enable All Hitgroups"
"no" "Aktiver alle treffgrupper"
}
"Hitgroups menu hitgroups headshots only"
{
"en" "Headshots Only"
"no" "Kun hodeskudd"
}
// Commands
"Hitgroups command syntax"
{
"en" "Toggles or sets if a zombie's hitgroup can be damaged. Usage: zr_hitgroup <hitgroup alias> [1/0]"
"no" "Veksle, aktiver eller deaktiver en treffgruppe til zombiene. Usage: zr_hitgroup <treffgruppe> [aktiv - 1/0]"
}
"Hitgroups command related commands"
{
"en" "Related command(s): zr_hitgroup_enable_all, zr_hitgroup_headshots_only"
"no" "Relaterte kommandoer: zr_hitgroup_enable_all, zr_hitgroup_headshots_only"
}
"Hitgroups command syntax names"
{
"en" "Hitgroup Names:"
"no" "Treffgruppenavn:"
}
"Hitgroups command successful on"
{
"#format" "{1:s}"
"en" "Damage for hitgroup \"{1}\" has been toggled on."
"no" "Skade for treffgruppen \"{1}\" er aktivert."
}
"Hitgroups command successful off"
{
"#format" "{1:s}"
"en" "Damage for hitgroup \"{1}\" has been toggled off."
"no" "Skade for treffgruppen \"{1}\" er deaktivert."
}
"Hitgroups command invalid hitgroup"
{
"#format" "{1:s}"
"en" "\"{1}\" is not a valid hitgroup alias. Type zr_hitgroup to view all aliases."
"no" "\"{1}\" er ikke en gyldig treffgruppe. Bruk zr_hitgroup for å se alle treffgruppenavnene."
}
"Hitgroups command enable all successful"
{
"en" "All zombie hitgroups have been enabled for damage."
"no" "Alle treffgruppene er aktivert."
}
"Hitgroups command headshots only successful"
{
"en" "Zombies may now only be damaged by headshots."
"no" "Zombiene kan nå kun bli skadet av hodeskudd."
}
// ===========================
@ -836,37 +777,37 @@
"ZAdmin main title"
{
"en" "ZAdmin\nSelect Category:"
"no" "ZAdmin\nVelg kategori:"
}
"ZAdmin main class multipliers"
{
"en" "Class Multipliers"
"no" "Klassemultiplikatorer"
}
"ZAdmin main weapons"
{
"en" "Weapon Management"
"no" "Våpenbehandling"
}
"ZAdmin main hitgroups"
{
"en" "Hitgroup Management"
"no" "Treffgruppebehandling"
}
"ZAdmin main zombie"
{
"en" "Zombie Management"
"no" "Spillerbehandling"
}
"ZAdmin main force zspawn"
{
"en" "Force ZSpawn"
"no" "Tving gjenoppliving"
}
"ZAdmin main force ztele"
{
"en" "Force ZTele"
"no" "Tving teleport"
}
// ===========================
@ -874,39 +815,37 @@
// ===========================
// Commands
// Not translating antistick phrases because hull width settings had no effect. To be removed.
"AntiStick command set width syntax"
{
"en" "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width <model/player> <width>"
"no" "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width <model/player> <width>"
}
"AntiStick command list models list"
{
"en" "Player name: Model: Hull width:\n-------------------------------------------------------------------------------------------------------------"
"no" "Player name: Model: Hull width:\n-------------------------------------------------------------------------------------------------------------"
}
"AntiStick command list models name"
{
"#format" "{1:-35s},{2:-51s},{3:-.2f}"
"en" "{1} {2} {3}"
"no" "{1} {2} {3}"
}
"AntiStick command set width successful"
{
"#format" "{1:s},{2:f}"
"en" "Model hull width for model \"{1}\" has been changed to \"{2}.\""
"no" "Model hull width for model \"{1}\" has been changed to \"{2}.\""
}
"AntiStick command set width invalid model"
{
"#format" "{1:s}"
"en" "Invalid model/player specified: \"{1}\""
"no" "Invalid model/player specified: \"{1}\""
}
"AntiStick command set width invalid width"
{
"#format" "{1:f}"
"en" "Invalid model hull width specified: \"{1}\""
"no" "Invalid model hull width specified: \"{1}\""
}
// ===========================
@ -917,23 +856,19 @@
"Spawn protection begin"
{
"#format" "{1:d}"
"en" "Zombies are present, you have {1} seconds to find a safe place before you lose immunity."
"ru" "Зомби на свободе, у вас {1} секунд, чтобы найти безопасное место, пока не потеряли иммунитет."
"no" "Zombier tilstede, du er beskyttet og har {1} sekunder på å finne et trygt sted."
}
"Spawn protection end"
{
"en" "You are now susceptible to zombie infection."
"ru" "Теперь вы восприимчивы к зомби инфекции."
"no" "Du er nå utsatt for å bli smittet av en zombie."
}
// HUD
"Spawn Protect"
{
"#format" "{1:d}"
"en" "Zombie protection ends in: {1} seconds."
"no" "Zombiebeskyttelsen stopper om {1} sekunder."
}
// ===========================
@ -942,30 +877,27 @@
"ZCookies Menu main title"
{
"en" "ZCookies\nSelect a Cookie:"
"no" "ZCookies\nVelg informasjonskapsel:"
}
"ZCookies menu main auto-rebuy"
{
"#format" "{1:s}"
"en" "ZMarket Auto-Rebuy: {1}"
"no" "Autokjøp (ZMarket): {1}"
}
"ZCookies menu main zhp"
{
"#format" "{1:s}"
"en" "ZHP Display: {1}"
"no" "ZHP-skjerm: {1}"
}
"ZCookies menu main overlay"
{
"#format" "{1:s}"
"en" "Human/Zombie Class Overlay: {1}"
"no" "Vis klasseoverlegg: {1}"
}
"ZCookies zmarket loadout"
{
"en" "ZMarket Loadout"
"no" "Våpenvalg (ZMarket)"
}
// ===========================
@ -976,40 +908,36 @@
"ZSpawn double spawn"
{
"en" "ZSpawn can only be used if you joined late during a round in progress."
"no" "ZSpawn kan kun bli brukt hvis du koblet til servern midt i en runde."
}
"ZSpawn timelimit"
{
"#format" "{1:d}"
"en" "The timelimit ({1} seconds), to use ZSpawn, has already expired."
"no" "Tidsfristen ({1} sekunder) for å bruke ZSpawn har gått ut."
}
// Menu
"ZSpawn clients title"
{
"en" "Force ZSpawn (zr_zspawn_force)\nSelect a Player:"
"no" "Tving gjenoppliving (zr_zspawn_force)\nVelg en spiller:"
}
// Commands
"ZSpawn command force syntax"
{
"en" "Force ZSpawn on a client. Usage: zr_zspawn_force <client> ['0' = Spawn as human | '1' = Spawn as zombie]"
"no" "Tving gjenoppliving på en spiller. Syntaks: zr_zspawn_force <spiller> ['0' = Menneske | '1' = Zombie]"
}
"ZSpawn command force successful"
{
"#format" "{1:s}"
"en" "Player {1} was successfully spawned."
"no" "{1} ble vellykket gjenopplivet."
}
"ZSpawn command force unsuccessful"
{
"#format" "{1:s}"
"en" "Player {1} couldn't be spawned."
"no" "{1} kunne ikke bli gjenopplivet."
}
// ===========================
@ -1020,70 +948,63 @@
"ZTele restricted human"
{
"en" "ZTele is restricted for humans at this time."
"no" "Mennesker kan ikke teleporteres for øyeblikket."
}
"ZTele max"
{
"#format" "{1:d}"
"en" "You have reached your max of {1} teleport(s) per round."
"no" "Du har brukt opp alle teleportene ({1}) for denne runden."
}
"ZTele in progress"
{
"en" "You are currently pending teleportation."
"no" "Du venter på allerede på en teleport."
}
"ZTele autocancel text"
{
"#format" "{1:d}"
"en" "Teleport has been cancelled. (Restrictive boundary is {1} ft.)"
"no" "Teleport avbrutt. Du har forflyttet deg lengre enn tillatt da du ventet på en teleport. Maks lengde er {1} fot."
}
// Center Text
"ZTele countdown"
{
"#format" "{1:d}"
"en" "Teleporting back to spawn in: {1} seconds."
"no" "Teleporterer til startområdet om {1} sekunder."
}
"ZTele autocancel centertext"
{
"en" "Teleport has been cancelled."
"no" "Teleport avbrutt."
}
"ZTele countdown end"
{
"#format" "{1:d},{2:d}"
"en" "Teleported back to spawn. (Count: {1}/{2})"
"no" "Teleportert til startområdet. (Antall: {1}/{2})"
}
// Menu
"ZTele clients title"
{
"en" "Force ZTele (zr_ztele_force)\nSelect a Player:"
"no" "Tving teleport (zr_ztele_force)\nVelg en spiller:"
}
// Commands
"ZTele command force syntax"
{
"en" "Force ZTele on a client. Usage: zr_ztele_force <client>"
"no" "Tving teleport på en spiller. Syntaks: zr_ztele_force <spiller>"
}
"ZTele command force successful"
{
"#format" "{1:s}"
"en" "Player {1} was successfully teleported."
"no" "{1} ble vellykket teleportert."
}
"ZTele command force unsuccessful"
{
"#format" "{1:s}"
"en" "Player {1} couldn't be teleported."
"no" "{1} kunne ikke bli teleportert."
}
// ===========================
@ -1094,22 +1015,19 @@
"ZHP enable"
{
"en" "HP display enabled, your real HP will be displayed after infection."
"no" "HP-skjerm aktivert. Du vil se din ekte helseverdi som zombie."
}
"ZHP disable"
{
"en" "HP display disabled."
"ru" "Отображение здоровья включено."
"no" "HP-skjerm deaktivert."
}
// HUD
"Display HP"
{
"#format" "{1:d}"
"en" "HP: {1}"
"ru" "Здоровье: {1}"
"no" "HP: {1}"
}
// ===========================
@ -1118,18 +1036,16 @@
"Vol Anticamp Message"
{
"en" "This area is restricted, please move along."
"no" "Dette området er sperret, vennligst gå videre."
}
"Vol Slay"
{
"#format" "{1:s},{2:d}"
"en" "Slayed player \"{1}\" for camping in a restricted area (ID: {2})."
"no" "Drepte \"{1}\" for opphold i sperret område (ID: {2})."
}
"Vol Ignite"
{
"#format" "{1:s},{2:d}"
"en" "Ignited player \"{1}\" for camping in a restricted area (ID: {2})."
"no" "Satt fyr på \"{1}\" for opphold i sperret område (ID: {2})."
}
}

View File

@ -65,7 +65,7 @@
"Must be zombie"
{
"en" "This feature requires that you are a zombie.
"en" "This feature requires that you are a zombie."
}
"Must be human"
@ -228,55 +228,31 @@
"en" "Class Selection:"
}
"Classes menu zombie"
{
"en" "Select Zombie Class:"
}
"Classes menu zombie current"
"Classes menu active"
{
"#format" "{1:s}"
"en" "Select Zombie Class\n {1}"
"en" "Active: {1}"
}
"Classes menu zombie next"
{
"#format" "{1:s},{2:s}"
"en" "Select Zombie Class\n Active: {1}\n Next spawn: {2}"
}
"Classes menu human"
{
"en" "Select Human Class:"
}
"Classes menu human current"
"Classes menu next"
{
"#format" "{1:s}"
"en" "Select Human Class\n {1}"
"en" "Next spawn: {1}"
}
"Classes menu human next"
"Classes menu select zombie"
{
"#format" "{1:s},{2:s}"
"en" "Select Human Class\n Active: {1}\n Next spawn: {2}"
"en" "Select Zombie Class"
}
"Classes menu admin"
"Classes menu select human"
{
"en" "Select Admin Mode Class:"
}
"Classes menu admin current"
{
"#format" "{1:s}"
"en" "Select Admin Mode Class\n {1}"
"en" "Select Human Class"
}
"Classes menu admin next"
"Classes menu select admin"
{
"#format" "{1:s},{2:s}"
"en" "Select Admin Mode Class\n Active: {1}\n Next spawn: {2}"
"en" "Select Admin Mode Class"
}
"Classes menu admin mode toggle"
@ -356,6 +332,11 @@
"en" "Jump Distance"
}
"Classes Selection Not Allowed"
{
"en" "Changing classes is not allowed."
}
// ===========================
// Overlays (core)
// ===========================
@ -461,44 +442,37 @@
"Menu main zadmin"
{
"#format" "{1:s}"
"en" "ZAdmin - Open admin menu. (Command: {1})"
"en" "ZAdmin - Open admin menu"
}
"Menu main zclass"
{
"#format" "{1:s}"
"en" "ZClass - Configure class settings. (Command: {1})"
"en" "ZClass - Configure class settings"
}
"Menu main zcookies"
{
"#format" "{1:s}"
"en" "ZCookies - Toggle personal ZR settings here. (Command: {1})"
"en" "ZCookies - Toggle personal ZR settings here"
}
"Menu main zspawn"
{
"#format" "{1:s}"
"en" "ZSpawn - Join late? Spawn with this. (Command: {1})"
"en" "ZSpawn - Join late? Spawn with this"
}
"Menu main ztele"
{
"#format" "{1:s}"
"en" "ZTele - Stuck? Teleport back to spawn. (Command: {1})"
"en" "ZTele - Stuck? Teleport back to spawn"
}
"Menu main zhp"
{
"#format" "{1:s}"
"en" "ZHP - Shows real HP as zombie. (Command: {1})"
"en" "ZHP - Shows real HP as zombie"
}
"Menu main zmarket"
{
"#format" "{1:s}"
"en" "ZMarket - Customize loadouts here. (Command: {1})"
"en" "ZMarket - Customize loadouts here"
}
// ===========================

View File

@ -91,7 +91,7 @@ zr_log "1"
// Default: "3"
zr_log_flags "3"
// Enable module filtering. Only log events from listed modules will be logged.
// Enable module filtering. Only events from listed modules will be logged.
// Default: "0"
zr_log_module_filter "0"
@ -133,6 +133,15 @@ zr_config_path_weapons "configs/zr/weapons.txt"
zr_config_path_hitgroups "configs/zr/hitgroups.txt"
// ----------------------------------------------------------------------------
// Permission settings
// ----------------------------------------------------------------------------
// Use group authentication instead of flags to access admin features. Generic admin flag is still required on some features.
// -
// Default: "0"
zr_permissions_use_groups "0"
// ----------------------------------------------------------------------------
// Classes (core)
// ----------------------------------------------------------------------------
@ -143,10 +152,18 @@ zr_config_path_hitgroups "configs/zr/hitgroups.txt"
// Default: "0"
zr_classes_spawn "0"
// Player is assigned a random class every spawn. [Override: zr_classes_spawn & zr_classes_default_*]
// Player is assigned a random class every spawn. [Override: zr_classes_default_*]
// Default: "0"
zr_classes_random "0"
// Time limit to change human class with instant change after spawning. Time is in seconds. Use 0 or negative to disable.
// Default: "20"
zr_classes_change_timelimit "20"
// Save players' class selections in server cookies and restore when connecting. [Override: zr_classes_default_*]
// Default: "1"
zr_classes_save "1"
// Admin class assigned to admins on connect. ["random" = Random admin class | "" = Class config default]
// Default: "random"
zr_classes_default_admin "random"
@ -163,6 +180,18 @@ zr_classes_default_zombie "random"
// Default: "motherzombies"
zr_classes_default_mother_zombie "motherzombies"
// Allow players to select zombie classes.
// Default: "1"
zr_classes_zombie_select "1"
// Allow players to select human classes.
// Default: "1"
zr_classes_human_select "1"
// Allow admins to select admin mode classes. (Not to be confused by admin-only classes!)
// Default: "1"
zr_classes_admin_select "1"
// Menu
// Automatically close class selection menu.

View File

@ -604,7 +604,7 @@ The list below explains all available class attributes in detail:
Attribute: Value type: Limits/Requirements:
===========================================================================
enabled boolean 0 or 1
enabled text "yes" or "no"
---------------------------------------------------------------------------
Enables or disables the class. Disabled classes won't show up in the
class selection menus. Also, if some attributes failed to validate the
@ -627,7 +627,7 @@ The list below explains all available class attributes in detail:
See the "flags" attribute for admin-only classes.
team_default boolean 0 or 1
team_default text "yes" or "no"
---------------------------------------------------------------------------
Marks the class as the default class for its specified team. This class
will be automatically selected on new players when they join the
@ -651,8 +651,13 @@ The list below explains all available class attributes in detail:
setting must be set to "motherzombies" for this flag to take
effect.
Remember that these flags can be used in a combination (1 + 2), so
it's a mother zombie class for admins only.
These flags can be used in a combination (1 + 2), so it could be a
mother zombie class for admins only.
group text Name of a valid SourceMod group.
---------------------------------------------------------------------------
Rescrict class to members of this SourceMod group. Useful for making
VIP-only classes. Leave blank to allow everyone to use this class.
name text Unique, not empty, max 64 charact.
---------------------------------------------------------------------------
@ -668,10 +673,13 @@ The list below explains all available class attributes in detail:
model_path text Max 256 characters, not empty
---------------------------------------------------------------------------
The model file to use on the player, path is relative to the "cstrike"
folder. There are two special values supported by this attribute:
folder. There are a few special values supported by this attribute:
"default" - Don't change model, use default CS models.
"random" - Selects a random model for the current team.
"default" - Use default CS models. The one players select when
selecting team.
"random" - Selects a random model for the current team.
"nochange" - Don't change model. To be used in combination with
other plugins that change model on players.
alpha_spawn number 0 - 255
---------------------------------------------------------------------------
@ -694,7 +702,7 @@ The list below explains all available class attributes in detail:
controlled by the night vision key ("n" by default). The path is
relative to "cstrike/materials". Leave blank to disable.
nvgs boolean 0 or 1
nvgs text "yes" or "no"
---------------------------------------------------------------------------
Gives night vision to the player.
@ -703,7 +711,7 @@ The list below explains all available class attributes in detail:
The field of view on the player. Note that the weapon hud disappear if
FOV is anything else than 90.
has_napalm boolean 0 or 1
has_napalm text "yes" or "no"
---------------------------------------------------------------------------
Human classes only. Specifies whether the human can trow napalm
grenades or not.
@ -725,7 +733,7 @@ The list below explains all available class attributes in detail:
The value for the specified immunity mode. This feature is currently
incomplete and values are ignored.
no_fall_damage boolean 0 or 1
no_fall_damage text "yes" or "no"
---------------------------------------------------------------------------
Blocks fall damage on the player.
@ -750,8 +758,8 @@ The list below explains all available class attributes in detail:
kill_bonus number 0 - 16
---------------------------------------------------------------------------
Zombie classes only. How many EXTRA points to give the killer of a
zombie. If this is 0, the default value of 1 point will be given.
Zombie classes only. How many extra points to give the killer of this
zombie. If this is 0, the default value of 1 point will be given.
speed decimal 10.0 - 2000.0
---------------------------------------------------------------------------
@ -762,13 +770,15 @@ The list below explains all available class attributes in detail:
Zombie classes only. Force to apply on the zombie when shot at. The
zombie is pushed in the same direction as the bullet.
jump_height decimal -500.0 - 500.0
jump_height decimal 0.0 - 5.0
---------------------------------------------------------------------------
Extra upward boost when jumping.
Jump height multiplier. Extra upward boost when jumping. If 1.0 or 0.0
no boost will be applied.
jump_distance decimal -500.0 - 500.0
jump_distance decimal 0.0 - 5.0
---------------------------------------------------------------------------
Extra forward boost when jumping.
Jump distance multiplier. Extra forward boost when jumping. If 1.0 or
0.0 no boost will be applied.
3.7.3 CLASS REQUIREMENTS
@ -798,29 +808,30 @@ Attribute flags:
team 2 2
team_default 3 4
flags 4 8
name 5 16
description 6 32
model_path 7 64
alpha_initial 8 128
alpha_damaged 9 256
alpha_damage 10 512
overlay_path 11 1024
nvgs 12 2048
fov 13 4096
has_napalm 14 8192
napalm_time 15 16384
immunity_mode 16 32768
immunity_amount 17 65536
no_fall_damage 18 131072
health 19 262144
health_regen_interval 20 524288
health_regen_amount 21 1048576
infect_gain 22 2097152
kill_bonus 23 4194304
speed 24 8388608
knockback 25 16777216
jump_height 26 33554432
jump_distance 27 67108864
group 5 16
name 6 32
description 7 64
model_path 8 128
alpha_initial 9 256
alpha_damaged 10 512
alpha_damage 11 1024
overlay_path 12 2048
nvgs 13 4096
fov 14 8192
has_napalm 15 16384
napalm_time 16 32768
immunity_mode 17 65536
immunity_amount 18 131072
no_fall_damage 19 262144
health 20 524288
health_regen_interval 21 1048576
health_regen_amount 22 2097152
infect_gain 23 4194304
kill_bonus 24 8388608
speed 25 16777216
knockback 26 33554432
jump_height 27 67108864
jump_distance 28 134217728
The error flags are stored in a bit field (explained in the log configuration
in section 3.2).
@ -873,6 +884,25 @@ Class console variables:
---------------------------------------------------------------------------
Assign random classes to all players each round.
This setting overrides zr_classes_save.
Options:
0 or 1
zr_classes_change_timelimit 20
---------------------------------------------------------------------------
The time limit to change human classes with instant change after
spawning. So humans don't have to set class before spawning. Time is in
seconds.
zr_classes_save 1
---------------------------------------------------------------------------
Save players' class selections in server cookies. Class selections are
restored next time players connect.
This setting overrides zr_classes_default_*, but on first-time
connecting players the default classes are assigned.
Options:
0 or 1

View File

@ -41,6 +41,7 @@
#include "zr/zombiereloaded"
#include "zr/translation"
#include "zr/cvars"
#include "zr/admintools"
#include "zr/log"
#include "zr/config"
#include "zr/steamidcache"
@ -49,6 +50,7 @@
#include "zr/menu"
#include "zr/cookies"
#include "zr/paramtools"
#include "zr/paramparser"
#include "zr/models"
#include "zr/downloads"
#include "zr/overlays"

168
src/zr/admintools.inc Normal file
View File

@ -0,0 +1,168 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: admintools.inc
* Type: Core
* Description: Functions for checking extended admin privileges.
*
* Copyright (C) 2009 Greyscale, Richard Helgeby
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================================
*/
/**
* @section Pre-defined group names for authenticating players.
*/
#define ZR_GROUP_ADMINS "zr_admins"
#define ZR_GROUP_MODERATORS "zr_moderators"
#define ZR_GROUP_CONFIGURATORS "zr_configurators"
/**
* @endsection
*/
/**
* List of operation types to specify the category of a admin operation.
*/
enum OperationTypes
{
OperationType_Invalid = -1, /** Invalid operation type. */
OperationType_Generic, /** Generic events like infecting or teleporting players. */
OperationType_Configuration, /** Changing settings. */
}
/**
* Returns whether a player is allowed to do a certain operation or not.
*
* @param client The client index.
* @param operationType The operation category.
* @return True if allowed, false otherwise.
*/
stock bool:ZRIsClientPrivileged(client, OperationTypes:operationType = OperationType_Generic)
{
// Validate client index.
if (!ZRIsClientValid(client))
{
return false;
}
// Check if group permissions is enabled.
new bool:groupauth = GetConVarBool(g_hCvarsList[CVAR_PERMISSIONS_USE_GROUPS]);
if (groupauth)
{
/**********************************
* *
* GROUP BASED AUTHENTICATION *
* *
**********************************/
// Check if client is full admin.
if (ZRIsClientInGroup(client, ZR_GROUP_ADMINS))
{
return true;
}
// Check operation type.
switch (operationType)
{
case OperationType_Generic:
{
return ZRIsClientInGroup(client, ZR_GROUP_MODERATORS);
}
case OperationType_Configuration:
{
return ZRIsClientInGroup(client, ZR_GROUP_CONFIGURATORS);
}
}
// Invalid operation type.
return false;
}
else
{
/*********************************
* *
* FLAG BASED AUTHENTICATION *
* *
*********************************/
new AdminFlag:flag;
// Check operation type.
switch (operationType)
{
case OperationType_Generic:
{
flag = Admin_Generic;
}
case OperationType_Configuration:
{
flag = Admin_Config;
}
default:
{
// Invalid operation type.
return false;
}
}
return GetAdminFlag(GetUserAdmin(client), flag);
}
}
/**
* Returns whether a player is in a spesific group or not.
*
* @param client The client index.
* @param groupName SourceMod group name to check.
* @return True if in the group, false otherwise.
*/
stock bool:ZRIsClientInGroup(client, const String:groupName[])
{
new AdminId:id = GetUserAdmin(client);
// Validate id.
if (id == INVALID_ADMIN_ID)
{
return false;
}
// Get number of groups.
new groupnum = GetAdminGroupCount(id);
decl String:groupname[64];
// Validate number of groups.
if (groupnum > 0)
{
// Loop through each group.
for (new group = 0; group < groupnum; group++)
{
// Get group name.
GetAdminGroup(id, group, groupname, sizeof(groupname));
// Compare names.
if (StrEqual(groupName, groupname, false))
{
return true;
}
}
}
// No groups or no match.
return false;
}

View File

@ -67,4 +67,36 @@ bool:CookiesGetClientCookieBool(client, Handle:cookie)
// Return string casted into an int, then to bool.
return bool:StringToInt(cookievalue);
}
}
/**
* Sets a integer value on a cookie.
*
* @param client The client index.
* @param cookie The handle to the cookie.
* @param value The value to set.
*/
CookiesSetInt(client, Handle:cookie, value)
{
// Convert value to string.
decl String:strValue[16];
IntToString(value, strValue, sizeof(strValue));
// Set string value.
SetClientCookie(client, cookie, strValue);
}
/**
* Gets a integer value from a cookie.
*
* @param client The client index.
* @param cookie The handle to the cookie.
*/
CookiesGetInt(client, Handle:cookie)
{
decl String:strValue[16];
strValue[0] = 0;
GetClientCookie(client, cookie, strValue, sizeof(strValue));
return StringToInt(strValue);
}

View File

@ -52,8 +52,11 @@ enum CvarsList
Handle:CVAR_CONFIG_PATH_CLASSES,
Handle:CVAR_CONFIG_PATH_WEAPONS,
Handle:CVAR_CONFIG_PATH_HITGROUPS,
Handle:CVAR_PERMISSIONS_USE_GROUPS,
Handle:CVAR_CLASSES_SPAWN,
Handle:CVAR_CLASSES_RANDOM,
Handle:CVAR_CLASSES_CHANGE_TIMELIMIT,
Handle:CVAR_CLASSES_SAVE,
Handle:CVAR_CLASSES_DEFAULT_ZOMBIE,
Handle:CVAR_CLASSES_DEFAULT_M_ZOMB,
Handle:CVAR_CLASSES_DEFAULT_HUMAN,
@ -62,6 +65,9 @@ enum CvarsList
Handle:CVAR_CLASSES_OVERLAY_TOGGLE,
Handle:CVAR_CLASSES_OVERLAY_TOGGLECMDS,
Handle:CVAR_CLASSES_OVERLAY_DEFAULT,
Handle:CVAR_CLASSES_ZOMBIE_SELECT,
Handle:CVAR_CLASSES_HUMAN_SELECT,
Handle:CVAR_CLASSES_ADMIN_SELECT,
Handle:CVAR_WEAPONS,
Handle:CVAR_WEAPONS_RESTRICT,
Handle:CVAR_WEAPONS_ZMARKET,
@ -216,7 +222,7 @@ CvarsCreate()
// ===========================
g_hCvarsList[CVAR_LOG] = CreateConVar("zr_log", "1", "Enable logging of events in the plugin. Fatal errors are logged independent on this setting.");
g_hCvarsList[CVAR_LOG_FLAGS] = CreateConVar("zr_log_flags", "3", "A bit field that specify what event types to log. See logging section (3.3) in manual for details.");
g_hCvarsList[CVAR_LOG_MODULE_FILTER] = CreateConVar("zr_log_module_filter", "0", "Enable module filtering. Only log events from listed modules will be logged.");
g_hCvarsList[CVAR_LOG_MODULE_FILTER] = CreateConVar("zr_log_module_filter", "0", "Enable module filtering. Only events from listed modules will be logged.");
g_hCvarsList[CVAR_LOG_IGNORE_CONSOLE] = CreateConVar("zr_log_ignore_console", "1", "Don't log events triggered by console commands that are executed by the console itself, like commands in configs. Enable this command to avoid spamming logs with events like weapon restrictions.");
g_hCvarsList[CVAR_LOG_ERROR_OVERRIDE] = CreateConVar("zr_log_error_override", "1", "Always log error messages. Overrides module filter and logging flags.");
g_hCvarsList[CVAR_LOG_PRINT_ADMINS] = CreateConVar("zr_log_print_admins", "0", "Print log events to admin chat in addition to the log file.");
@ -233,17 +239,28 @@ CvarsCreate()
g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt", "Path, relative to root sourcemod directory, to hitgroups config file.");
// ===========================
// Permission Settings
// ===========================
g_hCvarsList[CVAR_PERMISSIONS_USE_GROUPS] = CreateConVar("zr_permissions_use_groups", "0", "Use group authentication instead of flags to access admin features. Generic admin flag is still required on some features.");
// ===========================
// Classes (core)
// ===========================
// General
g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn.");
g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_spawn and zr_classes_default_*]");
g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_default_*]");
g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT] = CreateConVar("zr_classes_change_timelimit", "20", "Time limit to change human class with instant change after spawning. Time is in seconds. Use 0 or negative to disable.");
g_hCvarsList[CVAR_CLASSES_SAVE] = CreateConVar("zr_classes_save", "1", "Save players' class selections in server cookies and restore when connecting. [Override: zr_classes_default_*]");
g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. [\"random\" = Random zombie class | \"\" = Class config default]");
g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "motherzombies","Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]");
g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]");
g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", "Admin class assigned to admins on connect. [\"random\" = Random admin class | \"\" = Class config default]");
g_hCvarsList[CVAR_CLASSES_ZOMBIE_SELECT] = CreateConVar("zr_classes_zombie_select", "1", "Allow players to select zombie classes.");
g_hCvarsList[CVAR_CLASSES_HUMAN_SELECT] = CreateConVar("zr_classes_human_select", "1", "Allow players to select human classes.");
g_hCvarsList[CVAR_CLASSES_ADMIN_SELECT] = CreateConVar("zr_classes_admin_select", "1", "Allow admins to select admin mode classes. (Not to be confused by admin-only classes!)");
// Menu
g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE] = CreateConVar("zr_classes_menu_autoclose", "0", "Automatically close class selection menu after selecting a class.");

View File

@ -307,12 +307,6 @@ public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:dama
// Client was damaged by falling.
else if (damagetype & DMG_CSS_FALL)
{
// If client isn't a zombie, then allow damage.
if (!InfectIsClientInfected(client))
{
return ZRTools_Continue;
}
// If class has "nofalldamage" disabled, then allow damage.
new bool:blockfalldamage = ClassGetNoFallDamage(client);
if (!blockfalldamage)

View File

@ -624,7 +624,7 @@ public Action:Command_LogRemoveModule(client, argc)
if (argc < 1)
{
// Display syntax info.
StrCat(buffer, sizeof(buffer), "Add one or more modules to the module filter. Usage: zr_log_add_module <module> [module] ...\n");
StrCat(buffer, sizeof(buffer), "Remove one or more modules to the module filter. Usage: zr_log_remove_module <module> [module] ...\n");
StrCat(buffer, sizeof(buffer), "See zr_log_list to list available module names (short names).");
ReplyToCommand(client, buffer);
}

View File

@ -101,13 +101,13 @@ ZMenuMain(client)
// Translate each line into client's language.
Format(title, sizeof(title), "%t\n ", "Menu main title", publictrigger, silenttrigger);
Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin", SAYHOOKS_KEYWORD_ZADMIN);
Format(zclass, sizeof(zclass), "%t", "Menu main zclass", SAYHOOKS_KEYWORD_ZCLASS);
Format(zcookies, sizeof(zcookies), "%t", "Menu main zcookies", SAYHOOKS_KEYWORD_ZCOOKIES);
Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn", SAYHOOKS_KEYWORD_ZSPAWN);
Format(ztele, sizeof(ztele), "%t", "Menu main ztele", SAYHOOKS_KEYWORD_ZTELE);
Format(zhp, sizeof(zhp), "%t", "Menu main zhp", SAYHOOKS_KEYWORD_ZHP);
Format(zmarket, sizeof(zmarket), "%t", "Menu main zmarket", SAYHOOKS_KEYWORD_ZMARKET);
Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin");
Format(zclass, sizeof(zclass), "%t", "Menu main zclass");
Format(zcookies, sizeof(zcookies), "%t", "Menu main zcookies");
Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn");
Format(ztele, sizeof(ztele), "%t", "Menu main ztele");
Format(zhp, sizeof(zhp), "%t", "Menu main zhp");
Format(zmarket, sizeof(zmarket), "%t", "Menu main zmarket");
// Add items to menu.
@ -117,7 +117,10 @@ ZMenuMain(client)
new bool:admin = ZRIsClientAdmin(client);
AddMenuItem(menu_main, "zadmin", zadmin, MenuGetItemDraw(admin));
AddMenuItem(menu_main, "zclass", zclass);
// Decide whether the client can use zclass.
new zclassdraw = ClassAllowSelection(client) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
AddMenuItem(menu_main, "zclass", zclass, zclassdraw);
AddMenuItem(menu_main, "zcookies", zcookies);
AddMenuItem(menu_main, "zspawn", zspawn);
AddMenuItem(menu_main, "ztele", ztele);

531
src/zr/paramparser.inc Normal file
View File

@ -0,0 +1,531 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: paramparser.inc
* Type: Core
* Description: Provides functions for parsing single line strings with
* flags, and parameters in key=value format.
*
* Supports quoted strings and escaped characters like "\n"
* and "\t".
*
* Examle raw string:
* "type=interval -disabled msg="Title:\n\"Example\"."
*
* Copyright (C) 2009 Greyscale, Richard Helgeby
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================================
*/
/**
* @section Limit settings.
*/
#define PARAM_NAME_MAXLEN 64 /** Maximum length of key name or flag name. */
#define PARAM_VALUE_MAXLEN 256 /** Maximum length of value string. */
/**
* @endsection
*/
/**
* @section Parsing error codes.
*/
#define PARAM_ERROR_EMPTY 1 /** Source string is empty. */
#define PARAM_ERROR_FULL 2 /** Destination array is full. */
#define PARAM_ERROR_UNEXPECTED_KEY 3 /** Unexpected key name. Could not find a equation sign (=) after previous key name. */
#define PARAM_ERROR_UNEXPECTED_END 4 /** Unexpected end of source string. */
#define PARAM_ERROR_MISSING_QUOTE 5 /** Unexpected end of source string. Missing end quote character. */
#define PARAM_ERROR_UNKNOWN 6 /** Unknown error. The parser got a invalid result from a search function it couldn't handle. */
/**
* @endsection
*/
/**
* Modes for what to do and expect when parsing. White space characters between
* modes are ignored.
*/
enum ParamModes
{
ParamMode_TypeCheck, /** Check if it's a flag or a key. */
ParamMode_Flag, /** Expect a flag name (starts with "-"). */
ParamMode_Key, /** Expect a key name. */
ParamMode_Equal, /** Expect a equation sign. */
ParamMode_Value /** Expect a value string. */
}
/**
* Structure for storing a key/value pair.
*/
enum ParamParseResult
{
bool:Param_IsFlag, /** Specifies whether it's a flag or not. */
String:Param_Name[PARAM_NAME_MAXLEN], /** Key or flag name. */
String:Param_Value[PARAM_VALUE_MAXLEN] /** Value. Only used if a key. */
}
/**************************************
* *
* PARAMETER FUNCTIONS *
* *
**************************************/
/**
* Parses a parameter string in "key=value" format and store the result in a
* ParamParseResult array.
*
* @param buffer A ParamParseResult array to store results.
* @param maxlen Maximum number of keys that can be stored (first
* dimension of buffer).
* @param paramString The source string to parse. String is trimmed before
* parsing.
* @param err Opional output: Error code if parsing error.
* @param errPos Opional output: Position in paramString where the error
* occoured.
* @return Number of keys parsed.
*/
stock ParamParseString(buffer[][ParamParseResult], maxlen, String:paramString[], &err = 0, &errPos = -1)
{
/*
* VALIDATION OF INPUT AND BUFFERS
*/
// Trim raw string.
TrimString(paramString);
// Check if raw string is empty.
if (strlen(paramString) == 0)
{
err = PARAM_ERROR_EMPTY;
errPos = 0;
return 0;
}
// Validate specified length of destination buffer.
if (maxlen == 0)
{
err = PARAM_ERROR_FULL;
errPos = 0;
return 0;
}
/*
* PARSE LOOP
*/
// Get raw string length.
new rawlen = sizeof(paramString);
// Initialize. Expect the start to be a key or a flag.
new ParamModes:mode = ParamMode_TypeCheck;
// Counter for number of parameters parsed.
new paramcount;
// Buffers for temp values.
new startpos;
new endpos;
new bool:quoteon;
decl String:value[PARAM_VALUE_MAXLEN];
// Loop through all characters in the string. Exclude null terminator.
for (new strpos = 0; strpos < rawlen - 1; strpos++)
{
// Check if there's space left in the destination buffer.
if (paramcount > maxlen)
{
// Exit loop. No more parameters can be parsed.
err = PARAM_ERROR_FULL;
errPos = strpos;
break;
}
/*
* MODE CHECK
*/
// Check mode for deciding what to do.
switch (mode)
{
case ParamMode_TypeCheck:
{
// Find start position of first non white space character.
startpos = ParamFindStartPos(paramString, strpos);
// Check if it's a flag type.
if (paramString[startpos] == '-')
{
// It's a flag, change mode.
mode = ParamMode_Flag;
// Update current position.
strpos = startpos;
}
else
{
// Expect a key name.
mode = ParamMode_Key;
// Update current position. Substract by one to include
// the current character in next mode.
strpos = startpos - 1;
}
}
case ParamMode_Flag:
{
// Find stop position (last non white space character).
endpos = ParamFindEndPos(paramString, strpos);
// Extract key name.
StrExtract(value, sizeof(value), paramString, strpos, endpos);
// Copy flag to destination buffer.
strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value);
// Set flag type.
buffer[paramcount][Param_IsFlag] = true;
// Increment parameter counter.
paramcount++;
// Set next parse mode.
mode = ParamMode_TypeCheck;
}
case ParamMode_Key:
{
// Find stop position.
endpos = ParamFindEndPos(paramString, strpos);
// Extract key name.
StrExtract(value, sizeof(value), paramString, strpos, endpos);
// Copy key name to destination buffer.
strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value);
// Make sure flag type is not set.
buffer[paramcount][Param_IsFlag] = false;
// Note: Do not increment parameter counter until the
// entire key/value pair is parsed.
// Set next parse mode. Expect a equation sign.
mode = ParamMode_Equal;
}
case ParamMode_Equal:
{
// Find start position of first non white space character.
startpos = ParamFindStartPos(paramString, strpos);
// Validate position.
if (startpos >= 0)
{
// Check if it's a equation sign.
if (paramString[startpos] == '=')
{
// Change mode to expect a value at next position.
mode = ParamMode_Value;
// Update current position.
strpos = startpos;
}
else
{
// Parse error.
err = PARAM_ERROR_UNEXPECTED_KEY;
errPos = startpos;
break;
}
}
else
{
// Parse error.
err = PARAM_ERROR_UNEXPECTED_END;
errPos = strpos;
break;
}
}
case ParamMode_Value:
{
// Find start position of first non white space character.
startpos = ParamFindStartPos(paramString, strpos);
// Validate start position.
if (startpos >= 0)
{
// Reset quote and escape settings.
quoteon = false;
// Loop through all characters starting from the current
// position. Exclude null terminator.
for (strpos = startpos; strpos < rawlen - 1; strpos++)
{
// Check if the current character is a special character.
if (paramString[startpos] == '"')
{
// Toggle quote.
quoteon = !quoteon;
// Check quote state.
if (quoteon)
{
// Quote started, update start position.
startpos = strpos + 1;
}
else
{
// Quote end, set end position.
endpos = strpos - 1;
}
}
// Check if it's a white space character or end of the string.
else if (!quoteon && (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1))
{
// End of value reached. Save positions.
endpos = strpos - 1;
// Exit loop.
break;
}
}
// Check if quote still haven't ended.
if (quoteon)
{
// Parse error.
err = PARAM_ERROR_MISSING_QUOTE;
errPos = strpos;
break;
}
// Extract value string.
StrExtract(value, sizeof(value), paramString, startpos, endpos);
// Unescape string (converting "\n" to newline, etc.).
StrUnescape(value);
// Copy value string to destination buffer.
strcopy(buffer[paramcount][Param_Value], PARAM_VALUE_MAXLEN, value);
// Make sure flag type is not set.
buffer[paramcount][Param_IsFlag] = false;
// Increment parameter counter.
paramcount++;
// Set next parse mode. Expect a key or a flag.
mode = ParamMode_TypeCheck;
}
else
{
// Parse error.
err = PARAM_ERROR_UNEXPECTED_END;
errPos = strpos;
break;
}
}
}
}
// Return number of parameters parsed.
return paramcount;
}
/**
* Finds the first key index in a parameter array matching the specified key.
*
* @param params A ParamParseResult array to search through.
* @param maxlen Size of parameter array (first dimension).
* @param key Key to find.
* @param caseSensitive Specifies whether the search is case sensitive or
* not (default).
* @return Index of the key if found, -1 otherwise.
*/
stock ParamFindKey(const params[][ParamParseResult], maxlen, const String:key[], bool:caseSensitive = false)
{
// Loop through all parameters.
for (new index = 0; index < maxlen; index++)
{
// Check parameter type.
if (params[index][Param_IsFlag])
{
// It's a flag type, skip index.
continue;
}
// Match key name.
if (StrEqual(params[index][Param_Name], key, caseSensitive))
{
// Key found, return the key index.
return index;
}
}
return -1;
}
/**
* Checks if the specified flag is set in a parameter array.
*
* @param params A ParamParseResult array to search through.
* @param maxlen Size of parameter array (first dimension).
* @param flag Flag to check.
* @param caseSensitive Specifies whether the search is case sensitive or
* not (default).
* @return True flag is found, false otherwise.
*/
stock bool:ParamHasFlag(const params[][ParamParseResult], maxlen, const String:flag[], bool:caseSensitive = false)
{
// Loop through all parameters.
for (new index = 0; index < maxlen; index++)
{
// Check parameter type.
if (!params[index][Param_IsFlag])
{
// It's a key type, skip index.
continue;
}
// Match flag name.
if (StrEqual(params[index][Param_Name], flag, caseSensitive))
{
// Flag found.
return true;
}
}
return false;
}
/**************************************
* *
* HELPER FUNCTIONS *
* *
**************************************/
/**
* Finds the position of the last non white space character from a specified start position.
*
* @param paramString Raw string search in.
* @param startPos Optional. Position to start searching from.
* @return Position of the last non white space character, or -1
* if failed.
*/
stock ParamFindEndPos(const String:paramString[], startPos = 0)
{
new rawlen = sizeof(paramString);
// Validate string length.
if (rawlen == 0)
{
return -1;
}
// Loop through all characters from the specified start position.
for (new strpos = startPos; strpos < rawlen; strpos++)
{
// Check if white space or if current position is the last
// character before the null terminator.
if (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1)
{
return strpos - 1;
}
}
// It should never reach this place. Added to satisfy compiler.
return -1;
}
/**
* Finds the first non white space character in a string, starting from the
* specified position.
*
* @param paramString Raw string to search in.
* @param startPos Optional. Position to start searching from.
* @return Position of first character or -1 if failed.
*/
stock ParamFindStartPos(const String:paramString[], startPos = 0)
{
new rawlen = sizeof(paramString);
// Validate string length.
if (rawlen == 0)
{
return -1;
}
// Loop through all characters from the specified start position.
for (new strpos = startPos; strpos < rawlen; strpos++)
{
// Check if not white space.
if (!IsCharSpace(paramString[strpos]))
{
return strpos;
}
}
// No character found.
return -1;
}
/**
* Extracts a area in a string between two positions.
*
* @param buffer Destination string buffer.
* @param maxlen Size of destination buffer.
* @param source Source string to extract from.
* @param startpos Start position of string to extract.
* @param endpos End position of string to extract.
* @return Number of cells written.
*/
stock StrExtract(String:buffer[], maxlen, const String:source[], startpos, endpos)
{
new len;
// Calculate string length. Also add space for null terminator.
len = endpos - startpos + 1;
// Validate length.
if (len < 0)
{
return 0;
}
// Extract string and store it in the buffer.
return strcopy(buffer, len, source[startpos]);
}
/**
* Unescapes a string (replaces "\n" with newlines, etc.).
*
* @param str String to unescape.
*/
stock StrUnescape(String:str[])
{
new len = sizeof(str);
ReplaceString(str, len, "\\n", "\n");
ReplaceString(str, len, "\\r", "\r");
ReplaceString(str, len, "\\t", "\t");
ReplaceString(str, len, "\\\"", "\"");
ReplaceString(str, len, "\\\\", "\\");
}

View File

@ -89,16 +89,14 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
ClassGetModelPath(classindex, modelpath, sizeof(modelpath), cachetype);
}
// Check if the user specified a random model.
if (strcmp(modelpath, "random", false) == 0)
// Check if the user specified a pre-defined model setting.
if (StrEqual(modelpath, "random", false))
{
// TODO: Make a function that gets a random model from the specified team.
ModelsGetRandomModelIndex(modelpath, sizeof(modelpath), false, true);
Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
}
// Check if the user specified no change.
else if (strcmp(modelpath, "default", false) == 0)
else if (StrEqual(modelpath, "default", false))
{
// Get current model.
GetClientModel(client, modelpath, sizeof(modelpath));
@ -114,6 +112,11 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
return true;
}
}
else if (StrEqual(modelpath, "nochange", false))
{
// Do nothing.
return true;
}
SetEntityModel(client, modelpath);
return true;

View File

@ -52,15 +52,15 @@ stock bool:ClassIsEnabled(index, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_enabled];
return ClassData[index][Class_Enabled];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_enabled];
return ClassDataCache[index][Class_Enabled];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_enabled];
return ClassPlayerCache[index][Class_Enabled];
}
}
return false;
@ -84,15 +84,15 @@ stock ClassGetTeamID(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_team];
return ClassData[index][Class_Team];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_team];
return ClassDataCache[index][Class_Team];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_team];
return ClassPlayerCache[index][Class_Team];
}
}
return -1;
@ -118,15 +118,15 @@ stock bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_team_default];
return ClassData[index][Class_TeamDefault];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_team_default];
return ClassDataCache[index][Class_TeamDefault];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_team_default];
return ClassPlayerCache[index][Class_TeamDefault];
}
}
return false;
@ -151,15 +151,15 @@ stock ClassGetFlags(index, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_flags];
return ClassData[index][Class_Flags];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_flags];
return ClassDataCache[index][Class_Flags];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_flags];
return ClassPlayerCache[index][Class_Flags];
}
}
return -1;
@ -185,20 +185,55 @@ stock bool:ClassHasFlags(index, flags, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return bool:(ClassData[index][class_flags] & flags);
return bool:(ClassData[index][Class_Flags] & flags);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return bool:(ClassDataCache[index][class_flags] & flags);
return bool:(ClassDataCache[index][Class_Flags] & flags);
}
case ZR_CLASS_CACHE_PLAYER:
{
return bool:(ClassPlayerCache[index][class_flags] & flags);
return bool:(ClassPlayerCache[index][Class_Flags] & flags);
}
}
return false;
}
/**
* Gets the class group required to be a member of to use the class.
*
* @param index Index of the class in a class cache or a client index,
* depending on the cache type specified.
* @param buffer The destination string buffer.
* @param maxlen The length of the destination string buffer.
* @param cachetype Optional. Specifies what class cache to read from. Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
* ZR_CLASS_CACHE_MODIFIED - Changed/newest class data.
* ZR_CLASS_CACHE_PLAYER (default) - Player cache. If this one
* is used, index will be used as a client index.
* @return Number of cells written. -1 on error.
*/
stock ClassGetGroup(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER)
{
switch (cachetype)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return strcopy(buffer, maxlen, ClassData[index][Class_Group]);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return strcopy(buffer, maxlen, ClassDataCache[index][Class_Group]);
}
case ZR_CLASS_CACHE_PLAYER:
{
return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Group]);
}
}
return -1;
}
/**
* Gets the class name to be displayed in the class menu.
*
@ -219,15 +254,15 @@ stock ClassGetName(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PL
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return strcopy(buffer, maxlen, ClassData[index][class_name]);
return strcopy(buffer, maxlen, ClassData[index][Class_Name]);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return strcopy(buffer, maxlen, ClassDataCache[index][class_name]);
return strcopy(buffer, maxlen, ClassDataCache[index][Class_Name]);
}
case ZR_CLASS_CACHE_PLAYER:
{
return strcopy(buffer, maxlen, ClassPlayerCache[index][class_name]);
return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Name]);
}
}
@ -254,15 +289,15 @@ stock ClassGetDescription(index, String:buffer[], maxlen, cachetype = ZR_CLASS_C
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return strcopy(buffer, maxlen, ClassData[index][class_description]);
return strcopy(buffer, maxlen, ClassData[index][Class_Description]);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return strcopy(buffer, maxlen, ClassDataCache[index][class_description]);
return strcopy(buffer, maxlen, ClassDataCache[index][Class_Description]);
}
case ZR_CLASS_CACHE_PLAYER:
{
return strcopy(buffer, maxlen, ClassPlayerCache[index][class_description]);
return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Description]);
}
}
return -1;
@ -298,15 +333,15 @@ stock ClassGetModelPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CAC
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return strcopy(buffer, maxlen, ClassData[index][class_model_path]);
return strcopy(buffer, maxlen, ClassData[index][Class_ModelPath]);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return strcopy(buffer, maxlen, ClassDataCache[index][class_model_path]);
return strcopy(buffer, maxlen, ClassDataCache[index][Class_ModelPath]);
}
case ZR_CLASS_CACHE_PLAYER:
{
return strcopy(buffer, maxlen, ClassPlayerCache[index][class_model_path]);
return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_ModelPath]);
}
}
return -1;
@ -330,15 +365,15 @@ stock ClassGetAlphaInitial(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_alpha_initial];
return ClassData[index][Class_AlphaInitial];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_alpha_initial];
return ClassDataCache[index][Class_AlphaInitial];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_alpha_initial];
return ClassPlayerCache[index][Class_AlphaInitial];
}
}
return -1;
@ -363,15 +398,15 @@ stock ClassGetAlphaDamaged(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_alpha_damaged];
return ClassData[index][Class_AlphaDamaged];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_alpha_damaged];
return ClassDataCache[index][Class_AlphaDamaged];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_alpha_damaged];
return ClassPlayerCache[index][Class_AlphaDamaged];
}
}
return -1;
@ -396,15 +431,15 @@ stock ClassGetAlphaDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_alpha_damage];
return ClassData[index][Class_AlphaDamage];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_alpha_damage];
return ClassDataCache[index][Class_AlphaDamage];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_alpha_damage];
return ClassPlayerCache[index][Class_AlphaDamage];
}
}
return -1;
@ -440,15 +475,15 @@ stock ClassGetOverlayPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_C
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return strcopy(buffer, maxlen, ClassData[index][class_overlay_path]);
return strcopy(buffer, maxlen, ClassData[index][Class_OverlayPath]);
}
case ZR_CLASS_CACHE_MODIFIED:
{
return strcopy(buffer, maxlen, ClassDataCache[index][class_overlay_path]);
return strcopy(buffer, maxlen, ClassDataCache[index][Class_OverlayPath]);
}
case ZR_CLASS_CACHE_PLAYER:
{
return strcopy(buffer, maxlen, ClassPlayerCache[index][class_overlay_path]);
return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_OverlayPath]);
}
}
return -1;
@ -472,15 +507,15 @@ stock bool:ClassGetNvgs(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_nvgs];
return ClassData[index][Class_Nvgs];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_nvgs];
return ClassDataCache[index][Class_Nvgs];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_nvgs];
return ClassPlayerCache[index][Class_Nvgs];
}
}
return false;
@ -504,15 +539,15 @@ stock ClassGetFOV(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_fov];
return ClassData[index][Class_Fov];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_fov];
return ClassDataCache[index][Class_Fov];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_fov];
return ClassPlayerCache[index][Class_Fov];
}
}
return -1;
@ -546,15 +581,15 @@ stock bool:ClassGetHasNapalm(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_has_napalm];
return ClassData[index][Class_HasNapalm];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_has_napalm];
return ClassDataCache[index][Class_HasNapalm];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_has_napalm];
return ClassPlayerCache[index][Class_HasNapalm];
}
}
return false;
@ -580,15 +615,15 @@ stock Float:ClassGetNapalmTime(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_napalm_time];
return ClassData[index][Class_NapalmTime];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_napalm_time];
return ClassDataCache[index][Class_NapalmTime];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_napalm_time] * ClassGetAttributeMultiplier(index, ClassM_NapalmTime);
return ClassPlayerCache[index][Class_NapalmTime] * ClassGetAttributeMultiplier(index, ClassM_NapalmTime);
}
}
return -1.0;
@ -622,15 +657,15 @@ stock ClassGetImmunityMode(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_immunity_mode];
return ClassData[index][Class_ImmunityMode];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_immunity_mode];
return ClassDataCache[index][Class_ImmunityMode];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_immunity_mode];
return ClassPlayerCache[index][Class_ImmunityMode];
}
}
return -1;
@ -654,15 +689,15 @@ stock Float:ClassGetImmunityAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_immunity_amount];
return ClassData[index][Class_ImmunityAmount];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_immunity_amount];
return ClassDataCache[index][Class_ImmunityAmount];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_immunity_amount];
return ClassPlayerCache[index][Class_ImmunityAmount];
}
}
return -1.0;
@ -687,15 +722,15 @@ stock bool:ClassGetNoFallDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_no_fall_damage];
return ClassData[index][Class_NoFallDamage];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_no_fall_damage];
return ClassDataCache[index][Class_NoFallDamage];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_no_fall_damage];
return ClassPlayerCache[index][Class_NoFallDamage];
}
}
return false;
@ -721,15 +756,15 @@ stock ClassGetHealth(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_health];
return ClassData[index][Class_Health];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_health];
return ClassDataCache[index][Class_Health];
}
case ZR_CLASS_CACHE_PLAYER:
{
return RoundToCeil(ClassPlayerCache[index][class_health] * ClassGetAttributeMultiplier(index, ClassM_Health));
return RoundToCeil(ClassPlayerCache[index][Class_Health] * ClassGetAttributeMultiplier(index, ClassM_Health));
}
}
return -1;
@ -756,15 +791,15 @@ stock Float:ClassGetHealthRegenInterval(index, cachetype = ZR_CLASS_CACHE_PLAYER
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_health_regen_interval];
return ClassData[index][Class_HealthRegenInterval];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_health_regen_interval];
return ClassDataCache[index][Class_HealthRegenInterval];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_health_regen_interval] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenInterval);
return ClassPlayerCache[index][Class_HealthRegenInterval] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenInterval);
}
}
return -1.0;
@ -791,15 +826,15 @@ stock ClassGetHealthRegenAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_health_regen_amount];
return ClassData[index][Class_HealthRegenAmount];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_health_regen_amount];
return ClassDataCache[index][Class_HealthRegenAmount];
}
case ZR_CLASS_CACHE_PLAYER:
{
return RoundToCeil(ClassPlayerCache[index][class_health_regen_amount] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenAmount));
return RoundToCeil(ClassPlayerCache[index][Class_HealthRegenAmount] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenAmount));
}
}
return -1;
@ -826,15 +861,15 @@ stock ClassGetHealthInfectGain(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_health_infect_gain];
return ClassData[index][Class_HealthInfectGain];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_health_infect_gain];
return ClassDataCache[index][Class_HealthInfectGain];
}
case ZR_CLASS_CACHE_PLAYER:
{
return RoundToCeil(ClassPlayerCache[index][class_health_infect_gain] * ClassGetAttributeMultiplier(index, ClassM_HealthInfectGain));
return RoundToCeil(ClassPlayerCache[index][Class_HealthInfectGain] * ClassGetAttributeMultiplier(index, ClassM_HealthInfectGain));
}
}
return -1;
@ -858,15 +893,15 @@ stock ClassGetKillBonus(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_kill_bonus];
return ClassData[index][Class_KillBonus];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_kill_bonus];
return ClassDataCache[index][Class_KillBonus];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_kill_bonus];
return ClassPlayerCache[index][Class_KillBonus];
}
}
return -1;
@ -892,15 +927,15 @@ stock Float:ClassGetSpeed(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_speed];
return ClassData[index][Class_Speed];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_speed];
return ClassDataCache[index][Class_Speed];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_speed] * ClassGetAttributeMultiplier(index, ClassM_Speed);
return ClassPlayerCache[index][Class_Speed] * ClassGetAttributeMultiplier(index, ClassM_Speed);
}
}
return -1.0;
@ -926,15 +961,15 @@ stock Float:ClassGetKnockback(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_knockback];
return ClassData[index][Class_KnockBack];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_knockback];
return ClassDataCache[index][Class_KnockBack];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_knockback] * ClassGetAttributeMultiplier(index, ClassM_Knockback);
return ClassPlayerCache[index][Class_KnockBack] * ClassGetAttributeMultiplier(index, ClassM_Knockback);
}
}
return 0.0;
@ -960,15 +995,15 @@ stock Float:ClassGetJumpHeight(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_jump_height];
return ClassData[index][Class_JumpHeight];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_jump_height];
return ClassDataCache[index][Class_JumpHeight];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_jump_height] * ClassGetAttributeMultiplier(index, ClassM_JumpHeight);
return ClassPlayerCache[index][Class_JumpHeight] * ClassGetAttributeMultiplier(index, ClassM_JumpHeight);
}
}
return -1.0;
@ -994,15 +1029,15 @@ stock Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
return ClassData[index][class_jump_distance];
return ClassData[index][Class_JumpDistance];
}
case ZR_CLASS_CACHE_MODIFIED:
{
return ClassDataCache[index][class_jump_distance];
return ClassDataCache[index][Class_JumpDistance];
}
case ZR_CLASS_CACHE_PLAYER:
{
return ClassPlayerCache[index][class_jump_distance] * ClassGetAttributeMultiplier(index, ClassM_JumpDistance);
return ClassPlayerCache[index][Class_JumpDistance] * ClassGetAttributeMultiplier(index, ClassM_JumpDistance);
}
}
return -1.0;
@ -1034,6 +1069,10 @@ stock ClassAttributeNameToFlag(const String:attributename[])
{
return ZR_CLASS_FLAGS;
}
else if (StrEqual(attributename, "group", false))
{
return ZR_CLASS_GROUP;
}
else if (StrEqual(attributename, "name", false))
{
return ZR_CLASS_NAME;
@ -1230,7 +1269,8 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag)
}
// String.
case ZR_CLASS_NAME,
case ZR_CLASS_GROUP,
ZR_CLASS_NAME,
ZR_CLASS_DESCRIPTION,
ZR_CLASS_MODEL_PATH,
ZR_CLASS_OVERLAY_PATH:

View File

@ -59,7 +59,14 @@ public Action:ZClassCommand(client, argc)
// If client is console, then stop and tell them this feature is for players only.
if (ZRIsConsole(client))
{
TranslationPrintToServer("Must be player");
TranslationReplyToCommand(client, "Must be player");
return Plugin_Handled;
}
// Check if class selection is allowed.
if (!ClassAllowSelection(client))
{
TranslationReplyToCommand(client, "Classes Selection Not Allowed");
return Plugin_Handled;
}
@ -612,22 +619,22 @@ stock bool:ClassModifyBoolean(classindex, attributeflag, bool:value)
{
case ZR_CLASS_ENABLED:
{
ClassDataCache[classindex][class_enabled] = bool:value;
ClassDataCache[classindex][Class_Enabled] = bool:value;
return true;
}
case ZR_CLASS_NVGS:
{
ClassDataCache[classindex][class_nvgs] = bool:value;
ClassDataCache[classindex][Class_Nvgs] = bool:value;
return true;
}
case ZR_CLASS_NO_FALL_DAMAGE:
{
ClassDataCache[classindex][class_no_fall_damage] = bool:value;
ClassDataCache[classindex][Class_NoFallDamage] = bool:value;
return true;
}
case ZR_CLASS_HAS_NAPALM:
{
ClassDataCache[classindex][class_has_napalm] = bool:value;
ClassDataCache[classindex][Class_HasNapalm] = bool:value;
return true;
}
}
@ -663,80 +670,80 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.
{
case ZR_CLASS_FLAGS:
{
ClassDataCache[classindex][class_flags] = value;
ClassDataCache[classindex][Class_Flags] = value;
return true;
}
case ZR_CLASS_ALPHA_INITIAL:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_initial]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_AlphaInitial]) * multiplier);
}
ClassDataCache[classindex][class_alpha_initial] = value;
ClassDataCache[classindex][Class_AlphaInitial] = value;
return true;
}
case ZR_CLASS_ALPHA_DAMAGED:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_damaged]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_AlphaDamaged]) * multiplier);
}
ClassDataCache[classindex][class_alpha_damaged] = value;
ClassDataCache[classindex][Class_AlphaDamaged] = value;
return true;
}
case ZR_CLASS_ALPHA_DAMAGE:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_damage]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_AlphaDamage]) * multiplier);
}
ClassDataCache[classindex][class_alpha_damage] = value;
ClassDataCache[classindex][Class_AlphaDamage] = value;
return true;
}
case ZR_CLASS_FOV:
{
ClassDataCache[classindex][class_fov] = value;
ClassDataCache[classindex][Class_Fov] = value;
return true;
}
case ZR_CLASS_IMMUNITY_MODE:
{
ClassDataCache[classindex][class_fov] = value;
ClassDataCache[classindex][Class_ImmunityMode] = value;
return true;
}
case ZR_CLASS_HEALTH:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_Health]) * multiplier);
}
ClassDataCache[classindex][class_health] = value;
ClassDataCache[classindex][Class_Health] = value;
return true;
}
case ZR_CLASS_HEALTH_REGEN_AMOUNT:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health_regen_amount]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_HealthRegenAmount]) * multiplier);
}
ClassDataCache[classindex][class_health_regen_amount] = value;
ClassDataCache[classindex][Class_HealthRegenAmount] = value;
return true;
}
case ZR_CLASS_HEALTH_INFECT_GAIN:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health_infect_gain]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_HealthInfectGain]) * multiplier);
}
ClassDataCache[classindex][class_health_infect_gain] = value;
ClassDataCache[classindex][Class_HealthInfectGain] = value;
return true;
}
case ZR_CLASS_KILL_BONUS:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_kill_bonus]) * multiplier);
value = RoundToNearest(float(ClassData[classindex][Class_KillBonus]) * multiplier);
}
ClassDataCache[classindex][class_kill_bonus] = value;
ClassDataCache[classindex][Class_KillBonus] = value;
return true;
}
}
@ -770,63 +777,63 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier
{
if (ismultiplier)
{
value = ClassData[classindex][class_napalm_time] * value;
value = ClassData[classindex][Class_NapalmTime] * value;
}
ClassDataCache[classindex][class_napalm_time] = value;
ClassDataCache[classindex][Class_NapalmTime] = value;
return true;
}
case ZR_CLASS_IMMUNITY_AMOUNT:
{
if (ismultiplier)
{
value = ClassData[classindex][class_immunity_amount] * value;
value = ClassData[classindex][Class_ImmunityAmount] * value;
}
ClassDataCache[classindex][class_immunity_amount] = value;
ClassDataCache[classindex][Class_ImmunityAmount] = value;
return true;
}
case ZR_CLASS_HEALTH_REGEN_INTERVAL:
{
if (ismultiplier)
{
value = ClassData[classindex][class_health_regen_interval] * value;
value = ClassData[classindex][Class_HealthRegenInterval] * value;
}
ClassDataCache[classindex][class_health_regen_interval] = value;
ClassDataCache[classindex][Class_HealthRegenInterval] = value;
return true;
}
case ZR_CLASS_SPEED:
{
if (ismultiplier)
{
value = ClassData[classindex][class_speed] * value;
value = ClassData[classindex][Class_Speed] * value;
}
ClassDataCache[classindex][class_speed] = value;
ClassDataCache[classindex][Class_Speed] = value;
return true;
}
case ZR_CLASS_KNOCKBACK:
{
if (ismultiplier)
{
value = ClassData[classindex][class_knockback] * value;
value = ClassData[classindex][Class_KnockBack] * value;
}
ClassDataCache[classindex][class_knockback] = value;
ClassDataCache[classindex][Class_KnockBack] = value;
return true;
}
case ZR_CLASS_JUMP_HEIGHT:
{
if (ismultiplier)
{
value = ClassData[classindex][class_jump_height] * value;
value = ClassData[classindex][Class_JumpHeight] * value;
}
ClassDataCache[classindex][class_jump_height] = value;
ClassDataCache[classindex][Class_JumpHeight] = value;
return true;
}
case ZR_CLASS_JUMP_DISTANCE:
{
if (ismultiplier)
{
value = ClassData[classindex][class_jump_distance] * value;
value = ClassData[classindex][Class_JumpDistance] * value;
}
ClassDataCache[classindex][class_jump_distance] = value;
ClassDataCache[classindex][Class_JumpDistance] = value;
return true;
}
}
@ -853,24 +860,29 @@ stock ClassModifyString(classindex, attributeflag, const String:value[])
switch (attributeflag)
{
case ZR_CLASS_GROUP:
{
strcopy(ClassDataCache[classindex][Class_Group], 64, value);
return true;
}
case ZR_CLASS_NAME:
{
strcopy(ClassDataCache[classindex][class_name], 64, value);
strcopy(ClassDataCache[classindex][Class_Name], 64, value);
return true;
}
case ZR_CLASS_DESCRIPTION:
{
strcopy(ClassDataCache[classindex][class_description], 256, value);
strcopy(ClassDataCache[classindex][Class_Description], 256, value);
return true;
}
case ZR_CLASS_MODEL_PATH:
{
strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, value);
strcopy(ClassDataCache[classindex][Class_ModelPath], PLATFORM_MAX_PATH, value);
return true;
}
case ZR_CLASS_OVERLAY_PATH:
{
strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, value);
strcopy(ClassDataCache[classindex][Class_OverlayPath], PLATFORM_MAX_PATH, value);
return true;
}
}

View File

@ -24,6 +24,11 @@ ClassOnCookiesCreate()
{
// Forward event to sub-modules.
ClassOverlayOnCookiesCreate();
// Create class index cookies.
g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS] = RegClientCookie("zr_humanclass", "The last human class selected.", CookieAccess_Protected);
g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES] = RegClientCookie("zr_zombieclass", "The last zombie class selected.", CookieAccess_Protected);
g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS] = RegClientCookie("zr_adminclass", "The last admin mode class selected.", CookieAccess_Protected);
}
/**
@ -75,6 +80,7 @@ ClassOnClientSpawn(client)
decl String:originalmodel[PLATFORM_MAX_PATH];
decl String:steamid[16];
decl String:classname[64];
new filter[ClassFilter];
// Check if the player is dead. Spawning into the game is also a event in
// the connection process.
@ -121,15 +127,24 @@ ClassOnClientSpawn(client)
// Assign random classes if enabled. Always do it for bots.
if (randomclass || StrEqual(steamid, "BOT"))
{
// Exclude special class flags like mother zombies and admin classes.
new denyflags = ZR_CLASS_SPECIALFLAGS;
// Setup filtering
// ---------------
// Exclude special class flags like mother zombies and admin classes.
filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS;
// Allow admin classes if admin.
denyflags -= ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0;
filter[ClassFilter_DenyFlags] -= ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0;
// Specify client for checking group permissions.
filter[ClassFilter_Client] = client;
// Get classes
// -----------
// Get random classes for each type.
new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, denyflags);
new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, _, _, denyflags);
new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter);
new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, filter);
// Set selected zombie class index.
ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie;
@ -141,11 +156,34 @@ ClassOnClientSpawn(client)
ClassGetName(randomhuman, classname, sizeof(classname), ZR_CLASS_TEAM_HUMANS);
TranslationPrintToChat(client, "Classes random assignment", classname);
}
// Display class menu if enabled.
new bool:classmenu = GetConVarBool(g_hCvarsList[CVAR_CLASSES_SPAWN]);
if (classmenu)
{
ClassMenuMain(client);
}
}
// Apply class attributes for the active class.
ClassReloadPlayerCache(client, ClassGetActiveIndex(client));
ClassApplyAttributes(client);
// Check if instant class change cvar is set.
new Float:instantspawn = GetConVarFloat(g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT]);
if (instantspawn > 0)
{
// Allow instant class change.
ClassAllowInstantChange[client] = true;
// Create timer to disable instant change.
CreateTimer(instantspawn, Event_ClassDisableInstantSpawn, client, TIMER_FLAG_NO_MAPCHANGE);
}
else
{
// Make sure instant change is not allowed.
ClassAllowInstantChange[client] = false;
}
}
/**
@ -176,12 +214,16 @@ ClassOnClientInfected(client, bool:motherzombie = false)
new classindex = ClassGetActiveIndex(client);
new isadmin;
new motherindex;
new filter[ClassFilter];
decl String:motherzombiesetting[64];
// Disable class attributes with timers.
ClassHealthRegenStop(client);
// Make sure the player is not allowed to instantly change class.
ClassAllowInstantChange[client] = false;
// Check if it's a mother zombie.
if (motherzombie)
{
@ -198,8 +240,23 @@ ClassOnClientInfected(client, bool:motherzombie = false)
}
else if (StrEqual(motherzombiesetting, "random", false))
{
// Setup filtering
// ---------------
// Exclude special class flags.
filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS;
// Allow admin classes if admin.
filter[ClassFilter_DenyFlags] -= isadmin;
// Specify client for checking group permissions.
filter[ClassFilter_Client] = client;
// Get class
// ---------
// Get random regular zombie class. Remove admin flag if admin.
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS - isadmin);
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter);
// Validate index. Do not change class if it's invalid.
if (ClassValidateIndex(motherindex))
@ -213,8 +270,26 @@ ClassOnClientInfected(client, bool:motherzombie = false)
}
else if (StrEqual(motherzombiesetting, "motherzombies", false))
{
// Setup filtering
// ---------------
// Exclude special class flags except mother zombies.
filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS - ZR_CLASS_FLAG_MOTHER_ZOMBIE;
// Require mother zombie class flag.
filter[ClassFilter_RequireFlags] = ZR_CLASS_FLAG_MOTHER_ZOMBIE;
// Allow admin classes if admin.
filter[ClassFilter_DenyFlags] -= isadmin;
// Specify client for checking group permissions.
filter[ClassFilter_Client] = client;
// Get class
// ---------
// Get random mother zombie class. Include admin classes if admin.
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, ZR_CLASS_FLAG_MOTHER_ZOMBIE + isadmin, ZR_CLASS_FLAG_ADMIN_ONLY - isadmin);
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter);
// Validate index. Do not change class if it's invalid.
if (ClassValidateIndex(motherindex))
@ -259,3 +334,12 @@ ClassOnClientInfected(client, bool:motherzombie = false)
// Apply the new attributes.
ClassApplyAttributes(client, motherzombie);
}
/**
* Timer callback for disabling instant class change setting on a client.
*/
public Action:Event_ClassDisableInstantSpawn(Handle:timer, any:client)
{
// Disable instant class change.
ClassAllowInstantChange[client] = false;
}

View File

@ -65,18 +65,19 @@ ClassMenuMain(client)
// Get number of enabled classes per team.
new zombiecount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES);
new humancount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES);
new admincount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES);
new admincount = ClassCountTeam(ZR_CLASS_TEAM_ADMINS);
// Get previously selected class indexes, if set.
// Get next class indexes, if set.
new nextzombie = ClassSelectedNext[client][ZR_CLASS_TEAM_ZOMBIES];
new nexthuman = ClassSelectedNext[client][ZR_CLASS_TEAM_HUMANS];
new nextadmin = ClassSelectedNext[client][ZR_CLASS_TEAM_ADMINS];
// Set draw style on class options depending on number of enabled classes.
// Disable class selection if there's only one class.
new zombie_itemdraw = (zombiecount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
new human_itemdraw = (humancount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
new admin_itemdraw = (admincount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
// Set draw style on class options depending on number of enabled classes
// and selection permissions. Disable class selection if there's only one
// class.
new zombie_itemdraw = (zombiecount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_ZOMBIES)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
new human_itemdraw = (humancount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_HUMANS)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
new admin_itemdraw = (admincount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_ADMINS)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
// Check if the player is in admin mode.
if (ClassPlayerInAdminMode[client])
@ -92,18 +93,18 @@ ClassMenuMain(client)
// Get current class name.
ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES], zombieclass, sizeof(zombieclass), ZR_CLASS_CACHE_MODIFIED);
// Check if previous index is set.
// Check if next index is set.
if (ClassValidateIndex(nextzombie))
{
// Get name of previous class index and format item text.
ClassGetName(nextzombie, nextzombiename, sizeof(nextzombiename), ZR_CLASS_CACHE_MODIFIED);
Format(zombieselect, sizeof(zombieselect), "%t", "Classes menu zombie next", zombieclass, nextzombiename);
Format(zombieselect, sizeof(zombieselect), "%t\n %t\n %t", "Classes menu select zombie", "Classes menu active", zombieclass, "Classes menu next", nextzombiename);
}
else
{
// Use current class name and format item text.
Format(zombieselect, sizeof(zombieselect), "%t", "Classes menu zombie current", zombieclass);
Format(zombieselect, sizeof(zombieselect), "%t\n %s", "Classes menu select zombie", zombieclass);
}
// Add item to list.
@ -116,18 +117,18 @@ ClassMenuMain(client)
// Get current class name.
ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_HUMANS], humanclass, sizeof(humanclass), ZR_CLASS_CACHE_MODIFIED);
// Check if previous index is set.
// Check if next index is set.
if (ClassValidateIndex(nexthuman))
{
// Get name of previous class index and format item text.
ClassGetName(nexthuman, nexthumanname, sizeof(nexthumanname), ZR_CLASS_CACHE_MODIFIED);
Format(humanselect, sizeof(humanselect), "%t", "Classes menu human next", humanclass, nexthumanname);
Format(humanselect, sizeof(humanselect), "%t\n %t\n %t", "Classes menu select human", "Classes menu active", humanclass, "Classes menu next", nexthumanname);
}
else
{
// Use current class name and format item text.
Format(humanselect, sizeof(humanselect), "%t", "Classes menu human current", humanclass);
Format(humanselect, sizeof(humanselect), "%t\n %s", "Classes menu select human", humanclass);
}
// Add item to list.
@ -143,17 +144,17 @@ ClassMenuMain(client)
// Get current class name.
ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ADMINS], adminclass, sizeof(adminclass), ZR_CLASS_CACHE_MODIFIED);
// Check if previous index is set.
// Check if next index is set.
if (ClassValidateIndex(nextadmin))
{
// Get name of previous class index and format item text.
ClassGetName(nextadmin, nextadminname, sizeof(nextadminname), ZR_CLASS_CACHE_MODIFIED);
Format(adminselect, sizeof(adminselect), "%t", "Classes menu admin next", adminclass, nextadminname);
Format(adminselect, sizeof(adminselect), "%t\n %t\n %t", "Classes menu select admin", "Classes menu active", adminclass, "Classes menu next", nextadminname);
}
else
{
// Use current class name and format item text.
Format(adminselect, sizeof(adminselect), "%t", "Classes menu admin current", adminclass);
Format(adminselect, sizeof(adminselect), "%t\n %s", "Classes menu select admin", adminclass);
}
// Add item to list.
@ -246,7 +247,6 @@ ClassMenuSelect(client, teamid)
new Handle:menu = CreateMenu(ClassMenuSelectHandle);
new arraycount;
new classindex;
new denyflags;
decl String:title[MENU_LINE_TITLE_LENGTH];
decl String:classname[MENU_LINE_REG_LENGTH];
@ -260,15 +260,15 @@ ClassMenuSelect(client, teamid)
{
case ZR_CLASS_TEAM_ZOMBIES:
{
Format(title, sizeof(title), "%t\n", "Classes menu zombie");
Format(title, sizeof(title), "%t:\n", "Classes menu select zombie");
}
case ZR_CLASS_TEAM_HUMANS:
{
Format(title, sizeof(title), "%t\n", "Classes menu human");
Format(title, sizeof(title), "%t:\n", "Classes menu select human");
}
case ZR_CLASS_TEAM_ADMINS:
{
Format(title, sizeof(title), "%t\n", "Classes menu admin");
Format(title, sizeof(title), "%t:\n", "Classes menu select admin");
}
}
SetMenuTitle(menu, title);
@ -276,12 +276,24 @@ ClassMenuSelect(client, teamid)
// Create buffer array.
new Handle:classarray = CreateArray();
// Set up filtering.
denyflags = ZR_CLASS_FLAG_MOTHER_ZOMBIE; // Hide mother zombie classes.
denyflags += !ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; // Hide admin-only classes if not admin.
// Set up filtering
// ----------------
new filter[ClassFilter];
// Hide mother zombie classes.
filter[ClassFilter_DenyFlags] = ZR_CLASS_FLAG_MOTHER_ZOMBIE;
// Hide admin-only classes if not admin.
filter[ClassFilter_DenyFlags] += !ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0;
// Specify client for checking class group permissions.
filter[ClassFilter_Client] = client;
// Get classes
// -----------
// Copy all class indexes into the array, with the specified filter settings.
if (ClassAddToArray(classarray, teamid, _, _, denyflags))
if (ClassAddToArray(classarray, teamid, filter))
{
// Get number of classes.
arraycount = GetArraySize(classarray);
@ -331,28 +343,57 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot)
// Solve teamid from the class index.
teamid = ClassGetTeamID(classindex, ZR_CLASS_CACHE_MODIFIED);
// Check if the player is alive.
if (IsPlayerAlive(client))
// Allow instant class change if enabled and both class and player is human.
if (ClassAllowInstantChange[client] && !iszombie && teamid == ZR_CLASS_TEAM_HUMANS)
{
// Set next spawn index if the player is changing the class on
// his active team.
if ((iszombie && teamid == ZR_CLASS_TEAM_ZOMBIES) ||
(!iszombie && teamid == ZR_CLASS_TEAM_HUMANS) ||
(ClassPlayerInAdminMode[client] && teamid == ZR_CLASS_TEAM_ADMINS))
{
// Set class to be used on next spawn.
ClassSelectedNext[client][teamid] = classindex;
}
else
{
// Directly change the selected class index.
ClassSelected[client][teamid] = classindex;
}
// Directly change the selected class index.
ClassSelected[client][teamid] = classindex;
// Update cache and apply attributes.
ClassReloadPlayerCache(client, classindex);
ClassApplyAttributes(client);
}
else
{
// Player isn't alive. The class can be directly changed.
ClassSelected[client][teamid] = classindex;
// Check if the player is alive.
if (IsPlayerAlive(client))
{
// Set next spawn index if the player is changing the class on
// his active team.
if ((iszombie && teamid == ZR_CLASS_TEAM_ZOMBIES) ||
(!iszombie && teamid == ZR_CLASS_TEAM_HUMANS) ||
(ClassPlayerInAdminMode[client] && teamid == ZR_CLASS_TEAM_ADMINS))
{
// Check if player selected the same class that he already is.
if (ClassSelected[client][teamid] == classindex)
{
// Player is already the specified class. Disable
// next class for the specified team.
ClassSelectedNext[client][teamid] = -1;
}
else
{
// Set class to be used on next spawn.
ClassSelectedNext[client][teamid] = classindex;
}
}
else
{
// Directly change the selected class index.
ClassSelected[client][teamid] = classindex;
}
}
else
{
// Player isn't alive. The class can be directly changed.
ClassSelected[client][teamid] = classindex;
}
// Save selected class index in cookie if enabled.
if (GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE]))
{
CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classindex + 1);
}
}
}
case MenuAction_Cancel:
@ -395,15 +436,9 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot)
* @return True if displayed, false otherwise.
*/
bool:ClassTeamSelect(client)
{
// Validate client.
if (!ZRIsClientValid(client, false))
{
return false;
}
{
// Validate permissions.
if (!ZRIsClientAdmin(client, Admin_Config))
if (!ZRIsClientPrivileged(client, OperationType_Configuration))
{
return false;
}

View File

@ -47,8 +47,8 @@ stock bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL)
}
// Test if a zombie and human class was found.
zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS, cachetype);
humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, _, ZR_CLASS_SPECIALFLAGS, cachetype);
zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype);
humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, cachetype);
// Validate indexes.
if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex))
@ -79,8 +79,8 @@ stock bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL)
}
// Test if a default zombie and human class was found.
zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, _, _, cachetype);
humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, _, _, cachetype);
zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype);
humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, cachetype);
// Validate indexes.
if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex))
@ -107,26 +107,36 @@ stock ClassValidateAttributes(classindex)
new flags;
// Team.
if (ClassData[classindex][class_team] < ZR_CLASS_TEAM_MIN || ClassData[classindex][class_team] > ZR_CLASS_TEAM_MAX)
if (ClassData[classindex][Class_Team] < ZR_CLASS_TEAM_MIN || ClassData[classindex][Class_Team] > ZR_CLASS_TEAM_MAX)
{
flags += ZR_CLASS_TEAM;
}
// Class flags.
if (ClassData[classindex][class_flags] < ZR_CLASS_FLAGS_MIN || ClassData[classindex][class_flags] > ZR_CLASS_FLAGS_MAX)
if (ClassData[classindex][Class_Flags] < ZR_CLASS_FLAGS_MIN || ClassData[classindex][Class_Flags] > ZR_CLASS_FLAGS_MAX)
{
flags += ZR_CLASS_FLAGS;
}
// Group.
if (strlen(ClassData[classindex][Class_Group]))
{
// Check if the group exist.
if (FindAdmGroup(ClassData[classindex][Class_Group]) == INVALID_GROUP_ID)
{
flags += ZR_CLASS_GROUP;
}
}
// Name.
if (strlen(ClassData[classindex][class_name]) < ZR_CLASS_NAME_MIN)
if (strlen(ClassData[classindex][Class_Name]) < ZR_CLASS_NAME_MIN)
{
flags += ZR_CLASS_NAME;
}
else
{
decl String:name[64];
strcopy(name, sizeof(name), ClassData[classindex][class_name]);
strcopy(name, sizeof(name), ClassData[classindex][Class_Name]);
// Check for reserved name keyworks. These aren't allowed as names.
if (StrEqual(name, "all", false) ||
@ -139,21 +149,23 @@ stock ClassValidateAttributes(classindex)
}
// Description.
if (strlen(ClassData[classindex][class_description]) < ZR_CLASS_DESCRIPTION_MIN)
if (strlen(ClassData[classindex][Class_Description]) < ZR_CLASS_DESCRIPTION_MIN)
{
flags += ZR_CLASS_DESCRIPTION;
}
// Model path.
decl String:model_path[PLATFORM_MAX_PATH];
if (strcopy(model_path, sizeof(model_path), ClassData[classindex][class_model_path]) == 0)
if (strcopy(model_path, sizeof(model_path), ClassData[classindex][Class_ModelPath]) == 0)
{
flags += ZR_CLASS_MODEL_PATH;
}
else
{
// Check if a model different from default or random is specified.
if (!StrEqual(model_path, "random", false) && !StrEqual(model_path, "default", false))
// Check if a model different from a pre-defined setting.
if (!StrEqual(model_path, "random", false) &&
!StrEqual(model_path, "default", false) &&
!StrEqual(model_path, "nochange", false))
{
// Check if the file exists.
if (!FileExists(model_path))
@ -164,21 +176,21 @@ stock ClassValidateAttributes(classindex)
}
// Alpha, initial.
new alpha_initial = ClassData[classindex][class_alpha_initial];
new alpha_initial = ClassData[classindex][Class_AlphaInitial];
if (!(alpha_initial >= ZR_CLASS_ALPHA_INITIAL_MIN && alpha_initial <= ZR_CLASS_ALPHA_INITIAL_MAX))
{
flags += ZR_CLASS_ALPHA_INITIAL;
}
// Alpha, damaged.
new alpha_damaged = ClassData[classindex][class_alpha_damaged];
new alpha_damaged = ClassData[classindex][Class_AlphaDamaged];
if (!(alpha_damaged >= ZR_CLASS_ALPHA_DAMAGED_MIN && alpha_damaged <= ZR_CLASS_ALPHA_DAMAGED_MAX))
{
flags += ZR_CLASS_ALPHA_DAMAGED;
}
// Alpha, damage.
new alpha_damage = ClassData[classindex][class_alpha_damage];
new alpha_damage = ClassData[classindex][Class_AlphaDamage];
if (!(alpha_damage >= ZR_CLASS_ALPHA_DAMAGE_MIN && alpha_damage <= ZR_CLASS_ALPHA_DAMAGE_MAX))
{
flags += ZR_CLASS_ALPHA_DAMAGE;
@ -187,7 +199,7 @@ stock ClassValidateAttributes(classindex)
// Overlay path.
decl String:overlay_path[PLATFORM_MAX_PATH];
decl String:overlay[PLATFORM_MAX_PATH];
if (strcopy(overlay_path, sizeof(overlay_path), ClassData[classindex][class_overlay_path]) > 0)
if (strcopy(overlay_path, sizeof(overlay_path), ClassData[classindex][Class_OverlayPath]) > 0)
{
// Check if the file exists.
Format(overlay, sizeof(overlay), "materials/%s.vmt", overlay_path);
@ -198,77 +210,80 @@ stock ClassValidateAttributes(classindex)
}
// Field of view.
new fov = ClassData[classindex][class_fov];
new fov = ClassData[classindex][Class_Fov];
if (!(fov >= ZR_CLASS_FOV_MIN && fov <= ZR_CLASS_FOV_MAX))
{
flags += ZR_CLASS_FOV;
}
// Napalm time.
new Float:napalm_time = ClassData[classindex][class_napalm_time];
new Float:napalm_time = ClassData[classindex][Class_NapalmTime];
if (!(napalm_time >= ZR_CLASS_NAPALM_TIME_MIN && napalm_time <= ZR_CLASS_NAPALM_TIME_MAX))
{
flags += ZR_CLASS_NAPALM_TIME;
}
// Immunity mode (not implemented).
// Health.
new health = ClassData[classindex][class_health];
new health = ClassData[classindex][Class_Health];
if (!(health >= ZR_CLASS_HEALTH_MIN && health <= ZR_CLASS_HEALTH_MAX))
{
flags += ZR_CLASS_HEALTH;
}
// Health regen interval.
new Float:regen_interval = ClassData[classindex][class_health_regen_interval];
new Float:regen_interval = ClassData[classindex][Class_HealthRegenInterval];
if (!(regen_interval >= ZR_CLASS_REGEN_INTERVAL_MIN && regen_interval <= ZR_CLASS_REGEN_INTERVAL_MAX))
{
flags += ZR_CLASS_HEALTH_REGEN_INTERVAL;
}
// Health regen amount.
new regen_amount = ClassData[classindex][class_health_regen_amount];
new regen_amount = ClassData[classindex][Class_HealthRegenAmount];
if (!(regen_amount >= ZR_CLASS_REGEN_AMOUNT_MIN && regen_amount <= ZR_CLASS_REGEN_AMOUNT_MAX))
{
flags += ZR_CLASS_HEALTH_REGEN_AMOUNT;
}
// Health infect gain.
new infect_gain = ClassData[classindex][class_health_infect_gain];
new infect_gain = ClassData[classindex][Class_HealthInfectGain];
if (!(infect_gain >= ZR_CLASS_HEALTH_INFECT_GAIN_MIN && infect_gain <= ZR_CLASS_HEALTH_INFECT_GAIN_MAX))
{
flags += ZR_CLASS_HEALTH_INFECT_GAIN;
}
// Kill bonus.
new kill_bonus = ClassData[classindex][class_kill_bonus];
new kill_bonus = ClassData[classindex][Class_KillBonus];
if (!(kill_bonus >= ZR_CLASS_KILL_BONUS_MIN && kill_bonus <= ZR_CLASS_KILL_BONUS_MAX))
{
flags += ZR_CLASS_KILL_BONUS;
}
// Speed.
new Float:speed = ClassData[classindex][class_speed];
new Float:speed = ClassData[classindex][Class_Speed];
if (!(speed >= ZR_CLASS_SPEED_MIN && speed <= ZR_CLASS_SPEED_MAX))
{
flags += ZR_CLASS_SPEED;
}
// Knockback.
new Float:knockback = ClassData[classindex][class_knockback];
new Float:knockback = ClassData[classindex][Class_KnockBack];
if (!(knockback >= ZR_CLASS_KNOCKBACK_MIN && knockback <= ZR_CLASS_KNOCKBACK_MAX))
{
flags += ZR_CLASS_KNOCKBACK;
}
// Jump height.
new Float:jump_height = ClassData[classindex][class_jump_height];
new Float:jump_height = ClassData[classindex][Class_JumpHeight];
if (!(jump_height >= ZR_CLASS_JUMP_HEIGHT_MIN && jump_height <= ZR_CLASS_JUMP_HEIGHT_MAX))
{
flags += ZR_CLASS_JUMP_HEIGHT;
}
// Jump distance.
new Float:jump_distance = ClassData[classindex][class_jump_distance];
new Float:jump_distance = ClassData[classindex][Class_JumpDistance];
if (!(jump_distance >= ZR_CLASS_JUMP_DISTANCE_MIN && jump_distance <= ZR_CLASS_JUMP_DISTANCE_MAX))
{
flags += ZR_CLASS_JUMP_DISTANCE;
@ -315,21 +330,21 @@ stock bool:ClassTeamCompare(index, teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
case ZR_CLASS_CACHE_ORIGINAL:
{
if (ClassData[index][class_team] == teamid)
if (ClassData[index][Class_Team] == teamid)
{
return true;
}
}
case ZR_CLASS_CACHE_MODIFIED:
{
if (ClassDataCache[index][class_team] == teamid)
if (ClassDataCache[index][Class_Team] == teamid)
{
return true;
}
}
case ZR_CLASS_CACHE_PLAYER:
{
if (ClassPlayerCache[index][class_team] == teamid)
if (ClassPlayerCache[index][Class_Team] == teamid)
{
return true;
}
@ -448,6 +463,68 @@ stock Float:ClassGetAttributeMultiplier(client, ClassMultipliers:attribute)
}
}
/**
* Check if a class pass the specified filter.
*
* @param index Index of the class in a class cache or a client index,
* depending on the cache type specified.
* @param filter Structure with filter settings.
* @param cachetype Optional. Specifies what class cache to read from.
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
* ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest
* class data.
* ZR_CLASS_CACHE_PLAYER - Player cache. If this one is
* used index will be used as a client index.
* @return True if passed, false otherwise.
*/
stock bool:ClassFilterMatch(index, filter[ClassFilter], cachetype = ZR_CLASS_CACHE_MODIFIED)
{
// Check if the class is disabled and the enabled attribute is NOT ignored.
if (!filter[ClassFilter_IgnoreEnabled] && !ClassIsEnabled(index, cachetype))
{
return false;
}
// Check if class flags pass the flag filter.
if (!ClassFlagFilterMatch(index, filter[ClassFilter_RequireFlags], filter[ClassFilter_DenyFlags], cachetype))
{
return false;
}
// Get class group name.
decl String:groupname[64];
groupname[0] = 0;
ClassGetGroup(index, groupname, sizeof(groupname), cachetype);
// Check if a client is specified in the filter.
new client = filter[ClassFilter_Client];
if (ZRIsClientValid(client))
{
// Check if a group is set on the class.
if (strlen(groupname))
{
// Check if the client is not a member of that group.
if (!ZRIsClientInGroup(client, groupname))
{
return false;
}
}
}
// Check if classes with groups are set to be excluded.
if (client < 0)
{
// Exclude class if it has a group name.
if (strlen(groupname))
{
return false;
}
}
// The class passed the filter.
return true;
}
/**
* Check if a class pass the specified flag filters.
*
@ -515,6 +592,64 @@ stock bool:ClassFlagFilterMatch(index, require, deny, cachetype)
}
}
/**
* Decides whether a class selection menu should be enabled. The decision is
* based on zr_class_allow_* console variables.
*
* @param team Optional. Team ID to match. Default is all.
* @return True if allowed, false otherwise.
*/
bool:ClassAllowSelection(client, team = -1)
{
// Get selection settings.
new bool:zombie = GetConVarBool(g_hCvarsList[CVAR_CLASSES_ZOMBIE_SELECT]);
new bool:human = GetConVarBool(g_hCvarsList[CVAR_CLASSES_HUMAN_SELECT]);
new bool:admin = GetConVarBool(g_hCvarsList[CVAR_CLASSES_ADMIN_SELECT]);
// Since admin mode classes are optional they must be counted to verify
// that they exist.
new bool:adminexist;
// Check if player is admin.
new bool:isadmin = ZRIsClientAdmin(client);
// Only count admin mode classes if client is admin for better performance.
if (isadmin)
{
adminexist = ClassCountTeam(ZR_CLASS_TEAM_ADMINS) > 0;
}
// Check if a team id is specified.
if (team >= 0)
{
// Check team and return the corresponding selection setting.
switch (team)
{
case ZR_CLASS_TEAM_ZOMBIES:
{
return zombie;
}
case ZR_CLASS_TEAM_HUMANS:
{
return human;
}
case ZR_CLASS_TEAM_ADMINS:
{
// Player must be admin to select admin mode classes.
return admin && isadmin && adminexist;
}
}
// Team ID didn't match.
return false;
}
else
{
// Check zombie and human.
return zombie || human;
}
}
/**
* Gets all class indexes or from a specified team, and adds them to the
* specified array.
@ -522,12 +657,7 @@ stock bool:ClassFlagFilterMatch(index, require, deny, cachetype)
* @param array The destination array to add class indexes.
* @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or
* not. Default is false.
* @param requireflags Optional. Require certain class flags to be set.
* Default is no filtering.
* @param denyflags Optional. Require certain class flags to be off.
* Default is no filtering.
* @param filter Optional. Structure with filter settings.
* @param cachetype Optional. Specifies what class cache to read from.
* Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -536,7 +666,7 @@ stock bool:ClassFlagFilterMatch(index, require, deny, cachetype)
* @return True on success. False on error or if no classes were added or
* found.
*/
stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock bool:ClassAddToArray(Handle:array, teamfilter = -1, filter[ClassFilter] = ClassNoFilter, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
// Validate the array.
if (array == INVALID_HANDLE)
@ -551,46 +681,39 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f
}
// Store a local boolean that says if the user specified a team filter or not.
new bool:has_filter = bool:(teamfilter >= 0);
new classes_added;
new bool:hasteamfilter = bool:(teamfilter >= 0);
new classesadded;
// Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++)
{
if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype))
// Validate filter settings.
if (!ClassFilterMatch(classindex, filter, cachetype))
{
// The class is disabled and the enabled attribute is NOT ignored.
// Skip to the next class.
continue;
}
// Check flag filter match.
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
// The class is didn't pass the filter, skip class.
continue;
}
// Check team filtering.
if (has_filter)
if (hasteamfilter)
{
// Only add classes with matching team ID.
if (ClassGetTeamID(classindex, cachetype) == teamfilter)
{
// Team ID match. Add class index to array.
PushArrayCell(array, classindex);
classes_added++;
classesadded++;
}
}
else
{
// No filter. Add any class to the array.
PushArrayCell(array, classindex);
classes_added++;
classesadded++;
}
}
if (classes_added)
if (classesadded)
{
return true;
}
@ -606,12 +729,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f
*
* @param teamfilter Optional. The team ID to filter. Negative value for
* no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or
* not. Default is false.
* @param requireflags Optional. Require certain class flags to be set.
* Default is no filtering.
* @param denyflags Optional. Require certain class flags to be off.
* Default is no filtering.
* @param filter Optional. Structure with filter settings.
* @param cachetype Optional. Specifies what class cache to read from.
* Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -619,7 +737,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f
* class data.
* @return Number of total classes or classes in the specified team.
*/
stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock ClassCountTeam(teamfilter = -1, filter[ClassFilter] = ClassNoFilter, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
// Check if there are no classes.
if (ClassCount == 0)
@ -628,28 +746,21 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags =
}
// Store a local boolean that says if the user specified a team filter or not.
new bool:has_filter = bool:(teamfilter >= 0);
new bool:hasteamfilter = bool:(teamfilter >= 0);
new count;
// Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++)
{
if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype))
// Validate filter settings.
if (!ClassFilterMatch(classindex, filter, cachetype))
{
// The class is disabled and the enabled attribute is NOT ignored.
// Skip to the next class.
continue;
}
// Check flag filter match.
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
// The class is didn't pass the filter, skip class.
continue;
}
// Check team filtering.
if (has_filter)
if (hasteamfilter)
{
// Only add classes with matching team ID.
if (ClassGetTeamID(classindex, cachetype) == teamfilter)
@ -674,12 +785,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags =
*
* @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or
* not. Default is false.
* @param requireflags Optional. Require certain class flags to be set.
* Default is no filtering.
* @param denyflags Optional. Require certain class flags to be off.
* Default is no filtering.
* @param filter Optional. Structure with filter settings.
* @param cachetype Optional. Specifies what class cache to read from.
* Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -687,7 +793,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags =
* class data.
* @return The class index if successful, or -1 on error.
*/
stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock ClassGetRandomClass(teamfilter = -1, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
new Handle:classarray;
new arraycount;
@ -697,7 +803,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl
classarray = CreateArray();
// Try to get a class list.
if (ClassAddToArray(classarray, teamfilter, ignoreEnabled, requireflags, denyflags, cachetype))
if (ClassAddToArray(classarray, teamfilter, filter, cachetype))
{
// Get a random index from the new class array.
arraycount = GetArraySize(classarray);
@ -722,12 +828,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl
*
* @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or
* not. Default is false.
* @param requireflags Optional. Require certain class flags to be set.
* Default is no filtering.
* @param denyflags Optional. Require certain class flags to be off.
* Default is no filtering.
* @param filter Optional. Structure with filter settings.
* @param cachetype Optional. Specifies what class cache to read from.
* Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -736,7 +837,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl
* @return The first class index, or the first class index with the specified
* team ID. -1 on error.
*/
stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock ClassGetFirstClass(teamfilter = -1, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
// Check if there are no classes.
if (ClassCount == 0)
@ -744,26 +845,19 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla
return false;
}
new bool:has_filter = bool:(teamfilter >= 0);
new bool:hasteamfilter = bool:(teamfilter >= 0);
// Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++)
{
if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype))
// Validate filter settings.
if (!ClassFilterMatch(classindex, filter, cachetype))
{
// The class is disabled and the enabled attribute is NOT ignored.
// Skip to the next class.
// The class is didn't pass the filter, skip class.
continue;
}
// Check flag filter match.
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
continue;
}
if (has_filter)
if (hasteamfilter)
{
if (teamfilter == ClassGetTeamID(classindex, cachetype))
{
@ -785,12 +879,8 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla
* Gets the first class marked as default for the specified team.
*
* @param teamid The team ID.
* @param ignoreEnabled Optional. Ignore whether the class is enabled or
* not. Default is false.
* @param requireflags Optional. Require certain class flags to be set.
* Default is no filtering.
* @param denyflags Optional. Require certain class flags to be off.
* Default is to deny classes with special flags
* @param filter Optional. Structure with filter settings. Default
* is to deny classes with special flags
* (ZR_CLASS_SPECIALFLAGS).
* @param cachetype Optional. Specifies what class cache to read from.
* Options:
@ -799,7 +889,7 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla
* class data.
* @return The first default class index. -1 on error.
*/
stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0, denyflags = ZR_CLASS_SPECIALFLAGS, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock ClassGetDefaultClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
new Handle:classarray;
new arraycount;
@ -808,7 +898,7 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0,
classarray = CreateArray();
// Get all classes from the specified team.
if (!ClassAddToArray(classarray, teamid, ignoreEnabled, requireflags, denyflags, cachetype))
if (!ClassAddToArray(classarray, teamid, filter, cachetype))
{
// Failed to get classes.
CloseHandle(classarray);
@ -840,6 +930,8 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0,
* when players join the server.
*
* @param teamid The team ID.
* @param filter Optional. Structure with filter settings. Default is to
* deny classes with special flags (ZR_CLASS_SPECIALFLAGS).
* @param cachetype Optional. Specifies what class cache to read from. Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
* ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest class
@ -848,7 +940,7 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0,
* successful. -1 on critical errors. Otherwise it will try to fall
* back on the first class in the specified team.
*/
stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
stock ClassGetDefaultSpawnClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED)
{
decl String:classname[64];
new classindex;
@ -879,11 +971,11 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
if (strlen(classname) > 0)
{
// Check if the user set "random" as default class.
if (strcmp(classname, "random", false) == 0)
if (StrEqual(classname, "random", false))
{
// Get a list of all classes with the specified team ID. Deny
// classes with special flags.
classindex = ClassGetRandomClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype);
classindex = ClassGetRandomClass(teamid, filter, cachetype);
// Validate the result, in case there were errors.
if (ClassValidateIndex(classindex))
@ -915,7 +1007,7 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
// The class index is invalid or the team IDs didn't match.
// Because it's user input, we'll fall back to the first class
// in the specified team, and log a warning.
classindex = ClassGetFirstClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype);
classindex = ClassGetFirstClass(teamid, filter, cachetype);
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Default Spawn Class", "Warning: Failed to set \"%s\" as default spawn class for team %d. The class doesn't exist or the team IDs doesn't match. Falling back to the first class in the team.", classname, teamid);
@ -928,7 +1020,8 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
}
else
{
// Something went wrong. This is a critical error.
// Something went wrong. This is a critical error. There's
// probably missing classes with no special flags set.
return -1;
}
}
@ -937,6 +1030,6 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
else
{
// Blank class name, get the default class and return the index.
return ClassGetDefaultClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype);
return ClassGetDefaultClass(teamid, filter, cachetype);
}
}

View File

@ -31,7 +31,7 @@
- Zombies have to hurt humans so they loose hp. When the hp reach zero (or
below) they turn into zombies.
- Fully imune to all damage. Can't take or give damage. Sould only be used
on admin classes.
on admin mode classes.
TODO: Make class attributes for for changing model render mode and colors.
@ -100,10 +100,11 @@
* @section Overall default class settings. Since this is a zombie plugin the
* default values represent a zombie.
*/
#define ZR_CLASS_DEFAULT_ENABLED true
#define ZR_CLASS_DEFAULT_ENABLED "yes"
#define ZR_CLASS_DEFAULT_TEAM ZR_CLASS_TEAM_ZOMBIES
#define ZR_CLASS_DEFAULT_TEAM_DEFAULT true
#define ZR_CLASS_DEFAULT_TEAM_DEFAULT "yes"
#define ZR_CLASS_DEFAULT_FLAGS 0
#define ZR_CLASS_DEFAULT_GROUP ""
#define ZR_CLASS_DEFAULT_NAME "classic"
#define ZR_CLASS_DEFAULT_DESCRIPTION "Need brains!!! Arrrrggghh!"
#define ZR_CLASS_DEFAULT_MODEL_PATH "models/player/zh/zh_zombie003.mdl"
@ -111,13 +112,13 @@
#define ZR_CLASS_DEFAULT_ALPHA_DAMAGED 255
#define ZR_CLASS_DEFAULT_ALPHA_DAMAGE 0
#define ZR_CLASS_DEFAULT_OVERLAY_PATH "overlays/zr/zvision"
#define ZR_CLASS_DEFAULT_NVGS true
#define ZR_CLASS_DEFAULT_NVGS "no"
#define ZR_CLASS_DEFAULT_FOV 90
#define ZR_CLASS_DEFAULT_HAS_NAPALM 1
#define ZR_CLASS_DEFAULT_HAS_NAPALM "yes"
#define ZR_CLASS_DEFAULT_NAPALM_TIME 10.0
#define ZR_CLASS_DEFAULT_IMMUNITY_MODE ZR_CLASS_IMMUNITY_DISABLED
#define ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT 0.0
#define ZR_CLASS_DEFAULT_NO_FALL_DAMAGE true
#define ZR_CLASS_DEFAULT_NO_FALL_DAMAGE "on"
#define ZR_CLASS_DEFAULT_HEALTH 6000
#define ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL 0.0
#define ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT 2
@ -181,77 +182,94 @@
#define ZR_CLASS_TEAM (1<<1)
#define ZR_CLASS_TEAM_DEFAULT (1<<2)
#define ZR_CLASS_FLAGS (1<<3)
#define ZR_CLASS_NAME (1<<4)
#define ZR_CLASS_DESCRIPTION (1<<5)
#define ZR_CLASS_MODEL_PATH (1<<6)
#define ZR_CLASS_ALPHA_INITIAL (1<<7)
#define ZR_CLASS_ALPHA_DAMAGED (1<<8)
#define ZR_CLASS_ALPHA_DAMAGE (1<<9)
#define ZR_CLASS_OVERLAY_PATH (1<<10)
#define ZR_CLASS_NVGS (1<<11)
#define ZR_CLASS_FOV (1<<12)
#define ZR_CLASS_HAS_NAPALM (1<<13)
#define ZR_CLASS_NAPALM_TIME (1<<14)
#define ZR_CLASS_IMMUNITY_MODE (1<<15)
#define ZR_CLASS_IMMUNITY_AMOUNT (1<<16)
#define ZR_CLASS_NO_FALL_DAMAGE (1<<17)
#define ZR_CLASS_HEALTH (1<<18)
#define ZR_CLASS_HEALTH_REGEN_INTERVAL (1<<19)
#define ZR_CLASS_HEALTH_REGEN_AMOUNT (1<<20)
#define ZR_CLASS_HEALTH_INFECT_GAIN (1<<21)
#define ZR_CLASS_KILL_BONUS (1<<22)
#define ZR_CLASS_SPEED (1<<23)
#define ZR_CLASS_KNOCKBACK (1<<24)
#define ZR_CLASS_JUMP_HEIGHT (1<<25)
#define ZR_CLASS_JUMP_DISTANCE (1<<26)
#define ZR_CLASS_GROUP (1<<4)
#define ZR_CLASS_NAME (1<<5)
#define ZR_CLASS_DESCRIPTION (1<<6)
#define ZR_CLASS_MODEL_PATH (1<<7)
#define ZR_CLASS_ALPHA_INITIAL (1<<8)
#define ZR_CLASS_ALPHA_DAMAGED (1<<9)
#define ZR_CLASS_ALPHA_DAMAGE (1<<10)
#define ZR_CLASS_OVERLAY_PATH (1<<11)
#define ZR_CLASS_NVGS (1<<12)
#define ZR_CLASS_FOV (1<<13)
#define ZR_CLASS_HAS_NAPALM (1<<14)
#define ZR_CLASS_NAPALM_TIME (1<<15)
#define ZR_CLASS_IMMUNITY_MODE (1<<16)
#define ZR_CLASS_IMMUNITY_AMOUNT (1<<17)
#define ZR_CLASS_NO_FALL_DAMAGE (1<<18)
#define ZR_CLASS_HEALTH (1<<19)
#define ZR_CLASS_HEALTH_REGEN_INTERVAL (1<<20)
#define ZR_CLASS_HEALTH_REGEN_AMOUNT (1<<21)
#define ZR_CLASS_HEALTH_INFECT_GAIN (1<<22)
#define ZR_CLASS_KILL_BONUS (1<<23)
#define ZR_CLASS_SPEED (1<<24)
#define ZR_CLASS_KNOCKBACK (1<<25)
#define ZR_CLASS_JUMP_HEIGHT (1<<26)
#define ZR_CLASS_JUMP_DISTANCE (1<<27)
/**
* @endsection
*/
/**
* Generic player attributes.
*
* Stuff that must be updated when new attributes are added:
* ZR_CLASS_DEFAULT_... define
* ZR_CLASS_..._MAX/MIN defines
* ZR_CLASS_... define (place in same order as listed in ClassAttributes, bump bit numbers + update numbers in docs)
* ClassLoad
* ClassReloadDataCache
* ClassReloadPlayerCache
* ClassDumpData
* attributes.inc - Add new Get-function
* ClassAttributeNameToFlag
* ClassGetAttributeType
* ClassValidateAttributes
* ClassModify* in classcommands.inc
* Update docs with detailed attribute description
*/
enum ClassAttributes
{
/* General */
bool:class_enabled,
class_team,
bool:class_team_default,
class_flags,
bool:Class_Enabled,
Class_Team,
bool:Class_TeamDefault,
Class_Flags,
String:Class_Group[64],
String:class_name[64],
String:class_description[256],
String:Class_Name[64],
String:Class_Description[256],
/* Model */
String:class_model_path[PLATFORM_MAX_PATH],
class_alpha_initial,
class_alpha_damaged,
class_alpha_damage,
String:Class_ModelPath[PLATFORM_MAX_PATH],
Class_AlphaInitial,
Class_AlphaDamaged,
Class_AlphaDamage,
/* Hud */
String:class_overlay_path[PLATFORM_MAX_PATH],
bool:class_nvgs,
class_fov,
String:Class_OverlayPath[PLATFORM_MAX_PATH],
bool:Class_Nvgs,
Class_Fov,
/* Effects */
bool:class_has_napalm,
Float:class_napalm_time,
bool:Class_HasNapalm,
Float:Class_NapalmTime,
/* Player behaviour */
class_immunity_mode,
Float:class_immunity_amount,
bool:class_no_fall_damage,
Class_ImmunityMode,
Float:Class_ImmunityAmount,
bool:Class_NoFallDamage,
class_health,
Float:class_health_regen_interval,
class_health_regen_amount,
class_health_infect_gain,
class_kill_bonus,
Class_Health,
Float:Class_HealthRegenInterval,
Class_HealthRegenAmount,
Class_HealthInfectGain,
Class_KillBonus,
Float:class_speed,
Float:class_knockback,
Float:class_jump_height,
Float:class_jump_distance
Float:Class_Speed,
Float:Class_KnockBack,
Float:Class_JumpHeight,
Float:Class_JumpDistance
}
/**
@ -294,6 +312,27 @@ enum ClassDataTypes
ClassDataType_String /** String value */
}
/**
* Structure for class filter settings passed to various functions.
*/
enum ClassFilter
{
bool:ClassFilter_IgnoreEnabled, /** Ignore whether the class is disabled or not. */
ClassFilter_RequireFlags, /** Flags the classes must have set. */
ClassFilter_DenyFlags, /** Flags the classes cannot have set. */
ClassFilter_Client /** The client to check for class group permissions. Use 0 to ignore group filter and negative to exclude classes with groups set. */
}
/**
* Empty filter structure.
*/
new ClassNoFilter[ClassFilter];
/**
* Filter structure for excluding special classes.
*/
new ClassNoSpecialClasses[ClassFilter] = {false, 0, ZR_CLASS_SPECIALFLAGS, -1};
/**
* Keyvalue handle to store class data.
*/
@ -351,6 +390,11 @@ new ClassSelectedNext[MAXPLAYERS + 1][ZR_CLASS_TEAMCOUNT];
*/
new ClassAdminTeamSelected[MAXPLAYERS + 1];
/**
* Cookies for storing class indexes.
*/
new Handle:g_hClassCookieClassSelected[ZR_CLASS_TEAMCOUNT];
/**
* Cache for the currently selected attribute multiplier (admin menus).
*/
@ -362,9 +406,13 @@ new ClassMultipliers:ClassAdminAttributeSelected[MAXPLAYERS + 1];
new bool:ClassPlayerInAdminMode[MAXPLAYERS + 1];
/**
* Specifies the admin class to use on next admin mode spawn.
* Specifies whether a player is allowed to change class with instant effect.
* This is only used on human classes, and in combination with the
* zr_classes_change_timelimit time limit, but could be used other places too.
* The class menu will automatically check this setting and apply attributes if
* set to true.
*/
//new ClassPlayerNextAdminClass[MAXPLAYERS + 1];
new bool:ClassAllowInstantChange[MAXPLAYERS + 1];
/**
* Cache for storing original model path before applying custom models. Used
@ -431,6 +479,7 @@ ClassLoad(bool:keepMultipliers = false)
}
decl String:name[64];
decl String:group[64];
decl String:description[256];
decl String:model_path[PLATFORM_MAX_PATH];
decl String:overlay_path[PLATFORM_MAX_PATH];
@ -451,55 +500,58 @@ ClassLoad(bool:keepMultipliers = false)
}
/* General */
ClassData[ClassCount][class_enabled] = bool:KvGetNum(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED);
ClassData[ClassCount][class_team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM);
ClassData[ClassCount][class_team_default] = bool:KvGetNum(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT);
ClassData[ClassCount][class_flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS);
ClassData[ClassCount][Class_Enabled] = ConfigKvGetStringBool(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED);
ClassData[ClassCount][Class_Team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM);
ClassData[ClassCount][Class_TeamDefault] = ConfigKvGetStringBool(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT);
ClassData[ClassCount][Class_Flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS);
KvGetString(kvClassData, "group", group, sizeof(group), ZR_CLASS_DEFAULT_GROUP);
strcopy(ClassData[ClassCount][Class_Group], 64, group);
KvGetString(kvClassData, "name", name, sizeof(name), ZR_CLASS_DEFAULT_NAME);
strcopy(ClassData[ClassCount][class_name], 64, name);
strcopy(ClassData[ClassCount][Class_Name], 64, name);
KvGetString(kvClassData, "description", description, sizeof(description), ZR_CLASS_DEFAULT_DESCRIPTION);
strcopy(ClassData[ClassCount][class_description], 256, description);
strcopy(ClassData[ClassCount][Class_Description], 256, description);
/* Model */
KvGetString(kvClassData, "model_path", model_path, sizeof(model_path), ZR_CLASS_DEFAULT_MODEL_PATH);
strcopy(ClassData[ClassCount][class_model_path], PLATFORM_MAX_PATH, model_path);
strcopy(ClassData[ClassCount][Class_ModelPath], PLATFORM_MAX_PATH, model_path);
ClassData[ClassCount][class_alpha_initial] = KvGetNum(kvClassData, "alpha_initial", ZR_CLASS_DEFAULT_ALPHA_INITIAL);
ClassData[ClassCount][class_alpha_damaged] = KvGetNum(kvClassData, "alpha_damaged", ZR_CLASS_DEFAULT_ALPHA_DAMAGED);
ClassData[ClassCount][class_alpha_damage] = KvGetNum(kvClassData, "alpha_damage", ZR_CLASS_DEFAULT_ALPHA_DAMAGE);
ClassData[ClassCount][Class_AlphaInitial] = KvGetNum(kvClassData, "alpha_initial", ZR_CLASS_DEFAULT_ALPHA_INITIAL);
ClassData[ClassCount][Class_AlphaDamaged] = KvGetNum(kvClassData, "alpha_damaged", ZR_CLASS_DEFAULT_ALPHA_DAMAGED);
ClassData[ClassCount][Class_AlphaDamage] = KvGetNum(kvClassData, "alpha_damage", ZR_CLASS_DEFAULT_ALPHA_DAMAGE);
/* Hud */
KvGetString(kvClassData, "overlay_path", overlay_path, sizeof(overlay_path), ZR_CLASS_DEFAULT_OVERLAY_PATH);
strcopy(ClassData[ClassCount][class_overlay_path], PLATFORM_MAX_PATH, overlay_path);
strcopy(ClassData[ClassCount][Class_OverlayPath], PLATFORM_MAX_PATH, overlay_path);
ClassData[ClassCount][class_nvgs] = bool:KvGetNum(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS);
ClassData[ClassCount][class_fov] = KvGetNum(kvClassData, "fov", ZR_CLASS_DEFAULT_FOV);
ClassData[ClassCount][Class_Nvgs] = ConfigKvGetStringBool(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS);
ClassData[ClassCount][Class_Fov] = KvGetNum(kvClassData, "fov", ZR_CLASS_DEFAULT_FOV);
/* Effects */
ClassData[ClassCount][class_has_napalm] = bool:KvGetNum(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM);
ClassData[ClassCount][class_napalm_time] = KvGetFloat(kvClassData, "napalm_time", ZR_CLASS_DEFAULT_NAPALM_TIME);
ClassData[ClassCount][Class_HasNapalm] = ConfigKvGetStringBool(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM);
ClassData[ClassCount][Class_NapalmTime] = KvGetFloat(kvClassData, "napalm_time", ZR_CLASS_DEFAULT_NAPALM_TIME);
/* Player behaviour */
ClassData[ClassCount][class_immunity_mode] = KvGetNum(kvClassData, "immunity_mode", ZR_CLASS_DEFAULT_IMMUNITY_MODE);
ClassData[ClassCount][class_immunity_amount] = KvGetFloat(kvClassData, "immunity_amount", ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT);
ClassData[ClassCount][class_no_fall_damage] = bool:KvGetNum(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE);
ClassData[ClassCount][Class_ImmunityMode] = KvGetNum(kvClassData, "immunity_mode", ZR_CLASS_DEFAULT_IMMUNITY_MODE);
ClassData[ClassCount][Class_ImmunityAmount] = KvGetFloat(kvClassData, "immunity_amount", ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT);
ClassData[ClassCount][Class_NoFallDamage] = ConfigKvGetStringBool(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE);
ClassData[ClassCount][class_health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH);
ClassData[ClassCount][class_health_regen_interval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL);
ClassData[ClassCount][class_health_regen_amount] = KvGetNum(kvClassData, "health_regen_amount", ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT);
ClassData[ClassCount][class_health_infect_gain] = KvGetNum(kvClassData, "health_infect_gain", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN);
ClassData[ClassCount][class_kill_bonus] = KvGetNum(kvClassData, "kill_bonus", ZR_CLASS_DEFAULT_KILL_BONUS);
ClassData[ClassCount][Class_Health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH);
ClassData[ClassCount][Class_HealthRegenInterval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL);
ClassData[ClassCount][Class_HealthRegenAmount] = KvGetNum(kvClassData, "health_regen_amount", ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT);
ClassData[ClassCount][Class_HealthInfectGain] = KvGetNum(kvClassData, "health_infect_gain", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN);
ClassData[ClassCount][Class_KillBonus] = KvGetNum(kvClassData, "kill_bonus", ZR_CLASS_DEFAULT_KILL_BONUS);
ClassData[ClassCount][class_speed] = KvGetFloat(kvClassData, "speed", ZR_CLASS_DEFAULT_SPEED);
ClassData[ClassCount][class_knockback] = KvGetFloat(kvClassData, "knockback", ZR_CLASS_DEFAULT_KNOCKBACK);
ClassData[ClassCount][class_jump_height] = KvGetFloat(kvClassData, "jump_height", ZR_CLASS_DEFAULT_JUMP_HEIGHT);
ClassData[ClassCount][class_jump_distance] = KvGetFloat(kvClassData, "jump_distance", ZR_CLASS_DEFAULT_JUMP_DISTANCE);
ClassData[ClassCount][Class_Speed] = KvGetFloat(kvClassData, "speed", ZR_CLASS_DEFAULT_SPEED);
ClassData[ClassCount][Class_KnockBack] = KvGetFloat(kvClassData, "knockback", ZR_CLASS_DEFAULT_KNOCKBACK);
ClassData[ClassCount][Class_JumpHeight] = KvGetFloat(kvClassData, "jump_height", ZR_CLASS_DEFAULT_JUMP_HEIGHT);
ClassData[ClassCount][Class_JumpDistance] = KvGetFloat(kvClassData, "jump_distance", ZR_CLASS_DEFAULT_JUMP_DISTANCE);
// Validate the class attributes.
ClassErrorFlags = ClassValidateAttributes(ClassCount);
@ -507,7 +559,7 @@ ClassLoad(bool:keepMultipliers = false)
{
// There's one or more invalid class attributes. Disable the class
// and log an error message.
ClassData[ClassCount][class_enabled] = false;
ClassData[ClassCount][Class_Enabled] = false;
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Config Validation", "Warning: Invalid class at index %d, disabled class. Class error flags: %d.", ClassCount, ClassErrorFlags);
failedcount++;
@ -585,41 +637,42 @@ bool:ClassReloadDataCache()
for (new classindex = 0; classindex < ClassCount; classindex++)
{
/* General */
ClassDataCache[classindex][class_enabled] = ClassData[classindex][class_enabled];
ClassDataCache[classindex][class_team] = ClassData[classindex][class_team];
ClassDataCache[classindex][class_team_default] = ClassData[classindex][class_team_default];
ClassDataCache[classindex][class_flags] = ClassData[classindex][class_flags];
strcopy(ClassDataCache[classindex][class_name], 64, ClassData[classindex][class_name]);
strcopy(ClassDataCache[classindex][class_description], 256, ClassData[classindex][class_description]);
ClassDataCache[classindex][Class_Enabled] = ClassData[classindex][Class_Enabled];
ClassDataCache[classindex][Class_Team] = ClassData[classindex][Class_Team];
ClassDataCache[classindex][Class_TeamDefault] = ClassData[classindex][Class_TeamDefault];
ClassDataCache[classindex][Class_Flags] = ClassData[classindex][Class_Flags];
strcopy(ClassDataCache[classindex][Class_Group], 64, ClassData[classindex][Class_Group]);
strcopy(ClassDataCache[classindex][Class_Name], 64, ClassData[classindex][Class_Name]);
strcopy(ClassDataCache[classindex][Class_Description], 256, ClassData[classindex][Class_Description]);
/* Model */
strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, ClassData[classindex][class_model_path]);
ClassDataCache[classindex][class_alpha_initial] = ClassData[classindex][class_alpha_initial];
ClassDataCache[classindex][class_alpha_damaged] = ClassData[classindex][class_alpha_damaged];
ClassDataCache[classindex][class_alpha_damage] = ClassData[classindex][class_alpha_damage];
strcopy(ClassDataCache[classindex][Class_ModelPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_ModelPath]);
ClassDataCache[classindex][Class_AlphaInitial] = ClassData[classindex][Class_AlphaInitial];
ClassDataCache[classindex][Class_AlphaDamaged] = ClassData[classindex][Class_AlphaDamaged];
ClassDataCache[classindex][Class_AlphaDamage] = ClassData[classindex][Class_AlphaDamage];
/* Hud */
strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, ClassData[classindex][class_overlay_path]);
ClassDataCache[classindex][class_nvgs] = ClassData[classindex][class_nvgs];
ClassDataCache[classindex][class_fov] = ClassData[classindex][class_fov];
strcopy(ClassDataCache[classindex][Class_OverlayPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_OverlayPath]);
ClassDataCache[classindex][Class_Nvgs] = ClassData[classindex][Class_Nvgs];
ClassDataCache[classindex][Class_Fov] = ClassData[classindex][Class_Fov];
/* Effects */
ClassDataCache[classindex][class_has_napalm] = ClassData[classindex][class_has_napalm];
ClassDataCache[classindex][class_napalm_time] = ClassData[classindex][class_napalm_time];
ClassDataCache[classindex][Class_HasNapalm] = ClassData[classindex][Class_HasNapalm];
ClassDataCache[classindex][Class_NapalmTime] = ClassData[classindex][Class_NapalmTime];
/* Player behaviour */
ClassDataCache[classindex][class_immunity_mode] = ClassData[classindex][class_immunity_mode];
ClassDataCache[classindex][class_immunity_amount] = ClassData[classindex][class_immunity_amount];
ClassDataCache[classindex][class_no_fall_damage] = ClassData[classindex][class_no_fall_damage];
ClassDataCache[classindex][class_health] = ClassData[classindex][class_health];
ClassDataCache[classindex][class_health_regen_interval] = ClassData[classindex][class_health_regen_interval];
ClassDataCache[classindex][class_health_regen_amount] = ClassData[classindex][class_health_regen_amount];
ClassDataCache[classindex][class_health_infect_gain] = ClassData[classindex][class_health_infect_gain];
ClassDataCache[classindex][class_kill_bonus] = ClassData[classindex][class_kill_bonus];
ClassDataCache[classindex][class_speed] = ClassData[classindex][class_speed];
ClassDataCache[classindex][class_knockback] = ClassData[classindex][class_knockback];
ClassDataCache[classindex][class_jump_height] = ClassData[classindex][class_jump_height];
ClassDataCache[classindex][class_jump_distance] = ClassData[classindex][class_jump_distance];
ClassDataCache[classindex][Class_ImmunityMode] = ClassData[classindex][Class_ImmunityMode];
ClassDataCache[classindex][Class_ImmunityAmount] = ClassData[classindex][Class_ImmunityAmount];
ClassDataCache[classindex][Class_NoFallDamage] = ClassData[classindex][Class_NoFallDamage];
ClassDataCache[classindex][Class_Health] = ClassData[classindex][Class_Health];
ClassDataCache[classindex][Class_HealthRegenInterval] = ClassData[classindex][Class_HealthRegenInterval];
ClassDataCache[classindex][Class_HealthRegenAmount] = ClassData[classindex][Class_HealthRegenAmount];
ClassDataCache[classindex][Class_HealthInfectGain] = ClassData[classindex][Class_HealthInfectGain];
ClassDataCache[classindex][Class_KillBonus] = ClassData[classindex][Class_KillBonus];
ClassDataCache[classindex][Class_Speed] = ClassData[classindex][Class_Speed];
ClassDataCache[classindex][Class_KnockBack] = ClassData[classindex][Class_KnockBack];
ClassDataCache[classindex][Class_JumpHeight] = ClassData[classindex][Class_JumpHeight];
ClassDataCache[classindex][Class_JumpDistance] = ClassData[classindex][Class_JumpDistance];
}
return true;
@ -649,80 +702,82 @@ bool:ClassReloadPlayerCache(client, classindex, cachetype = ZR_CLASS_CACHE_MODIF
case ZR_CLASS_CACHE_ORIGINAL:
{
/* General */
ClassPlayerCache[client][class_enabled] = ClassData[classindex][class_enabled];
ClassPlayerCache[client][class_team] = ClassData[classindex][class_team];
ClassPlayerCache[client][class_team_default] = ClassData[classindex][class_team_default];
ClassPlayerCache[client][class_flags] = ClassData[classindex][class_flags];
strcopy(ClassPlayerCache[client][class_name], 64, ClassData[classindex][class_name]);
strcopy(ClassPlayerCache[client][class_description], 256, ClassData[classindex][class_description]);
ClassPlayerCache[client][Class_Enabled] = ClassData[classindex][Class_Enabled];
ClassPlayerCache[client][Class_Team] = ClassData[classindex][Class_Team];
ClassPlayerCache[client][Class_TeamDefault] = ClassData[classindex][Class_TeamDefault];
ClassPlayerCache[client][Class_Flags] = ClassData[classindex][Class_Flags];
strcopy(ClassPlayerCache[client][Class_Group], 64, ClassData[classindex][Class_Group]);
strcopy(ClassPlayerCache[client][Class_Name], 64, ClassData[classindex][Class_Name]);
strcopy(ClassPlayerCache[client][Class_Description], 256, ClassData[classindex][Class_Description]);
/* Model */
strcopy(ClassPlayerCache[client][class_model_path], PLATFORM_MAX_PATH, ClassData[classindex][class_model_path]);
ClassPlayerCache[client][class_alpha_initial] = ClassData[classindex][class_alpha_initial];
ClassPlayerCache[client][class_alpha_damaged] = ClassData[classindex][class_alpha_damaged];
ClassPlayerCache[client][class_alpha_damage] = ClassData[classindex][class_alpha_damage];
strcopy(ClassPlayerCache[client][Class_ModelPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_ModelPath]);
ClassPlayerCache[client][Class_AlphaInitial] = ClassData[classindex][Class_AlphaInitial];
ClassPlayerCache[client][Class_AlphaDamaged] = ClassData[classindex][Class_AlphaDamaged];
ClassPlayerCache[client][Class_AlphaDamage] = ClassData[classindex][Class_AlphaDamage];
/* Hud */
strcopy(ClassPlayerCache[client][class_overlay_path], PLATFORM_MAX_PATH, ClassData[classindex][class_overlay_path]);
ClassPlayerCache[client][class_nvgs] = ClassData[classindex][class_nvgs];
ClassPlayerCache[client][class_fov] = ClassData[classindex][class_fov];
strcopy(ClassPlayerCache[client][Class_OverlayPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_OverlayPath]);
ClassPlayerCache[client][Class_Nvgs] = ClassData[classindex][Class_Nvgs];
ClassPlayerCache[client][Class_Fov] = ClassData[classindex][Class_Fov];
/* Effects */
ClassPlayerCache[client][class_has_napalm] = ClassData[classindex][class_has_napalm];
ClassPlayerCache[client][class_napalm_time] = ClassData[classindex][class_napalm_time];
ClassPlayerCache[client][Class_HasNapalm] = ClassData[classindex][Class_HasNapalm];
ClassPlayerCache[client][Class_NapalmTime] = ClassData[classindex][Class_NapalmTime];
/* Player behaviour */
ClassPlayerCache[client][class_immunity_mode] = ClassData[classindex][class_immunity_mode];
ClassPlayerCache[client][class_immunity_amount] = ClassData[classindex][class_immunity_amount];
ClassPlayerCache[client][class_no_fall_damage] = ClassData[classindex][class_no_fall_damage];
ClassPlayerCache[client][class_health] = ClassData[classindex][class_health];
ClassPlayerCache[client][class_health_regen_interval] = ClassData[classindex][class_health_regen_interval];
ClassPlayerCache[client][class_health_regen_amount] = ClassData[classindex][class_health_regen_amount];
ClassPlayerCache[client][class_health_infect_gain] = ClassData[classindex][class_health_infect_gain];
ClassPlayerCache[client][class_kill_bonus] = ClassData[classindex][class_kill_bonus];
ClassPlayerCache[client][class_speed] = ClassData[classindex][class_speed];
ClassPlayerCache[client][class_knockback] = ClassData[classindex][class_knockback];
ClassPlayerCache[client][class_jump_height] = ClassData[classindex][class_jump_height];
ClassPlayerCache[client][class_jump_distance] = ClassData[classindex][class_jump_distance];
ClassPlayerCache[client][Class_ImmunityMode] = ClassData[classindex][Class_ImmunityMode];
ClassPlayerCache[client][Class_ImmunityAmount] = ClassData[classindex][Class_ImmunityAmount];
ClassPlayerCache[client][Class_NoFallDamage] = ClassData[classindex][Class_NoFallDamage];
ClassPlayerCache[client][Class_Health] = ClassData[classindex][Class_Health];
ClassPlayerCache[client][Class_HealthRegenInterval] = ClassData[classindex][Class_HealthRegenInterval];
ClassPlayerCache[client][Class_HealthRegenAmount] = ClassData[classindex][Class_HealthRegenAmount];
ClassPlayerCache[client][Class_HealthInfectGain] = ClassData[classindex][Class_HealthInfectGain];
ClassPlayerCache[client][Class_KillBonus] = ClassData[classindex][Class_KillBonus];
ClassPlayerCache[client][Class_Speed] = ClassData[classindex][Class_Speed];
ClassPlayerCache[client][Class_KnockBack] = ClassData[classindex][Class_KnockBack];
ClassPlayerCache[client][Class_JumpHeight] = ClassData[classindex][Class_JumpHeight];
ClassPlayerCache[client][Class_JumpDistance] = ClassData[classindex][Class_JumpDistance];
}
case ZR_CLASS_CACHE_MODIFIED:
{
/* General */
ClassPlayerCache[client][class_enabled] = ClassDataCache[classindex][class_enabled];
ClassPlayerCache[client][class_team] = ClassDataCache[classindex][class_team];
ClassPlayerCache[client][class_team_default] = ClassDataCache[classindex][class_team_default];
ClassPlayerCache[client][class_flags] = ClassDataCache[classindex][class_flags];
strcopy(ClassPlayerCache[client][class_name], 64, ClassDataCache[classindex][class_name]);
strcopy(ClassPlayerCache[client][class_description], 256, ClassDataCache[classindex][class_description]);
ClassPlayerCache[client][Class_Enabled] = ClassDataCache[classindex][Class_Enabled];
ClassPlayerCache[client][Class_Team] = ClassDataCache[classindex][Class_Team];
ClassPlayerCache[client][Class_TeamDefault] = ClassDataCache[classindex][Class_TeamDefault];
ClassPlayerCache[client][Class_Flags] = ClassDataCache[classindex][Class_Flags];
strcopy(ClassPlayerCache[client][Class_Group], 64, ClassDataCache[classindex][Class_Group]);
strcopy(ClassPlayerCache[client][Class_Name], 64, ClassDataCache[classindex][Class_Name]);
strcopy(ClassPlayerCache[client][Class_Description], 256, ClassDataCache[classindex][Class_Description]);
/* Model */
strcopy(ClassPlayerCache[client][class_model_path], PLATFORM_MAX_PATH, ClassDataCache[classindex][class_model_path]);
ClassPlayerCache[client][class_alpha_initial] = ClassDataCache[classindex][class_alpha_initial];
ClassPlayerCache[client][class_alpha_damaged] = ClassDataCache[classindex][class_alpha_damaged];
ClassPlayerCache[client][class_alpha_damage] = ClassDataCache[classindex][class_alpha_damage];
strcopy(ClassPlayerCache[client][Class_ModelPath], PLATFORM_MAX_PATH, ClassDataCache[classindex][Class_ModelPath]);
ClassPlayerCache[client][Class_AlphaInitial] = ClassDataCache[classindex][Class_AlphaInitial];
ClassPlayerCache[client][Class_AlphaDamaged] = ClassDataCache[classindex][Class_AlphaDamaged];
ClassPlayerCache[client][Class_AlphaDamage] = ClassDataCache[classindex][Class_AlphaDamage];
/* Hud */
strcopy(ClassPlayerCache[client][class_overlay_path], PLATFORM_MAX_PATH, ClassDataCache[classindex][class_overlay_path]);
ClassPlayerCache[client][class_nvgs] = ClassDataCache[classindex][class_nvgs];
ClassPlayerCache[client][class_fov] = ClassDataCache[classindex][class_fov];
strcopy(ClassPlayerCache[client][Class_OverlayPath], PLATFORM_MAX_PATH, ClassDataCache[classindex][Class_OverlayPath]);
ClassPlayerCache[client][Class_Nvgs] = ClassDataCache[classindex][Class_Nvgs];
ClassPlayerCache[client][Class_Fov] = ClassDataCache[classindex][Class_Fov];
/* Effects */
ClassPlayerCache[client][class_has_napalm] = ClassDataCache[classindex][class_has_napalm];
ClassPlayerCache[client][class_napalm_time] = ClassDataCache[classindex][class_napalm_time];
ClassPlayerCache[client][Class_HasNapalm] = ClassDataCache[classindex][Class_HasNapalm];
ClassPlayerCache[client][Class_NapalmTime] = ClassDataCache[classindex][Class_NapalmTime];
/* Player behaviour */
ClassPlayerCache[client][class_immunity_mode] = ClassDataCache[classindex][class_immunity_mode];
ClassPlayerCache[client][class_immunity_amount] = ClassDataCache[classindex][class_immunity_amount];
ClassPlayerCache[client][class_no_fall_damage] = ClassDataCache[classindex][class_no_fall_damage];
ClassPlayerCache[client][class_health] = ClassDataCache[classindex][class_health];
ClassPlayerCache[client][class_health_regen_interval] = ClassDataCache[classindex][class_health_regen_interval];
ClassPlayerCache[client][class_health_regen_amount] = ClassDataCache[classindex][class_health_regen_amount];
ClassPlayerCache[client][class_health_infect_gain] = ClassDataCache[classindex][class_health_infect_gain];
ClassPlayerCache[client][class_kill_bonus] = ClassDataCache[classindex][class_kill_bonus];
ClassPlayerCache[client][class_speed] = ClassDataCache[classindex][class_speed];
ClassPlayerCache[client][class_knockback] = ClassDataCache[classindex][class_knockback];
ClassPlayerCache[client][class_jump_height] = ClassDataCache[classindex][class_jump_height];
ClassPlayerCache[client][class_jump_distance] = ClassDataCache[classindex][class_jump_distance];
ClassPlayerCache[client][Class_ImmunityMode] = ClassDataCache[classindex][Class_ImmunityMode];
ClassPlayerCache[client][Class_ImmunityAmount] = ClassDataCache[classindex][Class_ImmunityAmount];
ClassPlayerCache[client][Class_NoFallDamage] = ClassDataCache[classindex][Class_NoFallDamage];
ClassPlayerCache[client][Class_Health] = ClassDataCache[classindex][Class_Health];
ClassPlayerCache[client][Class_HealthRegenInterval] = ClassDataCache[classindex][Class_HealthRegenInterval];
ClassPlayerCache[client][Class_HealthRegenAmount] = ClassDataCache[classindex][Class_HealthRegenAmount];
ClassPlayerCache[client][Class_HealthInfectGain] = ClassDataCache[classindex][Class_HealthInfectGain];
ClassPlayerCache[client][Class_KillBonus] = ClassDataCache[classindex][Class_KillBonus];
ClassPlayerCache[client][Class_Speed] = ClassDataCache[classindex][Class_Speed];
ClassPlayerCache[client][Class_KnockBack] = ClassDataCache[classindex][Class_KnockBack];
ClassPlayerCache[client][Class_JumpHeight] = ClassDataCache[classindex][Class_JumpHeight];
ClassPlayerCache[client][Class_JumpDistance] = ClassDataCache[classindex][Class_JumpDistance];
}
default:
{
@ -782,7 +837,7 @@ ClassResetMultiplierCache()
}
/**
* Resets the selected class indexes for next span on one or all clients.
* Resets the selected class indexes for next spawn on one or all clients.
*
* @param client Optional. Specify client to reset. Default is all.
*/
@ -814,7 +869,7 @@ ClassResetNextIndexes(client = -1)
* Note: Does not apply attributes. The classes are only marked as selected.
*
* @param client The client index.
* @param excludeTeam Do not restore the specified team.
* @param excludeTeam Optional. Do not restore the specified team.
*/
ClassRestoreNextIndexes(client, excludeTeam = -1)
{
@ -870,52 +925,157 @@ ClassRestoreNextIndexes(client, excludeTeam = -1)
* Sets default class indexes for each team on all players, or a single player
* if specified.
*
* @param client Optional. The client index.
* @param client Optional. The client index. If specified, cookies are used.
*/
ClassClientSetDefaultIndexes(client = -1)
{
// Get indexes.
new zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES);
new humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS);
new adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS);
new bool:clientvalid = ZRIsClientValid(client);
new filter[ClassFilter];
new bool:saveclasses = GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE]);
// Validate zombie class index.
new zombieindex;
new humanindex;
new adminindex;
new bool:haszombie;
new bool:hashuman;
new bool:hasadmin;
// Check if a client is specified.
if (clientvalid)
{
// Get cookie indexes if enabled.
if (saveclasses)
{
zombieindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES]);
humanindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS]);
adminindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS]);
}
else
{
// Do not use indexes in cookies. Set invalid values so it will
// fall back to default class.
zombieindex = 0;
humanindex = 0;
adminindex = 0;
}
// Note: When class indexes are set on cookies, they're incremented by
// one so zero means no class set and will result in a invalid
// class index when restored.
// Setup filtering so group permission is checked on player first.
filter[ClassFilter_Client] = client;
// Check if class indexes are set and that the client pass group
// permissions. If not, fall back to default class indexes. Otherwise
// substract index by one.
if (zombieindex <= 0 || !ClassFilterMatch(zombieindex, filter))
{
zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES, filter);
}
else
{
zombieindex--;
haszombie = true;
}
if (humanindex <= 0 || !ClassFilterMatch(humanindex, filter))
{
humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS, filter);
}
else
{
humanindex--;
hashuman = true;
}
if (adminindex <= 0 || !ClassFilterMatch(adminindex, filter))
{
adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS, filter);
}
else
{
adminindex--;
hasadmin = true;
}
}
else
{
// Setup filtering so classes with groups set are excluded.
filter[ClassFilter_Client] = -1;
// Get default class indexes.
zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES, filter);
humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS, filter);
adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS, filter);
}
// Validate indexes.
if (!ClassValidateIndex(zombieindex))
{
// Invalid class index. Fall back to default class in class config and
// log a warning.
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get default zombie class, falling back to default class in class config. Check spelling in \"zr_classes_default_zombie\".");
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified zombie class, falling back to default class in class config. Check spelling in \"zr_classes_default_zombie\".");
// Use default class.
zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES);
zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, filter);
}
// Validate human class index.
// Get human class index.
if (!ClassValidateIndex(humanindex))
{
// Invalid class index. Fall back to default class in class config and
// log a warning.
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get default human class, falling back to default class in class config. Check spelling in \"zr_classes_default_human\".");
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified human class, falling back to default class in class config. Check spelling in \"zr_classes_default_human\".");
// Use default class.
humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS);
humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, filter);
}
// Validate admin class index.
// Get admin class index.
if (!ClassValidateIndex(adminindex))
{
// Invalid class index. Fall back to default class in class config if
// possible. A invalid class index (-1) can also be stored if there are
// no admin classes at all.
adminindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ADMINS);
adminindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ADMINS, filter);
}
// Check if a client isn't specified.
if (client < 1)
// Check if a client is specified.
if (clientvalid)
{
// Set selected class idexes.
ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = zombieindex;
ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = humanindex;
ClassSelected[client][ZR_CLASS_TEAM_ADMINS] = adminindex;
// Copy human class data to player cache.
ClassReloadPlayerCache(client, humanindex);
// Save indexes in cookies if enabled, and not already saved.
if (saveclasses)
{
if (!haszombie)
{
CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES], zombieindex + 1);
}
if (!hashuman)
{
CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS], humanindex + 1);
}
if (!hasadmin)
{
CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS], adminindex + 1);
}
}
}
else
{
// No client specified. Loop through all players.
for (new clientindex = 1; clientindex <= MAXPLAYERS; clientindex++)
for (new clientindex = 1; clientindex <= MaxClients; clientindex++)
{
// Set selected class idexes.
ClassSelected[clientindex][ZR_CLASS_TEAM_ZOMBIES] = zombieindex;
ClassSelected[clientindex][ZR_CLASS_TEAM_HUMANS] = humanindex;
ClassSelected[clientindex][ZR_CLASS_TEAM_ADMINS] = adminindex;
@ -924,15 +1084,6 @@ ClassClientSetDefaultIndexes(client = -1)
ClassReloadPlayerCache(client, humanindex);
}
}
else
{
ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = zombieindex;
ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = humanindex;
ClassSelected[client][ZR_CLASS_TEAM_ADMINS] = adminindex;
// Copy human class data to player cache.
ClassReloadPlayerCache(client, humanindex);
}
}
/**
@ -976,6 +1127,10 @@ ClassDumpData(index, cachetype, String:buffer[], maxlen)
Format(attribute, sizeof(attribute), "flags: \"%d\"\n", ClassGetFlags(index, cachetype));
cellcount += StrCat(buffer, maxlen, attribute);
ClassGetGroup(index, format_buffer, sizeof(format_buffer), cachetype);
Format(attribute, sizeof(attribute), "group: \"%s\"\n", format_buffer);
cellcount += StrCat(buffer, maxlen, attribute);
ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype);
Format(attribute, sizeof(attribute), "name: \"%s\"\n", format_buffer);
cellcount += StrCat(buffer, maxlen, attribute);

View File

@ -333,16 +333,13 @@ stock TranslationReplyToCommand(client, any:...)
{
// Format string to create plugin style. (color)
TranslationPluginFormatString(translation, sizeof(translation));
// Print translated phrase to client's chat/console.
PrintToChat(client, translation);
}
else
{
// Format string to create plugin style. (no color)
TranslationPluginFormatString(translation, sizeof(translation), false);
// Print to server.
PrintToServer(translation);
}
// Print translated phrase to server or client's chat/console.
ReplyToCommand(client, translation);
}

View File

@ -64,7 +64,7 @@ public Action:ZAdminCommand(client, argc)
*/
bool:ZAdminMenu(client)
{
// If client isn't an admin, then stop.
// If client isn't an generic admin, then stop.
if (!ZRIsClientAdmin(client))
{
TranslationPrintToChat(client, "Must be admin");
@ -94,16 +94,18 @@ bool:ZAdminMenu(client)
Format(ztele, sizeof(ztele), "%t", "ZAdmin main force ztele");
// Get conditions for options.
new bool:hitgroupsenabled = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
new configdraw = MenuGetItemDraw(ZRIsClientPrivileged(client, OperationType_Configuration));
new moderatordraw = MenuGetItemDraw(ZRIsClientPrivileged(client, OperationType_Generic));
new bool:hitgroupsenabled = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]) && ZRIsClientPrivileged(client, OperationType_Configuration);
// Add items to menu.
SetMenuTitle(menu_zadmin, title);
AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers);
AddMenuItem(menu_zadmin, "weapons", weapons);
AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers, configdraw);
AddMenuItem(menu_zadmin, "weapons", weapons, configdraw);
AddMenuItem(menu_zadmin, "hitgroups", hitgroups, MenuGetItemDraw(hitgroupsenabled));
AddMenuItem(menu_zadmin, "infect", infect);
AddMenuItem(menu_zadmin, "zspawn", zspawn);
AddMenuItem(menu_zadmin, "ztele", ztele);
AddMenuItem(menu_zadmin, "infect", infect, moderatordraw);
AddMenuItem(menu_zadmin, "zspawn", zspawn, moderatordraw);
AddMenuItem(menu_zadmin, "ztele", ztele, moderatordraw);
// Set "Back" button.
SetMenuExitBackButton(menu_zadmin, true);

View File

@ -235,7 +235,7 @@ stock bool:ZRTeamHasClients(team = -1)
}
/**
* Returns whether a player is a generic admin or not.
* Returns whether a player is a admin or not.
*
* @param client The client index.
* @param flag Optional. Flag to check. Default is generic admin flag.
@ -249,7 +249,7 @@ stock bool:ZRIsClientAdmin(client, AdminFlag:flag = Admin_Generic)
return false;
}
// If client doesn't have the Admin_Generic flag, then stop.
// If client doesn't have the specified flag, then stop.
if (!GetAdminFlag(GetUserAdmin(client), flag))
{
return false;

View File

@ -233,7 +233,7 @@ bool:ZTeleClient(client, bool:force = false)
ZTeleTeleportClient(client)
{
// Teleport client.
TeleportEntity(client, g_vecZTeleSpawn[client], NULL_VECTOR, NULL_VECTOR);
TeleportEntity(client, g_vecZTeleSpawn[client], NULL_VECTOR, Float:{0.0, 0.0, 0.0});
}
/**