diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt index b483987..91a63f9 100644 --- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt +++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt @@ -26,6 +26,7 @@ // overlay_path text Overlay displayed at the player. // nvgs 0/1 Give night vision. // fov number Field of view value. 90 is default. +// has_napalm 0/1 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. diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index f322439..ba2cd3c 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -7,13 +7,12 @@ "General round objective" { "en" "The game is @greenHumans vs. Zombies@default, the goal for zombies is to infect all humans by knifing them." - "ru" "Битва @greenЛюдей против Зомби@default, цель для зомби - инфицировать всех людей." } "General zmenu reminder" { - "en" "For help on Zombie:Reloaded commands, type !zmenu in chat." - "ru" "Напишите !zmenu в чате для просмотра всех команд." + "#format" "{1:s},{2:s}" + "en" "For help on Zombie:Reloaded commands, type \"{1}{2}\" in chat." } // =========================== @@ -323,12 +322,58 @@ "en" "You have been infected! Go pass it on to as many other players as you can." } + "Infect human" + { + "en" "The merciful gods (known as admins) have resurrected your soul, find some cover!" + } + "Infect disconnect" { "en" "The last zombie has left the game, and has passed the infection on to you." "ru" "Последний зомби покинул игру и передал свою инфекцию вам." } + // Commands + + "Infect command infect syntax" + { + "en" "Infect a client. Usage: zr_infect [respawn - 1/0]" + } + + "Infect command human syntax" + { + "en" "Turn a client into a human. Usage: zr_human [respawn - 1/0] [protect - 1/0]" + } + + "Infect command infect successful" + { + "#format" "{1:s}" + "en" "Player @green{1} @defaulthas been successfully infected." + } + + "Infect command infect unsuccessful" + { + "#format" "{1:s}" + "en" "Player @green{1} @defaultis already a zombie." + } + + "Infect command human successful" + { + "#format" "{1:s}" + "en" "Player @green{1} @defaulthas been successfully brought back as a human." + } + + "Infect command human unsuccessful" + { + "#format" "{1:s}" + "en" "Player @green{1} @defaultis already a human." + } + + "Infect command zombie has not spawned" + { + "en" "The mother zombie must spawn before player infection states can be changed." + } + // =========================== // Damage (core) // =========================== @@ -346,44 +391,44 @@ "Menu main title" { - "en" "ZR Commands:" - "ru" "ZR Команды:" + "#format" "{1:s},{2:s}" + "en" "ZR Commands:\nPrefix command with \"{1}\" or \"{2}\" (quiet) when typing in chat." } "Menu main zadmin" { "#format" "{1:s}" - "en" "ZAdmin ({1}) - Open admin menu." + "en" "ZAdmin - Open admin menu. (Command: {1})" } "Menu main zclass" { "#format" "{1:s}" - "en" "ZClass ({1}) - Configure your class settings." + "en" "ZClass - Configure your class settings.(Command: {1})" } "Menu main zspawn" { "#format" "{1:s}" - "en" "ZSpawn ({1}) - Join late? Use this to spawn." + "en" "ZSpawn - Join late? Use this to spawn.(Command: {1})" } "Menu main ztele" { "#format" "{1:s}" - "en" "ZTele ({1}) - Teleport back to your spawn location." + "en" "ZTele - Teleport back to your spawn location.(Command: {1})" } "Menu main zhp" { "#format" "{1:s}" - "en" "ZHP ({1}) - Toggle real HP display when infected." + "en" "ZHP - Toggle real HP display when infected.(Command: {1})" } "Menu main zmarket" { "#format" "{1:s}" - "en" "ZMarket ({1}) - Need a weapon? Buy them here." + "en" "ZMarket - Need a weapon? Buy them here.(Command: {1})" } // =========================== diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index 58774f4..cdaa541 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -302,31 +302,6 @@ zr_damage_suicide_human "1" // Default: "kill, spectate, jointeam" zr_damage_suicide_cmds "kill, spectate, jointeam" // ---------------------------------------------------------------------------- -// Say Hooks (core) -// ---------------------------------------------------------------------------- -// Stop certain in-game commands from appearing in chat. [See zr_sayhooks_quiet_filter&zr_sayhooks_quiet_flags] -// Default: "1" -zr_sayhooks_quiet "1" - -// Stops any failed in-game command from showing in chat. Ex: Typing !zspawn while alive. [Dependency: zr_sayhooks_quiet] -// Default: "1" -zr_sayhooks_quiet_filter "1" - -// Flag separate in-game commands to always hide from chat. [Dependency: zr_sayhooks_quiet] -// In-Game Command Flags: -// * Add numbers of desired flags together to produce final flag value. -// -------------------------------------------------------------------- -// 1: !zmenu [] -// 2: !zadmin [X] -// 4: !zclass [] -// 8: !zspawn [X] -// 16: !ztele [X] -// 32: !zhp [X] -// 64: !zmarket [] -// -// Default: "58" (Have [X] at the end) -zr_sayhooks_quiet_flags "58" -// ---------------------------------------------------------------------------- // Overlays (core) // ---------------------------------------------------------------------------- // How often to update overlays on players. [0.0 = Disabled] @@ -356,6 +331,10 @@ zr_account_cashfill "1" // Amount of cash to set player's account to. [Dependency: zr_account_cashfill] // Default: "12000" zr_account_cashfill_value "12000" + +// Attacker receives amount of cash equivalent to the damage that was inflicted. +// Default: "0" +zr_account_cashdmg "0" // ---------------------------------------------------------------------------- // Visual Effects (module) // ---------------------------------------------------------------------------- @@ -426,9 +405,9 @@ zr_veffects_fog_farz "2000" // Default: "1" zr_veffects_ragdoll_remove "1" -// The ragdoll removal effect. [-1: Effectless removal | 0: Energy dissolve | 1: Heavy electrical dissolve | 2: Light electrical dissolve | 3: Core dissolve | Dependency: zr_veffects_ragdoll_remove] -// Default: "1" -zr_veffects_ragdoll_dissolve "1" +// The ragdoll removal effect. ['-2' = Effectless removal | '-1' = Random effect | '0' = Energy dissolve | '1' = Heavy electrical dissolve | '2' = Light electrical dissolve | '3' = Core dissolve | Dependency: zr_veffects_ragdoll_remove] +// Default: "-1" +zr_veffects_ragdoll_dissolve "-1" // Time to wait before removing the ragdoll. [Dependency: zr_veffects_ragdoll_remove] // Default: "0.5" diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 3e1189c..0a16839 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -118,9 +118,7 @@ public OnPluginStart() ToolsInit(); CommandsInit(); WeaponsInit(); - SayHooksInit(); EventInit(); - ZMarketInit(); } /** diff --git a/src/zr/account.inc b/src/zr/account.inc index 4c1ae65..22f2cb2 100644 --- a/src/zr/account.inc +++ b/src/zr/account.inc @@ -69,6 +69,31 @@ AccountOnClientSpawn(client) AccountSetClientCash(client, cash); } +/** Client has been hurt. + * + * @param attacker The attacker index. + * @param dmg The amount of damage inflicted. + */ +AccountOnClientHurt(attacker, dmg_health) +{ + // If attacker isn't valid, then stop. + if (!ZRIsClientValid(attacker)) + { + return; + } + + // If cashdmg cvar is disabled, then stop. + new bool:accountcashdmg = GetConVarBool(g_hCvarsList[CVAR_ACCOUNT_CASHDMG]); + if (!accountcashdmg) + { + return; + } + + // Get current cash, add the damage done to it, then set new value. + new cash = AccountGetClientCash(attacker); + AccountSetClientCash(attacker, cash + dmg_health); +} + /** * Get's a client's account value (cash) * @@ -94,11 +119,6 @@ stock AccountSetClientCash(client, value) { value = 0; } - // If value is above max, then set to max. - else if (value > ACCOUNT_CASH_MAX) - { - value = ACCOUNT_CASH_MAX; - } // Set client's cash. SetEntData(client, g_iToolsAccount, value, 4); diff --git a/src/zr/antistick.inc b/src/zr/antistick.inc index a21c379..f6c3cf8 100644 --- a/src/zr/antistick.inc +++ b/src/zr/antistick.inc @@ -168,13 +168,13 @@ public Action:AntiStickTimer(Handle:timer) continue; } - if (AntiStickClientCollisionGroup(x, false)) + if (AntiStickClientCollisionGroup(x, false) == ANTISTICK_COLLISIONS_ON) { AntiStickClientCollisionGroup(x, true, ANTISTICK_COLLISIONS_OFF); CreateTimer(0.5, AntiStickSolidify, x, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); } - if (AntiStickClientCollisionGroup(stuckindex, false)) + if (AntiStickClientCollisionGroup(stuckindex, false) == ANTISTICK_COLLISIONS_ON) { AntiStickClientCollisionGroup(stuckindex, true, ANTISTICK_COLLISIONS_OFF); CreateTimer(0.5, AntiStickSolidify, stuckindex, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); @@ -192,7 +192,7 @@ public Action:AntiStickTimer(Handle:timer) public Action:AntiStickSolidify(Handle:timer, any:client) { // Validate player is in-game, alive, and is being unstuck. - if (!IsClientInGame(client) || !IsPlayerAlive(client) || AntiStickClientCollisionGroup(client, false)) + if (!IsClientInGame(client) || !IsPlayerAlive(client) || AntiStickClientCollisionGroup(client, false) == ANTISTICK_COLLISIONS_ON) { return Plugin_Stop; } diff --git a/src/zr/commands.inc b/src/zr/commands.inc index 617adac..b3749aa 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -35,6 +35,12 @@ CommandsInit() LogOnCommandsCreate(); ClassOnCommandsCreate(); WeaponsOnCommandsCreate(); + InfectOnCommandsCreate(); + MenuOnCommandsCreate(); + ZAdminOnCommandsCreate(); + ZSpawnOnCommandsCreate(); + ZTeleOnCommandsCreate(); + ZHPOnCommandsCreate(); VolOnCommandsCreate(); // Forward event to modules. (hook commands) @@ -97,7 +103,7 @@ CommandsInit() for (new x = 0; x < tcount; x++) { - InfectClient(targets[x]); + InfectHumanToZombie(targets[x]); if (LogCheckFlag(LOG_GAME_EVENTS, LOG_MODULE_COMMANDS)) { GetClientName(targets[x], target_name, sizeof(target_name)); diff --git a/src/zr/config.inc b/src/zr/config.inc index 74ec854..310e945 100644 --- a/src/zr/config.inc +++ b/src/zr/config.inc @@ -175,10 +175,10 @@ new g_ConfigData[ConfigFile][ConfigData]; */ enum ConfigKvAction { - KvAction_Create, /** Create a key. */ - KvAction_KVDelete, /** Delete a key. */ - KvAction_KVSet, /** Modify setting of a key. */ - KvAction_KVGet, /** Get setting of a key. */ + KvAction_Create, /** Create a key. */ + KvAction_KVDelete, /** Delete a key. */ + KvAction_KVSet, /** Modify setting of a key. */ + KvAction_KVGet, /** Get setting of a key. */ } /** diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index d772078..09350dd 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -98,6 +98,7 @@ enum CvarsList Handle:CVAR_INFECT_SHAKE_DURATION, Handle:CVAR_ACCOUNT_CASHFILL, Handle:CVAR_ACCOUNT_CASHFILL_VALUE, + Handle:CVAR_ACCOUNT_CASHDMG, Handle:CVAR_VEFFECTS_LIGHTSTYLE, Handle:CVAR_VEFFECTS_LIGHTSTYLE_VALUE, Handle:CVAR_VEFFECTS_SKY, @@ -143,6 +144,7 @@ enum CvarsList Handle:CVAR_ZSPAWN_TEAM_ZOMBIE, Handle:CVAR_ZSPAWN_TIMELIMIT, Handle:CVAR_ZSPAWN_TIMELIMIT_TIME, + Handle:CVAR_ZSPAWN_TIMELIMIT_ZOMBIE, Handle:CVAR_ZTELE_ZOMBIE, Handle:CVAR_ZTELE_HUMAN_BEFORE, Handle:CVAR_ZTELE_HUMAN_AFTER, @@ -303,16 +305,6 @@ CvarsCreate() g_hCvarsList[CVAR_DAMAGE_SUICIDE_HUMAN] = CreateConVar("zr_damage_suicide_human", "1", "Intercept suicide commands attempted by humans."); g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS] = CreateConVar("zr_damage_suicide_cmds", "kill, spectate, jointeam", "List of client commands to intercept as suicide attempts. [Delimiter: \", \"]"); - - // =========================== - // Say Hooks (core) - // =========================== - g_hCvarsList[CVAR_SAYHOOKS_QUIET] = CreateConVar("zr_sayhooks_quiet", "1", "Stop certain in-game commands from appearing in chat. [See zr_sayhooks_quiet_filter&zr_sayhooks_quiet_flags]"); - g_hCvarsList[CVAR_SAYHOOKS_QUIET_FILTER] = CreateConVar("zr_sayhooks_quiet_filter", "1", "Stops any failed in-game command from showing in chat. Ex: Typing !zspawn while alive. [Dependency: zr_sayhooks_quiet]"); - g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS] = CreateConVar("zr_sayhooks_quiet_flags", "58", "Flag separate in-game commands to always hide from chat. [Dependency: zr_sayhooks_quiet]\n In-Game Command Flags:\n * Add numbers of desired flags together to produce final flag value.\n --------------------------------------------------------------------\n 1: !zmenu\n 2: !zadmin\n 4: !zclass\n 8: !zspawn\n 16: !ztele\n 32: !zhp\n 64: !zmarket"); - // Flags (default: 2 + 8 + 16 + 32) - - // =========================== // Overlays (core) // =========================== @@ -332,6 +324,7 @@ CvarsCreate() // =========================== g_hCvarsList[CVAR_ACCOUNT_CASHFILL] = CreateConVar("zr_account_cashfill", "1", "Reset player's cash each spawn."); g_hCvarsList[CVAR_ACCOUNT_CASHFILL_VALUE] = CreateConVar("zr_account_cashfill_value", "12000", "Amount of cash to set player's account to. [Dependency: zr_account_cashfill]"); + g_hCvarsList[CVAR_ACCOUNT_CASHDMG] = CreateConVar("zr_account_cashdmg", "0", "Attacker receives amount of cash equivalent to the damage that was inflicted."); // =========================== @@ -362,7 +355,7 @@ CvarsCreate() // Ragdoll g_hCvarsList[CVAR_VEFFECTS_RAGDOLL_REMOVE] = CreateConVar("zr_veffects_ragdoll_remove", "1", "Remove players' ragdolls from the game after a delay."); - g_hCvarsList[CVAR_VEFFECTS_RAGDOLL_DISSOLVE] = CreateConVar("zr_veffects_ragdoll_dissolve", "1", "The ragdoll removal effect. [-1: Effectless removal | 0: Energy dissolve | 1: Heavy electrical dissolve | 2: Light electrical dissolve | 3: Core dissolve | Dependency: zr_veffects_ragdoll_remove]"); + g_hCvarsList[CVAR_VEFFECTS_RAGDOLL_DISSOLVE] = CreateConVar("zr_veffects_ragdoll_dissolve", "-1", "The ragdoll removal effect. ['-2' = Effectless removal | '-1' = Random effect | '0' = Energy dissolve | '1' = Heavy electrical dissolve | '2' = Light electrical dissolve | '3' = Core dissolve | Dependency: zr_veffects_ragdoll_remove]"); g_hCvarsList[CVAR_VEFFECTS_RAGDOLL_DELAY] = CreateConVar("zr_veffects_ragdoll_delay", "0.5", "Time to wait before removing the ragdoll. [Dependency: zr_veffects_ragdoll_remove]"); // =========================== @@ -409,7 +402,7 @@ CvarsCreate() // Napalm (module) // =========================== - g_hCvarsList[CVAR_NAPALM_IGNITE] = CreateConVar("zr_napalm_ignite", "1", "Ignite grenade in mid-air after player throws it. [Dependency: Human Attribute 'napalm']"); + g_hCvarsList[CVAR_NAPALM_IGNITE] = CreateConVar("zr_napalm_ignite", "1", "Ignite grenade in mid-air after player throws it. [Dependency: Human Attribute 'hasnapalm']"); // =========================== // Jump Boost (module) @@ -430,13 +423,14 @@ CvarsCreate() // =========================== // ZSpawn (module) // =========================== - g_hCvarsList[CVAR_ZSPAWN] = CreateConVar("zr_zspawn", "1", "Allow players to spawn into the game late."); + g_hCvarsList[CVAR_ZSPAWN] = CreateConVar("zr_zspawn", "1", "Allow players to spawn into the game late."); - g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE] = CreateConVar("zr_zspawn_team_override", "1", "Override spawn team when spawning by means of ZSpawn."); - g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE] = CreateConVar("zr_zspawn_team_zombie", "0", "Spawn player on zombie team when spawning by means of ZSpawn. [Dependency: zr_zspawn_team_override | Override: zr_respawn_zombie]"); + g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE] = CreateConVar("zr_zspawn_team_override", "1", "Override spawn team when spawning by means of ZSpawn."); + g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE] = CreateConVar("zr_zspawn_team_zombie", "0", "Spawn player on zombie team when spawning by means of ZSpawn. [Dependency: zr_zspawn_team_override | Override: zr_respawn_zombie]"); - g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT] = CreateConVar("zr_zspawn_timelimit", "1", "Put a time limit on the use of ZSpawn."); - g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME] = CreateConVar("zr_zspawn_timelimit_time", "120.0", "Time from the start of the round to allow ZSpawn. [Dependency: zr_zspawn_timelimit]"); + g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT] = CreateConVar("zr_zspawn_timelimit", "1", "Put a time limit on the use of ZSpawn."); + g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME] = CreateConVar("zr_zspawn_timelimit_time", "120.0", "Time from the start of the round to allow ZSpawn. [Dependency: zr_zspawn_timelimit]"); + g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE] = CreateConVar("zr_zspawn_timelimit_zombie", "1", "Spawn player on the zombie team AFTER the timelimit is up. ['-1' = Block ZSpawn | '0' = Spawn as human | '1' = Spawn as zombie | Dependency: zr_zspawn_timelimit]"); // =========================== diff --git a/src/zr/event.inc b/src/zr/event.inc index 55a629c..9400637 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -81,12 +81,8 @@ EventHook(bool:unhook = false) */ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast) { - // Print round objective to all clients. - TranslationPrintToChatAll(true, false, "General round objective"); - // Forward event to sub-modules. OverlaysOnRoundStart(); - WeaponsOnRoundStart(); RoundStartOnRoundStart(); RoundEndOnRoundStart(); InfectOnRoundStart(); @@ -94,6 +90,23 @@ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadc AntiStickOnRoundStart(); ZSpawnOnRoundStart(); VolOnRoundStart(); + + // Fire post round_start event. + CreateTimer(0.0, EventRoundStartPost); +} + +/** + * Event callback (round_start) + * The round is starting. *Post + * + * @param event The event handle. + * @param name Name of the event. + * @dontBroadcast If true, event is broadcasted to all clients, false if not. + */ +public Action:EventRoundStartPost(Handle:timer, any:index) +{ + // Forward event to modules. + WeaponsOnRoundStartPost(); } /** @@ -180,7 +193,15 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad ZHPOnClientSpawn(index); VolOnPlayerSpawn(index); - TranslationPrintToChat(index, "General zmenu reminder"); + // Get public chat trigger prefix. + decl String:publictrigger[4]; + SayHooksGetPublicChatTrigger(publictrigger, sizeof(publictrigger)); + + // If public chat trigger is disabled, then don't print message. + if (!StrEqual(publictrigger, "N/A", false)) + { + TranslationPrintToChat(index, "General zmenu reminder", publictrigger, SAYHOOKS_KEYWORD_ZMENU); + } // Fire post player_spawn event. CreateTimer(0.0, EventPlayerSpawnPost, index); @@ -228,6 +249,7 @@ public Action:EventPlayerHurt(Handle:event, const String:name[], bool:dontBroadc // Forward event to modules. ClassAlphaUpdate(index); InfectOnClientHurt(index, attacker, weapon); + AccountOnClientHurt(attacker, dmg_health); SEffectsOnClientHurt(index); KnockbackOnClientHurt(index, attacker, weapon, hitgroup, dmg_health); NapalmOnClientHurt(index, attacker, weapon); diff --git a/src/zr/hitgroups.inc b/src/zr/hitgroups.inc index 115a17a..a4de4e8 100644 --- a/src/zr/hitgroups.inc +++ b/src/zr/hitgroups.inc @@ -212,7 +212,7 @@ stock HitgroupToIndex(hitgroup) } /** - * Gets the name of a hitgroup at a given index. + * Gets the name of a hitgroup at a given index. (static) * @param index The hitgroup index. * @param hitgroup The string to return name in. * @param maxlen The max length of the string. @@ -227,7 +227,7 @@ stock HitgroupsGetName(index, String:hitgroup[], maxlen) } /** - * Retrieve hitgroup index. + * Retrieve hitgroup index. (static) * * @param index The array index. * @return The hitgroup index. @@ -242,7 +242,22 @@ stock HitgroupsGetIndex(index) } /** - * Retrieve hitgroup damage value. + * Set hitgroup damage value. (dynamic) + * + * @param index The array index. + * @param candamage True to allow damage to hitgroup, false to block damage. + */ +stock HitgroupsSetDamage(index, bool:candamage) +{ + // Get array handle of hitgroup at given index. + new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index); + + // Return true if hitgroup can be damaged, false if not. + SetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_DAMAGE, candamage); +} + +/** + * Retrieve hitgroup damage value. (dynamic) * * @param index The array index. * @return True if hitgroup can be damaged, false if not. @@ -257,7 +272,22 @@ stock bool:HitgroupsCanDamage(index) } /** - * Retrieve hitgroup knockback value. + * Set hitgroup knockback value. (dynamic) + * + * @param index The array index. + * @param knockback The knockback multiplier for the hitgroup. + */ +stock HitgroupsSetKnockback(index, Float:knockback) +{ + // Get array handle of hitgroup at given index. + new Handle:arrayHitgroup = GetArrayCell(arrayHitgroups, index); + + // Return the knockback multiplier for the hitgroup. + SetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_KNOCKBACK, knockback); +} + +/** + * Retrieve hitgroup knockback value. (dynamic) * * @param index The array index. * @return The knockback multiplier of the hitgroup. diff --git a/src/zr/infect.inc b/src/zr/infect.inc index cbdb4a4..dd5d461 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -100,6 +100,15 @@ InfectLoad() AddFileToDownloadsTable(sound); } +/** + * Create commands specific to infect here. + */ +InfectOnCommandsCreate() +{ + RegAdminCmd("zr_infect", InfectInfectCommand, ADMFLAG_GENERIC, "Infect a client. Usage: zr_infect [respawn - 1/0]"); + RegAdminCmd("zr_human", InfectHumanCommand, ADMFLAG_GENERIC, "Turn a client into a human. Usage: zr_human [respawn - 1/0]"); +} + /** * Client is joining the server. * @@ -119,6 +128,12 @@ InfectClientInit(client) */ InfectOnClientDisconnect(client) { + // If client is still connecting, then stop. + if (!IsClientInGame(client)) + { + return; + } + // If zombie hasn't spawned, then stop. if (!g_bZombieSpawned) { @@ -192,7 +207,7 @@ InfectOnClientDisconnect(client) new randclient = GetArrayCell(arrayEligibleClients, randindex); // Infect player. - InfectClient(randclient); + InfectHumanToZombie(randclient); // Tell client they have been randomly been chosen to replace disconnecting zombie. TranslationPrintToChat(randclient, "Infect disconnect"); @@ -311,7 +326,7 @@ InfectOnClientHurt(client, attacker, const String:weapon[]) } // Infect client. - InfectClient(client, attacker); + InfectHumanToZombie(client, attacker); } /** @@ -470,7 +485,7 @@ public Action:InfectMotherZombie(Handle:timer) client = GetArrayCell(arrayEligibleClients, randindex); // Infect player. - InfectClient(client, _, true); + InfectHumanToZombie(client, _, true); } else { @@ -509,7 +524,7 @@ public Action:InfectMotherZombie(Handle:timer) client = GetArrayCell(arrayEligibleClients, randindex); // Infect player. - InfectClient(client, _, true); + InfectHumanToZombie(client, _, true); // Remove player from eligible zombie list. RemoveFromArray(arrayEligibleClients, randindex); @@ -524,14 +539,16 @@ public Action:InfectMotherZombie(Handle:timer) } /** - * Infects a player. Execute events, sets attributes and flags that indicate - * that the player is a zombie. + * Infects a client. Execute events, sets attributes and flags that indicate + * that the client is a zombie. * - * @param client The player to infect. - * @param attacker (Optional) The attacker who did the infect. - * @param motherinfect (Optional) Indicates a mother zombie infect. + * @param client The client to infect. + * @param attacker (Optional) The attacker who did the infect. + * @param motherinfect (Optional) Indicates a mother zombie infect. + * @param respawnoverride (Optional) Set to true to override respawn cvar. + * @param respawn (Optional) Value to override with. */ -InfectClient(client, attacker = -1, bool:motherinfect = false) +InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respawnoverride = false, bool:respawn = false) { // Mark player as zombie. bZombie[client] = true; @@ -631,8 +648,16 @@ InfectClient(client, attacker = -1, bool:motherinfect = false) ZTeleTeleportClient(client); } } + // Check override. + else + { + if (respawnoverride && respawn) + { + ZTeleTeleportClient(client); + } + } - // Format infection message. + // Set client as translation target. SetGlobalTransTarget(client); // Print message to client. @@ -646,6 +671,46 @@ InfectClient(client, attacker = -1, bool:motherinfect = false) ZHPOnClientInfected(client); } +/** + * Turns a zombie back into a human. Execute events, sets attributes and flags that indicate + * that the client is a human. + * + * @param client The client to make human. + * @param respawn Teleport client back to spawn if true. + * @param protect Start spawn protection on new human. + */ +InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) +{ + // Mark player as human. + bZombie[client] = false; + + // Switch the player to counter-terrorists. + CS_SwitchTeam(client, CS_TEAM_CT); + + // Set client as translation target. + SetGlobalTransTarget(client); + + // Print message to client. + TranslationPrintToChat(client, "Infect human"); + + // Forward event to modules. + ClassOnClientInfected(client, false); + RoundEndOnClientInfected(); + ZTeleOnClientInfected(client); + + // Check if we should respawn the client. + if (respawn) + { + ZTeleTeleportClient(client); + } + + // Check if we should spawn protect the client. + if (protect) + { + SpawnProtectStart(client); + } +} + /** * Creates effects on a newly infected client. * @@ -754,3 +819,139 @@ bool:InfectIsClientHuman(client) // Return opposite of client's zombie flag. return !bZombie[client]; } + +/** + * Command callback (zr_infect) + * Infects a client. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:InfectInfectCommand(client, argc) +{ + // If not enough arguments given, then stop. + if (argc < 1) + { + TranslationReplyToCommand(client, "Infect command infect syntax"); + return Plugin_Handled; + } + + if (!g_bZombieSpawned) + { + TranslationReplyToCommand(client, "Infect command zombie has not spawned"); + return Plugin_Handled; + } + + decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH]; + new targets[MAXPLAYERS], bool:tn_is_ml, result; + + // Get targetname. + GetCmdArg(1, target, sizeof(target)); + + // Find a target. + result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI, targetname, sizeof(targetname), tn_is_ml); + + // Check if there was a problem finding a client. + if (result <= 0) + { + ZRReplyToTargetError(client, result); + return Plugin_Handled; + } + + // Check if client is a human before turning into zombie. + if (InfectIsClientHuman(targets[0])) + { + new bool:respawnoverride, bool:respawn; + decl String:strRespawn[8]; + + // Get respawn parameter. + GetCmdArg(2, strRespawn, sizeof(strRespawn)); + + // If parameter exists then cast it into a bool and feed it to infect function. + if (strRespawn[0]) + { + respawnoverride = true; + respawn = bool:StringToInt(strRespawn); + } + + // Turn client into a zombie. + InfectHumanToZombie(targets[0], _, _, respawnoverride, respawn); + + // Tell admin command was successful. + TranslationReplyToCommand(client, "Infect command infect successful", targetname); + } + else + { + // Tell admin command was unsuccessful. + TranslationReplyToCommand(client, "Infect command infect unsuccessful", targetname); + } + + return Plugin_Handled; +} + +/** + * Command callback (zr_human) + * Turns a client into a human. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:InfectHumanCommand(client, argc) +{ + // If not enough arguments given, then stop. + if (argc < 1) + { + TranslationReplyToCommand(client, "Infect command human syntax"); + return Plugin_Handled; + } + + if (!g_bZombieSpawned) + { + TranslationReplyToCommand(client, "Infect command zombie has not spawned"); + return Plugin_Handled; + } + + decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH]; + new targets[MAXPLAYERS], bool:tn_is_ml, result; + + // Get targetname. + GetCmdArg(1, target, sizeof(target)); + + // Find a target. + result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI, targetname, sizeof(targetname), tn_is_ml); + + // Check if there was a problem finding a client. + if (result <= 0) + { + ZRReplyToTargetError(client, result); + return Plugin_Handled; + } + + // Check if client is a human before turning into zombie. + if (InfectIsClientInfected(targets[0])) + { + new bool:respawn, bool:protect; + decl String:strRespawn[8], String:strProtect[8]; + + // Get respawn&protect parameters + GetCmdArg(2, strRespawn, sizeof(strRespawn)); + GetCmdArg(3, strProtect, sizeof(strProtect)); + + // If parameter exists then cast it into a bool and feed it to "humanize" function. + respawn = (strRespawn[0]) ? (bool:StringToInt(strRespawn)) : false; + protect = (strProtect[0]) ? (bool:StringToInt(strProtect)) : false; + + // Turn client into a zombie. + InfectZombieToHuman(targets[0], respawn, protect); + + // Tell admin command was successful. + TranslationReplyToCommand(client, "Infect command human successful", targetname); + } + else + { + // Tell admin command was unsuccessful. + TranslationReplyToCommand(client, "Infect command human unsuccessful", targetname); + } + + return Plugin_Handled; +} \ No newline at end of file diff --git a/src/zr/menu.inc b/src/zr/menu.inc index be40ccb..c409e76 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -25,6 +25,38 @@ * ============================================================================ */ +/** + * Create commands specific to ZMenu. + */ +MenuOnCommandsCreate() +{ + // Register ZMenu command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZMENU, ZMenuCommand, "Opens ZR's main menu."); +} + +/** + * Command callback (zmenu) + * Opens ZR's main menu. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZMenuCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Send main menu. + MenuMain(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Show main menu to client. * @@ -38,16 +70,23 @@ MenuMain(client) // Make client global translations target. SetGlobalTransTarget(client); + decl String:publictrigger[4]; + decl String:silenttrigger[4]; + + // Get public/silent chat triggers. + SayHooksGetPublicChatTrigger(publictrigger, sizeof(publictrigger)); + SayHooksGetSilentChatTrigger(silenttrigger, sizeof(silenttrigger)); + // Set menu title. - SetMenuTitle(menu_main, "%t\n ", "Menu main title"); + SetMenuTitle(menu_main, "%t\n ", "Menu main title", publictrigger, silenttrigger); // Initialize menu lines. - decl String:zadmin[64]; - decl String:zclass[64]; - decl String:zspawn[64]; - decl String:ztele[64]; - decl String:zhp[64]; - decl String:zmarket[64]; + decl String:zadmin[256]; + decl String:zclass[256]; + decl String:zspawn[256]; + decl String:ztele[256]; + decl String:zhp[256]; + decl String:zmarket[256]; // Translate each line into client's language. Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin", SAYHOOKS_KEYWORD_ZMENU); diff --git a/src/zr/napalm.inc b/src/zr/napalm.inc index f68a2c5..a93a9c7 100644 --- a/src/zr/napalm.inc +++ b/src/zr/napalm.inc @@ -53,7 +53,7 @@ NapalmOnClientHurt(client, attacker, const String:weapon[]) } // If the attacker can't throw napalm grenades, then stop. - if (ClassGetHasNapalm(attacker)) + if (!ClassGetHasNapalm(attacker)) { return; } diff --git a/src/zr/playerclasses/classcommands.inc b/src/zr/playerclasses/classcommands.inc index 5a918e8..23e3e86 100644 --- a/src/zr/playerclasses/classcommands.inc +++ b/src/zr/playerclasses/classcommands.inc @@ -27,6 +27,9 @@ ClassOnCommandsCreate() { + // Register ZClass command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZCLASS, ZClassCommand, "Opens class selection menu."); + // Create base class commands. RegConsoleCmd("zr_class_dump", ClassDumpCommand, "Dumps class data at a specified index in the specified cache. Usage: zr_class_dump "); RegConsoleCmd("zr_class_dump_multipliers", ClassDumpMultipliersCommand, "Dumps class attribute multipliers for the specified team. Usage: zr_class_dump_multipliers <\"zombies\"|\"humans\">"); @@ -43,6 +46,29 @@ ClassOnCommandsHook() ClassOverlayOnCommandsHook(); } +/** + * Command callback (zclass) + * Opens class selection menu. + * + * @param client The client index. + * @param argc Argument count. + */ +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"); + return Plugin_Handled; + } + + // Send class menu. + ClassMenuMain(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Command callback. (zr_class_dump) * Dumps class data at a specified index in the specified cache. diff --git a/src/zr/respawn.inc b/src/zr/respawn.inc index 3e22c53..c36f3ce 100644 --- a/src/zr/respawn.inc +++ b/src/zr/respawn.inc @@ -155,13 +155,13 @@ RespawnSpawnClient(client, bool:zombie = false) // Infect if zombie is true. if (zombie) { - InfectClient(client); + InfectHumanToZombie(client); return; } if (GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE_WORLD]) && bKilledByWorld[client]) { - InfectClient(client); + InfectHumanToZombie(client); bKilledByWorld[client] = false; } } diff --git a/src/zr/roundstart.inc b/src/zr/roundstart.inc index 9bd438d..afeaf0c 100644 --- a/src/zr/roundstart.inc +++ b/src/zr/roundstart.inc @@ -35,6 +35,9 @@ */ RoundStartOnRoundStart() { + // Print round objective to all clients. + TranslationPrintToChatAll(true, false, "General round objective"); + // Kill all objective entities. RoundStartKillObjectives(); } diff --git a/src/zr/sayhooks.inc b/src/zr/sayhooks.inc index 3c97414..48639cc 100644 --- a/src/zr/sayhooks.inc +++ b/src/zr/sayhooks.inc @@ -25,6 +25,17 @@ * ============================================================================ */ +/** + * @section SM core config info. + */ +#define SAYHOOKS_CORE_KVNAME "Core" +#define SAYHOOKS_CORE_KVPATH "configs/core.cfg" +#define SAYHOOKS_CHAT_PUBLIC_DEFAULT "!" +#define SAYHOOKS_CHAT_SILENT_DEFAULT "/" +/** + * @endsection + */ + /** * Max number of characters in a chat text string. */ @@ -33,176 +44,85 @@ /** * @section Say command key words. */ -#define SAYHOOKS_KEYWORD_ZMENU "!zmenu" -#define SAYHOOKS_KEYWORD_ZADMIN "!zadmin" -#define SAYHOOKS_KEYWORD_ZCLASS "!zclass" -#define SAYHOOKS_KEYWORD_ZSPAWN "!zspawn" -#define SAYHOOKS_KEYWORD_ZTELE "!ztele" -#define SAYHOOKS_KEYWORD_ZHP "!zhp" -#define SAYHOOKS_KEYWORD_ZMARKET "!zmarket" +#define SAYHOOKS_KEYWORD_ZMENU "zmenu" +#define SAYHOOKS_KEYWORD_ZADMIN "zadmin" +#define SAYHOOKS_KEYWORD_ZCLASS "zclass" +#define SAYHOOKS_KEYWORD_ZSPAWN "zspawn" +#define SAYHOOKS_KEYWORD_ZTELE "ztele" +#define SAYHOOKS_KEYWORD_ZHP "zhp" +#define SAYHOOKS_KEYWORD_ZMARKET "zmarket" /** * @endsection */ /** - * @section Say hook quiet flags. - */ -#define SAYHOOKS_KEYWORD_FLAG_ZMENU 1 -#define SAYHOOKS_KEYWORD_FLAG_ZADMIN 2 -#define SAYHOOKS_KEYWORD_FLAG_ZCLASS 4 -#define SAYHOOKS_KEYWORD_FLAG_ZSPAWN 8 -#define SAYHOOKS_KEYWORD_FLAG_ZTELE 16 -#define SAYHOOKS_KEYWORD_FLAG_ZHP 32 -#define SAYHOOKS_KEYWORD_FLAG_ZMARKET 64 -/** - * @endsection - */ - -/** - * Say hooks module init function. - */ -SayHooksInit() -{ - // Hook client's say commands. - RegConsoleCmd("say", SayHooksCmdSay); - RegConsoleCmd("say_team", SayHooksCmdSay); -} - -/** - * Command callback. (say, say_team) - * Catches all client's say text and takes action on key words. + * Hack function to get the public chat trigger value. * - * @param client The client index. - * @param argc The number of arguments in command string. + * @param trigger The string to store value in. + * @param maxlen The maximum length of the string. */ -public Action:SayHooksCmdSay(client, argc) +SayHooksGetPublicChatTrigger(String:trigger[], maxlen) { - decl String:args[SAYHOOKS_MAX_CHAT_LENGTH]; + // Create kv handle. + new Handle:kvCore = CreateKeyValues(SAYHOOKS_CORE_KVNAME); - // Get client's command string (typically 'say "text"') - GetCmdArgString(args, sizeof(args)); + // Build path to file. + decl String:filepath[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, filepath, PLATFORM_MAX_PATH, SAYHOOKS_CORE_KVPATH); - // Strip away certain characters. - ReplaceString(args, sizeof(args), "\"", ""); // Strip quotes - ReplaceString(args, sizeof(args), " ", ""); // Strip all whitespace. + // Load kv into memory. + new bool:success = FileToKeyValues(kvCore, filepath); - new chatflag = SayHooksChatToFlag(args); - - // If chatflag is invalid, then continue. - if (!chatflag) + // If the file couldn't be loaded, then return the default value. + if (!success) { - return Plugin_Continue; + strcopy(trigger, maxlen, SAYHOOKS_CHAT_PUBLIC_DEFAULT); + return; } - // Define success as true until otherwise changed. - new bool:success = true; + // Rewind and find value. + KvRewind(kvCore); + KvGetString(kvCore, "PublicChatTrigger", trigger, maxlen, SAYHOOKS_CHAT_PUBLIC_DEFAULT); - switch(chatflag) + // If trigger is disabled, then display as "N/A". + if (!trigger[0]) { - // Client triggered ZMenu flag. - case SAYHOOKS_KEYWORD_FLAG_ZMENU: - { - // Send main menu. - MenuMain(client); - } - // Client triggered ZAdmin flag. - case SAYHOOKS_KEYWORD_FLAG_ZADMIN: - { - success = ZRAdminMenu(client); - } - // Client triggered ZClass flag. - case SAYHOOKS_KEYWORD_FLAG_ZCLASS: - { - // Send class menu. - ClassMenuMain(client); - } - // Client triggered ZSpawn flag. - case SAYHOOKS_KEYWORD_FLAG_ZSPAWN: - { - // Spawns a late-joining client into the game. - success = ZSpawnClient(client); - } - // Client triggered ZTele flag. - case SAYHOOKS_KEYWORD_FLAG_ZTELE: - { - success = ZTeleClient(client); - } - // Client triggered ZHP flag. - case SAYHOOKS_KEYWORD_FLAG_ZHP: - { - // Toggle ZHP. - success = ZHPToggle(client); - } - // Client triggered ZMarket flag. - case SAYHOOKS_KEYWORD_FLAG_ZMARKET: - { - success = ZMarketMenuTypes(client); - } + strcopy(trigger, maxlen, "N/A"); } - - // If quiet cvar is disabled, then continue. - new bool:quiet = GetConVarBool(g_hCvarsList[CVAR_SAYHOOKS_QUIET]); - if (!quiet) - { - return Plugin_Continue; - } - - // If filter is enabled, and the command failed to be executed, then stop. - new bool:filter = GetConVarBool(g_hCvarsList[CVAR_SAYHOOKS_QUIET_FILTER]); - if (filter && !success) - { - return Plugin_Handled; - } - - // If word is flagged to be quieted, then stop. - new quietflags = GetConVarInt(g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS]); - if (quietflags & chatflag) - { - return Plugin_Handled; - } - - return Plugin_Continue; } /** - * Convert chat text into a defined flag. + * Hack function to get the silent chat trigger value. * - * @param chat The chat text to convert. - * @return Returns flag for word given, returns 0 if matches none. + * @param trigger The string to store value in. + * @param maxlen The maximum length of the string. */ -SayHooksChatToFlag(const String:chat[]) +SayHooksGetSilentChatTrigger(String:trigger[], maxlen) { - // Return flag for chatstring. + // Create kv handle. + new Handle:kvCore = CreateKeyValues(SAYHOOKS_CORE_KVNAME); - if (StrEqual(chat, SAYHOOKS_KEYWORD_ZMENU, false)) + // Build path to file. + decl String:filepath[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, filepath, PLATFORM_MAX_PATH, SAYHOOKS_CORE_KVPATH); + + // Load kv into memory. + new bool:success = FileToKeyValues(kvCore, filepath); + + // If the file couldn't be loaded, then return the default value. + if (!success) { - return SAYHOOKS_KEYWORD_FLAG_ZMENU; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZADMIN, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZADMIN; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZCLASS, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZCLASS; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZSPAWN, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZSPAWN; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZTELE, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZTELE; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZHP, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZHP; - } - else if (StrEqual(chat, SAYHOOKS_KEYWORD_ZMARKET, false)) - { - return SAYHOOKS_KEYWORD_FLAG_ZMARKET; + strcopy(trigger, maxlen, SAYHOOKS_CHAT_SILENT_DEFAULT); + return; } - // Return 0. - return 0; -} + // Rewind and find value. + KvRewind(kvCore); + KvGetString(kvCore, "SilentChatTrigger", trigger, maxlen, SAYHOOKS_CHAT_SILENT_DEFAULT); + + // If trigger is disabled, then display as "N/A". + if (!trigger[0]) + { + strcopy(trigger, maxlen, "N/A"); + } +} \ No newline at end of file diff --git a/src/zr/spawnprotect.inc b/src/zr/spawnprotect.inc index 98c5e1a..05ec86e 100644 --- a/src/zr/spawnprotect.inc +++ b/src/zr/spawnprotect.inc @@ -73,8 +73,43 @@ SpawnProtectOnClientSpawn(client) */ SpawnProtectOnClientSpawnPost(client) { - // If client isn't on a team, then stop. - if (!ZRIsClientOnTeam(client)) + // If protect cvar is disabled, then stop. + new bool:protect = GetConVarBool(g_hCvarsList[CVAR_SPAWNPROTECT]); + if (!protect) + { + return; + } + + // Start spawn protection. + SpawnProtectStart(client); +} + +/** + * Client has been killed. + * + * @param client The client index. + */ +SpawnProtectOnClientDeath(client) +{ + // If timer is running, kill it. + if (tSpawnProtect[client] != INVALID_HANDLE) + { + KillTimer(tSpawnProtect[client]); + } + + // Reset timer handle. + tSpawnProtect[client] = INVALID_HANDLE; +} + +/** + * Start spawn protection on a client. + * + * @param client The client index. + */ +SpawnProtectStart(client) +{ + // If client is dead, then stop. + if (!IsPlayerAlive(client)) { return; } @@ -85,13 +120,6 @@ SpawnProtectOnClientSpawnPost(client) return; } - // If protect cvar is disabled, then stop. - new bool:protect = GetConVarBool(g_hCvarsList[CVAR_SPAWNPROTECT]); - if (!protect) - { - return; - } - // If client is a zombie, then stop. if (InfectIsClientInfected(client)) { @@ -123,23 +151,6 @@ SpawnProtectOnClientSpawnPost(client) tSpawnProtect[client] = CreateTimer(1.0, SpawnProtectTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); } -/** - * Client has been killed. - * - * @param client The client index. - */ -SpawnProtectOnClientDeath(client) -{ - // If timer is running, kill it. - if (tSpawnProtect[client] != INVALID_HANDLE) - { - KillTimer(tSpawnProtect[client]); - } - - // Reset timer handle. - tSpawnProtect[client] = INVALID_HANDLE; -} - /** * Timer callback function, countdown for spawn protection. * diff --git a/src/zr/visualeffects/ragdoll.inc b/src/zr/visualeffects/ragdoll.inc index 7a15d11..69c4a90 100644 --- a/src/zr/visualeffects/ragdoll.inc +++ b/src/zr/visualeffects/ragdoll.inc @@ -28,7 +28,8 @@ /** * @section Different dissolve types. */ -#define VEFFECTS_RAGDOLL_DISSOLVE_EFFECTLESS -1 +#define VEFFECTS_RAGDOLL_DISSOLVE_EFFECTLESS -2 +#define VEFFECTS_RAGDOLL_DISSOLVE_RANDOM -1 #define VEFFECTS_RAGDOLL_DISSOLVE_ENERGY 0 #define VEFFECTS_RAGDOLL_DISSOLVE_ELECTRICALH 1 #define VEFFECTS_RAGDOLL_DISSOLVE_ELECTRICALL 2 @@ -101,6 +102,12 @@ RagdollRemove(ragdoll) return; } + // If random, set value to any between "energy" effect and "core" effect. + if (dissolve == VEFFECTS_RAGDOLL_DISSOLVE_RANDOM) + { + dissolve = GetRandomInt(VEFFECTS_RAGDOLL_DISSOLVE_ENERGY, VEFFECTS_RAGDOLL_DISSOLVE_CORE); + } + // Prep the ragdoll for dissolving. decl String:targetname[64]; Format(targetname, sizeof(targetname), "zr_dissolve_%d", ragdoll); diff --git a/src/zr/visualeffects/visualambience.inc b/src/zr/visualeffects/visualambience.inc index 56152e4..59b8888 100644 --- a/src/zr/visualeffects/visualambience.inc +++ b/src/zr/visualeffects/visualambience.inc @@ -35,9 +35,6 @@ new String:g_VAmbienceDefaultSky[PLATFORM_MAX_PATH]; */ VAmbienceLoad() { - // Apply all visual effects now - VAmbienceApplyAll(); - // Find map's default sky. new Handle:hSkyname = FindConVar("sv_skyname"); if (hSkyname != INVALID_HANDLE) @@ -45,6 +42,13 @@ VAmbienceLoad() // Store map's default sky before applying new one. GetConVarString(hSkyname, g_VAmbienceDefaultSky, sizeof(g_VAmbienceDefaultSky)); } + else + { + LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_VEffects, "Sky Caching", "Couldn't find handle to cvar: \"sv_skyname\""); + } + + // Apply all visual effects now + VAmbienceApplyAll(); // If sky is disabled, then stop. new bool:sky = GetConVarBool(g_hCvarsList[CVAR_VEFFECTS_SKY]); diff --git a/src/zr/weapons/weaponalpha.inc b/src/zr/weapons/weaponalpha.inc index a314ca5..3f33240 100644 --- a/src/zr/weapons/weaponalpha.inc +++ b/src/zr/weapons/weaponalpha.inc @@ -69,7 +69,7 @@ WeaponAlphaOnClientDisconnect(client) /** * The round is starting. */ -WeaponAlphaOnRoundStart() +WeaponAlphaOnRoundStartPost() { // Allow weapon render mode to be modified. g_bWeaponAlpha = true; diff --git a/src/zr/weapons/weapons.inc b/src/zr/weapons/weapons.inc index 0009dd6..a2e0df8 100644 --- a/src/zr/weapons/weapons.inc +++ b/src/zr/weapons/weapons.inc @@ -118,6 +118,7 @@ WeaponsOnCommandsCreate() { // Forward event to sub-modules. RestrictOnCommandsCreate(); + ZMarketOnCommandsCreate(); } /** @@ -308,10 +309,10 @@ WeaponsOnClientSpawn(client) /** * The round is starting. */ -WeaponsOnRoundStart() +WeaponsOnRoundStartPost() { // Forward event to sub-modules - WeaponAlphaOnRoundStart(); + WeaponAlphaOnRoundStartPost(); } /** diff --git a/src/zr/weapons/zmarket.inc b/src/zr/weapons/zmarket.inc index b227aa4..d342a35 100644 --- a/src/zr/weapons/zmarket.inc +++ b/src/zr/weapons/zmarket.inc @@ -25,22 +25,6 @@ * ============================================================================ */ -/* * 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 . - **/ - /** * Variable to store buyzone offset value. */ @@ -67,10 +51,12 @@ new String:g_strZMarketLastWeapon[MAXPLAYERS + 1][WeaponsSlot][WEAPONS_MAX_LENGT new bool:g_bZMarketAutoRebuy[MAXPLAYERS + 1]; /** - * Initialize market data. + * Create commands specific to ZMarket. */ -ZMarketInit() +ZMarketOnCommandsCreate() { + // Register ZMarket command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZMARKET, ZMarketCommand, "Opens custom buymenu."); } /** @@ -114,7 +100,12 @@ ZMarketClientInit(client) ZMarketOnClientDisconnect(client) { // Destroy ZMarket array data for client. - CloseHandle(g_hZMarketPurchaseCount[client]); + if (g_hZMarketPurchaseCount[client] != INVALID_HANDLE) + { + CloseHandle(g_hZMarketPurchaseCount[client]); + } + + // Reset handle. g_hZMarketPurchaseCount[client] = INVALID_HANDLE; } @@ -131,7 +122,7 @@ ZMarketOnClientSpawn(client) // If auto-rebuy is enabled, then force client to rebuy weapons. if (g_bZMarketAutoRebuy[client]) { - ZMarketRebuy(client); + ZMarketRebuy(client, true); } } @@ -520,7 +511,7 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false) } new bool:zmarketbuyzone = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]); - if (zmarketbuyzone && !ZMarketIsClientInBuyZone(client)) + if (!rebuy && zmarketbuyzone && !ZMarketIsClientInBuyZone(client)) { TranslationPrintToChat(client, "Weapons zmarket buyzone"); return false; @@ -620,8 +611,11 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false) // Add 1 to the client's purchase count. ZMarketSetPurchaseCount(client, weapon, 1, true); - // Tell client they bought a weapon. - TranslationPrintToChat(client, "Weapons zmarket purchase", weapon); + if (slot != Slot_Invalid && slot != Slot_Projectile) + { + // Tell client they bought a weapon. + TranslationPrintToChat(client, "Weapons zmarket purchase", weapon); + } } else if (!rebuy) { @@ -647,7 +641,7 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false) * * @param client The client index. */ -ZMarketRebuy(client) +ZMarketRebuy(client, bool:rebuy = false) { // If client is a zombie, then stop. if (InfectIsClientInfected(client)) @@ -657,7 +651,7 @@ ZMarketRebuy(client) } new bool:zmarketbuyzone = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE]); - if (zmarketbuyzone && !ZMarketIsClientInBuyZone(client)) + if (!rebuy && zmarketbuyzone && !ZMarketIsClientInBuyZone(client)) { TranslationPrintToChat(client, "Weapons zmarket buyzone"); return; @@ -676,6 +670,29 @@ ZMarketRebuy(client) } } +/** + * Command callback (zmarket) + * Opens custom buymenu. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZMarketCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Send ZMarket menu. + ZMarketMenuTypes(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Checks if a client is in a buyzone. * diff --git a/src/zr/zadmin.inc b/src/zr/zadmin.inc index f407071..03d2f0f 100644 --- a/src/zr/zadmin.inc +++ b/src/zr/zadmin.inc @@ -25,16 +25,56 @@ * ============================================================================ */ +/** + * Create commands specific to ZAdmin. + */ +ZAdminOnCommandsCreate() +{ + // Register ZAdmin command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZADMIN, ZAdminCommand, "Opens ZR admin menu."); +} + +/** + * Command callback (zadmin) + * Opens ZR admin menu. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZAdminCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Send admin menu. + ZRAdminMenu(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + +/** + * Main admin menu. + * + * @param client The client index. + */ bool:ZRAdminMenu(client) { + // If client isn't an admin, then stop. if (!ZRIsClientAdmin(client)) { TranslationPrintToChat(client, "Must be admin"); return false; } + // Create menu handle. new Handle:menu = CreateMenu(ZRAdminMenuHandle); + // Set translation target as the client. SetGlobalTransTarget(client); SetMenuTitle(menu, "%t\n ", "!zadmin title"); @@ -70,6 +110,15 @@ bool:ZRAdminMenu(client) } public ZRAdminMenuHandle(Handle:menu, MenuAction:action, client, slot) +/** + * Menu callback (zadmin) + * Handles options selected in the admin menu. + * + * @param menu The menu handle. + * @param action Action client is doing in menu. + * @param client The client index. + * @param slot The menu slot selected. (starting from 0) + */ { if (action == MenuAction_Select) { @@ -152,7 +201,7 @@ public ZRAdminMenuHandle(Handle:menu, MenuAction:action, client, slot) { decl String:name[64]; GetClientName(target, name, sizeof(name)); - InfectClient(target); + InfectHumanToZombie(target); ShowActivity2(client, "[ZR] ", "Infected %s", name); ZRInfectMenu(client); } diff --git a/src/zr/zhp.inc b/src/zr/zhp.inc index 1870cd4..226e5d9 100644 --- a/src/zr/zhp.inc +++ b/src/zr/zhp.inc @@ -35,6 +35,15 @@ new Handle:tZHP[MAXPLAYERS + 1]; */ new bool:pZHP[MAXPLAYERS + 1]; +/** + * Create commands specific to ZHP. + */ +ZHPOnCommandsCreate() +{ + // Register ZHP command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZHP, ZHPCommand, "Shows real HP as zombie."); +} + /** * Client is joining the server. * @@ -204,6 +213,29 @@ ZHPUpdateHUD(client) TranslationPrintHUDText(client, "Display HP", health); } +/** + * Command callback (zhp) + * Shows real HP as zombie. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZHPCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Toggle ZHP setting. + ZHPToggle(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Timer callback. Repetitively calls ZHPUpdateHUD() until stopped. * diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 9408f41..2d27bd7 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -255,6 +255,54 @@ stock bool:ZRIsClientAdmin(client, AdminFlag:flag = Admin_Generic) return true; } +/** + * Replies to a client with a given message describing a targetting + * failure reason. (formatted for ZR) + * + * Note: The translation phrases are found in common.phrases.txt. + * + * @param client Client index, or 0 for server. + * @param reason COMMAND_TARGET reason. + */ +stock ZRReplyToTargetError(client, reason) +{ + switch (reason) + { + case COMMAND_TARGET_NONE: + { + TranslationReplyToCommand(client, "No matching client"); + } + case COMMAND_TARGET_NOT_ALIVE: + { + TranslationReplyToCommand(client, "Target must be alive"); + } + case COMMAND_TARGET_NOT_DEAD: + { + TranslationReplyToCommand(client, "Target must be dead"); + } + case COMMAND_TARGET_NOT_IN_GAME: + { + TranslationReplyToCommand(client, "Target is not in game"); + } + case COMMAND_TARGET_IMMUNE: + { + TranslationReplyToCommand(client, "Unable to target"); + } + case COMMAND_TARGET_EMPTY_FILTER: + { + TranslationReplyToCommand(client, "No matching clients"); + } + case COMMAND_TARGET_NOT_HUMAN: + { + TranslationReplyToCommand(client, "Cannot target bot"); + } + case COMMAND_TARGET_AMBIGUOUS: + { + TranslationReplyToCommand(client, "More than one client matched"); + } + } +} + /** * Adds support for printing strings longer than 1 KB to console. Max 4 KB. * diff --git a/src/zr/zspawn.inc b/src/zr/zspawn.inc index ce1e209..029f46c 100644 --- a/src/zr/zspawn.inc +++ b/src/zr/zspawn.inc @@ -30,6 +30,15 @@ */ new Handle:tZSpawn = INVALID_HANDLE; +/** + * Create commands specific to ZSpawn. + */ +ZSpawnOnCommandsCreate() +{ + // Register ZSpawn command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZSPAWN, ZSpawnCommand, "Spawn into the game after joining late."); +} + /** * Map is starting. */ @@ -175,31 +184,69 @@ bool:ZSpawnClient(client) return false; } + // Check if zspawn override is enabled, and if so get overidden value. + new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]); + new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]); + // Block is the time limit is up. new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]); if (zspawntimelimit) { if (tZSpawn == INVALID_HANDLE) { - // Get timelimit - new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); - - // Tell client the timelimit for this command has expired. - TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); - return false; + new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]); + switch(zspawntimelimitzombie) + { + case -1: + { + // Get timelimit + new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); + + // Tell client the timelimit for this command has expired. + TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); + return false; + } + case 0: + { + teamzombie = false; + } + case 1: + { + teamzombie = true; + } + } } } - // Check if zspawn override is enabled, and if so get overidden value. - new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]); - new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]); - // Tell respawn module to respawn client. RespawnSpawnClient(client, teamzombie); return true; } +/** + * Command callback (zspawn) + * Spawn into the game after joining late. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZSpawnCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Spawn client. + ZSpawnClient(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Timer callback, resets handle. * diff --git a/src/zr/ztele.inc b/src/zr/ztele.inc index 2f26666..e67118a 100644 --- a/src/zr/ztele.inc +++ b/src/zr/ztele.inc @@ -50,6 +50,15 @@ new Handle:tZTele[MAXPLAYERS + 1]; */ new g_iZTeleTimeLeft[MAXPLAYERS + 1]; +/** + * Create commands specific to ZTele. + */ +ZTeleOnCommandsCreate() +{ + // Register ZMenu command. + RegConsoleCmd(SAYHOOKS_KEYWORD_ZTELE, ZTeleCommand, "Teleport back to spawn if you are stuck."); +} + /** * Client is joining the server. * @@ -217,6 +226,29 @@ ZTeleTeleportClient(client) TeleportEntity(client, g_vecZTeleSpawn[client], NULL_VECTOR, NULL_VECTOR); } +/** + * Command callback (zmenu) + * Teleport back to spawn if you are stuck. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZTeleCommand(client, argc) +{ + // If client is console, then stop and tell them this feature is for players only. + if (ZRIsConsole(client)) + { + TranslationPrintToServer("Must be player"); + return Plugin_Handled; + } + + // Start teleportation process. + ZTeleClient(client); + + // This stops the "Unknown command" message in client's console. + return Plugin_Handled; +} + /** * Timer callback, counts down teleport to the client. *