From 5b7d1b2ff346960da21318f13d1a34baba6b0dce Mon Sep 17 00:00:00 2001 From: Richard Helgeby Date: Fri, 11 Jan 2013 10:07:18 +0100 Subject: [PATCH] Fixed immunity modes not obeying spawn protection. Implemented "kill" immunity mode. --- .../sourcemod/configs/zr/playerclasses.txt | 1 + docs/zr_manual.htm | 12 ++- src/zr/damage.inc | 10 +-- src/zr/immunityhandler.h.inc | 2 +- src/zr/immunityhandler.inc | 79 ++++++++++++++++--- src/zr/infect.inc | 43 ++++++---- 6 files changed, 109 insertions(+), 38 deletions(-) diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt index 9ca0a15..86ab719 100644 --- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt +++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt @@ -34,6 +34,7 @@ // napalm_time decimal Napalm burn duration. Zombies only. // immunity_mode text Special immunity modes. Some modes only works on humans or zombies: // "none" - Instant infection. +// "kill" - Humans are instantly killed instead of turning zombies when attacked by zombies. // "full" - Completely immune. Humans can't be infected, zombies don't receive damage or knock back. Careful with this, it might not be that fun. // "infect" - Humans are immune to infections until HP go below a threshold. Threshold at zero enable stabbing to death. // "damage" - Zombies are immune to damage from humans/grenades, but still vulnerable to knock back. diff --git a/docs/zr_manual.htm b/docs/zr_manual.htm index 35f71b1..9e6ac54 100644 --- a/docs/zr_manual.htm +++ b/docs/zr_manual.htm @@ -1257,6 +1257,11 @@ the admin-only flag in the flags attribute.

none No immunity mode. Instant infection of humans. + + kill + Humans only. Humans will die instantly instead of turning + zombies when attacked by zombies. + full Completely immune. Careful with this mode, it will break the game. @@ -1273,12 +1278,15 @@ the admin-only flag in the flags attribute.

damage Zombies only. Zombies are immune to damage from humans/ - grenades, but are still vulnerable to knock back. + grenades, but are still vulnerable to knock back. Since damage is blocked, + zombies aren't slowed down by bullet hits, but knock back alone. You might + need to increase knock back a bit. delay Humans only. Delay infection for a certain amount of - seconds (immunity_amount value). + seconds (immunity_amount value). There's no notification, so humans need to + be careful.

Subsequent zombie attacks will reduce the delay time with the number of seconds specified in the immunity_cooldown attribute. If you don't want diff --git a/src/zr/damage.inc b/src/zr/damage.inc index c739f68..4793955 100644 --- a/src/zr/damage.inc +++ b/src/zr/damage.inc @@ -278,8 +278,6 @@ public Action:DamageOnTakeDamage(client, &attacker, &inflictor, &Float:damage, & public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:damage, damagetype, ammotype) #endif { - //PrintToChatAll("DamageOnTakeDamage - damage:%f", damage); - // Get classname of the inflictor. decl String:classname[64]; GetEdictClassname(inflictor, classname, sizeof(classname)); @@ -332,10 +330,12 @@ public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:dama return ACTION_CONTINUE; } - // Check if immunity module blocked the damage. - if (ImmunityOnClientDamage(client, attacker, damage)) + // Check if immunity module blocked or modified the damage. + new Action:immunityAction = ImmunityOnClientDamage(client, attacker, damage); + if (immunityAction != Plugin_Continue) { - return ACTION_HANDLED; + // Damage was blocked or modified. + return immunityAction; } // Client is about to be infected, re-add HP so they aren't killed by diff --git a/src/zr/immunityhandler.h.inc b/src/zr/immunityhandler.h.inc index 7181634..f2b78e6 100644 --- a/src/zr/immunityhandler.h.inc +++ b/src/zr/immunityhandler.h.inc @@ -32,7 +32,7 @@ enum ImmunityMode { Immunity_Invalid = -1, /** Invalid immunity mode. Used by validators. */ Immunity_None, /** No immunity mode. */ - + Immunity_Kill, /** Humans are instantly killed when infected by zombies. */ Immunity_Full, /** Completely immune. Humans can't be infected, zombies don't receive damage or knock back. Admin commands may override this. */ Immunity_Infect, /** Humans are immune to infections until HP go below a threshold. Threshold at zero enable stabbing to death. */ Immunity_Damage, /** Zombies are immune to damage from humans/grenades, but still vulnerable to knock back. */ diff --git a/src/zr/immunityhandler.inc b/src/zr/immunityhandler.inc index 7f88406..1b026f1 100644 --- a/src/zr/immunityhandler.inc +++ b/src/zr/immunityhandler.inc @@ -107,8 +107,6 @@ public Action:Command_DeployShield(client, argc) */ bool:ImmunityOnClientInfect(client, attacker) { - //PrintToChatAll("ImmunityOnClientInfect(client=%d, attacker=%d)", client, attacker); - // Get immunity mode from client class. new ImmunityMode:mode = ClassGetImmunityMode(client); @@ -120,6 +118,11 @@ bool:ImmunityOnClientInfect(client, attacker) // Instant infection. return false; } + case Immunity_Kill: + { + // Block infection. Damage is increased in ImmunityOnClientDamage. + return true; + } case Immunity_Full: { // Full immunity, do nothing. @@ -160,8 +163,6 @@ bool:ImmunityOnClientInfect(client, attacker) */ bool:ImmunityOnClientTraceAttack(client, attacker, Float:damage, hitgroup, damageType) { - //PrintToChatAll("ImmunityOnClientTraceAttack(client=%d, attacker=%d, damage=%f, hitgroup=%d, damageType=%d)", client, attacker, damage, hitgroup, damageType); - // Check if there is no attacker (world damage). if (!ZRIsClientValid(attacker)) { @@ -262,16 +263,25 @@ bool:ImmunityOnClientTraceAttack(client, attacker, Float:damage, hitgroup, damag * @param client Client index. * @param attacker Attacker client, if any. * @param damage Damage received by client. + * @param weapon Weapon entity. * - * @return True if damage was blocked, false otherwise. + * @return Plugin_Handled if damage was blocked, Plugin_Changed if + * damage was modified, Plugin_Continue otherwise. */ -bool:ImmunityOnClientDamage(client, attacker, &Float:damage) +Action:ImmunityOnClientDamage(client, attacker, &Float:damage) { // Check if there is no attacker (world damage). if (!ZRIsClientValid(attacker)) { // Allow damage. - return false; + return Plugin_Continue; + } + + // Check if spawn protection is on. + if (bInfectImmune[client][INFECT_TYPE_NORMAL]) + { + // Block damage. + return Plugin_Handled; } // Get immunity mode from client class. @@ -279,6 +289,27 @@ bool:ImmunityOnClientDamage(client, attacker, &Float:damage) switch(mode) { + case Immunity_Kill: + { + // Client must be human and attacker must be zombie. + if (InfectIsClientInfected(client) + || !InfectIsClientInfected(attacker)) + { + // Don't modify damage. + return Plugin_Continue; + } + + // A zombie is attacking a human in kill immunity mode. Increase + // damage so human will be instantly killed. (Using a high damage + // value in case the human class has a lot of HP.) + damage = 60000.0; + + // Update score and health gain. + InfectUpdateScore(attacker, client); + + // Damage was changed. + return Plugin_Changed; + } case Immunity_Infect: { // Prevent humans with low HP from dying when a zombie is @@ -290,7 +321,7 @@ bool:ImmunityOnClientDamage(client, attacker, &Float:damage) InfectOnClientHurt(client, attacker, "knife"); // Block damage to prevent player from dying. - return true; + return Plugin_Handled; } } case Immunity_Delay: @@ -302,12 +333,12 @@ bool:ImmunityOnClientDamage(client, attacker, &Float:damage) InfectOnClientHurt(client, attacker, "knife"); // Block damage to prevent player from dying. - return true; + return Plugin_Handled; } } // Allow damage. - return false; + return Plugin_Continue; } /*____________________________________________________________________________*/ @@ -696,11 +727,14 @@ ImmunityOnMapEnd() * Returns whether the specified damage will take a client's HP below the * infection threshold. Only used by "infect" immunity mode. * + * If threshold is disabled (zero) this function will always return false. + * * @param client Client index. * @param damage Damage applied to client. * * @return True if client HP go below threshold (immunity_amount) when - * applying damage, false otherwise. + * applying damage, false if above threshold or if threshold + * is disabled (zero). */ bool:ImmunityBelowInfectThreshold(client, Float:damage) { @@ -708,8 +742,9 @@ bool:ImmunityBelowInfectThreshold(client, Float:damage) new clientHP = GetClientHealth(client); new dmg = RoundToNearest(damage); - // Check if the damage go below the HP threshold. - if (clientHP - dmg <= 0.0 && threshold > 0) + // Check if the damage go below the HP threshold. Client can only go below + // threshold when threshold is enabled (above zero). + if (clientHP - dmg <= threshold && threshold > 0) { return true; } @@ -737,6 +772,10 @@ ImmunityMode:ImmunityStringToMode(const String:mode[]) { return Immunity_None; } + if (StrEqual(mode, "kill", false)) + { + return Immunity_Kill; + } else if (StrEqual(mode, "full", false)) { return Immunity_Full; @@ -785,6 +824,10 @@ ImmunityModeToString(ImmunityMode:mode, String:buffer[], maxlen) { return strcopy(buffer, maxlen, "none"); } + case Immunity_Kill: + { + return strcopy(buffer, maxlen, "kill"); + } case Immunity_Full: { return strcopy(buffer, maxlen, "full"); @@ -833,6 +876,11 @@ bool:ImmunityIsValidAmount(ImmunityMode:mode, amount) // Immunity mode disabled, amount ignored. return true; } + case Immunity_Kill: + { + // Amount isn't used in this mode. + return true; + } case Immunity_Full: { // Amount isn't used in this mode. @@ -902,6 +950,11 @@ bool:ImmunityIsValidCooldown(ImmunityMode:mode, cooldown) // Immunity mode disabled, amount ignored. return true; } + case Immunity_Kill: + { + // Cooldown isn't used in this mode. + return true; + } case Immunity_Full: { // Cooldown isn't used in this mode. diff --git a/src/zr/infect.inc b/src/zr/infect.inc index f7957f6..fceb51c 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -751,23 +751,8 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa FireEvent(event, false); } - // Give client's infector a point. - new score = ToolsClientScore(attacker, true, false); - ToolsClientScore(attacker, true, true, ++score); - - // Add a death to the zombie's score. - new deaths = ToolsClientScore(client, false, false); - ToolsClientScore(client, false, true, ++deaths); - - // Apply infect HP gain. - new healthgain = ClassGetHealthInfectGain(attacker); - new health = GetClientHealth(attacker); - - // Set attacker's new health. - SetEntityHealth(attacker, health + healthgain); - - // Forward event to modules. - ZHPOnHealthInfectGain(attacker); + // Apply score and health gain. + InfectUpdateScore(attacker, client); } // Get a list of all client's weapon indexes. @@ -880,6 +865,30 @@ InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) ImmunityOnClientHuman(client); } +/** + * Updates score for attacker and victim. Applies health gain for attacker. + */ +InfectUpdateScore(attacker, victim) +{ + // Give client's infector a point. + new score = ToolsClientScore(attacker, true, false); + ToolsClientScore(attacker, true, true, ++score); + + // Add a death to the zombie's score. + new deaths = ToolsClientScore(victim, false, false); + ToolsClientScore(victim, false, true, ++deaths); + + // Apply infect HP gain. + new healthgain = ClassGetHealthInfectGain(attacker); + new health = GetClientHealth(attacker); + + // Set attacker's new health. + SetEntityHealth(attacker, health + healthgain); + + // Forward event to modules. + ZHPOnHealthInfectGain(attacker); +} + /** * Creates effects on a newly infected client. *