Implemented infect immunity mode. Debug messages are still enabled, and some parts aren't updated yet (compiler warnings).
This commit is contained in:
parent
cd604c2f95
commit
31c727f0a5
@ -32,14 +32,15 @@
|
|||||||
// fov number Field of view value. 90 is default.
|
// fov number Field of view value. 90 is default.
|
||||||
// has_napalm yes/no 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.
|
// napalm_time decimal Napalm burn duration. Zombies only.
|
||||||
// immunity_mode test How the human is infected (humans only):
|
// immunity_mode test Special immunity modes. Some modes only works on humans or zombies:
|
||||||
// "none" - Instant infection.
|
// "none" - Instant infection.
|
||||||
// "full" - Immune to infection. Careful with this, it might not be that fun.
|
// "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.
|
||||||
// "damage" - Allow zombies to stab humans to death, or below a HP threshold.
|
// "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.
|
||||||
// "delay" - Delay infection for a certain number of seconds.
|
// "delay" - Delay infection for a certain number of seconds.
|
||||||
// "shield" - Allow human to deploy a shield that will give a temporary full immunity against infections.
|
// "shield" - Shield against infections (humans) or knock back (zombies) for a certain amount of seconds (similar to TF2's übercharge).
|
||||||
// immunity_amount number Immunity data value (humans only). Depends on the immunity mode above:
|
// immunity_amount number Immunity data value (humans only). Depends on the immunity mode above:
|
||||||
// "damage" - HP threshold. Infection will be allowed when HP go below this value. Zero will enable stabbing to death.
|
// "infect" - HP threshold. Infection will be allowed when HP go below this value. Zero will enable stabbing to death.
|
||||||
// "delay" - Number of seconds the infection is delayed since first hit by a zombie.
|
// "delay" - Number of seconds the infection is delayed since first hit by a zombie.
|
||||||
// "shield" - Number of seconds the shield is active.
|
// "shield" - Number of seconds the shield is active.
|
||||||
// immunity_cooldown number Number of seconds of cooldown for temporary immunity effects (currently just shield mode).
|
// immunity_cooldown number Number of seconds of cooldown for temporary immunity effects (currently just shield mode).
|
||||||
@ -90,7 +91,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "2500"
|
"health" "2500"
|
||||||
@ -134,7 +136,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "2000"
|
"health" "2000"
|
||||||
@ -178,7 +181,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "3500"
|
"health" "3500"
|
||||||
@ -222,7 +226,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "4000"
|
"health" "4000"
|
||||||
@ -266,7 +271,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "2500"
|
"health" "2500"
|
||||||
@ -310,7 +316,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "3500"
|
"health" "3500"
|
||||||
@ -360,7 +367,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "no"
|
"no_fall_damage" "no"
|
||||||
|
|
||||||
"health" "100"
|
"health" "100"
|
||||||
@ -404,7 +412,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "200"
|
"health" "200"
|
||||||
@ -448,7 +457,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "200"
|
"health" "200"
|
||||||
@ -492,7 +502,8 @@
|
|||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "none"
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "1"
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "0"
|
"no_fall_damage" "0"
|
||||||
|
|
||||||
"health" "100"
|
"health" "100"
|
||||||
@ -535,8 +546,9 @@
|
|||||||
"napalm_time" "0.0"
|
"napalm_time" "0.0"
|
||||||
|
|
||||||
// Player behavior
|
// Player behavior
|
||||||
"immunity_mode" "none"
|
"immunity_mode" "infect" // Immune against infection,
|
||||||
"immunity_amount" "0"
|
"immunity_amount" "10" // when HP is above 10.
|
||||||
|
"immunity_cooldown" "60"
|
||||||
"no_fall_damage" "yes"
|
"no_fall_damage" "yes"
|
||||||
|
|
||||||
"health" "100"
|
"health" "100"
|
||||||
|
@ -38,11 +38,13 @@
|
|||||||
#include <sdkhooks>
|
#include <sdkhooks>
|
||||||
|
|
||||||
#define ACTION_CONTINUE Plugin_Continue
|
#define ACTION_CONTINUE Plugin_Continue
|
||||||
|
#define ACTION_CHANGED Plugin_Changed
|
||||||
#define ACTION_HANDLED Plugin_Handled
|
#define ACTION_HANDLED Plugin_Handled
|
||||||
#else
|
#else
|
||||||
#include <zrtools>
|
#include <zrtools>
|
||||||
|
|
||||||
#define ACTION_CONTINUE ZRTools_Continue
|
#define ACTION_CONTINUE ZRTools_Continue
|
||||||
|
#define ACTION_CHANGED ZRTools_Changed
|
||||||
#define ACTION_HANDLED ZRTools_Handled
|
#define ACTION_HANDLED ZRTools_Handled
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -198,6 +200,7 @@ public OnMapEnd()
|
|||||||
VolOnMapEnd();
|
VolOnMapEnd();
|
||||||
VEffectsOnMapEnd();
|
VEffectsOnMapEnd();
|
||||||
ZombieSoundsOnMapEnd();
|
ZombieSoundsOnMapEnd();
|
||||||
|
ImmunityOnMapEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,6 +263,7 @@ public OnClientPutInServer(client)
|
|||||||
RespawnClientInit(client);
|
RespawnClientInit(client);
|
||||||
ZTeleClientInit(client);
|
ZTeleClientInit(client);
|
||||||
ZHPClientInit(client);
|
ZHPClientInit(client);
|
||||||
|
ImmunityClientInit(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,6 +316,7 @@ public OnClientDisconnect(client)
|
|||||||
AntiStickOnClientDisconnect(client);
|
AntiStickOnClientDisconnect(client);
|
||||||
ZSpawnOnClientDisconnect(client);
|
ZSpawnOnClientDisconnect(client);
|
||||||
VolOnPlayerDisconnect(client);
|
VolOnPlayerDisconnect(client);
|
||||||
|
ImmunityOnClientDisconnect(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,6 +216,14 @@ public ZRTools_Action:DamageTraceAttack(client, inflictor, attacker, Float:damag
|
|||||||
|
|
||||||
// Here we know that attacker and client are different teams.
|
// Here we know that attacker and client are different teams.
|
||||||
|
|
||||||
|
// Check if immunity module requires damage to be blocked.
|
||||||
|
if (ImmunityOnClientTraceAttack(client, attacker, damage, hitgroup, damagetype))
|
||||||
|
{
|
||||||
|
// Block damage.
|
||||||
|
PrintToChatAll("DamageTraceAttack - Blocking damage.");
|
||||||
|
return ACTION_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
// If client is a human, then allow damage.
|
// If client is a human, then allow damage.
|
||||||
if (InfectIsClientHuman(client))
|
if (InfectIsClientHuman(client))
|
||||||
{
|
{
|
||||||
@ -271,6 +279,8 @@ public Action:DamageOnTakeDamage(client, &attacker, &inflictor, &Float:damage, &
|
|||||||
public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:damage, damagetype, ammotype)
|
public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:damage, damagetype, ammotype)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
PrintToChatAll("DamageOnTakeDamage - damage:%f", damage);
|
||||||
|
|
||||||
// Get classname of the inflictor.
|
// Get classname of the inflictor.
|
||||||
decl String:classname[64];
|
decl String:classname[64];
|
||||||
GetEdictClassname(inflictor, classname, sizeof(classname));
|
GetEdictClassname(inflictor, classname, sizeof(classname));
|
||||||
@ -323,13 +333,23 @@ public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:dama
|
|||||||
return ACTION_CONTINUE;
|
return ACTION_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is about to be infected, re-add HP so they aren't killed by knife.
|
// Check if immunity module blocked the damage.
|
||||||
|
if (ImmunityOnClientDamage(client, attacker, damage))
|
||||||
|
{
|
||||||
|
return ACTION_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client is about to be infected, re-add HP so they aren't killed by
|
||||||
|
// knife. But only do this when immunity mode is disabled.
|
||||||
|
if (ClassGetImmunityMode(client) == Immunity_None)
|
||||||
|
{
|
||||||
new health = GetClientHealth(client);
|
new health = GetClientHealth(client);
|
||||||
SetEntityHealth(client, health + RoundToNearest(damage));
|
SetEntityHealth(client, health + RoundToNearest(damage));
|
||||||
|
|
||||||
// Allow damage.
|
// Allow damage.
|
||||||
return ACTION_CONTINUE;
|
return ACTION_CONTINUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Client was damaged by explosion.
|
// Client was damaged by explosion.
|
||||||
else if (damagetype & DMG_CSS_BLAST)
|
else if (damagetype & DMG_CSS_BLAST)
|
||||||
{
|
{
|
||||||
|
@ -144,6 +144,7 @@ public Action:EventRoundEnd(Handle:event, const String:name[], bool:dontBroadcas
|
|||||||
RespawnOnRoundEnd();
|
RespawnOnRoundEnd();
|
||||||
ZSpawnOnRoundEnd();
|
ZSpawnOnRoundEnd();
|
||||||
VolOnRoundEnd();
|
VolOnRoundEnd();
|
||||||
|
ImmunityOnRoundEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,6 +163,7 @@ public Action:EventPlayerTeam(Handle:event, const String:name[], bool:dontBroadc
|
|||||||
|
|
||||||
// Forward event to modules.
|
// Forward event to modules.
|
||||||
InfectOnClientTeam(index, team);
|
InfectOnClientTeam(index, team);
|
||||||
|
ImmunityOnClientTeam(index);
|
||||||
|
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@ -190,6 +192,7 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad
|
|||||||
ZTeleOnClientSpawn(index);
|
ZTeleOnClientSpawn(index);
|
||||||
ZHPOnClientSpawn(index);
|
ZHPOnClientSpawn(index);
|
||||||
VolOnPlayerSpawn(index);
|
VolOnPlayerSpawn(index);
|
||||||
|
ImmunityClientSpawn(index);
|
||||||
|
|
||||||
// Fire post player_spawn event.
|
// Fire post player_spawn event.
|
||||||
CreateTimer(0.1, EventPlayerSpawnPost, index);
|
CreateTimer(0.1, EventPlayerSpawnPost, index);
|
||||||
@ -292,6 +295,7 @@ public Action:EventPlayerDeath(Handle:event, const String:name[], bool:dontBroad
|
|||||||
ZHPOnClientDeath(index);
|
ZHPOnClientDeath(index);
|
||||||
VolOnPlayerDeath(index);
|
VolOnPlayerDeath(index);
|
||||||
RoundEndOnClientDeath();
|
RoundEndOnClientDeath();
|
||||||
|
ImmunityOnClientDeath(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,23 +36,40 @@ new ImmunityMode:PlayerImmunityMode[MAXPLAYERS + 1] = {Immunity_None, ...};
|
|||||||
new Handle:PlayerImmunityTimer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
|
new Handle:PlayerImmunityTimer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last time a temporary immunity action was used (currently just shield mode).
|
* Remaining time of timed immunity actions.
|
||||||
* Used with cooldown of actions.
|
|
||||||
*/
|
*/
|
||||||
new PlayerImmunityLastUse[MAXPLAYERS + 1] = {-1, ...};
|
new PlayerImmunityDuration[MAXPLAYERS + 1] = {-1, ...};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached attacker index for delayed infections, if available.
|
||||||
|
*/
|
||||||
|
new PlayerImmunityAttacker[MAXPLAYERS + 1] = {0, ...};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of last action. Usage depends on mode (cooldown, etc).
|
||||||
|
*/
|
||||||
|
new PlayerImmunityLastUse[MAXPLAYERS + 1] = {0, ...};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the player has passed a threshold (infect mode).
|
||||||
|
*/
|
||||||
|
new bool:PlayerImmunityThresholdPassed[MAXPLAYERS + 1] = {false, ...};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles immunity when a client is about to be infected. This function may
|
* Handles immunity when a client is about to be infected. This function may
|
||||||
* delay or block infection according to the immunity mode class settings.
|
* delay or block infection according to the immunity mode class settings.
|
||||||
*
|
*
|
||||||
* @param client Client that's being infected.
|
* @param client Client that's being infected.
|
||||||
|
* @param attacker Attacker client (zombie).
|
||||||
*
|
*
|
||||||
* @return True if infection will be handled by this module, false if
|
* @return True if infection will be handled by this module, false if
|
||||||
* infection can be applied instantly.
|
* infection can be applied instantly.
|
||||||
*/
|
*/
|
||||||
bool:ImmunityOnClientInfect(client)
|
bool:ImmunityOnClientInfect(client, attacker)
|
||||||
{
|
{
|
||||||
// Get immunity data from client class.
|
PrintToChatAll("ImmunityOnClientInfect(client=%d, attacker=%d)", client, attacker);
|
||||||
|
|
||||||
|
// Get immunity mode from client class.
|
||||||
new ImmunityMode:mode = ClassGetImmunityMode(client);
|
new ImmunityMode:mode = ClassGetImmunityMode(client);
|
||||||
|
|
||||||
// Check mode.
|
// Check mode.
|
||||||
@ -68,35 +85,197 @@ bool:ImmunityOnClientInfect(client)
|
|||||||
// Full immunity, do nothing.
|
// Full immunity, do nothing.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Immunity_Damage:
|
case Immunity_Infect:
|
||||||
{
|
{
|
||||||
return ImmunityDamageModeHandler(client);
|
return ImmunityInfectModeHandler(client, attacker);
|
||||||
}
|
}
|
||||||
case Immunity_Delay:
|
case Immunity_Delay:
|
||||||
{
|
{
|
||||||
return ImmunityDelayModeHandler(client);
|
return ImmunityDelayModeHandler(client, attacker);
|
||||||
}
|
}
|
||||||
case Immunity_Shield:
|
case Immunity_Shield:
|
||||||
{
|
{
|
||||||
return ImmunityShieldModeHandler(client);
|
return ImmunityShieldModeHandler(client);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
{
|
|
||||||
ThrowError("Invalid immunity mode. This is a bug in ZR.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Current mode doesn't apply to infection.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client is about to receive damage (zombie).
|
* TraceAttack hook.
|
||||||
*
|
*
|
||||||
* @param Client that's receiving damage.
|
* Returns whether attacker damage should be blocked. If damage is blocked this
|
||||||
|
* module will handle it.
|
||||||
|
*
|
||||||
|
* @param client Client index.
|
||||||
|
* @param attacker Attacker client, if any.
|
||||||
|
* @param damage Damage received by client.
|
||||||
|
* @param hitgroup Hitgroup receiving damage.
|
||||||
*
|
*
|
||||||
* @return True if damage should be blocked, false otherwise.
|
* @return True if damage should be blocked, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool:ImmunityOnClientHurt(client)
|
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))
|
||||||
|
{
|
||||||
|
// Allow damage.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get immunity mode from client class.
|
||||||
|
new ImmunityMode:mode = ClassGetImmunityMode(client);
|
||||||
|
|
||||||
|
// Check mode.
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case Immunity_Full:
|
||||||
|
{
|
||||||
|
// Block damage.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Immunity_Infect:
|
||||||
|
{
|
||||||
|
// Client must be human.
|
||||||
|
if (InfectIsClientInfected(client))
|
||||||
|
{
|
||||||
|
// Allow damage.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if damage give HP below the infection threshold.
|
||||||
|
if (ImmunityBelowInfectThreshold(client, damage))
|
||||||
|
{
|
||||||
|
PrintToChatAll("ImmunityOnClientTraceAttack - Threshold passed");
|
||||||
|
PlayerImmunityThresholdPassed[client] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlayerImmunityThresholdPassed[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*new threshold = ClassGetImmunityAmount(client);
|
||||||
|
new clientHP = GetClientHealth(client);
|
||||||
|
new dmg = RoundToNearest(damage);
|
||||||
|
PrintToChatAll("threshold=%d, clientHp=%d", threshold, clientHP);
|
||||||
|
|
||||||
|
// Prevent humans with low HP from dying when a zombie is
|
||||||
|
// attacking, and stab to death is disabled (threshold above zero).
|
||||||
|
if (clientHP - dmg <= 0.0 && threshold > 0)
|
||||||
|
{
|
||||||
|
// Client is about to be infected. Remove damage, but don't
|
||||||
|
// block the damage event. The infect module need it to detect
|
||||||
|
// zombie attack.
|
||||||
|
damage = 0.0;
|
||||||
|
|
||||||
|
// Client is about to be infected, re-add HP so they aren't
|
||||||
|
// killed by knife. Don't block the damage, the infect
|
||||||
|
// module need the damage event.
|
||||||
|
//PrintToChatAll("Re-add HP.");
|
||||||
|
//SetEntityHealth(client, clientHP + dmg);
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
case Immunity_Damage:
|
||||||
|
{
|
||||||
|
// Client must be zombie.
|
||||||
|
if (!InfectIsClientInfected(client))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get attacker weapon.
|
||||||
|
decl String:weapon[32];
|
||||||
|
weapon[0] = 0;
|
||||||
|
if (damageType == DMG_BLAST)
|
||||||
|
{
|
||||||
|
// Most likely a HE grenade. GetClientWeapon can't be used if
|
||||||
|
// the attacker throw grenades. The attacker may switch weapon
|
||||||
|
// before the grenade explodes.
|
||||||
|
strcopy(weapon, sizeof(weapon), "hegrenade");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetClientWeapon(attacker, weapon, sizeof(weapon));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since damage is blocked, trigger knock back hurt event manually.
|
||||||
|
KnockbackOnClientHurt(client, attacker, weapon, hitgroup, RoundToNearest(damage));
|
||||||
|
|
||||||
|
// Block damage from attacker.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Immunity_Delay:
|
||||||
|
{
|
||||||
|
// Client must be human.
|
||||||
|
if (InfectIsClientInfected(client))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block damage if there's an infection in progress.
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintToChatAll("Allow damage.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TakeDamage hook.
|
||||||
|
*
|
||||||
|
* Blocks or modifies damage in certain situations.
|
||||||
|
*
|
||||||
|
* @param client Client index.
|
||||||
|
* @param attacker Attacker client, if any.
|
||||||
|
* @param damage Damage received by client.
|
||||||
|
*
|
||||||
|
* @return True if damage was blocked, false otherwise.
|
||||||
|
*/
|
||||||
|
bool:ImmunityOnClientDamage(client, attacker, &Float:damage)
|
||||||
|
{
|
||||||
|
PrintToChatAll("ImmunityOnClientDamage(client=%d, attacker=%d, damage=%f)", client, attacker, damage);
|
||||||
|
|
||||||
|
// Check if there is no attacker (world damage).
|
||||||
|
if (!ZRIsClientValid(attacker))
|
||||||
|
{
|
||||||
|
// Allow damage.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get immunity mode from client class.
|
||||||
|
new ImmunityMode:mode = ClassGetImmunityMode(client);
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case Immunity_Infect:
|
||||||
|
{
|
||||||
|
// Prevent humans with low HP from dying when a zombie is
|
||||||
|
// attacking, and stab to death is disabled (threshold above zero).
|
||||||
|
if (ImmunityBelowInfectThreshold(client, damage))
|
||||||
|
{
|
||||||
|
PrintToChatAll("ImmunityOnClientDamage - Below threshold, removing damage.");
|
||||||
|
// Client is about to be infected. Remove damage so the client
|
||||||
|
// won't die.
|
||||||
|
//damage = 0.0;
|
||||||
|
|
||||||
|
// Fake hurt event because it's not triggered when the damage
|
||||||
|
// was removed (because no one is actually hurt).
|
||||||
|
InfectOnClientHurt(client, attacker, "knife");
|
||||||
|
|
||||||
|
// Block damage to prevent player from dying.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow damage.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,15 +290,53 @@ bool:ImmunityOnClientKnockBack(client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles damage mode immunity.
|
* Handles infect mode immunity.
|
||||||
|
*
|
||||||
|
* Allow humans to receive damage from zombies until HP is below a certain
|
||||||
|
* threshold. If the threshold is zero, never infect.
|
||||||
*
|
*
|
||||||
* @param client Client that's being infected.
|
* @param client Client that's being infected.
|
||||||
|
* @param attacker Attacker client (zombie).
|
||||||
*
|
*
|
||||||
* @return True if infection will be handled by this module, false if
|
* @return True if infection will be handled by this module, false if
|
||||||
* infection can be applied instantly.
|
* infection can be applied instantly.
|
||||||
*/
|
*/
|
||||||
bool:ImmunityDamageModeHandler(client)
|
bool:ImmunityInfectModeHandler(client, attacker)
|
||||||
{
|
{
|
||||||
|
PrintToChatAll("ImmunityInfectModeHandler(client=%d, attacker=%d)", client, attacker);
|
||||||
|
|
||||||
|
// Note: ImmunityOnClientDamage and ImmunityOnClientTraceAttack hook into
|
||||||
|
// the damage module to prevent humans with low HP from dying when
|
||||||
|
// they're not supposed to.
|
||||||
|
|
||||||
|
new threshold = ClassGetImmunityAmount(client);
|
||||||
|
PrintToChatAll("threshold=%d", threshold);
|
||||||
|
|
||||||
|
// Check if infection is disabled.
|
||||||
|
if (threshold == 0)
|
||||||
|
{
|
||||||
|
// Infection is handled here: blocked.
|
||||||
|
PrintToChatAll("Infection disabled, block infection.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PlayerImmunityThresholdPassed[client])
|
||||||
|
{
|
||||||
|
// Client HP below threshold, allow instant infection.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*new clientHP = GetClientHealth(client);
|
||||||
|
PrintToChatAll("clientHP=%d", clientHP);
|
||||||
|
|
||||||
|
if (clientHP < threshold)
|
||||||
|
{
|
||||||
|
// Client HP below threshold, allow instant infection.
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
PrintToChatAll("Above threshold, block infection.");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,55 +347,146 @@ bool:ImmunityDamageModeHandler(client)
|
|||||||
* @return True if infection will be handled by this module, false if
|
* @return True if infection will be handled by this module, false if
|
||||||
* infection can be applied instantly.
|
* infection can be applied instantly.
|
||||||
*/
|
*/
|
||||||
bool:ImmunityDelayModeHandler(client)
|
bool:ImmunityDelayModeHandler(client, attacker)
|
||||||
{
|
{
|
||||||
|
// Check if an infection is in progress
|
||||||
|
if (PlayerImmunityTimer[client] != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
// Additional attacks while a delayed infection is in progress will
|
||||||
|
// speedup the infection.
|
||||||
|
|
||||||
|
// Trigger timer event to reduce duration.
|
||||||
|
ImmunityDelayTimerHandler(PlayerImmunityTimer[client], client);
|
||||||
|
|
||||||
|
// Block infection.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a delayed infection. Initialize duration and attacker.
|
||||||
|
PlayerImmunityDuration[client] = ClassGetImmunityAmount(client);
|
||||||
|
PlayerImmunityAttacker[client] = attacker;
|
||||||
|
|
||||||
|
// Create repated 1-second timer.
|
||||||
|
PlayerImmunityTimer[client] = CreateTimer(1.0, ImmunityDelayTimerHandler, client, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT);
|
||||||
|
|
||||||
|
// Block infection.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action:ImmunityDelayTimerHandler(Handle:timer, any:client)
|
||||||
|
{
|
||||||
|
// Verify that client is connected and alive.
|
||||||
|
if (!IsClientInGame(client) || !IsPlayerAlive(client))
|
||||||
|
{
|
||||||
|
// Client disconnected or died. Abort immunity action.
|
||||||
|
PlayerImmunityTimer[client] = INVALID_HANDLE;
|
||||||
|
ImmunityAbortHandler(client, false);
|
||||||
|
return Plugin_Stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Read cvar for reduction amount.
|
||||||
|
new reduction = 2;
|
||||||
|
|
||||||
|
// Reduce duration.
|
||||||
|
PlayerImmunityDuration[client] -= reduction;
|
||||||
|
|
||||||
|
// Check if time is up.
|
||||||
|
if (PlayerImmunityDuration[client] <= 0)
|
||||||
|
{
|
||||||
|
// Time is up. Reset data.
|
||||||
|
PlayerImmunityDuration[client] = 0;
|
||||||
|
PlayerImmunityTimer[client] = INVALID_HANDLE;
|
||||||
|
ZREndTimer(PlayerImmunityTimer[client]);
|
||||||
|
|
||||||
|
// Infect client.
|
||||||
|
InfectHumanToZombie(client, PlayerImmunityAttacker[client]);
|
||||||
|
|
||||||
|
return Plugin_Stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles shield mode immunity.
|
* Handles shield mode immunity.
|
||||||
*
|
*
|
||||||
* @param client Client that's being infected.
|
* Zombies will get a shield against knock back, while humans become immune of
|
||||||
|
* infections.
|
||||||
|
*
|
||||||
|
* @param client Client deploying shield.
|
||||||
|
* @param asZombie Client is a zombie.
|
||||||
*
|
*
|
||||||
* @return True if infection will be handled by this module, false if
|
* @return True if infection will be handled by this module, false if
|
||||||
* infection can be applied instantly.
|
* infection can be applied instantly.
|
||||||
*/
|
*/
|
||||||
bool:ImmunityShieldModeHandler(client)
|
bool:ImmunityShieldModeHandler(client, bool:asZombie = true)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts any immunity mode in action (shields, delays, etc.).
|
* Aborts any immunity mode in action (shields, delays, etc.). Resets values.
|
||||||
*
|
*
|
||||||
* @param client Client that's aborting immunity mode actions.
|
* @param client Client that's aborting immunity mode actions.
|
||||||
|
* @param resetLastUse Reset timestamp of last use. This will reset cooldown.
|
||||||
*/
|
*/
|
||||||
ImmunityAbortHandler(client)
|
ImmunityAbortHandler(client, bool:resetLastUse = true)
|
||||||
{
|
{
|
||||||
// TODO: Stop timers, disable shield.
|
// Stop timer, if running.
|
||||||
|
ZREndTimer(PlayerImmunityTimer[client]);
|
||||||
|
|
||||||
|
// Reset data.
|
||||||
|
PlayerImmunityDuration[client] = -1;
|
||||||
|
PlayerImmunityAttacker[client] = 0;
|
||||||
|
PlayerImmunityThresholdPassed[client] = false;
|
||||||
|
|
||||||
|
if (resetLastUse)
|
||||||
|
{
|
||||||
|
PlayerImmunityLastUse[client] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityAbortAll()
|
/**
|
||||||
|
* Aborts all immunity modes in action.
|
||||||
|
*
|
||||||
|
* @param resetLastUse Reset timestamp of last use. This will reset cooldown.
|
||||||
|
*/
|
||||||
|
ImmunityAbortAll(bool:resetLastUse = true)
|
||||||
{
|
{
|
||||||
|
for (new client = 0; client < MAXPLAYERS + 1; client++)
|
||||||
|
{
|
||||||
|
ImmunityAbortHandler(resetLastUse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityOnClientHuman(client)
|
ImmunityOnClientHuman(client)
|
||||||
{
|
{
|
||||||
|
ImmunityAbortHandler(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityOnClientDeath(client, attacker)
|
ImmunityOnClientDeath(client)
|
||||||
{
|
{
|
||||||
|
ImmunityAbortHandler(client, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityClientInit(client)
|
ImmunityClientInit(client)
|
||||||
{
|
{
|
||||||
// Abord old actions, initialize variables.
|
ImmunityAbortHandler(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityOnClientDisconnect(client, attacker)
|
ImmunityClientSpawn(client)
|
||||||
{
|
{
|
||||||
|
ImmunityAbortHandler(client, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityOnClientTeam(client, team)
|
ImmunityOnClientDisconnect(client)
|
||||||
{
|
{
|
||||||
|
// Loop through attacker cache and remove client (set to 0).
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmunityOnClientTeam(client)
|
||||||
|
{
|
||||||
|
ImmunityAbortHandler(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmunityOnRoundEnd()
|
ImmunityOnRoundEnd()
|
||||||
@ -191,6 +499,23 @@ ImmunityOnMapEnd()
|
|||||||
ImmunityAbortAll();
|
ImmunityAbortAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool:ImmunityBelowInfectThreshold(client, Float:damage)
|
||||||
|
{
|
||||||
|
new threshold = ClassGetImmunityAmount(client);
|
||||||
|
new clientHP = GetClientHealth(client);
|
||||||
|
new dmg = RoundToNearest(damage);
|
||||||
|
|
||||||
|
PrintToChatAll("threshold=%d, clientHp=%d", threshold, clientHP);
|
||||||
|
|
||||||
|
// Check if the damage go below the HP threshold.
|
||||||
|
if (clientHP - dmg <= 0.0 && threshold > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string to an immunity mode.
|
* Converts a string to an immunity mode.
|
||||||
*
|
*
|
||||||
|
@ -301,7 +301,8 @@ InfectOnClientDeath(client, attacker)
|
|||||||
ToolsClientScore(attacker, true, true, score + bonus);
|
ToolsClientScore(attacker, true, true, score + bonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Client has been hurt.
|
/**
|
||||||
|
* Client has been hurt.
|
||||||
*
|
*
|
||||||
* @param client The client index.
|
* @param client The client index.
|
||||||
* @param attacker The attacker index.
|
* @param attacker The attacker index.
|
||||||
@ -339,6 +340,13 @@ InfectOnClientHurt(client, attacker, const String:weapon[])
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the immunity module is handling the infection.
|
||||||
|
if (ImmunityOnClientInfect(client, attacker))
|
||||||
|
{
|
||||||
|
PrintToChatAll("InfectOnClientHurt - Infect blocked.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Infect client.
|
// Infect client.
|
||||||
InfectHumanToZombie(client, attacker);
|
InfectHumanToZombie(client, attacker);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user