diff --git a/changelog.txt b/changelog.txt index d2f1a70..a4246c2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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 * Removed unnecessary function call in OnPluginEnd causeing the periodical GameRules not available error. diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 2d49f79..14ca9b5 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -94,14 +94,15 @@ "!ztele amount" { "#format" "{1:d}" - "en" "You have @green{1}@default teleports left this round. (Teleport in 3 seconds)" - "ru" "У вас осталось @green{1}@default телепортов в этом раунде. (Телепортация через 3 секунды)" + "en" "You have @green{1}@default teleports left this round." + "ru" "У вас осталось @green{1}@default телепортов в этом раунде." } - "!ztele amount unlimited" + "!ztele time left" { - "en" "You will be teleported in 3 seconds." - "ru" "Вы будете телепортированы через 3 секунды." + "#format" "{1:d}" + "en" "You will be teleported in {1} seconds." + "ru" "Вы будете телепортированы через {1} секунды." } "!ztele limit reached" @@ -112,8 +113,43 @@ "!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" + } + + "!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" diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index a6dc4fd..33b3a91 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -15,7 +15,7 @@ #undef REQUIRE_PLUGIN #include -#define VERSION "2.5.1.15" +#define VERSION "2.5.1.16" #include "zr/zombiereloaded" #include "zr/global" @@ -26,6 +26,7 @@ #include "zr/classes" #include "zr/models" #include "zr/overlays" +#include "zr/teleport" #include "zr/zombie" #include "zr/menu" #include "zr/sayhooks" @@ -174,6 +175,7 @@ public OnClientDisconnect(client) ClientUnHookAttack(client); PlayerLeft(client); + ZTeleResetClient(client); new debug_val = GetConVarInt(gCvars[CVAR_DEBUG]); new String:debug_msg[64]; diff --git a/src/zr/commands.inc b/src/zr/commands.inc index f081f2f..6c99f1e 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -10,7 +10,9 @@ CreateCommands() { 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_teleport", Command_Teleport, ADMFLAG_GENERIC, "Teleports one or more players to spawn. Usage: zr_teleport "); + 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_unrestrict", Command_UnRestrict, ADMFLAG_GENERIC, "Unrestrict a specified weapon"); diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 9e64c3b..e4af07c 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -59,8 +59,12 @@ enum ZRSettings Handle:CVAR_ZMARKET_BUYZONE, Handle:CVAR_ZSPAWN, Handle:CVAR_ZTELE, - Handle:CVAR_ZTELE_LIMIT, - Handle:CVAR_ZTELE_HUMANS, + Handle:CVAR_ZTELE_STARTUP_DELAY, + 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_ZHP, 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_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_ZTELE] = CreateConVar("zr_ztele", "1", "Allows zombies who get stuck to teleport back 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_HUMANS] = CreateConVar("zr_ztele_humans", "1", "Allow humans to use the teleporter (0: Disabled)"); + gCvars[CVAR_ZTELE] = CreateConVar("zr_ztele", "1", "Allow players to use the teleporter to get to spawn. (0: Disable)"); + 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_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_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)"); diff --git a/src/zr/event.inc b/src/zr/event.inc index 25e2500..cf2f2c5 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -74,6 +74,9 @@ public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadca new Float:max = GetConVarFloat(gCvars[CVAR_SPAWN_MAX]); new Float:randlen = GetRandomFloat(min, max); tInfect = CreateTimer(randlen, MotherZombie, _, TIMER_FLAG_NO_MAPCHANGE); + + ZTeleEnable(); + } 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); } + + ZTeleReset(); } public Action:PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) @@ -177,10 +182,9 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) new cash = GetConVarInt(gCvars[CVAR_CASHAMOUNT]); SetPlayerMoney(index, cash); } - - teleCount[index] = 0; - GetClientAbsOrigin(index, spawnLoc[index]); - + + ZTeleClientSpawned(index); + NightVisionOn(index, false); NightVision(index, false); diff --git a/src/zr/menu.inc b/src/zr/menu.inc index e69d059..95976d8 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -77,7 +77,7 @@ public MainMenuHandle(Handle:menu_main, MenuAction:action, client, slot) } case 4: { - ZTele(client); + ZTeleClientCheck(client); MainMenu(client); } case 5: diff --git a/src/zr/sayhooks.inc b/src/zr/sayhooks.inc index 4b5f0c7..fb5d50f 100644 --- a/src/zr/sayhooks.inc +++ b/src/zr/sayhooks.inc @@ -45,9 +45,12 @@ public Action:SayCommand(client, argc) 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)) @@ -59,6 +62,12 @@ public Action:SayCommand(client, argc) { 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; } @@ -217,6 +226,7 @@ ZSpawn(client) AddPlayerToList(client); } +/* ZTele(client) { new bool:tele = GetConVarBool(gCvars[CVAR_ZTELE]); @@ -269,6 +279,7 @@ public Action:Teleport(Handle:timer, any:index) tHandles[index][TTELE] = INVALID_HANDLE; } +*/ ZStuck(client) { diff --git a/src/zr/teleport.inc b/src/zr/teleport.inc new file mode 100644 index 0000000..295fe81 --- /dev/null +++ b/src/zr/teleport.inc @@ -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; + } +} \ No newline at end of file diff --git a/src/zr/zombie.inc b/src/zr/zombie.inc index 394615a..cbb87b4 100644 --- a/src/zr/zombie.inc +++ b/src/zr/zombie.inc @@ -182,6 +182,9 @@ Zombify_Mother(client) InfectionEffects(client); + ztele_count[client] = 0; + AbortTeleport(client); + ZR_PrintToChat(client, "You are a zombie"); if (bZVision[client]) @@ -269,6 +272,9 @@ Zombify(client, attacker) InfectionEffects(client); + ztele_count[client] = 0; + AbortTeleport(client); + new ZTeam:team = IsRoundOver(); RoundWin(team); diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 677085c..1f093ed 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -49,9 +49,17 @@ new bool:pProtect[MAXPLAYERS+1]; new pClass[MAXPLAYERS+1]; new pNextClass[MAXPLAYERS+1]; -new teleCount[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; diff --git a/todo.txt b/todo.txt index 9f01397..b6443c2 100644 --- a/todo.txt +++ b/todo.txt @@ -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, using key/value. Integrate it with the zr_admin menu. -* Make a more advanced teleporter: - - Admin command: zr_teleport - - 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) Make it a CVAR, so for example zombies can't kill themselfs on some maps by going through lasers.