Added sound effects module, moved all moaning, groaning, and death sounds to zombie sounds sub-module, and made a basic sound API.

This commit is contained in:
Greyscale 2009-04-16 22:21:32 +02:00
parent 39ff709d7f
commit ee9d3a9f39
12 changed files with 460 additions and 156 deletions

View File

@ -212,6 +212,13 @@
"knockback" "100.0" "knockback" "100.0"
} }
"Knife"
{
"restrict" "no"
"menu" "no"
"knockback" "8.0"
}
"NVGs" "NVGs"
{ {
"restrict" "yes" "restrict" "yes"

View File

@ -41,6 +41,9 @@
// Weapons // Weapons
#include "zr/weapons/weapons" #include "zr/weapons/weapons"
// Sound effects
#include "zr/soundeffects/soundeffects"
// Hitgroups // Hitgroups
#include "zr/hitgroups" #include "zr/hitgroups"
@ -179,10 +182,10 @@ public OnConfigsExecuted()
public OnClientPutInServer(client) public OnClientPutInServer(client)
{ {
gBlockMotherInfect[client] = false; gBlockMotherInfect[client] = false;
gKilledByWorld[client] = false;
// Forward event to modules. // Forward event to modules.
ClassClientInit(client); ClassClientInit(client);
ZombieSoundsClientInit(client);
WeaponsClientInit(client); WeaponsClientInit(client);
SpawnProtectClientInit(client); SpawnProtectClientInit(client);
RespawnClientInit(client); RespawnClientInit(client);

View File

@ -15,11 +15,12 @@ enum ZRSettings
Handle:CVAR_AMBIENCE_FILE, Handle:CVAR_AMBIENCE_FILE,
Handle:CVAR_AMBIENCE_LENGTH, Handle:CVAR_AMBIENCE_LENGTH,
Handle:CVAR_AMBIENCE_VOLUME, Handle:CVAR_AMBIENCE_VOLUME,
Handle:CVAR_EMITSOUNDS, Handle:CVAR_SOUNDEFFECTS_MOAN,
Handle:CVAR_SOUNDEFFECTS_GROAN,
Handle:CVAR_SOUNDEFFECTS_DEATH,
Handle:CVAR_CLASSES, Handle:CVAR_CLASSES,
Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_SPAWN,
Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_RANDOM,
//Handle:CVAR_CLASSES_DEFAULT,
Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, Handle:CVAR_CLASSES_DEFAULT_ZOMBIE,
Handle:CVAR_CLASSES_DEFAULT_HUMAN, Handle:CVAR_CLASSES_DEFAULT_HUMAN,
Handle:CVAR_CLASSES_DEFAULT_ADMIN, Handle:CVAR_CLASSES_DEFAULT_ADMIN,
@ -104,11 +105,12 @@ CreateCvars()
gCvars[CVAR_AMBIENCE_FILE] = CreateConVar("zr_ambience_file", "ambient/zr/zr_ambience.mp3", "Path to ambient sound file that will be played throughout the game, when zr_ambience is 1"); gCvars[CVAR_AMBIENCE_FILE] = CreateConVar("zr_ambience_file", "ambient/zr/zr_ambience.mp3", "Path to ambient sound file that will be played throughout the game, when zr_ambience is 1");
gCvars[CVAR_AMBIENCE_LENGTH] = CreateConVar("zr_ambience_length", "60.0", "The length, in seconds, of the ambient sound file"); gCvars[CVAR_AMBIENCE_LENGTH] = CreateConVar("zr_ambience_length", "60.0", "The length, in seconds, of the ambient sound file");
gCvars[CVAR_AMBIENCE_VOLUME] = CreateConVar("zr_ambience_volume", "0.6", "Volume of ambient sounds when zr_ambience is 1 (0.0: Unhearable, 1.0: Max volume)"); gCvars[CVAR_AMBIENCE_VOLUME] = CreateConVar("zr_ambience_volume", "0.6", "Volume of ambient sounds when zr_ambience is 1 (0.0: Unhearable, 1.0: Max volume)");
gCvars[CVAR_EMITSOUNDS] = CreateConVar("zr_emitsounds", "50", "How often a zombie emits a sound, in seconds (0: Disable)"); gCvars[CVAR_SOUNDEFFECTS_MOAN] = CreateConVar("zr_soundeffects_moan", "50", "How often, in seconds, a zombie moans (0: Disable)");
gCvars[CVAR_SOUNDEFFECTS_GROAN] = CreateConVar("zr_soundeffects_groan", "5", "Chance factor a zombie will groan when shot (Lower: More often, 0: Disable)");
gCvars[CVAR_SOUNDEFFECTS_DEATH] = CreateConVar("zr_soundeffects_death", "1", "Zombie will emit a death sound when killed 0: Disable)");
gCvars[CVAR_CLASSES] = CreateConVar("zr_classes", "1", "Enable zombie classes"); gCvars[CVAR_CLASSES] = CreateConVar("zr_classes", "1", "Enable zombie classes");
gCvars[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Classmenu is re-displayed every spawn (0: Disable)"); gCvars[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Classmenu is re-displayed every spawn (0: Disable)");
gCvars[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "A random class is assigned to each player every round. Overrides zr_classes_spawn and default classes. (0: Disable)"); gCvars[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "A random class is assigned to each player every round. Overrides zr_classes_spawn and default classes. (0: Disable)");
//gCvars[CVAR_CLASSES_DEFAULT] = CreateConVar("zr_classes_default", "classic", "Default class selected for all players when they connect, or \"random\" to select a random class. Usage zr_classes_default <class name|\"random\">");
gCvars[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "", "Default zombie class selected for all players when they connect. Use \"random\" to select a random class, or blank to use class config defaults."); gCvars[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "", "Default zombie class selected for all players when they connect. Use \"random\" to select a random class, or blank to use class config defaults.");
gCvars[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "", "Default human class selected for all players when they connect. Use \"random\" to select a random class, or blank to use class config defaults."); gCvars[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "", "Default human class selected for all players when they connect. Use \"random\" to select a random class, or blank to use class config defaults.");
gCvars[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "", "Default admin-only class selected for admins when they connect. Use \"random\" to select a random class, or blank to use class config defaults."); gCvars[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "", "Default admin-only class selected for admins when they connect. Use \"random\" to select a random class, or blank to use class config defaults.");

View File

@ -163,18 +163,9 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
SetPlayerFOV(index, 90); SetPlayerFOV(index, 90);
ClientCommand(index, "r_screenoverlay \"\""); ClientCommand(index, "r_screenoverlay \"\"");
// Forward event to modules. // Check if client is on a team.
SpawnProtectOnClientSpawn(index); if (ZRIsClientOnTeam(index))
RespawnOnClientSpawn(index);
ZHPOnClientSpawn(index);
// Stop here if client isn't on a team.
new team = GetClientTeam(index);
if (team != CS_TEAM_T && team != CS_TEAM_CT)
{ {
return;
}
new bool:cashfill = GetConVarBool(gCvars[CVAR_CASHFILL]); new bool:cashfill = GetConVarBool(gCvars[CVAR_CASHFILL]);
if (cashfill) if (cashfill)
{ {
@ -188,7 +179,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
if (zombieSpawned) if (zombieSpawned)
{ {
if (team == CS_TEAM_T) if (ZRIsClientOnTeam(index, CS_TEAM_T))
{ {
CS_SwitchTeam(index, CS_TEAM_CT); CS_SwitchTeam(index, CS_TEAM_CT);
CS_RespawnPlayer(index); CS_RespawnPlayer(index);
@ -198,9 +189,14 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{ {
SetPlayerAlpha(index, 255); SetPlayerAlpha(index, 255);
} }
}
// Forward event to modules. // Forward event to modules.
ClassOnClientSpawn(index); ClassOnClientSpawn(index);
ZombieSoundsOnClientSpawn(index);
SpawnProtectOnClientSpawn(index);
RespawnOnClientSpawn(index);
ZHPOnClientSpawn(index);
ZTeleClientSpawned(index); ZTeleClientSpawned(index);
ZR_PrintToChat(index, "!zmenu reminder"); ZR_PrintToChat(index, "!zmenu reminder");
@ -232,35 +228,21 @@ public Action:PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
} }
} }
// Check if the player is a human. // Check if the player is a zombie.
if (IsPlayerHuman(index)) if (IsPlayerZombie(index))
{ {
// We're done now. Nothing more to do on humans.
return;
}
// Play a random zombie hurt sound.
if (GetRandomInt(1, 5) == 1)
{
decl String:sound[64];
new randsound = GetRandomInt(1, 6);
Format(sound, sizeof(sound), "npc/zombie/zombie_pain%d.wav", randsound);
PrecacheSound(sound);
EmitSoundToAll(sound, index);
}
// Napalm effect. // Napalm effect.
new Float:napalm_time = ClassGetNapalmTime(index); new Float:napalm_time = ClassGetNapalmTime(index);
if (StrEqual(weapon, "hegrenade", false) && napalm_time > 0.0) if (StrEqual(weapon, "hegrenade", false) && napalm_time > 0.0)
{ {
IgniteEntity(index, napalm_time); IgniteEntity(index, napalm_time);
} }
}
// Forward event to modules. // Forward event to modules.
ClassAlphaUpdate(index); ClassAlphaUpdate(index);
KnockbackPlayerHurt(index, attacker, weapon, hitgroup, dmg_health); ZombieSoundsOnClientHurt(index);
KnockbackOnClientHurt(index, attacker, weapon, hitgroup, dmg_health);
ZHPOnPlayerHurt(index); ZHPOnPlayerHurt(index);
} }
@ -304,13 +286,6 @@ public Action:PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{ {
if (IsPlayerZombie(index)) if (IsPlayerZombie(index))
{ {
decl String:sound[64];
new randsound = GetRandomInt(1, 3);
Format(sound, sizeof(sound), "npc/zombie/zombie_die%d.wav", randsound);
PrecacheSound(sound);
EmitSoundToAll(sound, index);
// Give kill bonus. // Give kill bonus.
if (ZRIsValidClient(attacker)) if (ZRIsValidClient(attacker))
@ -318,9 +293,6 @@ public Action:PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
new bonus = ClassGetKillBonus(attacker); new bonus = ClassGetKillBonus(attacker);
AddPlayerScore(attacker, bonus); AddPlayerScore(attacker, bonus);
} }
// Set gKilledByWorld to true if attacker is not a valid client.
gKilledByWorld[index] = !ZRIsValidClient(attacker);
} }
// Kill various timers. // Kill various timers.
@ -336,8 +308,9 @@ public Action:PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
// Forward event to modules. // Forward event to modules.
ClassOnClientDeath(index); ClassOnClientDeath(index);
ZombieSoundsOnClientDeath(index);
SpawnProtectOnClientDeath(index); SpawnProtectOnClientDeath(index);
RespawnOnClientDeath(index, weapon); RespawnOnClientDeath(index, attacker, weapon);
ZHPOnClientDeath(index); ZHPOnClientDeath(index);
new ZTeam:team = IsRoundOver(); new ZTeam:team = IsRoundOver();

View File

@ -14,7 +14,7 @@
* @param hitgroup Hitgroup attacker has damaged. * @param hitgroup Hitgroup attacker has damaged.
* @param dmg_health Damage done. * @param dmg_health Damage done.
*/ */
KnockbackPlayerHurt(client, attacker, const String:weapon[], hitgroup, dmg_health) KnockbackOnClientHurt(client, attacker, const String:weapon[], hitgroup, dmg_health)
{ {
// Check if the attacker is a player. // Check if the attacker is a player.
if (attacker != 0) if (attacker != 0)

View File

@ -14,6 +14,11 @@
*/ */
new Handle:tRespawn[MAXPLAYERS + 1]; new Handle:tRespawn[MAXPLAYERS + 1];
/**
* Array for flagging zombies who were killed by world.
*/
new bool:pKilledByWorld[MAXPLAYERS + 1];
/** /**
* Client is joining the server. * Client is joining the server.
*/ */
@ -22,8 +27,8 @@ RespawnClientInit(client)
// Reset timer handle. // Reset timer handle.
tRespawn[client] = INVALID_HANDLE; tRespawn[client] = INVALID_HANDLE;
// Init gKilledByWorld for client. // Init pKilledByWorld for client.
gKilledByWorld[client] = false; pKilledByWorld[client] = false;
} }
/** /**
@ -48,8 +53,15 @@ RespawnOnClientSpawn(client)
* *
* @param client The client index. * @param client The client index.
*/ */
RespawnOnClientDeath(client, const String:weapon[]) RespawnOnClientDeath(client, attacker, const String:weapon[])
{ {
// If client is a zombie, check if they were killed by world.
if (IsPlayerZombie(client))
{
// Set pKilledByWorld to true if attacker is not a valid client.
pKilledByWorld[client] = !ZRIsValidClient(attacker);
}
// If timer is running, kill it. // If timer is running, kill it.
if (tRespawn[client] != INVALID_HANDLE) if (tRespawn[client] != INVALID_HANDLE)
{ {
@ -74,6 +86,18 @@ RespawnOnClientDeath(client, const String:weapon[])
tRespawn[client] = CreateTimer(delay, RespawnTimer, client, TIMER_FLAG_NO_MAPCHANGE); tRespawn[client] = CreateTimer(delay, RespawnTimer, client, TIMER_FLAG_NO_MAPCHANGE);
} }
/**
* Returns if a player is to be respawned as a zombie, because they were killed by world.
*
* @param client The client index.
* @return True if they were killed by world, false if not or cvar is disabled.
*/
RespawnKilledByWorld(client)
{
// Return true if both the cvar is enabled and the player was killed by world.
return (GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && pKilledByWorld[client]);
}
/** /**
* Spawns a player into the round. * Spawns a player into the round.
* *
@ -106,10 +130,10 @@ RespawnSpawnClient(client)
return; return;
} }
if (GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && gKilledByWorld[client]) if (GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && pKilledByWorld[client])
{ {
InfectPlayer(client); InfectPlayer(client);
gKilledByWorld[client] = false; pKilledByWorld[client] = false;
} }
} }

View File

@ -75,6 +75,14 @@ public Action:SayCommand(client, argc)
{ {
ZR_PrintToChat(client, "!ztele stuck"); ZR_PrintToChat(client, "!ztele stuck");
} }
else if (StrEqual(args, "play", false))
{
SEffectsEmitAmbientSound("ambient/machines/heli_pass_distant1.wav");
}
else if (StrEqual(args, "stop", false))
{
SEffectsStopAmbientSound("ambient/machines/heli_pass_distant1.wav");
}
return Plugin_Continue; return Plugin_Continue;
} }

View File

@ -0,0 +1,69 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: soundeffects.inc
* Description: Basic sound-management API.
*
* ============================================================================
*/
/**
* Maximum sound path length.
*/
#define SOUND_MAX_PATH 128
/**
* Ambient sound channel.
*/
#define SOUND_AMBIENT_CHANNEL 8
#include "zr/soundeffects/zombiesounds"
/**
* Emits an ambient sound
*/
SEffectsEmitAmbientSound(const String:sound[], Float:soundvolume = 1.0)
{
// Precache sound before playing.
PrecacheSound(sound);
// Emit ambient sound.
EmitSoundToAll(sound, SOUND_FROM_PLAYER, SOUND_AMBIENT_CHANNEL, _, _, soundvolume);
}
/**
* Stop an ambient sound
*/
SEffectsStopAmbientSound(const String:sound[])
{
// x = client index.
for (new x = 1; x <= MaxClients; x++)
{
// If client isn't in-game, then stop.
if (!IsClientInGame(x))
{
continue;
}
// Stop ambient sound.
StopSound(x, SOUND_AMBIENT_CHANNEL, sound);
}
}
/**
* Emits a sound from a client.
*
* @param client The client index.
* @param sound The sound file relative to the sound/ directory.
* @param level The attenuation of the sound.
*/
SEffectsEmitSoundFromClient(client, const String:sound[], level = SNDLEVEL_NORMAL)
{
// Precache sound before playing.
PrecacheSound(sound);
// Emit sound from client.
EmitSoundToAll(sound, client, _, level);
}

View File

@ -0,0 +1,265 @@
/*
* ============================================================================
*
* Zombie:Reloaded
*
* File: zombiesounds.inc
* Description: Zombie sound effects.
*
* ============================================================================
*/
/**
* @section Defines for min/max moaning sound file index.
*/
#define SOUND_MOAN_PATH "npc/zombie/zombie_voice_idle%d.wav" // %d is sound file index
#define SOUND_MOAN_MIN 1
#define SOUND_MOAN_MAX 14
/**
* @endsection
*/
/**
* @section Defines for min/max groan sound file index.
*/
#define SOUND_GROAN_PATH "npc/zombie/zombie_pain%d.wav" // %d is sound file index
#define SOUND_GROAN_MIN 1
#define SOUND_GROAN_MAX 6
/**
* @endsection
*/
/**
* @section Defines for min/max death sound file index.
*/
#define SOUND_DEATH_PATH "npc/zombie/zombie_die%d.wav" // %d is sound file index
#define SOUND_DEATH_MIN 1
#define SOUND_DEATH_MAX 3
/**
* @endsection
*/
/**
* Zombie sound types
*/
enum ZombieSounds
{
Moan, /** Zombie's moan periodically */
Groan, /** When zombie is hurt */
Death, /** When a zombie is killed */
}
/**
* Array for storing zombie moaning timer handles per client.
*/
new Handle:tSEffectsMoan[MAXPLAYERS + 1];
/**
* Client is joining the server.
*
* @param client The client index.
*/
ZombieSoundsClientInit(client)
{
// Reset timer handle.
tSEffectsMoan[client] = INVALID_HANDLE;
}
/**
* Client is spawning into the game.
*
* @param client The client index.
*/
ZombieSoundsOnClientSpawn(client)
{
// If timer is running, kill it.
if (tSEffectsMoan[client] != INVALID_HANDLE)
{
KillTimer(tSEffectsMoan[client]);
}
// Reset timer handle.
tSEffectsMoan[client] = INVALID_HANDLE;
}
/**
* Client has been killed.
*
* @param client The client index.
*/
ZombieSoundsOnClientDeath(client)
{
// If timer is running, kill it.
if (tSEffectsMoan[client] != INVALID_HANDLE)
{
KillTimer(tSEffectsMoan[client]);
}
// Reset timer handle.
tSEffectsMoan[client] = INVALID_HANDLE;
// If player isn't a zombie, then stop.
if (!IsPlayerZombie(client))
{
return;
}
// If death sound cvar is disabled, then stop.
new bool:death = GetConVarBool(gCvars[CVAR_SOUNDEFFECTS_DEATH]);
if (!death)
{
return;
}
// Get random death sound.
decl String:sound[SOUND_MAX_PATH];
ZombieSoundsGetRandomSound(sound, Death);
SEffectsEmitSoundFromClient(client, sound);
}
/**
* Client has been hurt.
*
* @param client The client index.
*/
ZombieSoundsOnClientHurt(client)
{
// If player isn't a zombie, then stop.
if (!IsPlayerZombie(client))
{
return;
}
// Get groan factor, if 0, then stop.
new groan = GetConVarInt(gCvars[CVAR_SOUNDEFFECTS_GROAN]);
if (!groan)
{
return;
}
// 1 in 'groan' chance of groaning.
if (GetRandomInt(1, groan) == 1)
{
// Get random groan sound.
decl String:sound[SOUND_MAX_PATH];
ZombieSoundsGetRandomSound(sound, Groan);
SEffectsEmitSoundFromClient(client, sound);
}
}
/**
* Client has been infected.
*
* @param client The client index.
*/
ZombieSoundsOnClientInfected(client)
{
// If interval is set to 0, then stop.
new Float:interval = GetConVarFloat(gCvars[CVAR_SOUNDEFFECTS_MOAN]);
if (!interval)
{
return;
}
// If timer is currently running, kill it.
if (tSEffectsMoan[client] != INVALID_HANDLE)
{
KillTimer(tSEffectsMoan[client]);
}
// Start repeating timer.
tSEffectsMoan[client] = CreateTimer(interval, ZombieSoundsMoanTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
}
/**
* Gets a random zombie sound from hl2 folder.
*
* @param sound The randomly picked moan sound.
* @return True if sound was successfully picked, false otherwise.
*/
bool:ZombieSoundsGetRandomSound(String:sound[], ZombieSounds:soundtype)
{
new soundmin;
new soundmax;
decl String:soundpath[SOUND_MAX_PATH];
switch(soundtype)
{
// Find moan sound.
case Moan:
{
// Copy min and max
soundmin = SOUND_MOAN_MIN;
soundmax = SOUND_MOAN_MAX;
// Copy path
strcopy(soundpath, sizeof(soundpath), SOUND_MOAN_PATH);
}
// Find groan sound. (zombie shot)
case Groan:
{
// Copy min and max
soundmin = SOUND_GROAN_MIN;
soundmax = SOUND_GROAN_MAX;
// Copy path
strcopy(soundpath, sizeof(soundpath), SOUND_GROAN_PATH);
}
// Find death sound.
case Death:
{
// Copy min and max
soundmin = SOUND_DEATH_MIN;
soundmax = SOUND_DEATH_MAX;
// Copy path
strcopy(soundpath, sizeof(soundpath), SOUND_DEATH_PATH);
}
// Invalid case given.
default:
{
// No handled case was given.
return false;
}
}
// Pick a random integer between min and max sound file index.
new randsound = GetRandomInt(soundmin, soundmax);
// Format random index into sound path.
Format(sound, SOUND_MAX_PATH, soundpath, randsound);
// Found sound.
return true;
}
/**
* Timer callback, repeats a moaning sound on zombies.
*
* @param timer The timer handle.
* @param client The client index.
*/
public Action:ZombieSoundsMoanTimer(Handle:timer, any:client)
{
// If client isn't in-game or client is no longer a zombie, then stop.
if (!IsClientInGame(client) || !IsPlayerZombie(client))
{
// Reset timer handle.
tSEffectsMoan[client] = INVALID_HANDLE;
// Stop timer.
return Plugin_Stop;
}
// Get random moan sound.
decl String:sound[SOUND_MAX_PATH];
ZombieSoundsGetRandomSound(sound, Moan);
// Emit sound from client.
SEffectsEmitSoundFromClient(client, sound, SNDLEVEL_SCREAMING);
// Allow timer to continue.
return Plugin_Continue;
}

View File

@ -77,7 +77,7 @@ SpawnProtectOnClientSpawn(client)
// If player respawns as human, and either cvar zr_suicide_world_damage or the client // If player respawns as human, and either cvar zr_suicide_world_damage or the client
// wasn't killed by world is false, then continue on to protect client. // wasn't killed by world is false, then continue on to protect client.
new bool:respawn_zombie = GetConVarBool(gCvars[CVAR_RESPAWN_ZOMBIE]); new bool:respawn_zombie = GetConVarBool(gCvars[CVAR_RESPAWN_ZOMBIE]);
if (!respawn_zombie && !(GetConVarBool(gCvars[CVAR_SUICIDE_WORLD_DAMAGE]) && gKilledByWorld[client])) if (!respawn_zombie && !RespawnKilledByWorld(client))
{ {
// Set spawn protect flag on client. // Set spawn protect flag on client.
pSpawnProtect[client] = true; pSpawnProtect[client] = true;

View File

@ -159,41 +159,6 @@ public Action:MotherZombie(Handle:timer)
zombieSpawned = true; zombieSpawned = true;
} }
/*Zombify_Mother(client)
{
gZombie[client] = true;
motherZombie[client] = true;
CS_SwitchTeam(client, CS_TEAM_T);
RemoveAllPlayersWeapons(client);
GivePlayerItem(client, "weapon_knife");
ClassOnClientInfected(client, true);
InfectionEffects(client);
ztele_count[client] = 0;
AbortTeleport(client);
ZR_PrintToChat(client, "You are a zombie");
new bool:mother_zombie_respawn = GetConVarBool(gCvars[CVAR_MOTHER_ZOMBIE_RESPAWN]);
if (mother_zombie_respawn)
{
TeleportEntity(client, spawnLoc[client], NULL_VECTOR, NULL_VECTOR);
}
new Float:interval = GetConVarFloat(gCvars[CVAR_EMITSOUNDS]);
if (interval > 0.0)
{
if (tHandles[client][TMOAN] != INVALID_HANDLE)
{
KillTimer(tHandles[client][TMOAN]);
}
tHandles[client][TMOAN] = CreateTimer(interval, ZombieMoanTimer, client, TIMER_REPEAT);
}
}*/
/** /**
* Zombifies a player. Execute events, sets attributes and flags that indicate * Zombifies a player. Execute events, sets attributes and flags that indicate
* that the player is a zombie. * that the player is a zombie.
@ -235,20 +200,9 @@ InfectPlayer(client, attacker = -1, bool:motherinfect = false)
// Switch the player to terrorists. // Switch the player to terrorists.
CS_SwitchTeam(client, CS_TEAM_T); CS_SwitchTeam(client, CS_TEAM_T);
// Check if random zombie sounds are enabled.
new Float:interval = GetConVarFloat(gCvars[CVAR_EMITSOUNDS]);
if (interval > 0.0)
{
// Create timer.
if (tHandles[client][TMOAN] != INVALID_HANDLE)
{
KillTimer(tHandles[client][TMOAN]);
}
tHandles[client][TMOAN] = CreateTimer(interval, ZombieMoanTimer, client, TIMER_REPEAT);
}
// Forward event to modules. // Forward event to modules.
ClassOnClientInfected(client, motherinfect); ClassOnClientInfected(client, motherinfect);
ZombieSoundsOnClientInfected(client);
ZHPOnClientInfected(client); ZHPOnClientInfected(client);
AbortTeleport(client); AbortTeleport(client);
@ -268,8 +222,7 @@ InfectionEffects(client)
GetConVarString(gCvars[CVAR_INFECT_SOUND], sound, sizeof(sound)); GetConVarString(gCvars[CVAR_INFECT_SOUND], sound, sizeof(sound));
if (sound[0]) if (sound[0])
{ {
PrecacheSound(sound); SEffectsEmitSoundFromClient(client, sound, SNDLEVEL_SCREAMING);
EmitSoundToAll(sound, client, SNDCHAN_AUTO, SNDLEVEL_SCREAMING);
} }
new bool:esplash = GetConVarBool(gCvars[CVAR_INFECT_ESPLASH]); new bool:esplash = GetConVarBool(gCvars[CVAR_INFECT_ESPLASH]);
@ -524,31 +477,6 @@ RemoveObjectives()
} }
} }
ZombieMoan(client)
{
decl String:sound[64];
new randsound = GetRandomInt(1, 14);
Format(sound, sizeof(sound), "npc/zombie/zombie_voice_idle%d.wav", randsound);
PrecacheSound(sound);
EmitSoundToAll(sound, client, SNDCHAN_AUTO, SNDLEVEL_SCREAMING);
}
public Action:ZombieMoanTimer(Handle:timer, any:index)
{
if (!IsClientInGame(index) || !IsPlayerZombie(index))
{
tHandles[index][TMOAN] = INVALID_HANDLE;
return Plugin_Stop;
}
ZombieMoan(index);
return Plugin_Continue;
}
public Action:RoundOver(Handle:timer) public Action:RoundOver(Handle:timer)
{ {
tRound = INVALID_HANDLE; tRound = INVALID_HANDLE;

View File

@ -70,7 +70,6 @@ new bool:zombieSpawned;
new bool:motherZombie[MAXPLAYERS + 1]; new bool:motherZombie[MAXPLAYERS + 1];
new bool:gZombie[MAXPLAYERS + 1]; new bool:gZombie[MAXPLAYERS + 1];
new bool:gBlockMotherInfect[MAXPLAYERS + 1]; new bool:gBlockMotherInfect[MAXPLAYERS + 1];
new bool:gKilledByWorld[MAXPLAYERS + 1];
new Float:spawnLoc[MAXPLAYERS + 1][3]; new Float:spawnLoc[MAXPLAYERS + 1][3];
new Float:bufferLoc[MAXPLAYERS + 1][3]; new Float:bufferLoc[MAXPLAYERS + 1][3];
@ -88,9 +87,8 @@ new Handle:tInfect = INVALID_HANDLE;
new Handle:pList = INVALID_HANDLE; new Handle:pList = INVALID_HANDLE;
#define MAXTIMERS 2 #define MAXTIMERS 1
#define TMOAN 0
#define TTELE 1 #define TTELE 1
new Handle:tHandles[MAXPLAYERS + 1][MAXTIMERS]; new Handle:tHandles[MAXPLAYERS + 1][MAXTIMERS];
@ -228,6 +226,7 @@ bool:IsPlayerInList(client)
* *
* @param client The client index. * @param client The client index.
* @param console True to include console (index 0), false if not. * @param console True to include console (index 0), false if not.
* @return True if client is valid, false otherwise.
*/ */
bool:ZRIsValidClient(client, bool:console = false) bool:ZRIsValidClient(client, bool:console = false)
{ {
@ -241,6 +240,32 @@ bool:ZRIsValidClient(client, bool:console = false)
return console ? (client >= 0) : (client > 0); return console ? (client >= 0) : (client > 0);
} }
/**
* Check if a client index is on a team.
*
* @param client The client index.
* @param team Team to check if player is on, -1 to check both.
* @return True if client is on a team, false otherwise.
*/
bool:ZRIsClientOnTeam(client, team = -1)
{
// If index is invalid, then stop.
if (!ZRIsValidClient(client))
{
return false;
}
// Get client team.
new clientteam = GetClientTeam(client);
if (team == -1)
{
return (clientteam == CS_TEAM_T || clientteam == CS_TEAM_CT);
}
return (clientteam == team);
}
/** /**
* Returns whether a player is a generic admin or not. * Returns whether a player is a generic admin or not.
* *