sm-zombiereloaded-3/src/zr/zombie.inc

491 lines
13 KiB
PHP
Raw Normal View History

2008-10-04 22:59:11 +02:00
/**
* ====================
* Zombie:Reloaded
* File: zombie.inc
* Author: Greyscale
* ====================
*/
#define EXP_NODAMAGE 1
#define EXP_REPEATABLE 2
#define EXP_NOFIREBALL 4
#define EXP_NOSMOKE 8
#define EXP_NODECAL 16
#define EXP_NOSPARKS 32
#define EXP_NOSOUND 64
#define EXP_RANDOMORIENTATION 128
#define EXP_NOFIREBALLSMOKE 256
#define EXP_NOPARTICLES 512
#define EXP_NODLIGHTS 1024
#define EXP_NOCLAMPMIN 2048
#define EXP_NOCLAMPMAX 4096
new String:skyname[32];
HookCommands()
{
RegConsoleCmd("nightvision", Command_NightVision);
}
public Action:Command_NightVision(client, argc)
{
new bool:allow_disable = GetConVarBool(gCvars[CVAR_ZVISION_ALLOW_DISABLE]);
if (!allow_disable)
{
return;
}
new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]);
if (!enabled)
{
return;
}
if (!IsPlayerZombie(client))
{
return;
}
bClientOverlayOn[client] = !bClientOverlayOn[client];
2008-10-04 22:59:11 +02:00
decl String:overlay[256];
ClassGetOverlayPath(client, overlay, sizeof(overlay));
if (strlen(overlay) > 0)
2008-10-04 22:59:11 +02:00
{
if (bClientOverlayOn[client])
{
ClassOverlayInitialize(client, overlay);
}
else
{
ClassOverlayStop(client);
}
2008-10-04 22:59:11 +02:00
}
}
FindMapSky()
{
GetConVarString(FindConVar("sv_skyname"), skyname, sizeof(skyname));
}
ChangeLightStyle()
{
new bool:dark = GetConVarBool(gCvars[CVAR_DARK]);
if (dark)
{
decl String:darkness[2];
decl String:sky[32];
GetConVarString(gCvars[CVAR_DARK_LEVEL], darkness, sizeof(darkness));
GetConVarString(gCvars[CVAR_DARK_SKY], sky, sizeof(sky));
SetLightStyle(0, darkness);
SetConVarString(FindConVar("sv_skyname"), sky, true, false);
}
else
{
SetLightStyle(0, "n");
SetConVarString(FindConVar("sv_skyname"), skyname, true, false);
}
}
/**
* Create an array populated with eligible clients to be zombie.
*
* @param arrayEligibleClients The handle of the array, don't forget to call CloseHandle
* on it when finished!
* @param immunity True to ignore clients immune from mother infect, false to count them.
*/
CreateEligibleClientList(&Handle:arrayEligibleClients, bool:team = false, bool:alive = false, bool:human = false, bool:immunity = false)
2008-10-04 22:59:11 +02:00
{
// Create array.
arrayEligibleClients = CreateArray();
2008-10-04 22:59:11 +02:00
// Populate list with eligible clients.
// x = client index.
for (new x = 1; x <= MaxClients; x++)
2008-10-04 22:59:11 +02:00
{
// If client isn't in-game, then stop.
if (!IsClientInGame(x))
{
continue;
}
2008-10-04 22:59:11 +02:00
// If client isn't on a team, then stop.
if (team && !ZRIsClientOnTeam(x))
{
continue;
}
// If client is dead, then stop.
if (alive && !IsPlayerAlive(x))
{
continue;
}
// If client is already zombie (via admin), then stop.
if (human && !IsPlayerHuman(x))
2008-10-04 22:59:11 +02:00
{
continue;
2008-10-04 22:59:11 +02:00
}
// If client is immune from being a mother zombie, then stop.
if (immunity && bMotherInfectImmune[x])
2008-10-04 22:59:11 +02:00
{
// Take away immunity.
bMotherInfectImmune[x] = false;
2008-10-04 22:59:11 +02:00
continue;
}
// Add eligible client to array.
PushArrayCell(arrayEligibleClients, x);
2008-10-04 22:59:11 +02:00
}
return GetArraySize(arrayEligibleClients);
}
/**
* Timer callback, chooses mother zombies.
*
* @param timer The timer handle.
*/
public Action:MotherZombie(Handle:timer)
{
// Reset timer handle.
tInfect = INVALID_HANDLE;
// Create eligible player list.
new Handle:arrayEligibleClients = INVALID_HANDLE;
new eligibleclients = CreateEligibleClientList(arrayEligibleClients, true, true, true, true);
// If there are no eligible client's then stop.
if (!eligibleclients)
2008-10-04 22:59:11 +02:00
{
return;
}
// Move all clients to CT
for (new x = 1; x <= MaxClients; x++)
{
// If client isn't in-game, then stop.
if (!IsClientInGame(x))
{
continue;
}
// If client is dead, then stop.
if (!IsPlayerAlive(x))
{
continue;
}
// Switch client to CT team.
CS_SwitchTeam(x, CS_TEAM_CT);
}
// Variable to store randomly chosen array index.
new randindex;
// Variable to store client stored in random array index.
new client;
// Ratio of mother zombies to humans.
2008-10-04 22:59:11 +02:00
new ratio = GetConVarInt(gCvars[CVAR_MOTHER_ZOMBIE_RATIO]);
// If ratio is 0 or lower, then pick 1 zombie.
2008-10-04 22:59:11 +02:00
if (ratio <= 0)
{
// Get a random valid array index.
randindex = GetRandomInt(0, eligibleclients - 1);
2008-10-04 22:59:11 +02:00
// Get the client stored in the random array index.
client = GetArrayCell(arrayEligibleClients, randindex);
// Infect player.
InfectPlayer(client, _, true);
2008-10-04 22:59:11 +02:00
}
else
{
// Calculate mother zombie sound.
new mothercount = RoundToCeil(float(eligibleclients) / ratio);
2008-10-04 22:59:11 +02:00
// x = current mother zombie count.
2008-10-04 22:59:11 +02:00
for (new x = 0; x < mothercount; x++)
{
// Recount eligible clients.
eligibleclients = GetArraySize(arrayEligibleClients);
// If there are no more eligible clients, then break loop.
if (!eligibleclients)
2008-10-04 22:59:11 +02:00
{
break;
}
// Get a random valid array index.
randindex = GetRandomInt(0, eligibleclients - 1);
// Get the client stored in the random array index.
client = GetArrayCell(arrayEligibleClients, randindex);
2008-10-04 22:59:11 +02:00
// Infect player.
InfectPlayer(client, _, true);
// Remove player from eligible zombie list.
RemoveFromArray(arrayEligibleClients, randindex);
2008-10-04 22:59:11 +02:00
}
}
// Mother zombies have been infected.
g_bZombieSpawned = true;
// Destroy handle.
CloseHandle(arrayEligibleClients);
2008-10-04 22:59:11 +02:00
}
/**
* Zombifies a player. Execute events, sets attributes and flags that indicate
* that the player 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.
*/
InfectPlayer(client, attacker = -1, bool:motherinfect = false)
2008-10-04 22:59:11 +02:00
{
// Check if the attacker was specified.
if (ZRIsValidClient(attacker))
2008-10-04 22:59:11 +02:00
{
// Fire death event and set weapon info.
2008-10-04 22:59:11 +02:00
new Handle:event = CreateEvent("player_death");
if (event != INVALID_HANDLE)
{
SetEventInt(event, "userid", GetClientUserId(client));
SetEventInt(event, "attacker", GetClientUserId(attacker));
SetEventString(event, "weapon", "zombie_claws_of_death");
FireEvent(event, false);
}
}
// Set player status.
bZombie[client] = true;
2008-10-04 22:59:11 +02:00
// Remove all weapons and give a knife.
2008-10-04 22:59:11 +02:00
RemoveAllPlayersWeapons(client);
GivePlayerItem(client, "weapon_knife");
ztele_count[client] = 0; // In use?
// Terminate the round if the last player was infected.
new RoundEndOutcome:outcome;
if (RoundEndGetRoundStatus(outcome))
{
RoundEndTerminateRound(outcome);
}
2008-10-04 22:59:11 +02:00
// Switch the player to terrorists.
2008-10-04 22:59:11 +02:00
CS_SwitchTeam(client, CS_TEAM_T);
// Check if consecutive infection protection is enabled.
new bool:consecutive_infect = GetConVarBool(gCvars[CVAR_CONSECUTIVE_INFECT]);
// Flag player to be immune from being mother zombie twice, if consecutive infect protection is enabled.
bMotherInfectImmune[client] = consecutive_infect ? motherinfect : false;
// Forward event to modules.
ClassOnClientInfected(client, motherinfect);
SEffectsOnClientInfected(client);
ZHPOnClientInfected(client);
AbortTeleport(client);
// Apply effects.
InfectionEffects(client);
2008-10-04 22:59:11 +02:00
}
InfectionEffects(client)
{
new Float:clientloc[3];
new Float:direction[3] = {0.0, 0.0, 0.0};
GetClientAbsOrigin(client, clientloc);
clientloc[2] += 30;
decl String:sound[128];
GetConVarString(gCvars[CVAR_INFECT_SOUND], sound, sizeof(sound));
if (sound[0])
{
SEffectsEmitSoundFromClient(client, sound, SNDLEVEL_SCREAMING);
2008-10-04 22:59:11 +02:00
}
new bool:esplash = GetConVarBool(gCvars[CVAR_INFECT_ESPLASH]);
if (esplash)
{
TE_SetupEnergySplash(clientloc, direction, true);
TE_SendToAll();
}
new explosion = CreateEntityByName("env_explosion");
if (explosion != -1)
{
new flags = GetEntProp(explosion, Prop_Data, "m_spawnflags");
flags = flags | EXP_NODAMAGE | EXP_NODECAL;
new bool:fireball = GetConVarBool(gCvars[CVAR_INFECT_FIREBALL]);
if (!fireball)
{
flags = flags | EXP_NOFIREBALL;
}
new bool:smoke = GetConVarBool(gCvars[CVAR_INFECT_SMOKE]);
if (!smoke)
{
flags = flags | EXP_NOSMOKE;
}
new bool:sparks = GetConVarBool(gCvars[CVAR_INFECT_SPARKS]);
if (!sparks)
{
flags = flags | EXP_NOSPARKS;
}
SetEntProp(explosion, Prop_Data, "m_spawnflags", flags);
DispatchSpawn(explosion);
PrecacheModel("materials/sprites/xfireball3.vmt");
DispatchKeyValueVector(explosion, "origin", clientloc);
DispatchKeyValue(explosion, "fireballsprite", "materials/sprites/xfireball3.vmt");
AcceptEntityInput(explosion, "Explode");
}
new bool:shake = GetConVarBool(gCvars[CVAR_INFECT_SHAKE]);
if (shake)
{
new Handle:hShake = StartMessageOne("Shake", client);
if (hShake != INVALID_HANDLE)
{
BfWriteByte(hShake, 0);
BfWriteFloat(hShake, GetConVarFloat(gCvars[CVAR_INFECT_SHAKE_AMP]));
BfWriteFloat(hShake, GetConVarFloat(gCvars[CVAR_INFECT_SHAKE_FREQUENCY]));
BfWriteFloat(hShake, GetConVarFloat(gCvars[CVAR_INFECT_SHAKE_DURATION]));
EndMessage();
}
}
}
JumpBoost(client, Float:distance, Float:height)
{
new Float:vel[3];
GetPlayerVelocity(client, vel);
vel[0] *= distance;
vel[1] *= distance;
vel[2] *= height;
2008-10-04 22:59:11 +02:00
SetPlayerVelocity(client, vel, false);
2008-10-04 22:59:11 +02:00
}
/**
* Finds a new zombie if the last one disconnects.
*
* @param client The client index.
*/
2008-10-04 22:59:11 +02:00
PlayerLeft(client)
{
// If client is dead, then stop.
if (!IsPlayerAlive(client))
2008-10-04 22:59:11 +02:00
{
return;
}
// If client isn't a zombie, then stop.
if (!IsPlayerZombie(client))
2008-10-04 22:59:11 +02:00
{
return;
}
// Initialize count variables
new zombiecount;
new humancount;
// Count valid clients. (true to only allow living clients)
ZRCountValidClients(zombiecount, humancount);
// If there are other zombies besides the disconnecting player, then stop.
if (zombiecount - 1)
2008-10-04 22:59:11 +02:00
{
return;
}
// If there is 1 or no humans left, then stop.
if (humancount <= 1)
2008-10-04 22:59:11 +02:00
{
return;
}
// Create eligible player list.
new Handle:arrayEligibleClients = INVALID_HANDLE;
2008-10-04 22:59:11 +02:00
// Create eligible client list, with no mother infect immunities
new eligibleclients = CreateEligibleClientList(arrayEligibleClients, true, true, true);
2008-10-04 22:59:11 +02:00
// If there are no eligible client's then stop.
if (!eligibleclients)
2008-10-04 22:59:11 +02:00
{
return;
}
// Get a random valid array index.
new randindex = GetRandomInt(0, eligibleclients - 1);
2008-10-04 22:59:11 +02:00
// Get the client stored in the random array index.
new randclient = GetArrayCell(arrayEligibleClients, randindex);
// Infect player.
InfectPlayer(randclient);
2008-10-04 22:59:11 +02:00
// Tell client they have been randomly been chosen to replace disconnecting zombie.
ZR_PrintToChat(randclient, "Zombie replacement");
// Destroy handle.
CloseHandle(arrayEligibleClients);
2008-10-04 22:59:11 +02:00
}
RemoveObjectives()
{
decl String:classname[64];
new maxentities = GetMaxEntities();
for (new x = 0; x <= maxentities; x++)
{
if(!IsValidEdict(x))
{
continue;
}
GetEdictClassname(x, classname, sizeof(classname));
if( StrEqual(classname, "func_bomb_target") ||
StrEqual(classname, "func_hostage_rescue") ||
StrEqual(classname, "c4") ||
StrEqual(classname, "hostage_entity"))
{
RemoveEdict(x);
}
}
}
bool:IsPlayerZombie(client)
{
return bZombie[client];
2008-10-04 22:59:11 +02:00
}
bool:IsPlayerHuman(client)
{
return !bZombie[client];
}