Implemented shield immunity mode with zr_shield command.

This commit is contained in:
Richard Helgeby 2013-01-07 01:45:55 +01:00
parent d0d1de8197
commit ab6bb6575f
7 changed files with 290 additions and 26 deletions

View File

@ -328,6 +328,25 @@
"es" "No esta permitido el cambio de clases."
}
// ===========================
// Immunity
// ===========================
"Immunity Shield Not Available"
{
"en" "You don't have a shield."
}
"Immunity Shield Cooldown"
{
"en" "{1} seconds until shield is available."
}
"Immunity Shield Time Left"
{
"en" "Shield time left: {1}"
}
// ===========================
// Overlays (core)
// ===========================

View File

@ -327,6 +327,25 @@
"no" "Endring av klasse er ikke tillatt."
}
// ===========================
// Immunity
// ===========================
"Immunity Shield Not Available"
{
"en" "Du har ikke skjold."
}
"Immunity Shield Cooldown"
{
"en" "{1} sekunder igjen til skjoldet er tilgjengelig."
}
"Immunity Shield Time Left"
{
"en" "Tid igjen med skjold: {1}"
}
// ===========================
// Overlays (core)
// ===========================

View File

@ -328,6 +328,25 @@
"ru" "Изменение класса запрещено."
}
// ===========================
// Immunity
// ===========================
"Immunity Shield Not Available"
{
"en" "You don't have a shield."
}
"Immunity Shield Cooldown"
{
"en" "{1} seconds until shield is available."
}
"Immunity Shield Time Left"
{
"en" "Shield time left: {1}"
}
// ===========================
// Overlays (core)
// ===========================

View File

@ -341,6 +341,27 @@
"en" "Changing classes is not allowed."
}
// ===========================
// Immunity
// ===========================
"Immunity Shield Not Available"
{
"en" "You don't have a shield."
}
"Immunity Shield Cooldown"
{
"#format" "{1:d}"
"en" "{1} seconds until shield is available."
}
"Immunity Shield Time Left"
{
"#format" "{1:d}"
"en" "Shield time left: {1}"
}
// ===========================
// Overlays (core)
// ===========================

View File

@ -46,6 +46,7 @@ CommandsInit()
ZHPOnCommandsCreate();
VolOnCommandsCreate();
ZombieSoundsOnCommandsCreate();
ImmunityOnCommandsCreate();
#if defined ADD_VERSION_INFO
VersionOnCommandsCreate();

View File

@ -62,6 +62,39 @@ new bool:PlayerImmunityThresholdPassed[MAXPLAYERS + 1] = {false, ...};
/*____________________________________________________________________________*/
/**
* Console commands are being created.
*/
ImmunityOnCommandsCreate()
{
RegConsoleCmd("zr_shield", Command_DeployShield, "Deploy the shield, if available.");
}
/*____________________________________________________________________________*/
/**
* Client executed the deploy shield command.
*
* @param client Client index.
* @param argc Number of arguments.
*/
public Action:Command_DeployShield(client, argc)
{
// Block console.
if (ZRIsConsole(client))
{
TranslationPrintToServer("Must be player");
return Plugin_Handled;
}
// Attempt to deploy shield.
ImmunityDeployShield(client);
return Plugin_Handled;
}
/*____________________________________________________________________________*/
/**
* Handles immunity when a client is about to be infected. This function may
* delay or block infection according to the immunity mode class settings.
@ -196,6 +229,23 @@ bool:ImmunityOnClientTraceAttack(client, attacker, Float:damage, hitgroup, damag
// Block damage from attacker.
return true;
}
case Immunity_Shield:
{
// Client must be human.
if (InfectIsClientInfected(client))
{
// Allow damage.
return false;
}
// Check if shield is active.
if (PlayerImmunityTimer[client] != INVALID_HANDLE)
{
// Block damage for humans with shield enabled (preventing
// zombies from stabbing them to death).
return true;
}
}
}
// Allow damage.
@ -262,19 +312,6 @@ bool:ImmunityOnClientDamage(client, attacker, &Float:damage)
/*____________________________________________________________________________*/
/**
* Client is about to receive knock back (zombie).
*
* @param Client that's receiving knock back.
*
* @return True if knock back should be blocked, false otherwise.
*/
/*bool:ImmunityOnClientKnockBack(client)
{
}*/
/*____________________________________________________________________________*/
/**
* Handles infect mode immunity.
*
@ -371,7 +408,7 @@ public Action:ImmunityDelayTimerHandler(Handle:timer, any:client)
if (!IsClientInGame(client) || !IsPlayerAlive(client))
{
// Client disconnected or died. Abort immunity action.
ImmunityAbortHandler(client, false);
ImmunityAbortHandler(client);
return Plugin_Stop;
}
@ -397,36 +434,88 @@ public Action:ImmunityDelayTimerHandler(Handle:timer, any:client)
/*____________________________________________________________________________*/
/**
* Handles shield mode immunity.
* Handles shield mode immunity when client is about to become 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
* infection can be applied instantly.
*/
bool:ImmunityShieldModeHandler(client, bool:asZombie = true)
bool:ImmunityShieldModeHandler(client)
{
// Stop if cooldown is still in progress.
// Deploy shield.
if (asZombie)
// Check if shield is active.
if (PlayerImmunityTimer[client] != INVALID_HANDLE)
{
// Enable knock back shield.
}
else
{
// Enable infection shield.
// Block infection.
return true;
}
// Shield is not active, allow infection.
return false;
}
/*____________________________________________________________________________*/
/**
* Attempts to deploy the shield.
*
* @param client Client index.
*/
ImmunityDeployShield(client)
{
// Check if shield is available.
if (!ImmunityCanDeployShield(client))
{
// Not available.
return;
}
// Deploy the shield.
PlayerImmunityDuration[client] = ClassGetImmunityAmount(client);
PlayerImmunityLastUse[client] = GetTime();
PlayerImmunityTimer[client] = CreateTimer(1.0, ImmunityShieldTimerHandler, client, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT);
// Trigger initial countdown.
ImmunityShieldTimerHandler(PlayerImmunityTimer[client], client);
}
/*____________________________________________________________________________*/
/**
* Shield timer handler. Handles countdown and shield removal when time is up.
*/
public Action:ImmunityShieldTimerHandler(Handle:timer, any:client)
{
// Verify that client is still connected and alive.
if (!IsClientInGame(client) || !IsPlayerAlive(client))
{
// Client disconnected or died. Abort immunity action.
ImmunityAbortHandler(client);
return Plugin_Stop;
}
// Reduce duration.
PlayerImmunityDuration[client] -= 1;
// Print remaining shield time.
TranslationPrintCenterText(client, "Immunity Shield Time Left", PlayerImmunityDuration[client]);
// Check if time is up.
if (PlayerImmunityDuration[client] <= 0)
{
// Time is up. Reset data, but not last use timestamp.
ImmunityAbortHandler(client, false);
return Plugin_Stop;
}
return Plugin_Continue;
}
/*____________________________________________________________________________*/
/**
* Aborts any immunity mode in action (shields, delays, etc.). Resets values.
*
@ -466,6 +555,40 @@ ImmunityAbortAll(bool:resetLastUse = true)
/*____________________________________________________________________________*/
/**
* Client is about to receive knock back.
*
* @param Client that's receiving knock back.
*
* @return True if knock back should be blocked, false otherwise.
*/
bool:ImmunityOnClientKnockBack(client)
{
// Knock back filter is currently only used in shield mode.
if (ClassGetImmunityMode(client) == Immunity_Shield)
{
// Client must be zombie. (In case a future change allow knock back
// on humans.)
if (!InfectIsClientInfected(client))
{
// Client is human, allow knock back.
return false;
}
// Block knock back if shield is deployed.
if (PlayerImmunityTimer[client] != INVALID_HANDLE)
{
// Block knock back.
return true;
}
}
// Allow knock back.
return false;
}
/*____________________________________________________________________________*/
/**
* Client was infected.
*/
@ -687,6 +810,8 @@ ImmunityModeToString(ImmunityMode:mode, String:buffer[], maxlen)
return 0;
}
/*____________________________________________________________________________*/
/**
* Returns whether the amount value is valid for the specified mode.
*
@ -754,6 +879,8 @@ bool:ImmunityIsValidAmount(ImmunityMode:mode, amount)
return true;
}
/*____________________________________________________________________________*/
/**
* Returns whether the cooldown value is valid for the specified mode.
*
@ -820,3 +947,55 @@ bool:ImmunityIsValidCooldown(ImmunityMode:mode, cooldown)
// Passed.
return true;
}
/*____________________________________________________________________________*/
/**
* Returns whether the client is allowed to deploy a shield now. Tests whether
* the client has shield immunity mode and whether cooldown is done, or a shield
* is already active.
*
* @param client Client index.
* @param printResponse Whether a response message is printed on the
* client's screen.
*
* @return True if shield can be deployed, false otherwise.
*/
bool:ImmunityCanDeployShield(client, bool:printResponse = true)
{
// Check immunity mode.
if (ClassGetImmunityMode(client) != Immunity_Shield)
{
if (printResponse)
{
TranslationPrintToChat(client, "Immunity Shield Not Available");
}
return false;
}
// Check if cooldown is still in progress.
new cooldown = ClassGetImmunityCooldown(client);
new timeLeft = PlayerImmunityLastUse[client] + cooldown - GetTime();
if (timeLeft > 0)
{
if (printResponse)
{
TranslationPrintToChat(client, "Immunity Shield Cooldown", timeLeft);
}
return false;
}
// Check if a shield is already deployed.
if (PlayerImmunityTimer[client] != INVALID_HANDLE)
{
return false;
}
// Humans cannot deploy shield before first zombie.
if (!g_bZombieSpawned)
{
return false;
}
return true;
}

View File

@ -59,6 +59,12 @@ KnockbackOnClientHurt(client, attacker, const String:weapon[], hitgroup, dmg_hea
return;
}
// Block knock back if an immunity mode is handling this.
if (ImmunityOnClientKnockBack(client))
{
return;
}
// Get zombie knockback value.
new Float:knockback = ClassGetKnockback(client);