Improved the teleporter. Startup delay, cooldown, separate team delays and limits. Admin commands made, but not coded yet.

This commit is contained in:
richard 2008-12-20 20:46:05 +01:00
parent b66baa5dd0
commit 69799e1c0d
12 changed files with 440 additions and 31 deletions

View File

@ -1,3 +1,6 @@
2008.12.20 - 2.5.1.16
* Improved the teleporter. Startup delay, cooldown, separate team delays and limits. Admin commands made, but not coded yet.
2008.12.16 - 2.5.1.15 - Richard 2008.12.16 - 2.5.1.15 - Richard
* Removed unnecessary function call in OnPluginEnd causeing the periodical GameRules not available error. * Removed unnecessary function call in OnPluginEnd causeing the periodical GameRules not available error.

View File

@ -94,14 +94,15 @@
"!ztele amount" "!ztele amount"
{ {
"#format" "{1:d}" "#format" "{1:d}"
"en" "You have @green{1}@default teleports left this round. (Teleport in 3 seconds)" "en" "You have @green{1}@default teleports left this round."
"ru" "У вас осталось @green{1}@default телепортов в этом раунде. (Телепортация через 3 секунды)" "ru" "У вас осталось @green{1}@default телепортов в этом раунде."
} }
"!ztele amount unlimited" "!ztele time left"
{ {
"en" "You will be teleported in 3 seconds." "#format" "{1:d}"
"ru" "Вы будете телепортированы через 3 секунды." "en" "You will be teleported in {1} seconds."
"ru" "Вы будете телепортированы через {1} секунды."
} }
"!ztele limit reached" "!ztele limit reached"
@ -112,10 +113,45 @@
"!ztele humans restricted" "!ztele humans restricted"
{ {
"en" "Once a player has been infected, only zombies can use !ztele" "en" "Once a player has been infected, only zombies can use !ztele."
"ru" "После инфицирования кого-либо, только зомби могут использовать !ztele" "ru" "После инфицирования кого-либо, только зомби могут использовать !ztele"
} }
"!ztele zombies restricted"
{
"en" "The teleporter is disabled for zombies."
}
"!ztele stuck"
{
"en" "Tip: Use !tp to teleport away if you are stuck."
}
"!ztele not spawned"
{
"en" "You cannot use the teleporter before you've spawned."
}
"!ztele offline"
{
"en" "The teleporter is not online yet."
}
"!ztele cooldown"
{
"en" "Your teleporter is still on a cooldown."
}
"!ztele in progress"
{
"en" "You already have a teleportation in progress."
}
"!ztele successful"
{
"en" "Teleport successful."
}
"!zhp enabled" "!zhp enabled"
{ {
"en" "HP display enabled, your real HP will be displayed persistently after infection." "en" "HP display enabled, your real HP will be displayed persistently after infection."

View File

@ -15,7 +15,7 @@
#undef REQUIRE_PLUGIN #undef REQUIRE_PLUGIN
#include <market> #include <market>
#define VERSION "2.5.1.15" #define VERSION "2.5.1.16"
#include "zr/zombiereloaded" #include "zr/zombiereloaded"
#include "zr/global" #include "zr/global"
@ -26,6 +26,7 @@
#include "zr/classes" #include "zr/classes"
#include "zr/models" #include "zr/models"
#include "zr/overlays" #include "zr/overlays"
#include "zr/teleport"
#include "zr/zombie" #include "zr/zombie"
#include "zr/menu" #include "zr/menu"
#include "zr/sayhooks" #include "zr/sayhooks"
@ -174,6 +175,7 @@ public OnClientDisconnect(client)
ClientUnHookAttack(client); ClientUnHookAttack(client);
PlayerLeft(client); PlayerLeft(client);
ZTeleResetClient(client);
new debug_val = GetConVarInt(gCvars[CVAR_DEBUG]); new debug_val = GetConVarInt(gCvars[CVAR_DEBUG]);
new String:debug_msg[64]; new String:debug_msg[64];

View File

@ -10,7 +10,9 @@ CreateCommands()
{ {
RegAdminCmd("zr_infect", Command_Infect, ADMFLAG_GENERIC, "Infects the specified player"); RegAdminCmd("zr_infect", Command_Infect, ADMFLAG_GENERIC, "Infects the specified player");
RegAdminCmd("zr_spawn", Command_Respawn, ADMFLAG_GENERIC, "Respawns the specified player following auto-respawning rules"); RegAdminCmd("zr_spawn", Command_Respawn, ADMFLAG_GENERIC, "Respawns the specified player following auto-respawning rules");
RegAdminCmd("zr_teleport", Command_Teleport, ADMFLAG_GENERIC, "Teleports one or more players to spawn. Usage: zr_teleport <target>");
RegAdminCmd("zr_tele_saveloc", Command_TeleSaveLocation, ADMFLAG_GENERIC, "Saves your or a players location to a buffer. Usage: zr_tele_saveloc [#userid|name]");
RegAdminCmd("zr_tele_loc", Command_TeleportToLocation, ADMFLAG_GENERIC, "Teleports you or a player to the saved location. Usage: zr_tele_loc [#userid|name]");
RegAdminCmd("zr_restrict", Command_Restrict, ADMFLAG_GENERIC, "Restrict a specified weapon"); RegAdminCmd("zr_restrict", Command_Restrict, ADMFLAG_GENERIC, "Restrict a specified weapon");
RegAdminCmd("zr_unrestrict", Command_UnRestrict, ADMFLAG_GENERIC, "Unrestrict a specified weapon"); RegAdminCmd("zr_unrestrict", Command_UnRestrict, ADMFLAG_GENERIC, "Unrestrict a specified weapon");

View File

@ -59,8 +59,12 @@ enum ZRSettings
Handle:CVAR_ZMARKET_BUYZONE, Handle:CVAR_ZMARKET_BUYZONE,
Handle:CVAR_ZSPAWN, Handle:CVAR_ZSPAWN,
Handle:CVAR_ZTELE, Handle:CVAR_ZTELE,
Handle:CVAR_ZTELE_LIMIT, Handle:CVAR_ZTELE_STARTUP_DELAY,
Handle:CVAR_ZTELE_HUMANS, Handle:CVAR_ZTELE_COOLDOWN,
Handle:CVAR_ZTELE_HUMAN_DELAY,
Handle:CVAR_ZTELE_HUMAN_LIMIT,
Handle:CVAR_ZTELE_ZOMBIE_DELAY,
Handle:CVAR_ZTELE_ZOMBIE_LIMIT,
Handle:CVAR_ZSTUCK, Handle:CVAR_ZSTUCK,
Handle:CVAR_ZHP, Handle:CVAR_ZHP,
Handle:CVAR_ZHP_DEFAULT, Handle:CVAR_ZHP_DEFAULT,
@ -131,9 +135,13 @@ CreateCvars()
gCvars[CVAR_OVERLAYS_ZOMBIE] = CreateConVar("zr_overlays_zombie", "overlays/zr/zombies_win", "The overlay shown to tell everyone that zombies won when zr_overlays is 1"); gCvars[CVAR_OVERLAYS_ZOMBIE] = CreateConVar("zr_overlays_zombie", "overlays/zr/zombies_win", "The overlay shown to tell everyone that zombies won when zr_overlays is 1");
gCvars[CVAR_ZMARKET_BUYZONE] = CreateConVar("zr_zmarket_buyzone", "1", "Must be in buyzone to access !zmarket, if Market is installed (0: Can be used anywhere)"); gCvars[CVAR_ZMARKET_BUYZONE] = CreateConVar("zr_zmarket_buyzone", "1", "Must be in buyzone to access !zmarket, if Market is installed (0: Can be used anywhere)");
gCvars[CVAR_ZSPAWN] = CreateConVar("zr_zspawn", "1", "Allow players to spawn if they just joined the game (0: Disable)"); gCvars[CVAR_ZSPAWN] = CreateConVar("zr_zspawn", "1", "Allow players to spawn if they just joined the game (0: Disable)");
gCvars[CVAR_ZTELE] = CreateConVar("zr_ztele", "1", "Allows zombies who get stuck to teleport back to spawn (0: Disable)"); gCvars[CVAR_ZTELE] = CreateConVar("zr_ztele", "1", "Allow players to use the teleporter to get to spawn. (0: Disable)");
gCvars[CVAR_ZTELE_LIMIT] = CreateConVar("zr_ztele_limit", "1", "Max amount of teleports per round when zr_ztele is 1 (0: Unlimited)"); gCvars[CVAR_ZTELE_STARTUP_DELAY] = CreateConVar("zr_ztele_startup_delay", "40", "Number of seconds to wait before the teleporter is enabled (0: Always enabled)");
gCvars[CVAR_ZTELE_HUMANS] = CreateConVar("zr_ztele_humans", "1", "Allow humans to use the teleporter (0: Disabled)"); gCvars[CVAR_ZTELE_COOLDOWN] = CreateConVar("zr_ztele_cooldown", "30", "Number of seconds to wait before the teleporter can be used again, after a teleport. (0: Disable)");
gCvars[CVAR_ZTELE_HUMAN_DELAY] = CreateConVar("zr_ztele_human_delay", "20", "Teleport delay for humans. (0: No delay)");
gCvars[CVAR_ZTELE_HUMAN_LIMIT] = CreateConVar("zr_ztele_human_limit", "3", "Maximum number of teleports humans can do. (0: Humans can't use the teleporter. -1: Unlimited)");
gCvars[CVAR_ZTELE_ZOMBIE_DELAY] = CreateConVar("zr_ztele_zombie_delay", "0", "Teleport delay for zombies. (0: No delay)");
gCvars[CVAR_ZTELE_ZOMBIE_LIMIT] = CreateConVar("zr_ztele_zombie_limit", "8", "Maximum number of teleports zombies can do. (0: Zombies can't use the teleporter. -1: Unlimited)");
gCvars[CVAR_ZSTUCK] = CreateConVar("zr_zstuck", "1", "Allow players that are stuck together to get unstuck (0: Disable)"); gCvars[CVAR_ZSTUCK] = CreateConVar("zr_zstuck", "1", "Allow players that are stuck together to get unstuck (0: Disable)");
gCvars[CVAR_ZHP] = CreateConVar("zr_zhp", "1", "Allows clients to enable/disable zombie health display (1: On, 0: Off)"); gCvars[CVAR_ZHP] = CreateConVar("zr_zhp", "1", "Allows clients to enable/disable zombie health display (1: On, 0: Off)");
gCvars[CVAR_ZHP_DEFAULT] = CreateConVar("zr_zhp_default", "1", "The default value of zombie health display to new clients (1: On, 0: Off)"); gCvars[CVAR_ZHP_DEFAULT] = CreateConVar("zr_zhp_default", "1", "The default value of zombie health display to new clients (1: On, 0: Off)");

View File

@ -74,6 +74,9 @@ public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadca
new Float:max = GetConVarFloat(gCvars[CVAR_SPAWN_MAX]); new Float:max = GetConVarFloat(gCvars[CVAR_SPAWN_MAX]);
new Float:randlen = GetRandomFloat(min, max); new Float:randlen = GetRandomFloat(min, max);
tInfect = CreateTimer(randlen, MotherZombie, _, TIMER_FLAG_NO_MAPCHANGE); tInfect = CreateTimer(randlen, MotherZombie, _, TIMER_FLAG_NO_MAPCHANGE);
ZTeleEnable();
} }
public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
@ -118,6 +121,8 @@ public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{ {
ShowOverlays(5.0, Zombie); ShowOverlays(5.0, Zombie);
} }
ZTeleReset();
} }
public Action:PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) public Action:PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast)
@ -178,8 +183,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
SetPlayerMoney(index, cash); SetPlayerMoney(index, cash);
} }
teleCount[index] = 0; ZTeleClientSpawned(index);
GetClientAbsOrigin(index, spawnLoc[index]);
NightVisionOn(index, false); NightVisionOn(index, false);
NightVision(index, false); NightVision(index, false);

View File

@ -77,7 +77,7 @@ public MainMenuHandle(Handle:menu_main, MenuAction:action, client, slot)
} }
case 4: case 4:
{ {
ZTele(client); ZTeleClientCheck(client);
MainMenu(client); MainMenu(client);
} }
case 5: case 5:

View File

@ -45,9 +45,12 @@ public Action:SayCommand(client, argc)
ZSpawn(client); ZSpawn(client);
} }
else if (StrEqual(args, "!ztele", false)) else if (StrEqual(args, "!tp", false) ||
StrEqual(args, "!ztele", false) ||
StrEqual(args, "!tele", false) ||
StrEqual(args, "!teleport", false))
{ {
ZTele(client); ZTeleClientCheck(client);
} }
else if (StrEqual(args, "!zstuck", false)) else if (StrEqual(args, "!zstuck", false))
@ -59,6 +62,12 @@ public Action:SayCommand(client, argc)
{ {
ZHP(client); ZHP(client);
} }
else if (StrContains(args, "teleport", false) != -1
|| StrContains(args, "stuck", false) != -1
|| StrContains(args, "help", false) != -1)
{
ZR_PrintToChat(client, "!ztele stuck");
}
return Plugin_Continue; return Plugin_Continue;
} }
@ -217,6 +226,7 @@ ZSpawn(client)
AddPlayerToList(client); AddPlayerToList(client);
} }
/*
ZTele(client) ZTele(client)
{ {
new bool:tele = GetConVarBool(gCvars[CVAR_ZTELE]); new bool:tele = GetConVarBool(gCvars[CVAR_ZTELE]);
@ -269,6 +279,7 @@ public Action:Teleport(Handle:timer, any:index)
tHandles[index][TTELE] = INVALID_HANDLE; tHandles[index][TTELE] = INVALID_HANDLE;
} }
*/
ZStuck(client) ZStuck(client)
{ {

338
src/zr/teleport.inc Normal file
View File

@ -0,0 +1,338 @@
/**
* ====================
* Zombie:Reloaded
* File: teleport.inc
* Authors: Richard Helgeby / Cpt.Moore
* ====================
*/
ZTeleEnable()
{
ztele_online = false;
if (ztele_startup_timer != INVALID_HANDLE)
{
KillTimer(ztele_startup_timer);
}
new Float:startup_delay = GetConVarFloat(gCvars[CVAR_ZTELE_STARTUP_DELAY]);
if (startup_delay > 0)
{
ztele_startup_timer = CreateTimer(startup_delay, Event_TeleporterStartup);
}
else
{
ztele_online = true;
}
}
ZTeleReset()
{
ztele_online = false;
if (ztele_startup_timer != INVALID_HANDLE)
{
KillTimer(ztele_startup_timer);
ztele_startup_timer = INVALID_HANDLE;
}
for (new client = 1; client <= MAXPLAYERS; client++)
{
spawnLoc[client] = NULL_VECTOR;
ztele_spawned[client] = false;
ztele_countdown[client] = -1;
ztele_count[client] = 0;
// Stop any cooldown or teleportation in progress.
if (ztele_countdown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_countdown_timer[client]);
ztele_countdown_timer[client] = INVALID_HANDLE;
}
if (ztele_cooldown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_cooldown_timer[client]);
ztele_cooldown_timer[client] = INVALID_HANDLE;
}
}
}
ZTeleResetClient(client, bool:soft_reset = false)
{
if (!soft_reset)
{
spawnLoc[client] = NULL_VECTOR;
ztele_spawned[client] = false;
}
ztele_countdown[client] = -1;
ztele_count[client] = 0;
// Stop any cooldown or teleportation in progress.
if (ztele_countdown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_countdown_timer[client]);
ztele_countdown_timer[client] = INVALID_HANDLE;
}
if (ztele_cooldown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_cooldown_timer[client]);
ztele_cooldown_timer[client] = INVALID_HANDLE;
}
}
ZTeleClientSpawned(client)
{
if (IsFakeClient(client))
{
return;
}
ZTeleResetClient(client, true);
// Store location if not already stored.
if (!ztele_spawned[client])
{
GetClientAbsOrigin(client, spawnLoc[client]);
}
}
public Action:Event_TeleporterStartup(Handle:timer)
{
ztele_online = true;
ztele_startup_timer = INVALID_HANDLE;
}
public Action:Event_TeleportCountdown(Handle:timer, any:client)
{
ztele_countdown[client]--;
if (ztele_countdown[client] <= 0)
{
KillTimer(ztele_countdown_timer[client]);
ztele_countdown_timer[client] = INVALID_HANDLE;
// Do teleport.
TeleportClient(client, true);
// Create cooldown timer if enabled.
new cooldown = GetConVarInt(gCvars[CVAR_ZTELE_COOLDOWN]);
if (cooldown)
{
ztele_countdown[client] = cooldown;
ztele_cooldown_timer[client] = CreateTimer(1.0, Event_TeleportCooldown, client, TIMER_REPEAT);
}
}
else if ((ztele_countdown[client] % 3) == 0)
{
// Display countdown message.
ZR_PrintToChat(client, "!ztele time left", ztele_countdown[client]);
}
}
public Action:Event_TeleportCooldown(Handle:Timer, any:client)
{
ztele_countdown[client]--;
if (ztele_countdown[client] <= 0)
{
KillTimer(ztele_cooldown_timer[client]);
ztele_cooldown_timer[client] = INVALID_HANDLE;
}
}
public Action:Command_Teleport(client, argc)
{
// Check (on all specified clients) if a teleport/cooldown is in progress.
// If so, kill those timers.
// No cooldown when using this command.
return Plugin_Handled;
}
public Action:Command_TeleSaveLocation(client, argc)
{
return Plugin_Handled;
}
public Action:Command_TeleportToLocation(client, argc)
{
// Don't teleport if a location isn't saved yet.
// To do: Find or make a function to check if a vector array is a null vector.
/*if (bufferLoc[] != NULL_VECTOR)
{
return Plugin_Handled;
}
else
{
ZR_PrintToChat(client, "!ztele location not set");
return Plugin_Handled;
}*/
}
ZTeleClientCheck(client)
{
new bool:tele = GetConVarBool(gCvars[CVAR_ZTELE]);
if (!tele)
{
ZR_PrintToChat(client, "Feature is disabled");
return;
}
if (!ztele_online)
{
ZR_PrintToChat(client, "!ztele offline");
return;
}
// Check if there's already a teleport in process.
if (ztele_countdown_timer[client] != INVALID_HANDLE)
{
ZR_PrintToChat(client, "!ztele in progress");
return;
}
// Check if the cooldown isn't done yet.
if (ztele_cooldown_timer[client] != INVALID_HANDLE)
{
ZR_PrintToChat(client, "!ztele cooldown");
return;
}
// Check limits.
if (IsPlayerHuman(client))
{
new human_limit = GetConVarInt(gCvars[CVAR_ZTELE_HUMAN_LIMIT]);
new bool:tele_humans;
if (human_limit == 0)
{
tele_humans = false;
}
else
{
tele_humans = true;
}
if (!tele_humans && zombieSpawned)
{
ZR_PrintToChat(client, "!ztele humans restricted");
return;
}
if (human_limit > 0 && (ztele_count[client] >= human_limit))
{
ZR_PrintToChat(client, "!ztele limit reached");
return;
}
}
else
{
new zombie_limit = GetConVarInt(gCvars[CVAR_ZTELE_ZOMBIE_LIMIT]);
new bool:tele_zombies;
if (zombie_limit == 0)
{
tele_zombies = false;
}
else
{
tele_zombies = true;
}
if (!tele_zombies)
{
ZR_PrintToChat(client, "!ztele zombies restricted");
return;
}
if (zombie_limit > 0 && (ztele_count[client] >= zombie_limit))
{
ZR_PrintToChat(client, "!ztele limit reached");
return;
}
}
TeleportClient(client);
}
TeleportClient(client, bool:no_delay = false)
{
new teleports_left;
new bool:teleports_unlimited = false;
if (IsPlayerHuman(client))
{
new human_delay = GetConVarInt(gCvars[CVAR_ZTELE_HUMAN_DELAY]);
new human_limit = GetConVarInt(gCvars[CVAR_ZTELE_HUMAN_LIMIT]);
if (human_delay > 0)
{
ztele_countdown[client] = human_delay;
}
else
{
no_delay = true;
}
if (human_limit > 0)
{
teleports_left = human_limit - ztele_count[client] - 1;
}
else
{
teleports_unlimited = true;
}
}
else
{
new zombie_delay = GetConVarInt(gCvars[CVAR_ZTELE_ZOMBIE_DELAY]);
new zombie_limit = GetConVarInt(gCvars[CVAR_ZTELE_ZOMBIE_LIMIT]);
if (zombie_delay > 0)
{
ztele_countdown[client] = zombie_delay;
}
else
{
no_delay = true;
}
if (zombie_limit > 0)
{
teleports_left = zombie_limit - ztele_count[client] - 1;
}
else
{
teleports_unlimited = true;
}
}
if (no_delay)
{
ztele_countdown[client] = -1;
ztele_count[client]++;
TeleportEntity(client, spawnLoc[client], NULL_VECTOR, NULL_VECTOR);
ZR_PrintToChat(client, "!ztele successful");
if (!teleports_unlimited)
{
ZR_PrintToChat(client, "!ztele amount", teleports_left);
}
}
else
{
ztele_countdown_timer[client] = CreateTimer(1.0, Event_TeleportCountdown, client, TIMER_REPEAT);
if (!teleports_unlimited)
{
ZR_PrintToChat(client, "!ztele amount", teleports_left);
}
}
}
AbortTeleport(client)
{
ztele_countdown[client] = -1;
// Stop any cooldown or teleportation in progress.
if (ztele_countdown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_countdown_timer[client]);
ztele_countdown_timer[client] = INVALID_HANDLE;
}
if (ztele_cooldown_timer[client] != INVALID_HANDLE)
{
KillTimer(ztele_cooldown_timer[client]);
ztele_cooldown_timer[client] = INVALID_HANDLE;
}
}

View File

@ -182,6 +182,9 @@ Zombify_Mother(client)
InfectionEffects(client); InfectionEffects(client);
ztele_count[client] = 0;
AbortTeleport(client);
ZR_PrintToChat(client, "You are a zombie"); ZR_PrintToChat(client, "You are a zombie");
if (bZVision[client]) if (bZVision[client])
@ -269,6 +272,9 @@ Zombify(client, attacker)
InfectionEffects(client); InfectionEffects(client);
ztele_count[client] = 0;
AbortTeleport(client);
new ZTeam:team = IsRoundOver(); new ZTeam:team = IsRoundOver();
RoundWin(team); RoundWin(team);

View File

@ -49,9 +49,17 @@ new bool:pProtect[MAXPLAYERS+1];
new pClass[MAXPLAYERS+1]; new pClass[MAXPLAYERS+1];
new pNextClass[MAXPLAYERS+1]; new pNextClass[MAXPLAYERS+1];
new teleCount[MAXPLAYERS+1];
new protCount[MAXPLAYERS+1]; new protCount[MAXPLAYERS+1];
new Float:spawnLoc[MAXPLAYERS + 1][3]; new Float:spawnLoc[MAXPLAYERS + 1][3];
new Float:bufferLoc[3];
new bool:ztele_spawned[MAXPLAYERS + 1] = {false, ...};
new ztele_countdown[MAXPLAYERS + 1] = {-1, ...};
new ztele_count[MAXPLAYERS + 1];
new bool:ztele_online = false;
new Handle:ztele_startup_timer = INVALID_HANDLE;
new Handle:ztele_countdown_timer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
new Handle:ztele_cooldown_timer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
new maxclients; new maxclients;

View File

@ -13,15 +13,6 @@ Section content is listed in order of importance. Some of these can be ideas too
* Make a admin command to read and write settings to a spesific class, * Make a admin command to read and write settings to a spesific class,
using key/value. Integrate it with the zr_admin menu. using key/value. Integrate it with the zr_admin menu.
* Make a more advanced teleporter:
- Admin command: zr_teleport <player>
- Separate teleport limits for both teams
- Separate delays for both teams
- Startup time
- Separate cooldown for both teams
- Maybe some teleportation effects, like sound, glow or smoke.
(make a separate inc-file for the teleporter)
* Zombie dont have fall damage (damage by player 0 = server should always work) * Zombie dont have fall damage (damage by player 0 = server should always work)
Make it a CVAR, so for example zombies can't kill themselfs on some maps by Make it a CVAR, so for example zombies can't kill themselfs on some maps by
going through lasers. going through lasers.