Added zr_infect/zr_human, all conflicts from official version are fixed. Added feature to ZSpawn to allow to spawn to different team after timelimit is expired.
This commit is contained in:
parent
ec61c654cb
commit
1530d20308
@ -234,12 +234,58 @@
|
||||
"en" "You have been infected! Go pass it on to as many other players as you can."
|
||||
}
|
||||
|
||||
"Infect human"
|
||||
{
|
||||
"en" "The merciful gods (known as admins) have resurrected your soul, find some cover!"
|
||||
}
|
||||
|
||||
"Infect disconnect"
|
||||
{
|
||||
"en" "The last zombie has left the game, and has passed the infection on to you."
|
||||
"ru" "Последний зомби покинул игру и передал свою инфекцию вам."
|
||||
}
|
||||
|
||||
// Commands
|
||||
|
||||
"Infect command infect syntax"
|
||||
{
|
||||
"en" "Infect a client. Usage: zr_infect <filter> [respawn - 1/0]"
|
||||
}
|
||||
|
||||
"Infect command human syntax"
|
||||
{
|
||||
"en" "Turn a client into a human. Usage: zr_human <filter> [respawn - 1/0] [protect - 1/0]"
|
||||
}
|
||||
|
||||
"Infect command infect successful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player @green{1} @defaulthas been successfully infected."
|
||||
}
|
||||
|
||||
"Infect command infect unsuccessful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player @green{1} @defaultis already a zombie."
|
||||
}
|
||||
|
||||
"Infect command human successful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player @green{1} @defaulthas been successfully brought back as a human."
|
||||
}
|
||||
|
||||
"Infect command human unsuccessful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player @green{1} @defaultis already a human."
|
||||
}
|
||||
|
||||
"Infect command zombie has not spawned"
|
||||
{
|
||||
"en" "The mother zombie must spawn before player infection states can be changed."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Damage (core)
|
||||
// ===========================
|
||||
|
@ -35,6 +35,7 @@ CommandsInit()
|
||||
LogOnCommandsCreate();
|
||||
ClassOnCommandsCreate();
|
||||
WeaponsOnCommandsCreate();
|
||||
InfectOnCommandsCreate();
|
||||
VolOnCommandsCreate();
|
||||
|
||||
// Forward event to modules. (hook commands)
|
||||
@ -97,7 +98,7 @@ CommandsInit()
|
||||
|
||||
for (new x = 0; x < tcount; x++)
|
||||
{
|
||||
InfectClient(targets[x]);
|
||||
InfectHumanToZombie(targets[x]);
|
||||
if (LogCheckFlag(LOG_GAME_EVENTS, LOG_MODULE_COMMANDS))
|
||||
{
|
||||
GetClientName(targets[x], target_name, sizeof(target_name));
|
||||
|
@ -143,6 +143,7 @@ enum CvarsList
|
||||
Handle:CVAR_ZSPAWN_TEAM_ZOMBIE,
|
||||
Handle:CVAR_ZSPAWN_TIMELIMIT,
|
||||
Handle:CVAR_ZSPAWN_TIMELIMIT_TIME,
|
||||
Handle:CVAR_ZSPAWN_TIMELIMIT_ZOMBIE,
|
||||
Handle:CVAR_ZTELE_ZOMBIE,
|
||||
Handle:CVAR_ZTELE_HUMAN_BEFORE,
|
||||
Handle:CVAR_ZTELE_HUMAN_AFTER,
|
||||
@ -437,6 +438,7 @@ CvarsCreate()
|
||||
|
||||
g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT] = CreateConVar("zr_zspawn_timelimit", "1", "Put a time limit on the use of ZSpawn.");
|
||||
g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME] = CreateConVar("zr_zspawn_timelimit_time", "120.0", "Time from the start of the round to allow ZSpawn. [Dependency: zr_zspawn_timelimit]");
|
||||
g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE] = CreateConVar("zr_zspawn_timelimit_zombie", "1", "Spawn player on the zombie team AFTER the timelimit is up. ['-1' = Block ZSpawn | '0' = Spawn as human | '1' = Spawn as zombie | Dependency: zr_zspawn_timelimit]");
|
||||
|
||||
|
||||
// ===========================
|
||||
|
@ -100,6 +100,15 @@ InfectLoad()
|
||||
AddFileToDownloadsTable(sound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create commands specific to infect here.
|
||||
*/
|
||||
InfectOnCommandsCreate()
|
||||
{
|
||||
RegAdminCmd("zr_infect", InfectInfectCommand, ADMFLAG_GENERIC, "Infect a client. Usage: zr_infect <filter> [respawn - 1/0]");
|
||||
RegAdminCmd("zr_human", InfectHumanCommand, ADMFLAG_GENERIC, "Turn a client into a human. Usage: zr_human <filter> [respawn - 1/0]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Client is joining the server.
|
||||
*
|
||||
@ -192,7 +201,7 @@ InfectOnClientDisconnect(client)
|
||||
new randclient = GetArrayCell(arrayEligibleClients, randindex);
|
||||
|
||||
// Infect player.
|
||||
InfectClient(randclient);
|
||||
InfectHumanToZombie(randclient);
|
||||
|
||||
// Tell client they have been randomly been chosen to replace disconnecting zombie.
|
||||
TranslationPrintToChat(randclient, "Infect disconnect");
|
||||
@ -311,7 +320,7 @@ InfectOnClientHurt(client, attacker, const String:weapon[])
|
||||
}
|
||||
|
||||
// Infect client.
|
||||
InfectClient(client, attacker);
|
||||
InfectHumanToZombie(client, attacker);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,7 +479,7 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
client = GetArrayCell(arrayEligibleClients, randindex);
|
||||
|
||||
// Infect player.
|
||||
InfectClient(client, _, true);
|
||||
InfectHumanToZombie(client, _, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -509,7 +518,7 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
client = GetArrayCell(arrayEligibleClients, randindex);
|
||||
|
||||
// Infect player.
|
||||
InfectClient(client, _, true);
|
||||
InfectHumanToZombie(client, _, true);
|
||||
|
||||
// Remove player from eligible zombie list.
|
||||
RemoveFromArray(arrayEligibleClients, randindex);
|
||||
@ -524,14 +533,16 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Infects a player. Execute events, sets attributes and flags that indicate
|
||||
* that the player is a zombie.
|
||||
* Infects a client. Execute events, sets attributes and flags that indicate
|
||||
* that the client is a zombie.
|
||||
*
|
||||
* @param client The player to infect.
|
||||
* @param client The client to infect.
|
||||
* @param attacker (Optional) The attacker who did the infect.
|
||||
* @param motherinfect (Optional) Indicates a mother zombie infect.
|
||||
* @param respawnoverride (Optional) Set to true to override respawn cvar.
|
||||
* @param respawn (Optional) Value to override with.
|
||||
*/
|
||||
InfectClient(client, attacker = -1, bool:motherinfect = false)
|
||||
InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respawnoverride = false, bool:respawn = false)
|
||||
{
|
||||
// Mark player as zombie.
|
||||
bZombie[client] = true;
|
||||
@ -631,8 +642,16 @@ InfectClient(client, attacker = -1, bool:motherinfect = false)
|
||||
ZTeleTeleportClient(client);
|
||||
}
|
||||
}
|
||||
// Check override.
|
||||
else
|
||||
{
|
||||
if (respawnoverride && respawn)
|
||||
{
|
||||
ZTeleTeleportClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
// Format infection message.
|
||||
// Set client as translation target.
|
||||
SetGlobalTransTarget(client);
|
||||
|
||||
// Print message to client.
|
||||
@ -646,6 +665,46 @@ InfectClient(client, attacker = -1, bool:motherinfect = false)
|
||||
ZHPOnClientInfected(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a zombie back into a human. Execute events, sets attributes and flags that indicate
|
||||
* that the client is a human.
|
||||
*
|
||||
* @param client The client to make human.
|
||||
* @param respawn Teleport client back to spawn if true.
|
||||
* @param protect Start spawn protection on new human.
|
||||
*/
|
||||
InfectZombieToHuman(client, bool:respawn = false, bool:protect = false)
|
||||
{
|
||||
// Mark player as human.
|
||||
bZombie[client] = false;
|
||||
|
||||
// Switch the player to counter-terrorists.
|
||||
CS_SwitchTeam(client, CS_TEAM_CT);
|
||||
|
||||
// Set client as translation target.
|
||||
SetGlobalTransTarget(client);
|
||||
|
||||
// Print message to client.
|
||||
TranslationPrintToChat(client, "Infect human");
|
||||
|
||||
// Forward event to modules.
|
||||
ClassOnClientInfected(client, false);
|
||||
RoundEndOnClientInfected();
|
||||
ZTeleOnClientInfected(client);
|
||||
|
||||
// Check if we should respawn the client.
|
||||
if (respawn)
|
||||
{
|
||||
ZTeleTeleportClient(client);
|
||||
}
|
||||
|
||||
// Check if we should spawn protect the client.
|
||||
if (protect)
|
||||
{
|
||||
SpawnProtectStart(client);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates effects on a newly infected client.
|
||||
*
|
||||
@ -754,3 +813,139 @@ bool:InfectIsClientHuman(client)
|
||||
// Return opposite of client's zombie flag.
|
||||
return !bZombie[client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_infect)
|
||||
* Infects a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:InfectInfectCommand(client, argc)
|
||||
{
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 1)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Infect command infect syntax");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!g_bZombieSpawned)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Infect command zombie has not spawned");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH];
|
||||
new targets[MAXPLAYERS], bool:tn_is_ml, result;
|
||||
|
||||
// Get targetname.
|
||||
GetCmdArg(1, target, sizeof(target));
|
||||
|
||||
// Find a target.
|
||||
result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI, targetname, sizeof(targetname), tn_is_ml);
|
||||
|
||||
// Check if there was a problem finding a client.
|
||||
if (result <= 0)
|
||||
{
|
||||
ZRReplyToTargetError(client, result);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Check if client is a human before turning into zombie.
|
||||
if (InfectIsClientHuman(targets[0]))
|
||||
{
|
||||
new bool:respawnoverride, bool:respawn;
|
||||
decl String:strRespawn[8];
|
||||
|
||||
// Get respawn parameter.
|
||||
GetCmdArg(2, strRespawn, sizeof(strRespawn));
|
||||
|
||||
// If parameter exists then cast it into a bool and feed it to infect function.
|
||||
if (strRespawn[0])
|
||||
{
|
||||
respawnoverride = true;
|
||||
respawn = bool:StringToInt(strRespawn);
|
||||
}
|
||||
|
||||
// Turn client into a zombie.
|
||||
InfectHumanToZombie(targets[0], _, _, respawnoverride, respawn);
|
||||
|
||||
// Tell admin command was successful.
|
||||
TranslationReplyToCommand(client, "Infect command infect successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tell admin command was unsuccessful.
|
||||
TranslationReplyToCommand(client, "Infect command infect unsuccessful", targetname);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_human)
|
||||
* Turns a client into a human.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:InfectHumanCommand(client, argc)
|
||||
{
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 1)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Infect command human syntax");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if (!g_bZombieSpawned)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Infect command zombie has not spawned");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH];
|
||||
new targets[MAXPLAYERS], bool:tn_is_ml, result;
|
||||
|
||||
// Get targetname.
|
||||
GetCmdArg(1, target, sizeof(target));
|
||||
|
||||
// Find a target.
|
||||
result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE | COMMAND_FILTER_NO_MULTI, targetname, sizeof(targetname), tn_is_ml);
|
||||
|
||||
// Check if there was a problem finding a client.
|
||||
if (result <= 0)
|
||||
{
|
||||
ZRReplyToTargetError(client, result);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Check if client is a human before turning into zombie.
|
||||
if (InfectIsClientInfected(targets[0]))
|
||||
{
|
||||
new bool:respawn, bool:protect;
|
||||
decl String:strRespawn[8], String:strProtect[8];
|
||||
|
||||
// Get respawn&protect parameters
|
||||
GetCmdArg(2, strRespawn, sizeof(strRespawn));
|
||||
GetCmdArg(3, strProtect, sizeof(strProtect));
|
||||
|
||||
// If parameter exists then cast it into a bool and feed it to "humanize" function.
|
||||
respawn = (strRespawn[0]) ? (bool:StringToInt(strRespawn)) : false;
|
||||
protect = (strProtect[0]) ? (bool:StringToInt(strProtect)) : false;
|
||||
|
||||
// Turn client into a zombie.
|
||||
InfectZombieToHuman(targets[0], respawn, protect);
|
||||
|
||||
// Tell admin command was successful.
|
||||
TranslationReplyToCommand(client, "Infect command human successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tell admin command was unsuccessful.
|
||||
TranslationReplyToCommand(client, "Infect command human unsuccessful", targetname);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
@ -155,13 +155,13 @@ RespawnSpawnClient(client, bool:zombie = false)
|
||||
// Infect if zombie is true.
|
||||
if (zombie)
|
||||
{
|
||||
InfectClient(client);
|
||||
InfectHumanToZombie(client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE_WORLD]) && bKilledByWorld[client])
|
||||
{
|
||||
InfectClient(client);
|
||||
InfectHumanToZombie(client);
|
||||
bKilledByWorld[client] = false;
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +73,43 @@ SpawnProtectOnClientSpawn(client)
|
||||
*/
|
||||
SpawnProtectOnClientSpawnPost(client)
|
||||
{
|
||||
// If client isn't on a team, then stop.
|
||||
if (!ZRIsClientOnTeam(client))
|
||||
// If protect cvar is disabled, then stop.
|
||||
new bool:protect = GetConVarBool(g_hCvarsList[CVAR_SPAWNPROTECT]);
|
||||
if (!protect)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start spawn protection.
|
||||
SpawnProtectStart(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Client has been killed.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
SpawnProtectOnClientDeath(client)
|
||||
{
|
||||
// If timer is running, kill it.
|
||||
if (tSpawnProtect[client] != INVALID_HANDLE)
|
||||
{
|
||||
KillTimer(tSpawnProtect[client]);
|
||||
}
|
||||
|
||||
// Reset timer handle.
|
||||
tSpawnProtect[client] = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start spawn protection on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
SpawnProtectStart(client)
|
||||
{
|
||||
// If client is dead, then stop.
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -85,13 +120,6 @@ SpawnProtectOnClientSpawnPost(client)
|
||||
return;
|
||||
}
|
||||
|
||||
// If protect cvar is disabled, then stop.
|
||||
new bool:protect = GetConVarBool(g_hCvarsList[CVAR_SPAWNPROTECT]);
|
||||
if (!protect)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If client is a zombie, then stop.
|
||||
if (InfectIsClientInfected(client))
|
||||
{
|
||||
@ -123,23 +151,6 @@ SpawnProtectOnClientSpawnPost(client)
|
||||
tSpawnProtect[client] = CreateTimer(1.0, SpawnProtectTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Client has been killed.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
SpawnProtectOnClientDeath(client)
|
||||
{
|
||||
// If timer is running, kill it.
|
||||
if (tSpawnProtect[client] != INVALID_HANDLE)
|
||||
{
|
||||
KillTimer(tSpawnProtect[client]);
|
||||
}
|
||||
|
||||
// Reset timer handle.
|
||||
tSpawnProtect[client] = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback function, countdown for spawn protection.
|
||||
*
|
||||
|
@ -333,7 +333,7 @@ public ZRAdminMenuHandle(Handle:menu_admin, MenuAction:action, client, slot)
|
||||
{
|
||||
decl String:name[64];
|
||||
GetClientName(target, name, sizeof(name));
|
||||
InfectClient(target);
|
||||
InfectHumanToZombie(target);
|
||||
ShowActivity2(client, "[ZR] ", "Infected %s", name);
|
||||
ZRInfectMenu(client);
|
||||
}
|
||||
|
@ -254,6 +254,54 @@ stock bool:ZRIsClientAdmin(client)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replies to a client with a given message describing a targetting
|
||||
* failure reason. (formatted for ZR)
|
||||
*
|
||||
* Note: The translation phrases are found in common.phrases.txt.
|
||||
*
|
||||
* @param client Client index, or 0 for server.
|
||||
* @param reason COMMAND_TARGET reason.
|
||||
*/
|
||||
stock ZRReplyToTargetError(client, reason)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case COMMAND_TARGET_NONE:
|
||||
{
|
||||
TranslationReplyToCommand(client, "No matching client");
|
||||
}
|
||||
case COMMAND_TARGET_NOT_ALIVE:
|
||||
{
|
||||
TranslationReplyToCommand(client, "Target must be alive");
|
||||
}
|
||||
case COMMAND_TARGET_NOT_DEAD:
|
||||
{
|
||||
TranslationReplyToCommand(client, "Target must be dead");
|
||||
}
|
||||
case COMMAND_TARGET_NOT_IN_GAME:
|
||||
{
|
||||
TranslationReplyToCommand(client, "Target is not in game");
|
||||
}
|
||||
case COMMAND_TARGET_IMMUNE:
|
||||
{
|
||||
TranslationReplyToCommand(client, "Unable to target");
|
||||
}
|
||||
case COMMAND_TARGET_EMPTY_FILTER:
|
||||
{
|
||||
TranslationReplyToCommand(client, "No matching clients");
|
||||
}
|
||||
case COMMAND_TARGET_NOT_HUMAN:
|
||||
{
|
||||
TranslationReplyToCommand(client, "Cannot target bot");
|
||||
}
|
||||
case COMMAND_TARGET_AMBIGUOUS:
|
||||
{
|
||||
TranslationReplyToCommand(client, "More than one client matched");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds support for printing strings longer than 1 KB to console. Max 4 KB.
|
||||
*
|
||||
|
@ -175,11 +175,20 @@ bool:ZSpawnClient(client)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if zspawn override is enabled, and if so get overidden value.
|
||||
new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]);
|
||||
new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]);
|
||||
|
||||
// Block is the time limit is up.
|
||||
new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]);
|
||||
if (zspawntimelimit)
|
||||
{
|
||||
if (tZSpawn == INVALID_HANDLE)
|
||||
{
|
||||
new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]);
|
||||
switch(zspawntimelimitzombie)
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
// Get timelimit
|
||||
new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]);
|
||||
@ -188,11 +197,17 @@ bool:ZSpawnClient(client)
|
||||
TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime));
|
||||
return false;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
teamzombie = false;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
teamzombie = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if zspawn override is enabled, and if so get overidden value.
|
||||
new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]);
|
||||
new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]);
|
||||
|
||||
// Tell respawn module to respawn client.
|
||||
RespawnSpawnClient(client, teamzombie);
|
||||
|
Loading…
Reference in New Issue
Block a user