Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6255e871d3 | ||
|
|
29dc99af0c | ||
|
|
572ced8387 | ||
|
|
206bbfdd91 | ||
|
|
99b0a6aa12 | ||
|
|
29badd3d87 | ||
|
|
ca9f7b0d13 |
@@ -325,6 +325,34 @@ zr_infect_mzombie_countdown "0"
|
||||
// Default: "0"
|
||||
zr_infect_mzombie_respawn "0"
|
||||
|
||||
// Exclude fake clients (bots, SourceTV) from being picked as mother zombie. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_fakeclients "1"
|
||||
|
||||
// Exclude AFK players (AFKManager idle time of at least zr_infect_mzombie_exclude_afk_time) from being picked as mother zombie. Requires the AFKManager plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_afk "1"
|
||||
|
||||
// Seconds a player has to be idle (according to AFKManager) to count as AFK for mother zombie selection.
|
||||
// Default: "180"
|
||||
zr_infect_mzombie_exclude_afk_time "180"
|
||||
|
||||
// Exclude autism bots (IsClientAutismBot from the BotTargeting plugin) from being picked as mother zombie. Requires the BotTargeting plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_autismbots "1"
|
||||
|
||||
// The zr_infect_mzombie_exclude_* cvars only apply while at least this many REAL players are present.
|
||||
// A REAL player is a player who is:
|
||||
// - NOT a fake client
|
||||
// - NOT AFK (AFKManager idle time >= zr_infect_mzombie_exclude_afk_time)
|
||||
// - NOT an autism bot (BotTargeting)
|
||||
// - NOT in spectate/unassigned
|
||||
// - NOT dead
|
||||
// Example: 5 = while there are fewer than 5 real players, fake clients, AFKs and autism bots can be mother zombie too.
|
||||
// [0 = Always apply the exclusions]
|
||||
// Default: "0"
|
||||
zr_infect_mzombie_exclude_min_real "0"
|
||||
|
||||
// Maximum time from the start of the round until picking the mother zombie(s).
|
||||
// Default: "50.0"
|
||||
zr_infect_spawntime_max "50.0"
|
||||
|
||||
@@ -1143,6 +1143,69 @@
|
||||
"en" "HP: {1}"
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// ZVolume (module)
|
||||
// ===========================
|
||||
|
||||
"Volume_Menu_Title"
|
||||
{
|
||||
"en" "[ZR] Volume Control Menu\nCommand: !zvolume"
|
||||
}
|
||||
|
||||
"Zombie Voice"
|
||||
{
|
||||
"en" "Zombie Voice"
|
||||
}
|
||||
|
||||
"Ambient"
|
||||
{
|
||||
"en" "Ambient"
|
||||
}
|
||||
|
||||
"ZombieVoice_Usage"
|
||||
{
|
||||
"en" "Usage: zr_zombie_volume <0 - 100>"
|
||||
}
|
||||
|
||||
"ZombieVoice_Title_Menu"
|
||||
{
|
||||
"#format" "{1:d}"
|
||||
"en" "[ZR] Zombie Voice Volume (Current: {1:d}%)"
|
||||
}
|
||||
|
||||
"ZombieVoice_CommandUsage"
|
||||
{
|
||||
"en" "Command: !zombie_volume <1-100>"
|
||||
}
|
||||
|
||||
"Set_ZombieVoice_Volume"
|
||||
{
|
||||
"#format" "{1:d}"
|
||||
"en" "Set Zombie Voice Volume to {lightgreen}{1:d}%."
|
||||
}
|
||||
|
||||
"Ambient_Usage"
|
||||
{
|
||||
"en" "Usage: zr_ambient_volume <0 - 100>"
|
||||
}
|
||||
|
||||
"Ambient_Title_Menu"
|
||||
{
|
||||
"#format" "{1:d}"
|
||||
"en" "[ZR] Ambient Volume (Current: {1:d}%)"
|
||||
}
|
||||
|
||||
"Ambient_CommandUsage"
|
||||
{
|
||||
"en" "Command: !ambient_volume <1-100>"
|
||||
}
|
||||
|
||||
"Set_Ambient_Volume"
|
||||
{
|
||||
"#format" "{1:d}"
|
||||
"en" "Set Ambient Volume to {lightgreen}{1:d}%."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Volumetric features (module)
|
||||
// ===========================
|
||||
|
||||
@@ -325,6 +325,34 @@ zr_infect_mzombie_countdown "0"
|
||||
// Default: "0"
|
||||
zr_infect_mzombie_respawn "0"
|
||||
|
||||
// Exclude fake clients (bots, SourceTV) from being picked as mother zombie. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_fakeclients "1"
|
||||
|
||||
// Exclude AFK players (AFKManager idle time of at least zr_infect_mzombie_exclude_afk_time) from being picked as mother zombie. Requires the AFKManager plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_afk "1"
|
||||
|
||||
// Seconds a player has to be idle (according to AFKManager) to count as AFK for mother zombie selection.
|
||||
// Default: "180"
|
||||
zr_infect_mzombie_exclude_afk_time "180"
|
||||
|
||||
// Exclude autism bots (IsClientAutismBot from the BotTargeting plugin) from being picked as mother zombie. Requires the BotTargeting plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_exclude_autismbots "1"
|
||||
|
||||
// The zr_infect_mzombie_exclude_* cvars only apply while at least this many REAL players are present.
|
||||
// A REAL player is a player who is:
|
||||
// - NOT a fake client
|
||||
// - NOT AFK (AFKManager idle time >= zr_infect_mzombie_exclude_afk_time)
|
||||
// - NOT an autism bot (BotTargeting)
|
||||
// - NOT in spectate/unassigned
|
||||
// - NOT dead
|
||||
// Example: 5 = while there are fewer than 5 real players, fake clients, AFKs and autism bots can be mother zombie too.
|
||||
// [0 = Always apply the exclusions]
|
||||
// Default: "0"
|
||||
zr_infect_mzombie_exclude_min_real "0"
|
||||
|
||||
// Maximum time from the start of the round until picking the mother zombie(s).
|
||||
// Default: "50.0"
|
||||
zr_infect_spawntime_max "50.0"
|
||||
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
#if defined _BotTargeting_Included
|
||||
#endinput
|
||||
#endif
|
||||
#define _BotTargeting_Included
|
||||
|
||||
/**
|
||||
* Returns whether the client is one of the BotTargeting "autism bot" SteamIDs.
|
||||
*
|
||||
* @param client Client index. Must be in-game and authorized, otherwise a native error is thrown.
|
||||
* @return True if the client is an autism bot, false otherwise.
|
||||
*/
|
||||
native bool IsClientAutismBot(int client);
|
||||
|
||||
public SharedPlugin __pl_BotTargeting =
|
||||
{
|
||||
name = "BotTargeting",
|
||||
file = "BotTargeting.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1,
|
||||
#else
|
||||
required = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public __pl_BotTargeting_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("IsClientAutismBot");
|
||||
}
|
||||
#endif
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#if defined _unloze_playtime_included_
|
||||
#endinput
|
||||
#endif
|
||||
#define _unloze_playtime_included_
|
||||
|
||||
/**
|
||||
* @returns the average playtime of all connected players excluding autism bots, fakeclients, AFKS and nosteamers
|
||||
*/
|
||||
native int GetAveragePlayerTimeOnServer();
|
||||
|
||||
/**
|
||||
* @returns the players rtv amount boost
|
||||
*/
|
||||
native int GetPlayerWorthRTV_boost_(int client);
|
||||
|
||||
/**
|
||||
* returns a players hours for a specific server
|
||||
*
|
||||
* @int the actual client
|
||||
* @int Game time hours that the client has on the server.
|
||||
* @int Game time minutes the client has on the server.
|
||||
*/
|
||||
|
||||
native int GetPlayerTier_native(int client); //just the clients tier
|
||||
forward void GetPlayerHoursServer(int client, int hours, int minutes);
|
||||
forward void GetPlayerTier(int client, int tier);
|
||||
@@ -351,6 +351,7 @@ public OnClientCookiesCached(client)
|
||||
ClassOnCookiesCached(client);
|
||||
WeaponsOnCookiesCached(client);
|
||||
ZHPOnCookiesCached(client);
|
||||
ZVolumeOnCookiesCached(client);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,7 @@ CommandsInit()
|
||||
ZTele_OnCommandsCreate();
|
||||
ZHPOnCommandsCreate();
|
||||
VolOnCommandsCreate();
|
||||
ZVolumeOnCommandsCreate();
|
||||
ZombieSoundsOnCommandsCreate();
|
||||
ImmunityOnCommandsCreate();
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ CookiesInit()
|
||||
ClassOnCookiesCreate();
|
||||
WeaponsOnCookiesCreate();
|
||||
ZHPOnCookiesCreate();
|
||||
ZVolumeOnCookiesCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,6 +116,11 @@ enum CvarsList
|
||||
Handle:CVAR_INFECT_MZOMBIE_MAX,
|
||||
Handle:CVAR_INFECT_MZOMBIE_COUNTDOWN,
|
||||
Handle:CVAR_INFECT_MZOMBIE_RESPAWN,
|
||||
Handle:CVAR_INFECT_MZOMBIE_EXCLUDE_FAKECLIENTS,
|
||||
Handle:CVAR_INFECT_MZOMBIE_EXCLUDE_AFK,
|
||||
Handle:CVAR_INFECT_MZOMBIE_EXCLUDE_AFK_TIME,
|
||||
Handle:CVAR_INFECT_MZOMBIE_EXCLUDE_AUTISMBOTS,
|
||||
Handle:CVAR_INFECT_MZOMBIE_EXCLUDE_MIN_REAL,
|
||||
Handle:CVAR_INFECT_EXPLOSION,
|
||||
Handle:CVAR_INFECT_FIREBALL,
|
||||
Handle:CVAR_INFECT_SMOKE,
|
||||
@@ -152,6 +157,7 @@ enum CvarsList
|
||||
Handle:CVAR_SEFFECTS_DEATH,
|
||||
Handle:CVAR_SEFFECTS_COMMAND_LIMIT,
|
||||
Handle:CVAR_SEFFECTS_COMMAND_TIMESPAN,
|
||||
Handle:CVAR_SEFFECTS_VOLUME,
|
||||
Handle:CVAR_AMBIENTSOUNDS,
|
||||
Handle:CVAR_AMBIENTSOUNDS_FILE,
|
||||
Handle:CVAR_AMBIENTSOUNDS_LENGTH,
|
||||
@@ -337,6 +343,11 @@ CvarsCreate()
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_MAX] = CreateConVar("zr_infect_mzombie_max", "3", "Maximum number of mother zombies. Range mode only, cannot be zero.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_COUNTDOWN] = CreateConVar("zr_infect_mzombie_countdown", "0", "Counts down to the first infection of the round. Countdown is printed in the middle of the client's screen.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_RESPAWN] = CreateConVar("zr_infect_mzombie_respawn", "0", "Teleport mother zombies back to spawn on infect.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_FAKECLIENTS] = CreateConVar("zr_infect_mzombie_exclude_fakeclients", "1", "Exclude fake clients (bots, SourceTV) from being picked as mother zombie. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK] = CreateConVar("zr_infect_mzombie_exclude_afk", "1", "Exclude AFK players (AFKManager idle time of at least zr_infect_mzombie_exclude_afk_time) from being picked as mother zombie. Requires the AFKManager plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK_TIME] = CreateConVar("zr_infect_mzombie_exclude_afk_time", "180", "Seconds a player has to be idle (according to AFKManager) to count as AFK for mother zombie selection.", _, true, 1.0);
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AUTISMBOTS] = CreateConVar("zr_infect_mzombie_exclude_autismbots", "1", "Exclude autism bots (IsClientAutismBot from the BotTargeting plugin) from being picked as mother zombie. Requires the BotTargeting plugin. Excluded players are still used as a last resort when no one else can be picked. [0 = Include | 1 = Exclude]");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_MIN_REAL] = CreateConVar("zr_infect_mzombie_exclude_min_real", "0", "The zr_infect_mzombie_exclude_* cvars only apply while at least this many REAL players are present. A REAL player is a player who is NOT a fake client, NOT AFK (AFKManager idle time >= zr_infect_mzombie_exclude_afk_time), NOT an autism bot (BotTargeting), NOT in spectate/unassigned and NOT dead. Example: 5 = while there are fewer than 5 real players, fake clients, AFKs and autism bots can be mother zombie too. [0 = Always apply the exclusions]", _, true, 0.0);
|
||||
g_hCvarsList[CVAR_INFECT_SPAWNTIME_MIN] = CreateConVar("zr_infect_spawntime_min", "30.0", "Minimum time from the start of the round until picking the mother zombie(s).");
|
||||
g_hCvarsList[CVAR_INFECT_SPAWNTIME_MAX] = CreateConVar("zr_infect_spawntime_max", "50.0", "Maximum time from the start of the round until picking the mother zombie(s).");
|
||||
g_hCvarsList[CVAR_INFECT_CONSECUTIVE_BLOCK] = CreateConVar("zr_infect_consecutive_block", "1", "Prevent a player from being chosen as mother zombie two rounds in a row.");
|
||||
@@ -450,6 +461,7 @@ CvarsCreate()
|
||||
g_hCvarsList[CVAR_SEFFECTS_DEATH] = CreateConVar("zr_seffects_death", "1", "Emit a death sound when a zombie dies.");
|
||||
g_hCvarsList[CVAR_SEFFECTS_COMMAND_LIMIT] = CreateConVar("zr_seffects_command_limit", "4", "Number of sound commands allowed within the time span, or total limit if time span is disabled. ['0' = Disable sound command limit]");
|
||||
g_hCvarsList[CVAR_SEFFECTS_COMMAND_TIMESPAN] = CreateConVar("zr_seffects_command_timespan", "10", "Time span for sound command limiter (in seconds). ['0' = Disable time span check | positive number = Time span]");
|
||||
g_hCvarsList[CVAR_SEFFECTS_VOLUME] = CreateConVar("zr_seffects_volume", "0.8", "Default volume of the zombie voice sounds, used as each client's starting !zsound value. [1.0 = Max volume | 0.0001 = Not audible]");
|
||||
|
||||
// Ambient Sounds
|
||||
g_hCvarsList[CVAR_AMBIENTSOUNDS] = CreateConVar("zr_ambientsounds", "1", "Play an ambient sound to all players during gameplay.");
|
||||
|
||||
+280
-35
@@ -32,6 +32,7 @@
|
||||
|
||||
#tryinclude "AFKManager.inc"
|
||||
#tryinclude "TeamManager.inc"
|
||||
#include <BotTargeting>
|
||||
|
||||
/* Restore old REQUIRE_PLUGIN value if necessary */
|
||||
#if defined TEMP_REQUIRE_PLUGIN
|
||||
@@ -41,6 +42,7 @@
|
||||
|
||||
new bool:g_AFKManagerLoaded = false;
|
||||
new bool:g_TeamManagerLoaded = false;
|
||||
new bool:g_BotTargetingLoaded = false;
|
||||
|
||||
/**
|
||||
* @section Explosion flags.
|
||||
@@ -122,6 +124,9 @@ InfectOnAllPluginsLoaded()
|
||||
g_TeamManagerLoaded = LibraryExists("TeamManager");
|
||||
LogMessage("TeamManager: %s", (g_TeamManagerLoaded ? "loaded" : "not loaded"));
|
||||
#endif
|
||||
|
||||
g_BotTargetingLoaded = LibraryExists("BotTargeting");
|
||||
LogMessage("BotTargeting: %s", (g_BotTargetingLoaded ? "loaded" : "not loaded"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +144,11 @@ InfectOnLibraryAdded(const String:name[])
|
||||
// TeamManager loaded.
|
||||
g_TeamManagerLoaded = true;
|
||||
}
|
||||
else if (StrEqual(name, "BotTargeting"))
|
||||
{
|
||||
// BotTargeting loaded.
|
||||
g_BotTargetingLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,6 +166,200 @@ InfectOnLibraryRemoved(const String:name[])
|
||||
// TeamManager unloaded.
|
||||
g_TeamManagerLoaded = false;
|
||||
}
|
||||
else if (StrEqual(name, "BotTargeting"))
|
||||
{
|
||||
// BotTargeting unloaded.
|
||||
g_BotTargetingLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a (non-fake) client is AFK according to AFKManager.
|
||||
*
|
||||
* @param client The client index. Must be in-game and not a fake client.
|
||||
* @return True if AFKManager is loaded and the client has been idle for
|
||||
* at least zr_infect_mzombie_exclude_afk_time seconds.
|
||||
*/
|
||||
bool:InfectIsClientAFK(client)
|
||||
{
|
||||
#if defined _AFKManager_Included
|
||||
if (g_AFKManagerLoaded && GetClientIdleTime(client) >= GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK_TIME]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a (non-fake) client is an autism bot according to BotTargeting.
|
||||
*
|
||||
* @param client The client index. Must be in-game and not a fake client.
|
||||
* @return True if BotTargeting is loaded and says the client is an autism bot.
|
||||
*/
|
||||
bool:InfectIsClientAutismBot(client)
|
||||
{
|
||||
// The native throws on unauthorized clients, so check that first.
|
||||
return (g_BotTargetingLoaded && IsClientAuthorized(client) && IsClientAutismBot(client));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a client falls in one of the categories excluded from mother zombie
|
||||
* by the zr_infect_mzombie_exclude_fakeclients/afk/autismbots cvars.
|
||||
*
|
||||
* This only looks at the category cvars, not at zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* @param client The client index. Must be in-game.
|
||||
* @return True if the client is excluded, false otherwise.
|
||||
*/
|
||||
bool:InfectIsClientMotherExcluded(client)
|
||||
{
|
||||
// Bots / SourceTV.
|
||||
if (IsFakeClient(client))
|
||||
{
|
||||
return GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_FAKECLIENTS]);
|
||||
}
|
||||
|
||||
// AFK players.
|
||||
if (GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK]) && InfectIsClientAFK(client))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Autism bots.
|
||||
if (GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AUTISMBOTS]) && InfectIsClientAutismBot(client))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a client is a "real" player, as used by zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* A real player is in-game, on a team (not spectate/unassigned), alive, and is
|
||||
* not a fake client, not AFK and not an autism bot. This definition is fixed and
|
||||
* does not depend on the zr_infect_mzombie_exclude_* category cvars.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @return True if the client is a real player, false otherwise.
|
||||
*/
|
||||
bool:InfectIsClientRealPlayer(client)
|
||||
{
|
||||
if (!IsClientInGame(client) || !ZRIsClientOnTeam(client) || !IsPlayerAlive(client))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsFakeClient(client) || InfectIsClientAFK(client) || InfectIsClientAutismBot(client))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the mother zombie exclusions currently apply, based on
|
||||
* zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* @return True if there are at least zr_infect_mzombie_exclude_min_real real
|
||||
* players (or the cvar is 0), false otherwise.
|
||||
*/
|
||||
bool:InfectMotherExclusionsActive()
|
||||
{
|
||||
new minreal = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_MIN_REAL]);
|
||||
if (minreal <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
new realplayers = 0;
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
if (InfectIsClientRealPlayer(x))
|
||||
{
|
||||
realplayers++;
|
||||
}
|
||||
}
|
||||
|
||||
return (realplayers >= minreal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the mother zombie candidate lists.
|
||||
*
|
||||
* All alive humans on a team that the API allows are split into two lists:
|
||||
* - arrayEligibleClients: regular candidates. Only these go through the
|
||||
* consecutive block / round-robin cycle logic.
|
||||
* - arrayExcludedClients: fake clients, AFKs and autism bots excluded by the
|
||||
* zr_infect_mzombie_exclude_* cvars. Only used as a last resort when the
|
||||
* regular candidates can't fill the mother zombie count.
|
||||
*
|
||||
* When zr_infect_mzombie_exclude_min_real isn't reached, nobody is excluded.
|
||||
*
|
||||
* @param arrayEligibleClients Array to push regular candidates into.
|
||||
* @param arrayExcludedClients Array to push excluded candidates into.
|
||||
* @return Number of regular candidates.
|
||||
*/
|
||||
InfectCreateMotherCandidateLists(Handle:arrayEligibleClients, Handle:arrayExcludedClients)
|
||||
{
|
||||
new Handle:arrayAllClients = CreateArray();
|
||||
new allclients = ZRCreateEligibleClientList(arrayAllClients, true, true, true, true);
|
||||
|
||||
new bool:exclude = InfectMotherExclusionsActive();
|
||||
new eligibleclients = 0;
|
||||
|
||||
for (new n = 0; n < allclients; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayAllClients, n);
|
||||
|
||||
if (exclude && InfectIsClientMotherExcluded(client))
|
||||
{
|
||||
PushArrayCell(arrayExcludedClients, client);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushArrayCell(arrayEligibleClients, client);
|
||||
eligibleclients++;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(arrayAllClients);
|
||||
return eligibleclients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks a random client from the list that is still human.
|
||||
*
|
||||
* @param arrayClients List of client indexes.
|
||||
* @return Client index, or -1 if nobody in the list is human.
|
||||
*/
|
||||
InfectGetRandomHumanFromList(Handle:arrayClients)
|
||||
{
|
||||
new Handle:arrayHumans = CreateArray();
|
||||
new size = GetArraySize(arrayClients);
|
||||
|
||||
for (new n = 0; n < size; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayClients, n);
|
||||
if (IsClientInGame(client) && InfectIsClientHuman(client))
|
||||
{
|
||||
PushArrayCell(arrayHumans, client);
|
||||
}
|
||||
}
|
||||
|
||||
new client = -1;
|
||||
new humans = GetArraySize(arrayHumans);
|
||||
if (humans)
|
||||
{
|
||||
client = GetArrayCell(arrayHumans, Math_GetRandomInt(0, humans - 1));
|
||||
}
|
||||
|
||||
CloseHandle(arrayHumans);
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,13 +438,10 @@ InfectClientInit(client)
|
||||
if(!IsClientInGame(x))
|
||||
continue;
|
||||
|
||||
#if defined _AFKManager_Included
|
||||
if(g_AFKManagerLoaded)
|
||||
{
|
||||
if(GetClientIdleTime(x) > 3 * 60)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// Clients that can never be mother zombie are never in the cycle,
|
||||
// don't let them water down the ratio.
|
||||
if(InfectIsClientMotherExcluded(x))
|
||||
continue;
|
||||
|
||||
players++;
|
||||
|
||||
@@ -578,15 +779,18 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create eligible player list.
|
||||
// Create candidate lists: regular candidates and excluded (fake clients, AFKs, autism bots).
|
||||
new Handle:arrayEligibleClients = CreateArray();
|
||||
new eligibleclients = ZRCreateEligibleClientList(arrayEligibleClients, true, true, true, true);
|
||||
new Handle:arrayExcludedClients = CreateArray();
|
||||
new eligibleclients = InfectCreateMotherCandidateLists(arrayEligibleClients, arrayExcludedClients);
|
||||
new excludedclients = GetArraySize(arrayExcludedClients);
|
||||
|
||||
// If there are no eligible client's then stop.
|
||||
if (!eligibleclients)
|
||||
// If nobody is alive on a team (everyone dead or in spectate), then stop.
|
||||
if (!eligibleclients && !excludedclients)
|
||||
{
|
||||
// Destroy handle.
|
||||
// Destroy handles.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
CloseHandle(arrayExcludedClients);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -688,6 +892,15 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
}
|
||||
|
||||
// Split excluded clients too, so the last resort prefers those who weren't mother zombie last round.
|
||||
new Handle:aExcludedMain = CreateArray();
|
||||
new Handle:aExcludedAlt = CreateArray();
|
||||
for (new n = 0; n < excludedclients; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayExcludedClients, n);
|
||||
PushArrayCell(g_bInfectMotherLast[client] ? aExcludedAlt : aExcludedMain, client);
|
||||
}
|
||||
|
||||
// Remove mother zombie last flag from all players.
|
||||
for (int client = 0; client <= MAXPLAYERS; client++)
|
||||
{
|
||||
@@ -699,16 +912,19 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
// Infect players.
|
||||
new infected = 0;
|
||||
new infected_human_to_zombie_failed = 0;
|
||||
while (infected < mothercount)
|
||||
|
||||
// Only run the regular selection (and its cycle reset) if there are regular candidates.
|
||||
// If there are none, all alive players are excluded ones and the cycle of the regular
|
||||
// players must not be touched.
|
||||
while (eligibleclients && infected < mothercount)
|
||||
{
|
||||
// Infect one of the main candidates.
|
||||
if (candidatesMain)
|
||||
{
|
||||
// Get a random array index.
|
||||
new i = Math_GetRandomInt(0, candidatesMain - 1);
|
||||
|
||||
// Get the client stored in the random array index.
|
||||
new client = GetArrayCell(aCandidatesMain, i);
|
||||
new client = GetArrayCell(aCandidatesMain, i);
|
||||
|
||||
// Infect player.
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
@@ -737,7 +953,6 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
{
|
||||
// Get a random array index.
|
||||
new i = Math_GetRandomInt(0, candidatesAlt - 1);
|
||||
|
||||
// Get the client stored in the random array index.
|
||||
new client = GetArrayCell(aCandidatesAlt, i);
|
||||
|
||||
@@ -745,46 +960,76 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
infected++;
|
||||
|
||||
// Remove player from eligible client list.
|
||||
// Remove player from eligible client list.
|
||||
RemoveFromArray(aCandidatesAlt, i);
|
||||
candidatesAlt--;
|
||||
}
|
||||
else // We have no candidates at all. time to fuck over random people!
|
||||
{
|
||||
// Infect player.
|
||||
if (eligibleclients)
|
||||
// Pick a random regular candidate that is still human (ignores the consecutive block).
|
||||
new client = InfectGetRandomHumanFromList(arrayEligibleClients);
|
||||
if (client == -1)
|
||||
{
|
||||
new randindex = Math_GetRandomInt(0, eligibleclients - 1);
|
||||
new client = GetArrayCell(arrayEligibleClients, randindex);
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
infected_human_to_zombie_failed++;
|
||||
if (infected_human_to_zombie_failed > 100)
|
||||
{
|
||||
break;
|
||||
//doing testround on dev server would cause script time execution, hence this was added.
|
||||
}
|
||||
}
|
||||
break; // All regular candidates are zombies already, fall through to the excluded clients.
|
||||
}
|
||||
|
||||
// Infect player.
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; //prevent infinite loop. should be very unlikely we end up here.
|
||||
infected_human_to_zombie_failed++;
|
||||
if (infected_human_to_zombie_failed > 100)
|
||||
{
|
||||
break;
|
||||
//doing testround on dev server would cause script time execution, hence this was added.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort: not enough regular candidates, so infect excluded clients (fake clients, AFKs,
|
||||
// autism bots). A round must not start without mother zombies.
|
||||
// Prefer those who weren't mother zombie last round.
|
||||
while (infected < mothercount)
|
||||
{
|
||||
new Handle:aExcluded = INVALID_HANDLE;
|
||||
if (GetArraySize(aExcludedMain))
|
||||
{
|
||||
aExcluded = aExcludedMain;
|
||||
}
|
||||
else if (GetArraySize(aExcludedAlt))
|
||||
{
|
||||
aExcluded = aExcludedAlt;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // Nobody left.
|
||||
}
|
||||
|
||||
new i = Math_GetRandomInt(0, GetArraySize(aExcluded) - 1);
|
||||
new client = GetArrayCell(aExcluded, i);
|
||||
RemoveFromArray(aExcluded, i);
|
||||
|
||||
if (IsClientInGame(client) && InfectIsClientHuman(client) && InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
}
|
||||
|
||||
// Mother zombies have been infected.
|
||||
g_bZombieSpawned = true;
|
||||
|
||||
// Destroy client list.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
CloseHandle(arrayExcludedClients);
|
||||
CloseHandle(aCandidatesMain);
|
||||
CloseHandle(aCandidatesAlt);
|
||||
CloseHandle(aExcludedMain);
|
||||
CloseHandle(aExcludedAlt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "zr/soundeffects/voice"
|
||||
#include "zr/soundeffects/ambientsounds"
|
||||
#include "zr/soundeffects/zombiesounds"
|
||||
#include "zr/soundeffects/volumecontrol"
|
||||
|
||||
/**
|
||||
* Load sound effects data.
|
||||
@@ -172,8 +173,17 @@ SEffectsEmitAmbientSound(const String:sound[], Float:ambientvolume = 1.0, client
|
||||
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
// Scale by this client's personal ambient volume setting.
|
||||
new Float:finalvolume = ambientvolume * ZVolume_GetAmbientVolume(client);
|
||||
|
||||
// If client has muted ambient sounds, then stop.
|
||||
if (finalvolume <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit ambient sound.
|
||||
EmitSoundToClient(client, sound, SOUND_FROM_PLAYER, SOUND_AMBIENT_CHANNEL, _, _, ambientvolume);
|
||||
EmitSoundToClient(client, sound, SOUND_FROM_PLAYER, SOUND_AMBIENT_CHANNEL, _, _, finalvolume);
|
||||
|
||||
// Flag client that sound is playing.
|
||||
bAmbientSoundsIsPlaying[client] = true;
|
||||
@@ -188,8 +198,17 @@ SEffectsEmitAmbientSound(const String:sound[], Float:ambientvolume = 1.0, client
|
||||
continue;
|
||||
}
|
||||
|
||||
// Scale by this client's personal ambient volume setting.
|
||||
new Float:finalvolume = ambientvolume * ZVolume_GetAmbientVolume(x);
|
||||
|
||||
// If client has muted ambient sounds, then skip them.
|
||||
if (finalvolume <= 0.0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Emit ambient sound.
|
||||
EmitSoundToClient(x, sound, SOUND_FROM_PLAYER, SNDCHAN_AUTO, _, _, ambientvolume);
|
||||
EmitSoundToClient(x, sound, SOUND_FROM_PLAYER, SNDCHAN_AUTO, _, _, finalvolume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,6 +252,25 @@ SEffectsEmitSoundFromClient(client, const String:sound[], level = SNDLEVEL_NORMA
|
||||
// Precache sound before playing.
|
||||
PrecacheSound(sound);
|
||||
|
||||
// Emit sound from client.
|
||||
EmitSoundToAll(sound, client, _, level);
|
||||
// x = receiving client index.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// If client isn't in-game, then skip.
|
||||
if (!IsClientInGame(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get this client's personal zombie-voice volume.
|
||||
new Float:zvolume = ZVolume_GetZSoundVolume(x);
|
||||
|
||||
// If client has muted zombie voice sounds, then skip them.
|
||||
if (zvolume <= 0.0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Emit sound from client, at this receiving client's personal volume.
|
||||
EmitSoundToClient(x, sound, client, _, level, _, zvolume);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* ============================================================================
|
||||
*
|
||||
* Zombie:Reloaded
|
||||
*
|
||||
* File: volumecontrol.inc
|
||||
* Type: Core
|
||||
* Description: Basic volume control for player to change.
|
||||
*
|
||||
* Copyright (C) 2009-2013 Greyscale, Richard Helgeby
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cookie names for client volume settings.
|
||||
*/
|
||||
#define ZVOLUME_COOKIE_ZSOUND "zr_zombie_volume"
|
||||
#define ZVOLUME_COOKIE_AMBIENT "zr_ambient_volume"
|
||||
|
||||
/**
|
||||
* Cookie handles for client volume settings.
|
||||
*/
|
||||
new Handle:g_hZSoundVolumeCookie = INVALID_HANDLE;
|
||||
new Handle:g_hAmbientVolumeCookie = INVALID_HANDLE;
|
||||
|
||||
/**
|
||||
* Per-client volume, as a fraction (0.0 - 1.0), applied on top of sounds
|
||||
* emitted through SEffectsEmitSoundFromClient() and SEffectsEmitAmbientSound().
|
||||
*/
|
||||
new Float:zfZSoundVolume[MAXPLAYERS + 1];
|
||||
new Float:zfAmbientVolume[MAXPLAYERS + 1];
|
||||
|
||||
/**
|
||||
* Create commands specific to ZVolume.
|
||||
*/
|
||||
ZVolumeOnCommandsCreate()
|
||||
{
|
||||
RegConsoleCmd("sm_zvol", Command_ZVolume, "Brings up the zvolume menu");
|
||||
RegConsoleCmd("sm_zvolume", Command_ZVolume, "Brings up the zvolume menu");
|
||||
RegConsoleCmd("sm_zsound", Command_ZSound, "Brings up the zsound menu");
|
||||
RegConsoleCmd("sm_zombie_volume", Command_ZSound, "Brings up the zsound menu");
|
||||
RegConsoleCmd("sm_zambient", Command_ZAmbient, "Brings up the ambient menu");
|
||||
RegConsoleCmd("sm_ambient_volume", Command_ZAmbient, "Brings up the ambient menu");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ZVolume-related cookies here.
|
||||
*/
|
||||
ZVolumeOnCookiesCreate()
|
||||
{
|
||||
if (g_hZSoundVolumeCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hZSoundVolumeCookie = RegClientCookie(ZVOLUME_COOKIE_ZSOUND, "Control Zombie Sound.", CookieAccess_Protected);
|
||||
}
|
||||
|
||||
if (g_hAmbientVolumeCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hAmbientVolumeCookie = RegClientCookie(ZVOLUME_COOKIE_AMBIENT, "Control Ambient Sound.", CookieAccess_Protected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called once a client's saved cookies have been loaded from the database.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
ZVolumeOnCookiesCached(client)
|
||||
{
|
||||
decl String:sValue[8];
|
||||
|
||||
sValue[0] = '\0';
|
||||
GetClientCookie(client, g_hZSoundVolumeCookie, sValue, sizeof(sValue));
|
||||
if (!sValue[0])
|
||||
{
|
||||
new Float:seffectsvolume = GetConVarFloat(g_hCvarsList[CVAR_SEFFECTS_VOLUME]);
|
||||
IntToString(RoundToNearest(seffectsvolume * 100.0), sValue, sizeof(sValue));
|
||||
}
|
||||
SetZombieVoiceVolume(client, StringToInt(sValue));
|
||||
|
||||
sValue[0] = '\0';
|
||||
GetClientCookie(client, g_hAmbientVolumeCookie, sValue, sizeof(sValue));
|
||||
if (!sValue[0])
|
||||
{
|
||||
new Float:ambientvolume = GetConVarFloat(g_hCvarsList[CVAR_AMBIENTSOUNDS_VOLUME]);
|
||||
IntToString(RoundToNearest(ambientvolume * 100.0), sValue, sizeof(sValue));
|
||||
}
|
||||
SetAmbientVolume(client, StringToInt(sValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client's personal zombie-voice volume, as a fraction (0.0 - 1.0).
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
Float:ZVolume_GetZSoundVolume(client)
|
||||
{
|
||||
return zfZSoundVolume[client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client's personal ambient-sound volume, as a fraction (0.0 - 1.0).
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
Float:ZVolume_GetAmbientVolume(client)
|
||||
{
|
||||
return zfAmbientVolume[client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (sm_zvol, sm_zvolume)
|
||||
* Opens the volume control menu.
|
||||
*/
|
||||
public Action:Command_ZVolume(client, args)
|
||||
{
|
||||
if (IsClientInGame(client))
|
||||
{
|
||||
VolumeControlMenu(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
VolumeControlMenu(client)
|
||||
{
|
||||
new Handle:menu = CreateMenu(VolumeControlMenuHandler);
|
||||
|
||||
decl String:sMenuTitle[128];
|
||||
Format(sMenuTitle, sizeof(sMenuTitle), "%t", "Volume_Menu_Title");
|
||||
SetMenuTitle(menu, sMenuTitle);
|
||||
|
||||
decl String:sItem[64];
|
||||
|
||||
Format(sItem, sizeof(sItem), "%t", "Zombie Voice");
|
||||
AddMenuItem(menu, "1", sItem);
|
||||
|
||||
Format(sItem, sizeof(sItem), "%t", "Ambient");
|
||||
AddMenuItem(menu, "2", sItem);
|
||||
|
||||
SetMenuExitBackButton(menu, true);
|
||||
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||
}
|
||||
|
||||
public VolumeControlMenuHandler(Handle:menu, MenuAction:action, param1, param2)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MenuAction_Select:
|
||||
{
|
||||
decl String:info[32];
|
||||
GetMenuItem(menu, param2, info, sizeof(info));
|
||||
if (StrEqual(info, "1", false))
|
||||
{
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "2"))
|
||||
{
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_Cancel:
|
||||
{
|
||||
if (param2 == MenuCancel_ExitBack)
|
||||
{
|
||||
ZMenuMain(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_End:
|
||||
{
|
||||
CloseHandle(menu);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Zombie Voice Section
|
||||
/**
|
||||
* Command callback (sm_zsound, sm_zombie_volume)
|
||||
*/
|
||||
public Action:Command_ZSound(client, args)
|
||||
{
|
||||
if (args == 0)
|
||||
{
|
||||
ZombieVoiceVolumeMenu(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:sArg[32];
|
||||
GetCmdArg(1, sArg, sizeof(sArg));
|
||||
new iVolume = StringToInt(sArg);
|
||||
|
||||
if (iVolume < 0 || iVolume > 100)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZombieVoice_Usage");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
else if (0 <= iVolume <= 100)
|
||||
{
|
||||
SetZombieVoiceVolume(client, iVolume);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
ZombieVoiceVolumeMenu(client)
|
||||
{
|
||||
new Handle:menu = CreateMenu(ZombieVoiceVolumeMenuHandler);
|
||||
|
||||
decl String:sMenuTitle[128];
|
||||
Format(sMenuTitle, sizeof(sMenuTitle), "%t\n%t", "ZombieVoice_Title_Menu", RoundToNearest(zfZSoundVolume[client] * 100), "ZombieVoice_CommandUsage");
|
||||
SetMenuTitle(menu, sMenuTitle);
|
||||
|
||||
AddMenuItem(menu, "1", "100%");
|
||||
AddMenuItem(menu, "2", "80%");
|
||||
AddMenuItem(menu, "3", "60%");
|
||||
AddMenuItem(menu, "4", "40%");
|
||||
AddMenuItem(menu, "5", "20%");
|
||||
|
||||
SetMenuExitBackButton(menu, true);
|
||||
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||
}
|
||||
|
||||
public ZombieVoiceVolumeMenuHandler(Handle:menu, MenuAction:action, param1, param2)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MenuAction_Select:
|
||||
{
|
||||
decl String:info[32];
|
||||
GetMenuItem(menu, param2, info, sizeof(info));
|
||||
if (StrEqual(info, "1", false))
|
||||
{
|
||||
SetZombieVoiceVolume(param1, 100);
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "2"))
|
||||
{
|
||||
SetZombieVoiceVolume(param1, 80);
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "3"))
|
||||
{
|
||||
SetZombieVoiceVolume(param1, 60);
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "4"))
|
||||
{
|
||||
SetZombieVoiceVolume(param1, 40);
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "5"))
|
||||
{
|
||||
SetZombieVoiceVolume(param1, 20);
|
||||
ZombieVoiceVolumeMenu(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_Cancel:
|
||||
{
|
||||
if (param2 == MenuCancel_ExitBack)
|
||||
{
|
||||
VolumeControlMenu(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_End:
|
||||
{
|
||||
CloseHandle(menu);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetZombieVoiceVolume(client, volume)
|
||||
{
|
||||
zfZSoundVolume[client] = volume * 0.01;
|
||||
|
||||
decl String:sValue[8];
|
||||
IntToString(volume, sValue, sizeof(sValue));
|
||||
SetClientCookie(client, g_hZSoundVolumeCookie, sValue);
|
||||
|
||||
if (IsClientInGame(client))
|
||||
{
|
||||
TranslationPrintToChat(client, "Set_ZombieVoice_Volume", volume);
|
||||
}
|
||||
}
|
||||
|
||||
// Ambient Section
|
||||
/**
|
||||
* Command callback (sm_zambient, sm_ambient_volume)
|
||||
*/
|
||||
public Action:Command_ZAmbient(client, args)
|
||||
{
|
||||
if (args == 0)
|
||||
{
|
||||
AmbientVolumeMenu(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:sArg[32];
|
||||
GetCmdArg(1, sArg, sizeof(sArg));
|
||||
new iVolume = StringToInt(sArg);
|
||||
|
||||
if (iVolume < 0 || iVolume > 100)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Ambient_Usage");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
else if (0 <= iVolume <= 100)
|
||||
{
|
||||
SetAmbientVolume(client, iVolume);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
AmbientVolumeMenu(client)
|
||||
{
|
||||
new Handle:menu = CreateMenu(AmbientVolumeMenuHandler);
|
||||
|
||||
decl String:sMenuTitle[128];
|
||||
Format(sMenuTitle, sizeof(sMenuTitle), "%t\n%t", "Ambient_Title_Menu", RoundToNearest(zfAmbientVolume[client] * 100), "Ambient_CommandUsage");
|
||||
SetMenuTitle(menu, sMenuTitle);
|
||||
|
||||
AddMenuItem(menu, "1", "100%");
|
||||
AddMenuItem(menu, "2", "80%");
|
||||
AddMenuItem(menu, "3", "60%");
|
||||
AddMenuItem(menu, "4", "40%");
|
||||
AddMenuItem(menu, "5", "20%");
|
||||
|
||||
SetMenuExitBackButton(menu, true);
|
||||
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||
}
|
||||
|
||||
public AmbientVolumeMenuHandler(Handle:menu, MenuAction:action, param1, param2)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MenuAction_Select:
|
||||
{
|
||||
decl String:info[32];
|
||||
GetMenuItem(menu, param2, info, sizeof(info));
|
||||
if (StrEqual(info, "1", false))
|
||||
{
|
||||
SetAmbientVolume(param1, 100);
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "2"))
|
||||
{
|
||||
SetAmbientVolume(param1, 80);
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "3"))
|
||||
{
|
||||
SetAmbientVolume(param1, 60);
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "4"))
|
||||
{
|
||||
SetAmbientVolume(param1, 40);
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
else if (StrEqual(info, "5"))
|
||||
{
|
||||
SetAmbientVolume(param1, 20);
|
||||
AmbientVolumeMenu(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_Cancel:
|
||||
{
|
||||
if (param2 == MenuCancel_ExitBack)
|
||||
{
|
||||
VolumeControlMenu(param1);
|
||||
}
|
||||
}
|
||||
case MenuAction_End:
|
||||
{
|
||||
CloseHandle(menu);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetAmbientVolume(client, volume)
|
||||
{
|
||||
zfAmbientVolume[client] = volume * 0.01;
|
||||
|
||||
decl String:sValue[8];
|
||||
IntToString(volume, sValue, sizeof(sValue));
|
||||
SetClientCookie(client, g_hAmbientVolumeCookie, sValue);
|
||||
|
||||
if (IsClientInGame(client))
|
||||
{
|
||||
TranslationPrintToChat(client, "Set_Ambient_Volume", volume);
|
||||
}
|
||||
}
|
||||
+116
-2
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
#define ZMARKET_COOKIE_AUTOREBUY "zr_zmarket_autorebuy"
|
||||
#define ZMARKET_COOKIE_REBUY "zr_zmarket_rebuy"
|
||||
#define ZMARKET_COOKIE_RANDOMIZE "zr_zmarket_randomize"
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
@@ -39,6 +40,14 @@
|
||||
*/
|
||||
#define ZMARKET_REBUY_WEAPONS_SLOTS_MAX 1
|
||||
|
||||
|
||||
/**
|
||||
* 2026 randomization of zmarket guns for round start.
|
||||
*/
|
||||
new Handle:g_hZMarketRandomizeCookie = INVALID_HANDLE;
|
||||
new bool:g_bZMarketRandomize[MAXPLAYERS + 1];
|
||||
new String:g_sZMarketRandomHistoryPrimary[MAXPLAYERS + 1][3][WEAPONS_MAX_LENGTH];
|
||||
|
||||
/**
|
||||
* Array to store the client's current weapon type within menu.
|
||||
*/
|
||||
@@ -90,6 +99,12 @@ ZMarketOnCookiesCreate()
|
||||
g_hZMarketLoadoutCookie[x] = RegClientCookie(rebuycookiename, rebuycookiedesc, CookieAccess_Protected);
|
||||
}
|
||||
}
|
||||
|
||||
// Randomize toggle cookie.
|
||||
if (g_hZMarketRandomizeCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hZMarketRandomizeCookie = RegClientCookie(ZMARKET_COOKIE_RANDOMIZE, "Whether weapon randomization is enabled", CookieAccess_Protected);
|
||||
}
|
||||
}
|
||||
|
||||
ZMarketLoad()
|
||||
@@ -207,6 +222,12 @@ ZMarketClientInit(client)
|
||||
|
||||
// No weapons bought automatically.
|
||||
g_bZMarketWeaponsBought[client] = false;
|
||||
|
||||
// Clear randomize weapon history.
|
||||
for (new i = 0; i < 3; i++)
|
||||
{
|
||||
g_sZMarketRandomHistoryPrimary[client][i][0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,6 +237,10 @@ ZMarketClientInit(client)
|
||||
*/
|
||||
ZMarketOnCookiesCached(client)
|
||||
{
|
||||
decl String:value[4];
|
||||
GetClientCookie(client, g_hZMarketRandomizeCookie, value, sizeof(value));
|
||||
g_bZMarketRandomize[client] = (value[0] == '1');
|
||||
|
||||
// Rebuy wapons (if auto-rebuy is enabled, and not bought already).
|
||||
if (!g_bZMarketWeaponsBought[client])
|
||||
{
|
||||
@@ -371,6 +396,7 @@ bool:ZMarketMenuMain(client)
|
||||
decl String:editloadout[MENU_LINE_REG_LENGTH];
|
||||
decl String:rebuy[MENU_LINE_REG_LENGTH];
|
||||
decl String:weaponslist[MENU_LINE_REG_LENGTH];
|
||||
decl String:randomize[MENU_LINE_REG_LENGTH];
|
||||
|
||||
// Format menu options.
|
||||
Format(title, sizeof(title), "%t\n ", "Weapons menu zmarket main title");
|
||||
@@ -378,6 +404,7 @@ bool:ZMarketMenuMain(client)
|
||||
Format(editloadout, sizeof(editloadout), "%t", "Weapons menu zmarket main edit loadout");
|
||||
Format(rebuy, sizeof(rebuy), "%t", "Weapons menu zmarket main rebuy");
|
||||
Format(weaponslist, sizeof(weaponslist), "%t", "Weapons menu zmarket main weapons list");
|
||||
Format(randomize, sizeof(randomize), "Randomize Weapons: %s", g_bZMarketRandomize[client] ? "ON" : "OFF");
|
||||
|
||||
// Add formatted options to menu.
|
||||
SetMenuTitle(menu_zmarket_main, title);
|
||||
@@ -385,6 +412,7 @@ bool:ZMarketMenuMain(client)
|
||||
AddMenuItem(menu_zmarket_main, "Edit Loadout", editloadout, MenuGetItemDraw(zmarketrebuy || zmarketrebuyauto));
|
||||
AddMenuItem(menu_zmarket_main, "Rebuy", rebuy, MenuGetItemDraw(zmarketrebuy || zmarketrebuyauto));
|
||||
AddMenuItem(menu_zmarket_main, "Weapons List", weaponslist);
|
||||
AddMenuItem(menu_zmarket_main, "Randomize", randomize);
|
||||
|
||||
// Set exit back button.
|
||||
SetMenuExitBackButton(menu_zmarket_main, true);
|
||||
@@ -440,6 +468,18 @@ public ZMarketMenuMainHandle(Handle:menu_zmarket_main, MenuAction:action, client
|
||||
// Send the weapon types list.
|
||||
ZMarketMenuTypes(client);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
// Toggle randomize.
|
||||
g_bZMarketRandomize[client] = !g_bZMarketRandomize[client];
|
||||
|
||||
decl String:value[4];
|
||||
Format(value, sizeof(value), "%d", g_bZMarketRandomize[client] ? 1 : 0);
|
||||
SetClientCookie(client, g_hZMarketRandomizeCookie, value);
|
||||
PrintToChat(client, "Weapons zmarket randomize toggled: %s", g_bZMarketRandomize[client] ? "ON" : "OFF");
|
||||
|
||||
ZMarketMenuMain(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Client closed the menu.
|
||||
@@ -1305,6 +1345,75 @@ stock ZMarketSetRebuyCookie(client, WeaponsSlot:slot, const String:value[])
|
||||
CloseHandle(rebuycookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks a random weapon name from the given slot, avoiding the client's
|
||||
* last 3 picks for the primiary slot.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param slot Slot_Primary
|
||||
* @param buffer Output buffer for the weapon name.
|
||||
* @param maxlen Size of buffer.
|
||||
*/
|
||||
stock ZMarketGetRandomWeaponForSlot(client, WeaponsSlot:slot, String:buffer[], maxlen)
|
||||
{
|
||||
new Handle:candidates = CreateArray(WEAPONS_MAX_LENGTH);
|
||||
|
||||
new size = GetArraySize(arrayWeapons);
|
||||
decl String:weaponname[WEAPONS_MAX_LENGTH];
|
||||
|
||||
for (new i = 0; i < size; i++)
|
||||
{
|
||||
if (WeaponsGetSlot(i) != slot)
|
||||
continue;
|
||||
|
||||
WeaponsGetName(i, weaponname, sizeof(weaponname));
|
||||
|
||||
// Skip if restricted.
|
||||
if (RestrictIsWeaponRestricted(i))
|
||||
continue;
|
||||
|
||||
// Skip if in the client's last-3 history for this slot.
|
||||
new bool:inHistory = false;
|
||||
for (new h = 0; h < 3; h++)
|
||||
{
|
||||
decl String:histEntry[WEAPONS_MAX_LENGTH];
|
||||
if (slot == Slot_Primary)
|
||||
strcopy(histEntry, sizeof(histEntry), g_sZMarketRandomHistoryPrimary[client][h]);
|
||||
if (StrEqual(histEntry, weaponname))
|
||||
{
|
||||
inHistory = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inHistory)
|
||||
continue;
|
||||
|
||||
PushArrayString(candidates, weaponname);
|
||||
}
|
||||
|
||||
new candidateCount = GetArraySize(candidates);
|
||||
|
||||
if (candidateCount == 0)
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
CloseHandle(candidates);
|
||||
return;
|
||||
}
|
||||
|
||||
new pick = Math_GetRandomInt(0, candidateCount - 1);
|
||||
GetArrayString(candidates, pick, buffer, maxlen);
|
||||
CloseHandle(candidates);
|
||||
|
||||
// Push into history (shift, then insert at front).
|
||||
if (slot == Slot_Primary)
|
||||
{
|
||||
strcopy(g_sZMarketRandomHistoryPrimary[client][2], WEAPONS_MAX_LENGTH, g_sZMarketRandomHistoryPrimary[client][1]);
|
||||
strcopy(g_sZMarketRandomHistoryPrimary[client][1], WEAPONS_MAX_LENGTH, g_sZMarketRandomHistoryPrimary[client][0]);
|
||||
strcopy(g_sZMarketRandomHistoryPrimary[client][0], WEAPONS_MAX_LENGTH, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a client to rebuy their weapons.
|
||||
*
|
||||
@@ -1340,9 +1449,14 @@ ZMarketRebuy(client, bool:autorebuy = false)
|
||||
// x = Weapon slot.
|
||||
for (new x = 0; x < ZMARKET_REBUY_WEAPONS_SLOTS_MAX + 1; x++)
|
||||
{
|
||||
// If slot is empty, then use the default value.
|
||||
if (!rebuyweapons[x][0])
|
||||
// If randomize is enabled, override any saved loadout for primary/secondary.
|
||||
if (g_bZMarketRandomize[client] && (x == Slot_Primary || x == Slot_Secondary))
|
||||
{
|
||||
ZMarketGetRandomWeaponForSlot(client, WeaponsSlot:x, rebuyweapons[x], sizeof(rebuyweapons[]));
|
||||
}
|
||||
else if (!rebuyweapons[x][0])
|
||||
{
|
||||
// No saved loadout, fall back to cvar default.
|
||||
switch(x)
|
||||
{
|
||||
case Slot_Primary:
|
||||
|
||||
Reference in New Issue
Block a user