Fixed admin infect bug (I think), made roundend core module, handles all round end events, modified ClassApplyOverlay, removed mp_restartgame hook, recoded PlayerLeft and BalanceTeam functions. And added comments.
This commit is contained in:
parent
879446ac7c
commit
c34e32097d
|
@ -17,15 +17,28 @@
|
||||||
|
|
||||||
#define VERSION "3.0-dev"
|
#define VERSION "3.0-dev"
|
||||||
|
|
||||||
|
// Core include.
|
||||||
#include "zr/zombiereloaded"
|
#include "zr/zombiereloaded"
|
||||||
#include "zr/global"
|
|
||||||
#include "zr/cvars"
|
|
||||||
#include "zr/translation"
|
|
||||||
#include "zr/offsets"
|
|
||||||
#include "zr/models"
|
|
||||||
#include "zr/overlays"
|
|
||||||
|
|
||||||
// Class system
|
// External api (not done)
|
||||||
|
//#include "zr/global"
|
||||||
|
|
||||||
|
// Cvars (core)
|
||||||
|
#include "zr/cvars"
|
||||||
|
|
||||||
|
// Translations (core)
|
||||||
|
#include "zr/translation"
|
||||||
|
|
||||||
|
// Offsets (core)
|
||||||
|
#include "zr/offsets"
|
||||||
|
|
||||||
|
// Models (core)
|
||||||
|
#include "zr/models"
|
||||||
|
|
||||||
|
// Round end (core)
|
||||||
|
#include "zr/roundend"
|
||||||
|
|
||||||
|
// Class system (module)
|
||||||
#include "zr/playerclasses/playerclasses"
|
#include "zr/playerclasses/playerclasses"
|
||||||
|
|
||||||
#include "zr/anticamp"
|
#include "zr/anticamp"
|
||||||
|
@ -34,31 +47,31 @@
|
||||||
#include "zr/menu"
|
#include "zr/menu"
|
||||||
#include "zr/sayhooks"
|
#include "zr/sayhooks"
|
||||||
|
|
||||||
// Weapons
|
// Weapons (module)
|
||||||
#include "zr/weapons/weapons"
|
#include "zr/weapons/weapons"
|
||||||
|
|
||||||
// Sound effects
|
// Sound effects (module)
|
||||||
#include "zr/soundeffects/soundeffects"
|
#include "zr/soundeffects/soundeffects"
|
||||||
|
|
||||||
// Antistick
|
// Antistick (module)
|
||||||
#include "zr/antistick"
|
#include "zr/antistick"
|
||||||
|
|
||||||
// Hitgroups
|
// Hitgroups (module)
|
||||||
#include "zr/hitgroups"
|
#include "zr/hitgroups"
|
||||||
|
|
||||||
// Knockback
|
// Knockback (module)
|
||||||
#include "zr/knockback"
|
#include "zr/knockback"
|
||||||
|
|
||||||
// Spawn protect
|
// Spawn protect (module)
|
||||||
#include "zr/spawnprotect"
|
#include "zr/spawnprotect"
|
||||||
|
|
||||||
// Respawn
|
// Respawn (module)
|
||||||
#include "zr/respawn"
|
#include "zr/respawn"
|
||||||
|
|
||||||
// Napalm
|
// Napalm (module)
|
||||||
#include "zr/napalm"
|
#include "zr/napalm"
|
||||||
|
|
||||||
// ZHP
|
// ZHP (module)
|
||||||
#include "zr/zhp"
|
#include "zr/zhp"
|
||||||
|
|
||||||
#include "zr/zadmin"
|
#include "zr/zadmin"
|
||||||
|
@ -77,7 +90,8 @@ public Plugin:myinfo =
|
||||||
|
|
||||||
public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
|
public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
|
||||||
{
|
{
|
||||||
CreateGlobals();
|
// Todo: External API
|
||||||
|
//CreateGlobals();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -146,6 +160,7 @@ public OnMapStart()
|
||||||
LoadDownloadData();
|
LoadDownloadData();
|
||||||
|
|
||||||
// Forward event to modules.
|
// Forward event to modules.
|
||||||
|
RoundEndOnMapStart();
|
||||||
ClassLoad();
|
ClassLoad();
|
||||||
WeaponsLoad();
|
WeaponsLoad();
|
||||||
SEffectsOnMapStart();
|
SEffectsOnMapStart();
|
||||||
|
@ -190,6 +205,7 @@ public OnClientPutInServer(client)
|
||||||
bMotherInfectImmune[client] = false;
|
bMotherInfectImmune[client] = false;
|
||||||
|
|
||||||
// Forward event to modules.
|
// Forward event to modules.
|
||||||
|
RoundEndGetClientDXLevel(client);
|
||||||
ClassClientInit(client);
|
ClassClientInit(client);
|
||||||
SEffectsClientInit(client);
|
SEffectsClientInit(client);
|
||||||
WeaponsClientInit(client);
|
WeaponsClientInit(client);
|
||||||
|
@ -198,7 +214,6 @@ public OnClientPutInServer(client)
|
||||||
ZHPClientInit(client);
|
ZHPClientInit(client);
|
||||||
|
|
||||||
ClientHookAttack(client);
|
ClientHookAttack(client);
|
||||||
ZRFindClientDXLevel(client);
|
|
||||||
|
|
||||||
for (new x = 0; x < MAXTIMERS; x++)
|
for (new x = 0; x < MAXTIMERS; x++)
|
||||||
{
|
{
|
||||||
|
@ -229,7 +244,6 @@ public OnClientDisconnect(client)
|
||||||
|
|
||||||
MapChangeCleanup()
|
MapChangeCleanup()
|
||||||
{
|
{
|
||||||
tRound = INVALID_HANDLE;
|
|
||||||
tInfect = INVALID_HANDLE;
|
tInfect = INVALID_HANDLE;
|
||||||
AntiStickReset();
|
AntiStickReset();
|
||||||
|
|
||||||
|
@ -246,7 +260,7 @@ MapChangeCleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZREnd()
|
/*ZREnd()
|
||||||
{
|
{
|
||||||
TerminateRound(3.0, Game_Commencing);
|
TerminateRound(3.0, Game_Commencing);
|
||||||
|
|
||||||
|
@ -272,4 +286,4 @@ ZREnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
|
@ -64,9 +64,9 @@ enum ZRSettings
|
||||||
Handle:CVAR_ANTISTICK_INTERVAL,
|
Handle:CVAR_ANTISTICK_INTERVAL,
|
||||||
Handle:CVAR_PROTECT,
|
Handle:CVAR_PROTECT,
|
||||||
Handle:CVAR_CONSECUTIVE_INFECT,
|
Handle:CVAR_CONSECUTIVE_INFECT,
|
||||||
Handle:CVAR_OVERLAYS,
|
Handle:CVAR_ROUNDEND_OVERLAY,
|
||||||
Handle:CVAR_OVERLAYS_HUMAN,
|
Handle:CVAR_ROUNDEND_OVERLAY_ZOMBIE,
|
||||||
Handle:CVAR_OVERLAYS_ZOMBIE,
|
Handle:CVAR_ROUNDEND_OVERLAY_HUMAN,
|
||||||
Handle:CVAR_ZMARKET_BUYZONE,
|
Handle:CVAR_ZMARKET_BUYZONE,
|
||||||
Handle:CVAR_ZSPAWN,
|
Handle:CVAR_ZSPAWN,
|
||||||
Handle:CVAR_ZTELE,
|
Handle:CVAR_ZTELE,
|
||||||
|
@ -154,9 +154,9 @@ CreateCvars()
|
||||||
gCvars[CVAR_ANTISTICK_INTERVAL] = CreateConVar("zr_antistick_interval", "1.0", "How often, in seconds, the anti-stick module checks each player for being stuck. (1.0: Default)");
|
gCvars[CVAR_ANTISTICK_INTERVAL] = CreateConVar("zr_antistick_interval", "1.0", "How often, in seconds, the anti-stick module checks each player for being stuck. (1.0: Default)");
|
||||||
gCvars[CVAR_PROTECT] = CreateConVar("zr_protect", "10", "Players that join late will be protected for this long, in seconds (0: Disable)");
|
gCvars[CVAR_PROTECT] = CreateConVar("zr_protect", "10", "Players that join late will be protected for this long, in seconds (0: Disable)");
|
||||||
gCvars[CVAR_CONSECUTIVE_INFECT] = CreateConVar("zr_consecutive_infect", "0", "Allow player to be randomly chosen twice in a row to be a mother zombie (0: Disable)");
|
gCvars[CVAR_CONSECUTIVE_INFECT] = CreateConVar("zr_consecutive_infect", "0", "Allow player to be randomly chosen twice in a row to be a mother zombie (0: Disable)");
|
||||||
gCvars[CVAR_OVERLAYS] = CreateConVar("zr_overlays", "1", "Will show overlays that tell who the winner of the round was (0: Disable)");
|
gCvars[CVAR_ROUNDEND_OVERLAY] = CreateConVar("zr_roundend_overlay", "1", "Shows an overlay to all clients when a team wins. (0: Disable)");
|
||||||
gCvars[CVAR_OVERLAYS_HUMAN] = CreateConVar("zr_overlays_human", "overlays/zr/humans_win", "The overlay shown to tell everyone that humans won when zr_overlays is 1");
|
gCvars[CVAR_ROUNDEND_OVERLAY_HUMAN] = CreateConVar("zr_roundend_overlays_human", "overlays/zr/humans_win", "Path to \"humans win\" overlay");
|
||||||
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_ROUNDEND_OVERLAY_ZOMBIE] = CreateConVar("zr_roundend_overlays_zombie", "overlays/zr/zombies_win", "Path to \"zombies win\" overlay");
|
||||||
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_tele", "1", "Allow players to use the teleporter to get to spawn. (0: Disable)");
|
gCvars[CVAR_ZTELE] = CreateConVar("zr_tele", "1", "Allow players to use the teleporter to get to spawn. (0: Disable)");
|
||||||
|
@ -184,7 +184,9 @@ CreateCvars()
|
||||||
gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL] = CreateConVar("zr_anticamp_update_interval", "1", "How often to update player locations (in seconds).");
|
gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL] = CreateConVar("zr_anticamp_update_interval", "1", "How often to update player locations (in seconds).");
|
||||||
gCvars[CVAR_ANTICAMP_ECHO] = CreateConVar("zr_anticamp_echo", "1", "Log kills done by anticamp to admin chat.");
|
gCvars[CVAR_ANTICAMP_ECHO] = CreateConVar("zr_anticamp_echo", "1", "Log kills done by anticamp to admin chat.");
|
||||||
|
|
||||||
HookConVarChange(gCvars[CVAR_ENABLE], EnableHook);
|
// TODO: Recode.
|
||||||
|
//HookConVarChange(gCvars[CVAR_ENABLE], EnableHook);
|
||||||
|
|
||||||
HookConVarChange(gCvars[CVAR_ANTICAMP], AnticampHook);
|
HookConVarChange(gCvars[CVAR_ANTICAMP], AnticampHook);
|
||||||
HookConVarChange(gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL], UpdateIntervalHook);
|
HookConVarChange(gCvars[CVAR_ANTICAMP_UPDATE_INTERVAL], UpdateIntervalHook);
|
||||||
|
|
||||||
|
@ -198,19 +200,15 @@ HookCvars()
|
||||||
|
|
||||||
HookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook);
|
HookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook);
|
||||||
HookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook);
|
HookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook);
|
||||||
|
|
||||||
HookConVarChange(FindConVar("mp_restartgame"), RestartGameHook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UnhookCvars()
|
UnhookCvars()
|
||||||
{
|
{
|
||||||
UnhookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook);
|
UnhookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook);
|
||||||
UnhookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook);
|
UnhookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook);
|
||||||
|
|
||||||
UnhookConVarChange(FindConVar("mp_restartgame"), RestartGameHook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnableHook(Handle:convar, const String:oldValue[], const String:newValue[])
|
/*public EnableHook(Handle:convar, const String:oldValue[], const String:newValue[])
|
||||||
{
|
{
|
||||||
new bool:enable = bool:StringToInt(newValue);
|
new bool:enable = bool:StringToInt(newValue);
|
||||||
|
|
||||||
|
@ -225,7 +223,7 @@ public EnableHook(Handle:convar, const String:oldValue[], const String:newValue[
|
||||||
{
|
{
|
||||||
ZREnd();
|
ZREnd();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public AutoTeamBalanceHook(Handle:convar, const String:oldValue[], const String:newValue[])
|
public AutoTeamBalanceHook(Handle:convar, const String:oldValue[], const String:newValue[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,37 +36,39 @@ public Action:RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
{
|
{
|
||||||
ChangeLightStyle();
|
ChangeLightStyle();
|
||||||
|
|
||||||
// Forward event to sub-modules.
|
|
||||||
SEffectsOnRoundStart();
|
|
||||||
AntiStickOnRoundStart();
|
|
||||||
|
|
||||||
if (tRound != INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
KillTimer(tRound);
|
|
||||||
tRound = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tInfect != INVALID_HANDLE)
|
if (tInfect != INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
KillTimer(tInfect);
|
KillTimer(tInfect);
|
||||||
tInfect = INVALID_HANDLE;
|
tInfect = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_bZombieSpawned = false;
|
||||||
|
|
||||||
|
for (new x = 1; x<= MaxClients; x++)
|
||||||
|
{
|
||||||
|
if (!IsClientInGame(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bZombie[x] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance teams, and respawn all players.
|
||||||
|
BalanceTeams(true);
|
||||||
|
|
||||||
ZR_PrintToChat(0, "Round objective");
|
ZR_PrintToChat(0, "Round objective");
|
||||||
|
|
||||||
|
// Forward event to sub-modules.
|
||||||
|
RoundEndOnRoundStart();
|
||||||
|
SEffectsOnRoundStart();
|
||||||
|
AntiStickOnRoundStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast)
|
public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
{
|
{
|
||||||
RemoveObjectives();
|
RemoveObjectives();
|
||||||
|
|
||||||
if (tRound != INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
KillTimer(tRound);
|
|
||||||
}
|
|
||||||
|
|
||||||
new Float:roundlen = GetConVarFloat(FindConVar("mp_roundtime")) * 60.0;
|
|
||||||
tRound = CreateTimer(roundlen, RoundOver, _, TIMER_FLAG_NO_MAPCHANGE);
|
|
||||||
|
|
||||||
if (tInfect != INVALID_HANDLE)
|
if (tInfect != INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
KillTimer(tInfect);
|
KillTimer(tInfect);
|
||||||
|
@ -78,17 +80,14 @@ public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadca
|
||||||
tInfect = CreateTimer(randlen, MotherZombie, _, TIMER_FLAG_NO_MAPCHANGE);
|
tInfect = CreateTimer(randlen, MotherZombie, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
|
||||||
// Forward events to modules.
|
// Forward events to modules.
|
||||||
|
RoundEndOnRoundFreezeEnd();
|
||||||
ZTeleEnable();
|
ZTeleEnable();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
|
public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
{
|
{
|
||||||
if (tRound != INVALID_HANDLE)
|
new reason = GetEventInt(event, "reason");
|
||||||
{
|
|
||||||
KillTimer(tRound);
|
|
||||||
tRound = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tInfect != INVALID_HANDLE)
|
if (tInfect != INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
|
@ -108,19 +107,11 @@ public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
bZombie[x] = false;
|
bZombie[x] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Balance teams.
|
||||||
BalanceTeams();
|
BalanceTeams();
|
||||||
|
|
||||||
new reason = GetEventInt(event, "reason");
|
// Forward event to modules.
|
||||||
|
RoundEndOnRoundEnd(reason);
|
||||||
if (reason == CTs_PreventEscape)
|
|
||||||
{
|
|
||||||
ShowOverlays(5.0, Human);
|
|
||||||
}
|
|
||||||
else if (reason == Terrorists_Escaped)
|
|
||||||
{
|
|
||||||
ShowOverlays(5.0, Zombie);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZTeleReset();
|
ZTeleReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +287,11 @@ public Action:PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
RespawnOnClientDeath(index, attacker, weapon);
|
RespawnOnClientDeath(index, attacker, weapon);
|
||||||
ZHPOnClientDeath(index);
|
ZHPOnClientDeath(index);
|
||||||
|
|
||||||
new ZTeam:team = IsRoundOver();
|
new RoundEndOutcome:outcome;
|
||||||
RoundWin(team);
|
if (RoundEndGetRoundStatus(outcome))
|
||||||
|
{
|
||||||
|
RoundEndTerminateRound(outcome);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action:PlayerJump(Handle:event, const String:name[], bool:dontBroadcast)
|
public Action:PlayerJump(Handle:event, const String:name[], bool:dontBroadcast)
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
/**
|
|
||||||
* ====================
|
|
||||||
* Zombie:Reloaded
|
|
||||||
* File: overlays.inc
|
|
||||||
* Author: Greyscale
|
|
||||||
* ====================
|
|
||||||
*/
|
|
||||||
|
|
||||||
ShowOverlays(Float:time, ZTeam:winner)
|
|
||||||
{
|
|
||||||
new bool:overlays = GetConVarBool(gCvars[CVAR_OVERLAYS]);
|
|
||||||
if (overlays)
|
|
||||||
{
|
|
||||||
decl String:overlay[64];
|
|
||||||
if (winner == Human)
|
|
||||||
{
|
|
||||||
GetConVarString(gCvars[CVAR_OVERLAYS_HUMAN], overlay, sizeof(overlay));
|
|
||||||
}
|
|
||||||
else if (winner == Zombie)
|
|
||||||
{
|
|
||||||
GetConVarString(gCvars[CVAR_OVERLAYS_ZOMBIE], overlay, sizeof(overlay));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
|
||||||
{
|
|
||||||
if (IsClientInGame(x))
|
|
||||||
{
|
|
||||||
ZRDisplayClientOverlay(x, overlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateTimer(time, KillOverlays);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action:KillOverlays(Handle:timer)
|
|
||||||
{
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
|
||||||
{
|
|
||||||
if (IsClientInGame(x))
|
|
||||||
{
|
|
||||||
ClientCommand(x, "r_screenoverlay \"\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -54,7 +54,7 @@ bool:ClassApplyAttributes(client, bool:improved = false)
|
||||||
*/
|
*/
|
||||||
bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
||||||
{
|
{
|
||||||
decl String:modelpath[256];
|
decl String:modelpath[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
// Get the model path from the specified cache.
|
// Get the model path from the specified cache.
|
||||||
if (cachetype == ZR_CLASS_CACHE_PLAYER)
|
if (cachetype == ZR_CLASS_CACHE_PLAYER)
|
||||||
|
@ -130,27 +130,34 @@ bool:ClassApplyAlpha(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
||||||
*/
|
*/
|
||||||
bool:ClassApplyOverlay(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
bool:ClassApplyOverlay(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
||||||
{
|
{
|
||||||
decl String:overlay[256];
|
// If dxLevel is 0, then query on client failed, so try again, then stop.
|
||||||
|
if (!dxLevel[client])
|
||||||
// Validate DirectX requirements.
|
|
||||||
if (dxLevel[client] < DXLEVEL_MIN)
|
|
||||||
{
|
{
|
||||||
// DirectX version is too old.
|
// Query dxlevel cvar.
|
||||||
// TODO: Log warning?
|
RoundEndGetClientDXLevel(client);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If client doesn't meet minimum requirement, then print unsupported text.
|
||||||
|
if (dxLevel[client] < ROUNDEND_MIN_DXLEVEL)
|
||||||
|
{
|
||||||
|
ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], ROUNDEND_MIN_DXLEVEL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decl String:overlaypath[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
// Get the overlay path from the specified cache.
|
// Get the overlay path from the specified cache.
|
||||||
if (cachetype == ZR_CLASS_CACHE_PLAYER)
|
if (cachetype == ZR_CLASS_CACHE_PLAYER)
|
||||||
{
|
{
|
||||||
ClassGetOverlayPath(client, overlay, sizeof(overlay), cachetype);
|
ClassGetOverlayPath(client, overlaypath, sizeof(overlaypath), cachetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ClassGetOverlayPath(classindex, overlay, sizeof(overlay), cachetype);
|
ClassGetOverlayPath(classindex, overlaypath, sizeof(overlaypath), cachetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassOverlayInitialize(client, overlay);
|
ClassOverlayInitialize(client, overlaypath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ new bClientOverlayOn[MAXPLAYERS + 1];
|
||||||
/**
|
/**
|
||||||
* Path to the currently active overlay.
|
* Path to the currently active overlay.
|
||||||
*/
|
*/
|
||||||
new String:ActiveOverlay[MAXPLAYERS + 1][256];
|
new String:ActiveOverlay[MAXPLAYERS + 1][PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
bool:ClientHasOverlay(client)
|
bool:ClientHasOverlay(client)
|
||||||
{
|
{
|
||||||
|
|
405
src/zr/roundend.inc
Normal file
405
src/zr/roundend.inc
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
/*
|
||||||
|
* ============================================================================
|
||||||
|
*
|
||||||
|
* Zombie:Reloaded
|
||||||
|
*
|
||||||
|
* File: roundend.inc
|
||||||
|
* Description: (Core) Handles round end actions.
|
||||||
|
*
|
||||||
|
* ============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @section All round end reasons.
|
||||||
|
*/
|
||||||
|
#define ROUNDEND_TARGET_BOMBED 1 // Target Successfully Bombed!
|
||||||
|
#define ROUNDEND_VIP_ESCAPED 2 // The VIP has escaped!
|
||||||
|
#define ROUNDEND_VIP_ASSASSINATED 3 // VIP has been assassinated!
|
||||||
|
#define ROUNDEND_TERRORISTS_ESCAPED 4 // The terrorists have escaped!
|
||||||
|
#define ROUNDEND_CTS_PREVENTESCAPE 5 // The CT's have prevented most of the terrorists from escaping!
|
||||||
|
#define ROUNDEND_ESCAPING_TERRORISTS_NEUTRALIZED 6 // Escaping terrorists have all been neutralized!
|
||||||
|
#define ROUNDEND_BOMB_DEFUSED 7 // The bomb has been defused!
|
||||||
|
#define ROUNDEND_CTS_WIN 8 // Counter-Terrorists Win!
|
||||||
|
#define ROUNDEND_TERRORISTS_WIN 9 // Terrorists Win!
|
||||||
|
#define ROUNDEND_ROUND_DRAW 10 // Round Draw!
|
||||||
|
#define ROUNDEND_ALL_HOSTAGES_RESCUED 11 // All Hostages have been rescued!
|
||||||
|
#define ROUNDEND_TARGET_SAVED 12 // Target has been saved!
|
||||||
|
#define ROUNDEND_HOSTAGES_NOT_RESCUED 13 // Hostages have not been rescued!
|
||||||
|
#define ROUNDEND_TERRORISTS_NOT_ESCAPED 14 // Terrorists have not escaped!
|
||||||
|
#define ROUNDEND_VIP_NOT_ESCAPED 15 // VIP has not escaped!
|
||||||
|
#define ROUNDEND_GAME_COMMENCING 16 // Game Commencing!
|
||||||
|
/**
|
||||||
|
* @endsection
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delay between round ending and new round starting. (Normal)
|
||||||
|
*/
|
||||||
|
#define ROUNDEND_DELAY_NORMAL 5.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delay between round ending and new round starting. (Short, for ROUNDEND_GAME_COMMENCING)
|
||||||
|
*/
|
||||||
|
#define ROUNDEND_DELAY_SHORT 3.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum dx level required to see overlays.
|
||||||
|
*/
|
||||||
|
#define ROUNDEND_MIN_DXLEVEL 90
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible round end outcomes.
|
||||||
|
*/
|
||||||
|
enum RoundEndOutcome
|
||||||
|
{
|
||||||
|
HumansWin, /** Humans have killed all zombies. */
|
||||||
|
ZombiesWin, /** Zombies have infected all humans. */
|
||||||
|
Draw, /** Round has ended in unexpected way. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global variable to store round win timer handle.
|
||||||
|
*/
|
||||||
|
new Handle:tRoundEnd = INVALID_HANDLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global variable to store a convar query cookie
|
||||||
|
*/
|
||||||
|
new QueryCookie:mat_dxlevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map is starting.
|
||||||
|
*/
|
||||||
|
RoundEndOnMapStart()
|
||||||
|
{
|
||||||
|
// Reset timer handle.
|
||||||
|
tRoundEnd = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The round is starting.
|
||||||
|
*/
|
||||||
|
RoundEndOnRoundStart()
|
||||||
|
{
|
||||||
|
// If round end timer is running, then kill it.
|
||||||
|
if (tRoundEnd != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
// Kill timer.
|
||||||
|
KillTimer(tRoundEnd);
|
||||||
|
|
||||||
|
// Reset timer handle.
|
||||||
|
tRoundEnd = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The freeze time is ending.
|
||||||
|
*/
|
||||||
|
RoundEndOnRoundFreezeEnd()
|
||||||
|
{
|
||||||
|
// Calculate round length, in seconds.
|
||||||
|
// Get mp_roundtime. (in minutes)
|
||||||
|
new Float:roundtime = GetConVarFloat(FindConVar("mp_roundtime"));
|
||||||
|
|
||||||
|
// Convert to seconds.
|
||||||
|
roundtime *= 60.0;
|
||||||
|
|
||||||
|
// Start timer.
|
||||||
|
tRoundEnd = CreateTimer(roundtime, RoundEndTimer, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The round is ending.
|
||||||
|
*
|
||||||
|
* @param reason Reason the round has ended.
|
||||||
|
*/
|
||||||
|
RoundEndOnRoundEnd(reason)
|
||||||
|
{
|
||||||
|
// If round end timer is running, then kill it.
|
||||||
|
if (tRoundEnd != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
// Kill timer.
|
||||||
|
KillTimer(tRoundEnd);
|
||||||
|
|
||||||
|
// Reset timer handle.
|
||||||
|
tRoundEnd = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get outcome of the round.
|
||||||
|
new RoundEndOutcome:outcome = RoundEndReasonToOutcome(reason);
|
||||||
|
|
||||||
|
// Display the overlay to all clients.
|
||||||
|
RoundEndOverlayStart(ROUNDEND_DELAY_NORMAL, outcome);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds DX level of a client.
|
||||||
|
*
|
||||||
|
* @param client The client index.
|
||||||
|
*/
|
||||||
|
RoundEndGetClientDXLevel(client)
|
||||||
|
{
|
||||||
|
// If client is fake (or bot), then stop.
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query mat_dxlevel on client.
|
||||||
|
mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", RoundEndQueryClientDXLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query callback function.
|
||||||
|
*
|
||||||
|
* @param cookie Unique cookie of the query.
|
||||||
|
* @param client The client index.
|
||||||
|
* @param result The result of the query (see console.inc enum ConVarQueryResult)
|
||||||
|
* @param cvarName Name of the cvar.
|
||||||
|
* @param cvarValue Value of the cvar.
|
||||||
|
*/
|
||||||
|
public RoundEndQueryClientDXLevel(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[])
|
||||||
|
{
|
||||||
|
// If query cookie does not match cookie given by mat_dxlevel query, then stop, this isn't our query.
|
||||||
|
if (cookie != mat_dxlevel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset dxLevel.
|
||||||
|
dxLevel[client] = 0;
|
||||||
|
|
||||||
|
// If result is any other than ConVarQuery_Okay, then stop.
|
||||||
|
if (result != ConVarQuery_Okay)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy cvar value to dxLevel array.
|
||||||
|
dxLevel[client] = StringToInt(cvarValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a round_end reason, to a round winner, or draw.
|
||||||
|
*
|
||||||
|
* @param reason The round_end reason.
|
||||||
|
* @return The winner of the round. (see enum RoundEndOutcome)
|
||||||
|
*/
|
||||||
|
RoundEndOutcome:RoundEndReasonToOutcome(reason)
|
||||||
|
{
|
||||||
|
switch(reason)
|
||||||
|
{
|
||||||
|
// CTs won the round.
|
||||||
|
case ROUNDEND_CTS_WIN:
|
||||||
|
{
|
||||||
|
return HumansWin;
|
||||||
|
}
|
||||||
|
// Ts won the round.
|
||||||
|
case ROUNDEND_TERRORISTS_WIN:
|
||||||
|
{
|
||||||
|
return ZombiesWin;
|
||||||
|
}
|
||||||
|
// Unexpected case.
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return Draw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return draw to satisfy compiler. (code will never reach this point.)
|
||||||
|
return Draw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer callback, called when round time reaches 0.
|
||||||
|
*
|
||||||
|
* @param timer The timer handle.
|
||||||
|
*/
|
||||||
|
public Action:RoundEndTimer(Handle:timer)
|
||||||
|
{
|
||||||
|
// Terminate the round with a normal delay, and CTs as the winner.
|
||||||
|
TerminateRound(ROUNDEND_DELAY_NORMAL, ROUNDEND_CTS_WIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the round is over.
|
||||||
|
*
|
||||||
|
* @param outcome Set to the outcome of the round, if round is over.
|
||||||
|
* @return True if the round is over, false otherwise.
|
||||||
|
*/
|
||||||
|
bool:RoundEndGetRoundStatus(&RoundEndOutcome:outcome)
|
||||||
|
{
|
||||||
|
// If zombie hasn't spawned, then stop.
|
||||||
|
if (!g_bZombieSpawned)
|
||||||
|
{
|
||||||
|
// Round isn't over.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize count variables
|
||||||
|
new zombiecount;
|
||||||
|
new humancount;
|
||||||
|
|
||||||
|
// Count valid clients. (true to only allow living clients)
|
||||||
|
ZRCountValidClients(zombiecount, humancount);
|
||||||
|
|
||||||
|
// If there are no clients on either teams, then stop.
|
||||||
|
if (!zombiecount && !humancount)
|
||||||
|
{
|
||||||
|
// Round isn't active.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are clients on both teams, then stop.
|
||||||
|
if (zombiecount && humancount)
|
||||||
|
{
|
||||||
|
// Round isn't over.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know here, that either zombiecount or humancount is 0. (not both)
|
||||||
|
|
||||||
|
// If there are zombies, then zombies won the round.
|
||||||
|
if (zombiecount)
|
||||||
|
{
|
||||||
|
outcome = ZombiesWin;
|
||||||
|
}
|
||||||
|
// If there are no zombies, that means there must be humans, they win the round.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outcome = HumansWin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round is over.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the round with the given outcome.
|
||||||
|
*
|
||||||
|
* @param outcome The outcome of the round.
|
||||||
|
*/
|
||||||
|
RoundEndTerminateRound(RoundEndOutcome:outcome)
|
||||||
|
{
|
||||||
|
switch(outcome)
|
||||||
|
{
|
||||||
|
// Zombies won.
|
||||||
|
case ZombiesWin:
|
||||||
|
{
|
||||||
|
// Terminate the round with a normal delay, and Ts as the winner.
|
||||||
|
TerminateRound(ROUNDEND_DELAY_NORMAL, ROUNDEND_TERRORISTS_WIN);
|
||||||
|
}
|
||||||
|
// Humans won.
|
||||||
|
case HumansWin:
|
||||||
|
{
|
||||||
|
// Terminate the round with a normal delay, and CTs as the winner.
|
||||||
|
TerminateRound(ROUNDEND_DELAY_NORMAL, ROUNDEND_CTS_WIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays overlay to client, or prints unsupported message on client's screen.
|
||||||
|
*
|
||||||
|
* @param client The client index.
|
||||||
|
* @param overlay The overlay path.
|
||||||
|
*/
|
||||||
|
RoundEndDisplayClientOverlay(client, const String:overlay[])
|
||||||
|
{
|
||||||
|
// If dxLevel is 0, then query on client failed, so try again, then stop.
|
||||||
|
if (!dxLevel[client])
|
||||||
|
{
|
||||||
|
// Query dxlevel cvar.
|
||||||
|
RoundEndGetClientDXLevel(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dxLevel is above or equal to minimum requirement, then display overlay.
|
||||||
|
if (dxLevel[client] >= ROUNDEND_MIN_DXLEVEL)
|
||||||
|
{
|
||||||
|
ClientCommand(client, "r_screenoverlay \"%s\"", overlay);
|
||||||
|
}
|
||||||
|
// If client doesn't meet minimum requirement, then print unsupported text.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], ROUNDEND_MIN_DXLEVEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays overlays to clients, depending on the outcome.
|
||||||
|
*
|
||||||
|
* @param time Time to display overlays.
|
||||||
|
* @param outcome The outcome of the round.
|
||||||
|
*/
|
||||||
|
RoundEndOverlayStart(Float:time, RoundEndOutcome:outcome)
|
||||||
|
{
|
||||||
|
// If round end overlays are disabled, then stop.
|
||||||
|
new bool:overlay = GetConVarBool(gCvars[CVAR_ROUNDEND_OVERLAY]);
|
||||||
|
if (!overlay)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decl String:overlaypath[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
|
switch(outcome)
|
||||||
|
{
|
||||||
|
// Show "zombies win" overlay.
|
||||||
|
case ZombiesWin:
|
||||||
|
{
|
||||||
|
GetConVarString(gCvars[CVAR_ROUNDEND_OVERLAY_ZOMBIE], overlaypath, sizeof(overlaypath));
|
||||||
|
}
|
||||||
|
// Show "humans win" overlay.
|
||||||
|
case HumansWin:
|
||||||
|
{
|
||||||
|
GetConVarString(gCvars[CVAR_ROUNDEND_OVERLAY_HUMAN], overlaypath, sizeof(overlaypath));
|
||||||
|
}
|
||||||
|
// Show no overlay.
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
strcopy(overlaypath, sizeof(overlaypath), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// x = client index.
|
||||||
|
for (new x = 1; x <= MaxClients; x++)
|
||||||
|
{
|
||||||
|
// If client isn't in-game, then stop.
|
||||||
|
if (!IsClientInGame(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoundEndDisplayClientOverlay(x, overlaypath);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateTimer(time, RoundEndOverlayTimer, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoundEndOverlayStop()
|
||||||
|
{
|
||||||
|
// x = client index.
|
||||||
|
for (new x = 1; x <= MaxClients; x++)
|
||||||
|
{
|
||||||
|
// If client isn't in-game, then stop.
|
||||||
|
if (!IsClientInGame(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes overlay from client's screen.
|
||||||
|
ClientCommand(x, "r_screenoverlay \"\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer callback, stops overlays on all clients.
|
||||||
|
*
|
||||||
|
* @param timer The timer handle.
|
||||||
|
*/
|
||||||
|
public Action:RoundEndOverlayTimer(Handle:timer)
|
||||||
|
{
|
||||||
|
// Stop all overlays.
|
||||||
|
RoundEndOverlayStop();
|
||||||
|
}
|
|
@ -90,10 +90,60 @@ ChangeLightStyle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestartGameHook(Handle:convar, const String:oldValue[], const String:newValue[])
|
/**
|
||||||
|
* 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)
|
||||||
{
|
{
|
||||||
SetConVarInt(FindConVar("mp_restartgame"), 0);
|
// Create array.
|
||||||
TerminateRound(StringToFloat(newValue), Round_Draw);
|
arrayEligibleClients = CreateArray();
|
||||||
|
|
||||||
|
// Populate list with eligible clients.
|
||||||
|
// x = client index.
|
||||||
|
for (new x = 1; x <= MaxClients; x++)
|
||||||
|
{
|
||||||
|
// If client isn't in-game, then stop.
|
||||||
|
if (!IsClientInGame(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If client is immune from being a mother zombie, then stop.
|
||||||
|
if (immunity && bMotherInfectImmune[x])
|
||||||
|
{
|
||||||
|
// Take away immunity.
|
||||||
|
bMotherInfectImmune[x] = false;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add eligible client to array.
|
||||||
|
PushArrayCell(arrayEligibleClients, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetArraySize(arrayEligibleClients);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,40 +156,11 @@ public Action:MotherZombie(Handle:timer)
|
||||||
// Reset timer handle.
|
// Reset timer handle.
|
||||||
tInfect = INVALID_HANDLE;
|
tInfect = INVALID_HANDLE;
|
||||||
|
|
||||||
// Create array.
|
// Create eligible player list.
|
||||||
new Handle:arrayEligibleClients = CreateArray();
|
new Handle:arrayEligibleClients = INVALID_HANDLE;
|
||||||
|
new eligibleclients = CreateEligibleClientList(arrayEligibleClients, true, true, true, true);
|
||||||
// Populate list with eligible clients.
|
|
||||||
// x = client index.
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If client is immune from being a mother zombie, then stop.
|
|
||||||
if (bMotherInfectImmune[x])
|
|
||||||
{
|
|
||||||
// Take away immunity.
|
|
||||||
bMotherInfectImmune[x] = false;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add eligible client to array.
|
|
||||||
PushArrayCell(arrayEligibleClients, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no eligible client's then stop.
|
// If there are no eligible client's then stop.
|
||||||
new eligibleclients = GetArraySize(arrayEligibleClients);
|
|
||||||
if (!eligibleclients)
|
if (!eligibleclients)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -217,6 +238,9 @@ public Action:MotherZombie(Handle:timer)
|
||||||
|
|
||||||
// Mother zombies have been infected.
|
// Mother zombies have been infected.
|
||||||
g_bZombieSpawned = true;
|
g_bZombieSpawned = true;
|
||||||
|
|
||||||
|
// Destroy handle.
|
||||||
|
CloseHandle(arrayEligibleClients);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,7 +254,7 @@ public Action:MotherZombie(Handle:timer)
|
||||||
InfectPlayer(client, attacker = -1, bool:motherinfect = false)
|
InfectPlayer(client, attacker = -1, bool:motherinfect = false)
|
||||||
{
|
{
|
||||||
// Check if the attacker was specified.
|
// Check if the attacker was specified.
|
||||||
if (attacker > 0)
|
if (ZRIsValidClient(attacker))
|
||||||
{
|
{
|
||||||
// Fire death event and set weapon info.
|
// Fire death event and set weapon info.
|
||||||
new Handle:event = CreateEvent("player_death");
|
new Handle:event = CreateEvent("player_death");
|
||||||
|
@ -253,14 +277,21 @@ InfectPlayer(client, attacker = -1, bool:motherinfect = false)
|
||||||
ztele_count[client] = 0; // In use?
|
ztele_count[client] = 0; // In use?
|
||||||
|
|
||||||
// Terminate the round if the last player was infected.
|
// Terminate the round if the last player was infected.
|
||||||
new ZTeam:team = IsRoundOver();
|
new RoundEndOutcome:outcome;
|
||||||
RoundWin(team);
|
if (RoundEndGetRoundStatus(outcome))
|
||||||
|
{
|
||||||
|
RoundEndTerminateRound(outcome);
|
||||||
|
}
|
||||||
|
|
||||||
// Switch the player to terrorists.
|
// Switch the player to terrorists.
|
||||||
CS_SwitchTeam(client, CS_TEAM_T);
|
CS_SwitchTeam(client, CS_TEAM_T);
|
||||||
|
|
||||||
// Flag player to be immune from being mother zombie twice.
|
|
||||||
bMotherInfectImmune[client] = motherinfect;
|
// 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.
|
// Forward event to modules.
|
||||||
ClassOnClientInfected(client, motherinfect);
|
ClassOnClientInfected(client, motherinfect);
|
||||||
|
@ -360,159 +391,131 @@ JumpBoost(client, Float:distance, Float:height)
|
||||||
SetPlayerVelocity(client, vel, false);
|
SetPlayerVelocity(client, vel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a new zombie if the last one disconnects.
|
||||||
|
*
|
||||||
|
* @param client The client index.
|
||||||
|
*/
|
||||||
PlayerLeft(client)
|
PlayerLeft(client)
|
||||||
{
|
{
|
||||||
if (!IsClientConnected(client) || !IsClientInGame(client))
|
// If client is dead, then stop.
|
||||||
|
if (!IsPlayerAlive(client))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new ZTeam:team = IsRoundOver();
|
// If client isn't a zombie, then stop.
|
||||||
if (team == Zombie)
|
if (!IsPlayerZombie(client))
|
||||||
{
|
|
||||||
RoundWin(team);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsPlayerAlive(client) || !IsPlayerZombie(client))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new zombiecount = GetZTeamCount(Zombie);
|
// Initialize count variables
|
||||||
if (zombiecount > 1)
|
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)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new count = GetTeamClientCount(CS_TEAM_CT);
|
// If there is 1 or no humans left, then stop.
|
||||||
if (count <= 1)
|
if (humancount <= 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new Handle:aClients = CreateArray();
|
// Create eligible player list.
|
||||||
|
new Handle:arrayEligibleClients = INVALID_HANDLE;
|
||||||
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
// Create eligible client list, with no mother infect immunities
|
||||||
{
|
new eligibleclients = CreateEligibleClientList(arrayEligibleClients, true, true, true);
|
||||||
if (!IsClientInGame(x) || !IsPlayerAlive(x) || client == x || GetClientTeam(x) != CS_TEAM_CT || bMotherInfectImmune[x])
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushArrayCell(aClients, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
new size = GetArraySize(aClients);
|
// If there are no eligible client's then stop.
|
||||||
if (!size)
|
if (!eligibleclients)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new randclient = GetArrayCell(aClients, GetRandomInt(0, size-1));
|
// Get a random valid array index.
|
||||||
InfectPlayer(randclient, _, true);
|
new randindex = GetRandomInt(0, eligibleclients - 1);
|
||||||
|
|
||||||
|
// Get the client stored in the random array index.
|
||||||
|
new randclient = GetArrayCell(arrayEligibleClients, randindex);
|
||||||
|
|
||||||
|
// Infect player.
|
||||||
|
InfectPlayer(randclient);
|
||||||
|
|
||||||
|
// Tell client they have been randomly been chosen to replace disconnecting zombie.
|
||||||
ZR_PrintToChat(randclient, "Zombie replacement");
|
ZR_PrintToChat(randclient, "Zombie replacement");
|
||||||
|
|
||||||
CloseHandle(aClients);
|
// Destroy handle.
|
||||||
|
CloseHandle(arrayEligibleClients);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetZTeamCount(ZTeam:team)
|
/**
|
||||||
|
* Balances teams
|
||||||
|
*
|
||||||
|
* @param spawn If true, it will respawn player after switching their team.
|
||||||
|
*/
|
||||||
|
BalanceTeams(bool:spawn = false)
|
||||||
{
|
{
|
||||||
new count = 0;
|
// Create eligible player list.
|
||||||
|
new Handle:arrayEligibleClients = INVALID_HANDLE;
|
||||||
|
new eligibleclients = CreateEligibleClientList(arrayEligibleClients, true);
|
||||||
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
// If there are no eligible client's then stop.
|
||||||
|
if (!eligibleclients)
|
||||||
{
|
{
|
||||||
if (!IsClientInGame(x) || !IsPlayerAlive(x))
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new client;
|
||||||
|
|
||||||
|
// Move all clients to T
|
||||||
|
|
||||||
|
// x = array index.
|
||||||
|
// client = client index.
|
||||||
|
for (new x = 0; x < eligibleclients; x++)
|
||||||
|
{
|
||||||
|
// Get client stored in array index.
|
||||||
|
client = GetArrayCell(arrayEligibleClients, x);
|
||||||
|
|
||||||
|
// Switch client to T
|
||||||
|
CS_SwitchTeam(client, CS_TEAM_T);
|
||||||
|
|
||||||
|
// If spawn is false, then stop.
|
||||||
|
if (!spawn)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
new ZTeam:pTeam = GetPlayerZTeam(x);
|
CS_RespawnPlayer(client);
|
||||||
if (pTeam == team)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
// Move every other client back to CT
|
||||||
}
|
|
||||||
|
|
||||||
ZTeam:IsRoundOver()
|
|
||||||
{
|
|
||||||
new bool:zombies = false;
|
|
||||||
new bool:humans = false;
|
|
||||||
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
// x = array index
|
||||||
|
// client = client index.
|
||||||
|
for (new x = 0; x < eligibleclients; x += 2)
|
||||||
{
|
{
|
||||||
if (!IsClientInGame(x) || !IsPlayerAlive(x))
|
// Get client stored in array index.
|
||||||
|
client = GetArrayCell(arrayEligibleClients, x);
|
||||||
|
|
||||||
|
// Switch client to CT
|
||||||
|
CS_SwitchTeam(client, CS_TEAM_CT);
|
||||||
|
|
||||||
|
// If spawn is false, then stop.
|
||||||
|
if (!spawn)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsPlayerZombie(x))
|
CS_RespawnPlayer(client);
|
||||||
{
|
|
||||||
zombies = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
humans = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zombies && !humans)
|
|
||||||
{
|
|
||||||
return Zombie;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (humans && !zombies)
|
|
||||||
{
|
|
||||||
if (g_bZombieSpawned)
|
|
||||||
{
|
|
||||||
return Human;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Neither;
|
|
||||||
}
|
|
||||||
|
|
||||||
RoundWin(ZTeam:team)
|
|
||||||
{
|
|
||||||
if (team == Human)
|
|
||||||
{
|
|
||||||
TerminateRound(5.0, CTs_PreventEscape);
|
|
||||||
}
|
|
||||||
else if (team == Zombie)
|
|
||||||
{
|
|
||||||
TerminateRound(5.0, Terrorists_Escaped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BalanceTeams()
|
|
||||||
{
|
|
||||||
new count = 0;
|
|
||||||
new cPlayers[MAXPLAYERS];
|
|
||||||
|
|
||||||
for (new x = 1; x <= MaxClients; x++)
|
|
||||||
{
|
|
||||||
if (!IsClientInGame(x) || GetClientTeam(x) <= 1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CS_SwitchTeam(x, CS_TEAM_T);
|
|
||||||
cPlayers[count++] = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (new x = 0; x < count; x++)
|
|
||||||
{
|
|
||||||
if (!IsClientInGame(cPlayers[x]) || GetClientTeam(cPlayers[x]) <= 1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CS_SwitchTeam(cPlayers[x], CS_TEAM_CT);
|
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,13 +542,6 @@ RemoveObjectives()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action:RoundOver(Handle:timer)
|
|
||||||
{
|
|
||||||
tRound = INVALID_HANDLE;
|
|
||||||
|
|
||||||
RoundWin(Human);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool:IsPlayerZombie(client)
|
bool:IsPlayerZombie(client)
|
||||||
{
|
{
|
||||||
return bZombie[client];
|
return bZombie[client];
|
||||||
|
@ -554,14 +550,4 @@ bool:IsPlayerZombie(client)
|
||||||
bool:IsPlayerHuman(client)
|
bool:IsPlayerHuman(client)
|
||||||
{
|
{
|
||||||
return !bZombie[client];
|
return !bZombie[client];
|
||||||
}
|
}
|
||||||
|
|
||||||
ZTeam:GetPlayerZTeam(client)
|
|
||||||
{
|
|
||||||
if (IsPlayerZombie(client))
|
|
||||||
{
|
|
||||||
return Zombie;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Human;
|
|
||||||
}
|
|
|
@ -5,25 +5,7 @@
|
||||||
* Author: Greyscale
|
* Author: Greyscale
|
||||||
* ====================
|
* ====================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define Target_Bombed 1 // Target Successfully Bombed!
|
|
||||||
#define VIP_Escaped 2 // The VIP has escaped!
|
|
||||||
#define VIP_Assassinated 3 // VIP has been assassinated!
|
|
||||||
#define Terrorists_Escaped 4 // The terrorists have escaped!
|
|
||||||
#define CTs_PreventEscape 5 // The CT's have prevented most of the terrorists from escaping!
|
|
||||||
#define Escaping_Terrorists_Neutralized 6 // Escaping terrorists have all been neutralized!
|
|
||||||
#define Bomb_Defused 7 // The bomb has been defused!
|
|
||||||
#define CTs_Win 8 // Counter-Terrorists Win!
|
|
||||||
#define Terrorists_Win 9 // Terrorists Win!
|
|
||||||
#define Round_Draw 10 // Round Draw!
|
|
||||||
#define All_Hostages_Rescued 11 // All Hostages have been rescued!
|
|
||||||
#define Target_Saved 12 // Target has been saved!
|
|
||||||
#define Hostages_Not_Rescued 13 // Hostages have not been rescued!
|
|
||||||
#define Terrorists_Not_Escaped 14 // Terrorists have not escaped!
|
|
||||||
#define VIP_Not_Escaped 15 // VIP has not escaped!
|
|
||||||
#define Game_Commencing 16 // Game Commencing!
|
|
||||||
|
|
||||||
#define DXLEVEL_MIN 90
|
|
||||||
#define DEFAULT_FOV 90
|
#define DEFAULT_FOV 90
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,16 +38,6 @@
|
||||||
* @endsection
|
* @endsection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Lists possible returns of the game at any time.
|
|
||||||
*/
|
|
||||||
enum ZTeam
|
|
||||||
{
|
|
||||||
Neither, /** Round is not over */
|
|
||||||
Zombie, /** Round is over because zombies win */
|
|
||||||
Human, /** Round is over because humans wins */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global variable set to true if market plugin is installed
|
* Global variable set to true if market plugin is installed
|
||||||
*/
|
*/
|
||||||
|
@ -91,11 +63,6 @@ new bool:bZombie[MAXPLAYERS + 1];
|
||||||
*/
|
*/
|
||||||
new bool:bMotherInfectImmune[MAXPLAYERS + 1];
|
new bool:bMotherInfectImmune[MAXPLAYERS + 1];
|
||||||
|
|
||||||
/**
|
|
||||||
* Global variable to store round win timer handle.
|
|
||||||
*/
|
|
||||||
new Handle:tRound = INVALID_HANDLE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global variable to store the infect timer handle.
|
* Global variable to store the infect timer handle.
|
||||||
*/
|
*/
|
||||||
|
@ -161,86 +128,6 @@ ZRBoolToConfigSetting(bool:bOption, String:option[], maxlen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Global variable to store a convar query cookie
|
|
||||||
*/
|
|
||||||
new QueryCookie:mat_dxlevel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds DX level of a client.
|
|
||||||
*
|
|
||||||
* @param client The client index.
|
|
||||||
*/
|
|
||||||
ZRFindClientDXLevel(client)
|
|
||||||
{
|
|
||||||
// If client is fake (or bot), then stop.
|
|
||||||
if (IsFakeClient(client))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query mat_dxlevel on client.
|
|
||||||
mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", ZRDXLevelClientQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query callback function.
|
|
||||||
*
|
|
||||||
* @param cookie Unique cookie of the query.
|
|
||||||
* @param client The client index.
|
|
||||||
* @param result The result of the query (see console.inc enum ConVarQueryResult)
|
|
||||||
* @param cvarName Name of the cvar.
|
|
||||||
* @param cvarValue Value of the cvar.
|
|
||||||
*/
|
|
||||||
public ZRDXLevelClientQuery(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[])
|
|
||||||
{
|
|
||||||
// If query cookie does not match cookie given by mat_dxlevel query, then stop, this isn't our query.
|
|
||||||
if (cookie != mat_dxlevel)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset dxLevel.
|
|
||||||
dxLevel[client] = 0;
|
|
||||||
|
|
||||||
// If result is any other than ConVarQuery_Okay, then stop.
|
|
||||||
if (result != ConVarQuery_Okay)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy cvar value to dxLevel array.
|
|
||||||
dxLevel[client] = StringToInt(cvarValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays overlay to client, or prints unsupported message on client's screen.
|
|
||||||
*
|
|
||||||
* @param client The client index.
|
|
||||||
* @param overlay The overlay path.
|
|
||||||
*/
|
|
||||||
ZRDisplayClientOverlay(client, const String:overlay[])
|
|
||||||
{
|
|
||||||
// If dxLevel is 0, then query on client failed, so try again, then stop.
|
|
||||||
if (!dxLevel[client])
|
|
||||||
{
|
|
||||||
// Query dxlevel cvar.
|
|
||||||
ZRFindClientDXLevel(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If dxLevel is above or equal to minimum requirement, then display overlay.
|
|
||||||
if (dxLevel[client] >= DXLEVEL_MIN)
|
|
||||||
{
|
|
||||||
ClientCommand(client, "r_screenoverlay \"%s\"", overlay);
|
|
||||||
}
|
|
||||||
// If client doesn't meet minimum requirement, then print unsupported text.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], DXLEVEL_MIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a client index is a valid player.
|
* Check if a client index is a valid player.
|
||||||
*
|
*
|
||||||
|
@ -260,6 +147,58 @@ bool:ZRIsValidClient(client, bool:console = false)
|
||||||
return console ? (client >= 0) : (client > 0);
|
return console ? (client >= 0) : (client > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count clients on each team.
|
||||||
|
*
|
||||||
|
* @param zombies This is set to the number of clients that are zombies.
|
||||||
|
* @param humans This is set to the number of clients that are humans.
|
||||||
|
* @param alive If true it will only count live players, false will count alive and dead.
|
||||||
|
* @return True if successful (zombie has spawned), false otherwise.
|
||||||
|
*/
|
||||||
|
bool:ZRCountValidClients(&zombiecount = 0, &humancount = 0, bool:alive = true)
|
||||||
|
{
|
||||||
|
// If zombie hasn't spawned, then stop.
|
||||||
|
if (!g_bZombieSpawned)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x = client index.
|
||||||
|
for (new x = 1; x <= MaxClients; x++)
|
||||||
|
{
|
||||||
|
// If client isn't in-game, then stop.
|
||||||
|
if (!IsClientInGame(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If client isn't on a team, then stop.
|
||||||
|
if (!ZRIsClientOnTeam(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If player must be alive, and player is dead, then stop.
|
||||||
|
if (alive && !IsPlayerAlive(x))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If player is a zombie, then increment zombie variable.
|
||||||
|
if (IsPlayerZombie(x))
|
||||||
|
{
|
||||||
|
zombiecount++;
|
||||||
|
}
|
||||||
|
// If player is a human, then increment human variable.
|
||||||
|
else if (IsPlayerHuman(x))
|
||||||
|
{
|
||||||
|
humancount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a client index is on a team.
|
* Check if a client index is on a team.
|
||||||
*
|
*
|
||||||
|
@ -291,7 +230,7 @@ bool:ZRIsClientOnTeam(client, team = -1)
|
||||||
*
|
*
|
||||||
* @param team (Optional) Team to check if there are clients on.
|
* @param team (Optional) Team to check if there are clients on.
|
||||||
*/
|
*/
|
||||||
ZRTeamHasClients(team = -1)
|
bool:ZRTeamHasClients(team = -1, bool:alive = false)
|
||||||
{
|
{
|
||||||
// If team is
|
// If team is
|
||||||
if (team == -1)
|
if (team == -1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user