Member
|
03-25-2021
, 23:01
problem with Galileo choice map
|
#1
|
Galileo use. At the moment of the voting of maps, the voting menu does not appear to all users. solution?
galileo.cfg
Quote:
// Galileo Configuration File
// $Revision: 286 $ $Date: 2009-02-18 21:493 -0500 (Wed, 18 Feb 2009) $
echo Executing Galileo (GAL) Configuration File
////////////////////////////////////////////////////////////////////////
// Allowing an extension of the current map's time limit will add an //
// "extend the map" option to map votes which, if the option wins, //
// will increase the time limit by a predetermined amount, letting //
// players stay on the current map longer. //
////////////////////////////////////////////////////////////////////////
// Specifies the maximum number of minutes a map can be played, if it
// has been extended. A value less than mp_timelimit will not let the
// map be extended.
amx_extendmap_max 90
// Specifies the number of minutes a map will be extended each time
// the "Extend Map" option wins the map vote.
amx_extendmap_step 15
////////////////////////////////////////////////////////////////////////
// There are two standard HL1 map related commands that you may not //
// want to function normally, if at all, when using this plugin, so //
// as to avoid conflicts of map voting procedures. //
////////////////////////////////////////////////////////////////////////
// Indicates how the standard HL1 "votemap" command should function.
// 0 - disable
// 1 - behave normally
gal_cmd_votemap 1
// Indicates how the standard HL1 "listmaps" command should function.
// 0 - disable
// 1 - behave normally
// 2 - behave the same as the "gal_listmaps" command (galileo default)
gal_cmd_listmaps 2
////////////////////////////////////////////////////////////////////////
// Banning recently played maps means that the last several maps that //
// have been played can not be nominated or otherwise placed in the //
// map vote. This ensures that a map can not be played over and over //
// again at the expense of playing a variety of other maps. //
////////////////////////////////////////////////////////////////////////
// Specifies how many of the most recent maps are disallowed from a
// map vote. A value of 0 will disable this feature.
gal_banrecent 3
// Indicates the style in which the recent maps are displayed when a
// player uses the "recentmaps" say command.
// 1 - all maps on one line
// 2 - each map on a separate line
gal_banrecentstyle 2
////////////////////////////////////////////////////////////////////////
// Rocking the vote is a way players can indicate their desire to //
// start an early map vote to change maps. Once enough players have //
// rocked it, a vote will begin. //
////////////////////////////////////////////////////////////////////////
// Indicates which say commands can be used to rock the vote.
// The flags are additive. A value of 0 will disable this feature.
// 1 - standard "rockthevote" command
// 2 - shorthand "rtv" command
// 4 - dynamic "rockthe<anything>vote" command (allows a player to type
// any one word (i.e. no spaces) that starts with "rockthe" and ends
// with "vote". Some examples might be: "rockthedamnvote",
// "rockthesillylittlevote", or "rockthefreakingvote". The total
// length of the word can not be longer than 31 characters. That
// leaves 20 characters for creativeness once you factor in the
// lengths of "rockthe" and "vote")
gal_rtv_commands 2
// Specifies the number of minutes after a map starts that players
// have to wait before they can rock the vote. When a single player
// is on the server, that player can rock the vote at any time,
// regardless of this setting.
gal_rtv_wait 0
// Specifies the ratio of players that need to rock the vote before a
// vote will be forced to occur. When a single player is on the server,
// that player can rock the vote and start an immediate vote.
gal_rtv_ratio 0.60
// Specifies how often, in minutes, to remind everyone how many more
// rocks are still needed, after the last rock has been made.
// A value of 0 will disable this feature.
gal_rtv_reminder 2
////////////////////////////////////////////////////////////////////////
// Nominations can be used to let players nominate maps they would //
// like included in the next map vote. Depending on how many maps //
// have been nominated, it is possible that not all nominations will //
// make it into the next vote. //
////////////////////////////////////////////////////////////////////////
// Specifies how many nominations each player can make.
// There is a hard cap defined, MAX_NOMINATION_CNT, that is set to 5
// in the SMA. It can be changed, if needed.
// This CVAR needs to be set equal to or less than the hard cap.
// A value of 0 will disable this feature.
gal_nom_playerallowance 2
// Specifies the file to use which holds the names of the maps, listed
// one per line, that players can nominate. Use * for all maps in the
// server's maps folder.
// You can specify a relative path before the filename, relative from
// your gamemod folder (i.e. /addons/amxmodx/configs/mymapcycle1.txt).
gal_nom_mapfile mapcycle1.txt
// Indicates if the ./amxmodx/configs/galileo/prefixes.ini file should
// be used to attempt to match map names if the player's entered
// text doesn't match any.
gal_nom_prefixes 0
// Specifies how many of the nominations made will be
// considered for use in the next map vote.
// A value of 0 means all the nominated maps will be considered.
gal_nom_qtyused 0
////////////////////////////////////////////////////////////////////////
// Runoff voting happens when none of the normal vote options receive //
// over 50% of a given vote. The two options with the highest vote //
// counts will be in the runoff vote. //
////////////////////////////////////////////////////////////////////////
// Indicates whether to allow runoff voting or not.
// 0 - disable runoff voting
// 1 - enable runoff voting
gal_runoff_enabled 1
// Specifies the number of seconds the runoff vote should last.
gal_runoff_duration 15
////////////////////////////////////////////////////////////////////////
// Weighted votes allows admins to have their vote counted as more //
// than a regular player's vote. //
////////////////////////////////////////////////////////////////////////
// Specifies how many votes a single admin vote should count as.
// A value of 0 or 1 will disable this feature.
gal_vote_weight 0
// Specifies the standard access flags needed to have weighted votes.
// You can specify multiple flags.
gal_vote_weightflags y
////////////////////////////////////////////////////////////////////////
// Ending a map on a new round after time has expired, for round- //
// based mods, is a much nicer way of ending the current map than the //
// standard HL1 way, which is to suddenly end the map the second time //
// runs out. //
////////////////////////////////////////////////////////////////////////
// Indicates when a map should end when time runs out.
// 0 - end immediately when time runs out
// 1 - when time runs out, end after the current round
gal_endonround 1
////////////////////////////////////////////////////////////////////////
// By showing the status of the vote, you allow players to see how //
// many votes the various choices received. //
////////////////////////////////////////////////////////////////////////
// Indicates when the vote progress should be shown to a player.
// A value of 0 disables this feature.
// 0 - never
// 1 - after player has voted
// 2 - after the vote ends
gal_vote_showstatus 1
// Indicates how to show the progress of a vote.
// 1 - as vote count
// 2 - as percentage of all votes cast
gal_vote_showstatustype 1
////////////////////////////////////////////////////////////////////////
// Server restarts could be due to a benign reason or could be due to //
// a map that just crashed the server. In any case, you can specify //
// what happens when the server restarts. //
////////////////////////////////////////////////////////////////////////
// Indicates which action to take when it is detected
// that the server has been restarted.
// 0 - stay on the map the server started with
// 1 - change to the map that was being played when the server was reset
// 2 - change to what would have been the next map had the server not
// been restarted (if the next map isn't known, this acts like 3)
// 3 - start an early map vote after the first two minutes
// 4 - change to a randomly selected map from your nominatable map list
gal_srv_start 1
////////////////////////////////////////////////////////////////////////
// Some people like to stick to their defined map cycle unless a vote //
// is started in the meantime. Other people like to always have a //
// vote near the end of the map to decide what the next map will be. //
////////////////////////////////////////////////////////////////////////
// Indicates whether there should be a vote near the end
// of the map to decide what the next map will be.
gal_endofmapvote 1
////////////////////////////////////////////////////////////////////////
// Paginating the map listings displayed from the gal_listmaps //
// console command will prevent players from getting kicked when you //
// are listing a large number of maps. When paginated, the listings //
// will only display a portion of the total map list at a time. //
////////////////////////////////////////////////////////////////////////
// Specifies how many maps per "page" to show when using
// the gal_listmaps console command.
// Setting it to 0 will not paginate the map listing.
// Pagination will be in the style of the amx_help command.
gal_listmaps_paginate 30
////////////////////////////////////////////////////////////////////////
// Primary voting is what most people generally think of when they //
// think of starting a vote for a new map. It's just your standard //
// map vote. //
////////////////////////////////////////////////////////////////////////
// Specifies the number of maps players can choose from during the vote.
// The number of maps must be between 2 and 8.
gal_vote_mapchoices 3
// Specifies the number of seconds the vote should last.
gal_vote_duration 15
// Specifies the file to use which either holds the names of the maps,
// one per line, that the vote will be filled with or is used in the
// map group feature to specify how many maps to use from each group.
// You can specify a relative path before the filename, relative from
// your gamemod folder (i.e. /addons/amxmodx/configs/mymapcycle1.txt).
gal_vote_mapfile "/addons/amxmodx/configs/mymapcycle1.txt"
// Indicates whether the maps being added, after nominations have been
// added to a vote, should have unique map prefixes from those already
// in the vote.
gal_vote_uniqueprefixes 0
////////////////////////////////////////////////////////////////////////
// The vote expiration countdown begins display a timer, to players //
// that haven't voted, when there are 10 seconds left in the current //
// vote. The timer counts down from 10 to 0, at which point the vote //
// will be over. //
////////////////////////////////////////////////////////////////////////
// Indicates whether a vote expiration countdown should be displayed.
// 0 - do not show the countdown
// 1 - show the countdown
gal_vote_expirationcountdown 1
////////////////////////////////////////////////////////////////////////
// When the player's choice is announced, everyone on the server is //
// shown what every other player's selection was. //
////////////////////////////////////////////////////////////////////////
// Indicates whether to announce each player's choice.
// 0 - keep the player's choice private
// 1 - announce the player's choice
gal_vote_announcechoice 1
////////////////////////////////////////////////////////////////////////
// You may have a lot of maps but only a few are sure to attract a //
// lot of players. When the server is empty, you may want the server //
// to change to those maps. //
////////////////////////////////////////////////////////////////////////
// Specifies how many minutes to wait, when the server is empty, before
// changing to an alternate empty-server map cycle.
// A value of 0 disables this feature.
gal_emptyserver_wait 10
// Specifies the file which contains a listing of maps, one per line,
// to be used as the map cycle when the server is empty.
// You can specify a relative path before the filename, relative from
// your gamemod folder (i.e. /addons/amxmodx/configs/mymapcycle1.txt).
gal_emptyserver_mapfile "/addons/amxmodx/configs/emptycycle.txt"
////////////////////////////////////////////////////////////////////////
// There will be words spoken during certain events to reinenforce, //
// in a player's mind, what is happening. You may choose to mute any //
// that you would rather not have spoken. //
////////////////////////////////////////////////////////////////////////
// Indicates if any sounds should be muted during the various events in
// which they'd normal be spoken.
// The flags are additive. A value of 0 will not mute any of the sounds.
// 1 - "get ready to choose a map"
// 2 - "7", "6", "5", "4", "3", "2", "1"
// 4 - "time to choose"
// 8 - "runoff voting is required"
gal_sounds_mute 1
|
galileo.sma
Code:
new const PLUGIN_VERSION[] = "1.1 $Revision: 290 $"; // $Date: 2009-02-26 11:20:25 -0500 (Thu, 26 Feb 2009) $;
#include <amxmodx>
#include <amxmisc>
#pragma semicolon 1
#define TASKID_EMPTYSERVER 98176977
#define TASKID_REMINDER 52691153
#define RTV_CMD_STANDARD 1
#define RTV_CMD_SHORTHAND 2
#define RTV_CMD_DYNAMIC 4
#define SOUND_GETREADYTOCHOOSE 0
#define SOUND_COUNTDOWN 2
#define SOUND_TIMETOCHOOSE 4
#define SOUND_RUNOFFREQUIRED 8
#define MAPFILETYPE_SINGLE 1
#define MAPFILETYPE_GROUPS 2
#define SHOWSTATUS_VOTE 1
#define SHOWSTATUS_END 2
#define SHOWSTATUSTYPE_COUNT 1
#define SHOWSTATUSTYPE_PERCENTAGE 2
#define ANNOUNCECHOICE_PLAYERS 1
#define ANNOUNCECHOICE_ADMINS 2
#define MAX_NOMINATION_CNT 5
#define MAX_PREFIX_CNT 32
#define MAX_RECENT_MAP_CNT 16
#define MAX_PLAYER_CNT 32
#define MAX_STANDARD_MAP_CNT 25
#define MAX_MAPNAME_LEN 31
#define MAX_MAPS_IN_VOTE 8
#define MAX_NOM_MATCH_CNT 1000
#define VOTE_IN_PROGRESS 1
#define VOTE_FORCED 2
#define VOTE_IS_RUNOFF 4
#define VOTE_IS_OVER 8
#define VOTE_IS_EARLY 16
#define VOTE_HAS_EXPIRED 32
#define SRV_START_CURRENTMAP 1
#define SRV_START_NEXTMAP 2
#define SRV_START_MAPVOTE 3
#define SRV_START_RANDOMMAP 4
#define LISTMAPS_USERID 0
#define LISTMAPS_LAST 1
#define TIMELIMIT_NOT_SET -1.0
new MENU_CHOOSEMAP[] = "gal_menuChooseMap";
new DIR_CONFIGS[64];
new DIR_DATA[64];
new CLR_RED[3]; // \r
new CLR_WHITE[3]; // \w
new CLR_YELLOW[3]; // \y
new CLR_GREY[3]; // \d
new bool:g_wasLastRound = false;
new g_mapPrefix[MAX_PREFIX_CNT][16], g_mapPrefixCnt = 1;
new g_currentMap[MAX_MAPNAME_LEN+1], Float:g_originalTimelimit = TIMELIMIT_NOT_SET;
new g_nomination[MAX_PLAYER_CNT + 1][MAX_NOMINATION_CNT + 1], g_nominationCnt, g_nominationMatchesMenu[MAX_PLAYER_CNT];
//new g_nonOverlapHudSync;
new g_voteWeightFlags[32];
new Array:g_emptyCycleMap, bool:g_isUsingEmptyCycle = false, g_emptyMapCnt = 0;
new Array:g_mapCycle1;
new g_recentMap[MAX_RECENT_MAP_CNT][MAX_MAPNAME_LEN + 1], g_cntRecentMap;
new Array:g_nominationMap, g_nominationMapCnt;
new Array:g_fillerMap;
new Float:g_rtvWait;
new bool:g_rockedVote[MAX_PLAYER_CNT + 1], g_rockedVoteCnt;
new g_mapChoice[MAX_MAPS_IN_VOTE + 1][MAX_MAPNAME_LEN + 1], g_choiceCnt, g_choiceMax;
new bool:g_voted[MAX_PLAYER_CNT + 1] = {true, ...}, g_mapVote[MAX_MAPS_IN_VOTE + 1];
new g_voteStatus, g_voteDuration, g_votesCast;
new g_runoffChoice[2];
new g_vote[512];
new bool:g_handleMapChange = true;
new g_refreshVoteStatus = true, g_voteTallyType[3], g_snuffDisplay[MAX_PLAYER_CNT + 1];
new g_menuChooseMap;
new g_pauseMapEndVoteTask, g_pauseMapEndManagerTask;
new cvar_extendmapMax, cvar_extendmapStep;
new cvar_endOnRound, cvar_endOfMapVote;
new cvar_rtvWait, cvar_rtvRatio, cvar_rtvCommands;
new cvar_cmdVotemap, cvar_cmdListmaps, cvar_listmapsPaginate;
new cvar_banRecent, cvar_banRecentStyle, cvar_voteDuration;
new cvar_nomMapFile, cvar_nomPrefixes;
new cvar_nomQtyUsed, cvar_nomPlayerAllowance;
new cvar_voteExpCountdown, cvar_voteWeightFlags, cvar_voteWeight;
new cvar_voteMapChoiceCnt, cvar_voteAnnounceChoice, cvar_voteUniquePrefixes;
new cvar_voteMapFile, cvar_rtvReminder;
new cvar_srvStart;
new cvar_emptyWait, cvar_emptyMapFile, cvar_emptyCycle;
new cvar_runoffEnabled, cvar_runoffDuration;
new cvar_voteStatus, cvar_voteStatusType;
new cvar_soundsMute;
public plugin_init()
{
// build version information
new jnk[1], version[8], rev[8];
parse(PLUGIN_VERSION, version, sizeof(version)-1, jnk, sizeof(jnk)-1, rev, sizeof(rev)-1, jnk, sizeof(jnk)-1);
new pluginVersion[16];
formatex(pluginVersion, sizeof(pluginVersion)-1, "%s.%s", version, rev);
register_plugin("Galileo", pluginVersion, "Brad Jones");
register_cvar("gal_version", pluginVersion, FCVAR_SERVER|FCVAR_SPONLY);
set_cvar_string("gal_version", pluginVersion);
register_cvar("gal_server_starting", "1", FCVAR_SPONLY);
cvar_emptyCycle = register_cvar("gal_in_empty_cycle", "0", FCVAR_SPONLY);
register_cvar("gal_debug", "0");
register_dictionary("common.txt");
register_dictionary("nextmap.txt");
register_dictionary("galileo.txt");
if (module_exists("cstrike"))
{
register_event("HLTV", "event_round_start", "a", "1=0", "2=0");
}
else if (module_exists("dodx"))
{
register_event("RoundState", "event_round_start", "a", "1=1");
}
register_event("TextMsg", "event_game_commencing", "a", "2=#Game_Commencing", "2=#Game_will_restart_in");
register_event("30", "event_intermission", "a");
g_menuChooseMap = register_menuid(MENU_CHOOSEMAP);
register_menucmd(g_menuChooseMap, MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9|MENU_KEY_0, "vote_handleChoice");
register_clcmd("say", "cmd_say", -1);
register_clcmd("say nextmap", "cmd_nextmap", 0, "- displays nextmap");
register_clcmd("say currentmap", "cmd_currentmap", 0, "- display current map");
register_clcmd("say ff", "cmd_ff", 0, "- display friendly fire status"); // grrface
register_clcmd("votemap", "cmd_HL1_votemap");
register_clcmd("listmaps", "cmd_HL1_listmaps");
register_concmd("say startvote", "cmd_startVote", ADMIN_MAP);
register_concmd("gal_createmapfile", "cmd_createMapFile", ADMIN_RCON);
register_cvar("amx_nextmap", "", FCVAR_SERVER|FCVAR_EXTDLL|FCVAR_SPONLY);
cvar_extendmapMax = register_cvar("amx_extendmap_max", "90");
cvar_extendmapStep = register_cvar("amx_extendmap_step", "15");
cvar_cmdVotemap = register_cvar("gal_cmd_votemap", "0");
cvar_cmdListmaps = register_cvar("gal_cmd_listmaps", "2");
cvar_listmapsPaginate = register_cvar("gal_listmaps_paginate", "10");
cvar_banRecent = register_cvar("gal_banrecent", "3");
cvar_banRecentStyle = register_cvar("gal_banrecentstyle", "1");
cvar_endOnRound = register_cvar("gal_endonround", "1");
cvar_endOfMapVote = register_cvar("gal_endofmapvote", "1");
cvar_emptyWait = register_cvar("gal_emptyserver_wait", "0");
cvar_emptyMapFile = register_cvar("gal_emptyserver_mapfile", "");
cvar_srvStart = register_cvar("gal_srv_start", "0");
cvar_rtvCommands = register_cvar("gal_rtv_commands", "3");
cvar_rtvWait = register_cvar("gal_rtv_wait", "10");
cvar_rtvRatio = register_cvar("gal_rtv_ratio", "0.60");
cvar_rtvReminder = register_cvar("gal_rtv_reminder", "2");
cvar_nomPlayerAllowance = register_cvar("gal_nom_playerallowance", "2");
cvar_nomMapFile = register_cvar("gal_nom_mapfile", "mapcycle1");
cvar_nomPrefixes = register_cvar("gal_nom_prefixes", "1");
cvar_nomQtyUsed = register_cvar("gal_nom_qtyused", "0");
cvar_voteWeight = register_cvar("gal_vote_weight", "2");
cvar_voteWeightFlags = register_cvar("gal_vote_weightflags", "y");
cvar_voteMapFile = register_cvar("gal_vote_mapfile", "mapcycle1.txt");
cvar_voteDuration = register_cvar("gal_vote_duration", "15");
cvar_voteExpCountdown = register_cvar("gal_vote_expirationcountdown", "1");
cvar_voteMapChoiceCnt = register_cvar("gal_vote_mapchoices", "5");
cvar_voteAnnounceChoice = register_cvar("gal_vote_announcechoice", "1");
cvar_voteStatus = register_cvar("gal_vote_showstatus", "1");
cvar_voteStatusType = register_cvar("gal_vote_showstatustype", "2");
cvar_voteUniquePrefixes = register_cvar("gal_vote_uniqueprefixes", "0");
cvar_runoffEnabled = register_cvar("gal_runoff_enabled", "0");
cvar_runoffDuration = register_cvar("gal_runoff_duration", "10");
cvar_soundsMute = register_cvar("gal_sounds_mute", "0");
//set_task(1.0, "dbg_test",_,_,_,"a", 15);
}
public dbg_fakeVotes()
{
if (!(g_voteStatus & VOTE_IS_RUNOFF))
{
g_mapVote[0] += 2; // map 1
g_mapVote[1] += 0; // map 2
g_mapVote[2] += 6; // map 3
g_mapVote[3] += 0; // map 4
g_mapVote[4] += 0; // map 5
g_mapVote[5] += 4; // extend option
g_votesCast = g_mapVote[0] + g_mapVote[1] + g_mapVote[2] + g_mapVote[3] + g_mapVote[4] + g_mapVote[5];
}
else if (g_voteStatus & VOTE_IS_RUNOFF)
{
g_mapVote[0] += 1; // choice 1
g_mapVote[1] += 0; // choice 2
g_votesCast = g_mapVote[0] + g_mapVote[1];
}
}
public plugin_cfg()
{
formatex(DIR_CONFIGS[get_configsdir(DIR_CONFIGS, sizeof(DIR_CONFIGS)-1)], sizeof(DIR_CONFIGS)-1, "/galileo");
formatex(DIR_DATA[get_datadir(DIR_DATA, sizeof(DIR_DATA)-1)], sizeof(DIR_DATA)-1, "/galileo");
server_cmd("exec %s/galileo.cfg", DIR_CONFIGS);
server_exec();
if (colored_menus())
{
copy(CLR_RED, 2, "\r");
copy(CLR_WHITE, 2, "\w");
copy(CLR_YELLOW, 2, "\y");
}
g_rtvWait = get_pcvar_float(cvar_rtvWait);
get_pcvar_string(cvar_voteWeightFlags, g_voteWeightFlags, sizeof(g_voteWeightFlags)-1);
get_mapname(g_currentMap, sizeof(g_currentMap)-1);
g_choiceMax = max(min(MAX_MAPS_IN_VOTE, get_pcvar_num(cvar_voteMapChoiceCnt)), 2);
// g_nonOverlapHudSync = CreateHudSyncObj();
g_fillerMap = ArrayCreate(32);
g_nominationMap = ArrayCreate(32);
// initialize nominations table
nomination_clearAll();
if (get_pcvar_num(cvar_banRecent))
{
register_clcmd("say recentmaps", "cmd_listrecent", 0);
map_loadRecentList();
if (!(get_cvar_num("gal_server_starting") && get_pcvar_num(cvar_srvStart)))
{
map_writeRecentList();
}
}
if (get_pcvar_num(cvar_rtvCommands) & RTV_CMD_STANDARD)
{
register_clcmd("say rockthevote", "cmd_rockthevote", 0);
}
if (get_pcvar_num(cvar_nomPlayerAllowance))
{
register_concmd("gal_listmaps", "cmd_listmaps");
register_clcmd("say nominations", "cmd_nominations", 0, "- displays current nominations for next map");
if (get_pcvar_num(cvar_nomPrefixes))
{
map_loadPrefixList();
}
map_loadNominationList();
}
new mapName[32];
get_mapname(mapName, 31);
dbg_log(6, "[%s]", mapName);
dbg_log(6, "");
if (get_cvar_num("gal_server_starting"))
{
srv_handleStart();
}
set_task(10.0, "vote_setupEnd");
if (get_pcvar_num(cvar_emptyWait))
{
g_emptyCycleMap = ArrayCreate(32);
map_loadEmptyCycleList();
set_task(60.0, "srv_initEmptyCheck");
}
}
public plugin_end()
{
map_restoreOriginalTimeLimit();
}
public vote_setupEnd()
{
dbg_log(4, "%32s mp_timelimit: %f g_originalTimelimit: %f", "vote_setupEnd(in)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
g_originalTimelimit = get_cvar_float("mp_timelimit");
new nextMap[32];
if (get_pcvar_num(cvar_endOfMapVote))
{
formatex(nextMap, sizeof(nextMap)-1, "%L", LANG_SERVER, "GAL_NEXTMAP_UNKNOWN");
}
else
{
g_mapCycle1 = ArrayCreate(32);
map_populateList(g_mapCycle1, "mapcycle1.txt");
map_getNext(g_mapCycle1, g_currentMap, nextMap);
}
map_setNext(nextMap);
// as long as the time limit isn't set to 0, we can manage the end of the map automatically
if (g_originalTimelimit)
{
set_task(15.0, "vote_manageEnd", _, _, _, "b");
}
dbg_log(2, "%32s mp_timelimit: %f g_originalTimelimit: %f", "vote_setupEnd(out)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
}
map_getNext(Array:mapArray, currentMap[], nextMap[32])
{
new thisMap[32], mapCnt = ArraySize(mapArray), nextmapIdx = 0, returnVal = -1;
for (new mapIdx = 0; mapIdx < mapCnt; mapIdx++)
{
ArrayGetString(mapArray, mapIdx, thisMap, sizeof(thisMap)-1);
if (equal(currentMap, thisMap))
{
nextmapIdx = (mapIdx == mapCnt - 1) ? 0 : mapIdx + 1;
returnVal = nextmapIdx;
break;
}
}
ArrayGetString(mapArray, nextmapIdx, nextMap, sizeof(nextMap)-1);
return returnVal;
}
public srv_handleStart()
{
// this is the key that tells us if this server has been restarted or not
set_cvar_num("gal_server_starting", 0);
// take the defined "server start" action
new startAction = get_pcvar_num(cvar_srvStart);
if (startAction)
{
new nextMap[32];
if (startAction == SRV_START_CURRENTMAP || startAction == SRV_START_NEXTMAP)
{
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/info.dat", DIR_DATA);
new file = fopen(filename, "rt");
if (file) // !feof(file)
{
fgets(file, nextMap, sizeof(nextMap)-1);
if (startAction == SRV_START_NEXTMAP)
{
nextMap[0] = 0;
fgets(file, nextMap, sizeof(nextMap)-1);
}
}
fclose(file);
}
else if (startAction == SRV_START_RANDOMMAP)
{
// pick a random map from allowable nominations
// if noms aren't allowed, the nomination list hasn't already been loaded
if (get_pcvar_num(cvar_nomPlayerAllowance) == 0)
{
map_loadNominationList();
}
if (g_nominationMapCnt)
{
ArrayGetString(g_nominationMap, random_num(0, g_nominationMapCnt - 1), nextMap, sizeof(nextMap)-1);
}
}
trim(nextMap);
if (nextMap[0] && is_map_valid(nextMap))
{
server_cmd("changelevel %s", nextMap);
}
else
{
vote_manageEarlyStart();
}
}
}
vote_manageEarlyStart()
{
g_voteStatus |= VOTE_IS_EARLY;
set_task(120.0, "vote_startDirector");
}
map_setNext(nextMap[])
{
// set the queryable cvar
set_cvar_string("amx_nextmap", nextMap);
// update our data file
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/info.dat", DIR_DATA);
new file = fopen(filename, "wt");
if (file)
{
fprintf(file, "%s", g_currentMap);
fprintf(file, "^n%s", nextMap);
fclose(file);
}
else
{
//error
}
}
public vote_manageEnd()
{
new secondsLeft = get_timeleft();
// are we ready to start an "end of map" vote?
if (secondsLeft < 150 && secondsLeft > 90 && !g_pauseMapEndVoteTask && get_pcvar_num(cvar_endOfMapVote) && !get_pcvar_num(cvar_emptyCycle))
{
vote_startDirector(false);
}
// are we managing the end of the map?
if (secondsLeft < 20 && !g_pauseMapEndManagerTask)
{
map_manageEnd();
}
}
public map_loadRecentList()
{
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/recentmaps.dat", DIR_DATA);
new file = fopen(filename, "rt");
if (file)
{
new buffer[32];
while (!feof(file))
{
fgets(file, buffer, sizeof(buffer)-1);
trim(buffer);
if (buffer[0])
{
if (g_cntRecentMap == get_pcvar_num(cvar_banRecent))
{
break;
}
copy(g_recentMap[g_cntRecentMap++], sizeof(buffer)-1, buffer);
}
}
fclose(file);
}
}
public map_writeRecentList()
{
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/recentmaps.dat", DIR_DATA);
new file = fopen(filename, "wt");
if (file)
{
fprintf(file, "%s", g_currentMap);
for (new idxMap = 0; idxMap < get_pcvar_num(cvar_banRecent) - 1; ++idxMap)
{
fprintf(file, "^n%s", g_recentMap[idxMap]);
}
fclose(file);
}
}
public map_loadFillerList(filename[])
{
return map_populateList(g_fillerMap, filename);
}
public cmd_rockthevote(id)
{
client_print(id, print_chat, "%L", id, "GAL_CMD_RTV");
vote_rock(id);
return PLUGIN_CONTINUE;
}
public cmd_nominations(id)
{
client_print(id, print_chat, "%L", id, "GAL_CMD_NOMS");
nomination_list(id);
return PLUGIN_CONTINUE;
}
public cmd_nextmap(id)
{
new map[32];
get_cvar_string("amx_nextmap", map, sizeof(map)-1);
client_print(0, print_chat, "%L %s", LANG_PLAYER, "NEXT_MAP", map);
return PLUGIN_CONTINUE;
}
public cmd_currentmap(id)
{
client_print(0, print_chat, "%L: %s", LANG_PLAYER, "PLAYED_MAP", g_currentMap);
return PLUGIN_CONTINUE;
}
public cmd_listrecent(id)
{
switch (get_pcvar_num(cvar_banRecentStyle))
{
case 1:
{
new msg[101], msgIdx;
for (new idx = 0; idx < g_cntRecentMap; ++idx)
{
msgIdx += format(msg[msgIdx], sizeof(msg)-1-msgIdx, ", %s", g_recentMap[idx]);
}
client_print(0, print_chat, "%L: %s", LANG_PLAYER, "GAL_MAP_RECENTMAPS", msg[2]);
}
case 2:
{
for (new idx = 0; idx < g_cntRecentMap; ++idx)
{
client_print(0, print_chat, "%L (%i): %s", LANG_PLAYER, "GAL_MAP_RECENTMAP", idx+1, g_recentMap[idx]);
}
}
}
return PLUGIN_HANDLED;
}
public cmd_startVote(id, level, cid)
{
if (!cmd_access(id, level, cid, 1))
return PLUGIN_HANDLED;
if (g_voteStatus & VOTE_IN_PROGRESS)
{
client_print(id, print_chat, "%L", id, "GAL_VOTE_INPROGRESS");
}
else if (g_voteStatus & VOTE_IS_OVER)
{
client_print(id, print_chat, "%L", id, "GAL_VOTE_ENDED");
}
else
{
// we may not want to actually change the map after outcome of vote is determined
if (read_argc() == 2)
{
new arg[32];
read_args(arg, sizeof(arg)-1);
if (equali(arg, "-nochange"))
{
g_handleMapChange = false;
}
}
vote_startDirector(true);
}
return PLUGIN_HANDLED;
}
map_populateList(Array:mapArray, mapFilename[])
{
// clear the map array in case we're reusing it
ArrayClear(mapArray);
// load the array with maps
new mapCnt;
if (!equal(mapFilename, "*"))
{
new file = fopen(mapFilename, "rt");
if (file)
{
new buffer[32];
while (!feof(file))
{
fgets(file, buffer, sizeof(buffer)-1);
trim(buffer);
if (buffer[0] && !equal(buffer, "//", 2) && !equal(buffer, ";", 1) && is_map_valid(buffer))
{
ArrayPushString(mapArray, buffer);
++mapCnt;
}
}
fclose(file);
}
else
{
log_error(AMX_ERR_NOTFOUND, "%L", LANG_SERVER, "GAL_MAPS_FILEMISSING", mapFilename);
}
}
else
{
// no file provided, assuming contents of "maps" folder
new dir, mapName[32];
dir = open_dir("maps", mapName, sizeof(mapName)-1);
if (dir)
{
new lenMapName;
while (next_file(dir, mapName, sizeof(mapName)-1))
{
lenMapName = strlen(mapName);
if (lenMapName > 4 && equali(mapName[lenMapName - 4], ".bsp", 4))
{
mapName[lenMapName-4] = '^0';
if (is_map_valid(mapName))
{
ArrayPushString(mapArray, mapName);
++mapCnt;
}
}
}
close_dir(dir);
}
else
{
// directory not found, wtf?
log_error(AMX_ERR_NOTFOUND, "%L", LANG_SERVER, "GAL_MAPS_FOLDERMISSING");
}
}
return mapCnt;
}
public map_loadNominationList()
{
new filename[256];
get_pcvar_string(cvar_nomMapFile, filename, sizeof(filename)-1);
g_nominationMapCnt = map_populateList(g_nominationMap, filename);
}
// grrface, this has no place in a map choosing plugin. just replicating it because it's in AMXX's
public cmd_ff()
{
client_print(0, print_chat, "%L: %L", LANG_PLAYER, "FRIEND_FIRE", LANG_PLAYER, get_cvar_num("mp_friendlyfire") ? "ON" : "OFF");
return PLUGIN_CONTINUE;
}
public cmd_createMapFile(id, level, cid)
{
if (!cmd_access(id, level, cid, 1))
return PLUGIN_HANDLED;
new cntArg = read_argc() - 1;
switch (cntArg)
{
case 1:
{
new arg1[256];
read_argv(1, arg1, sizeof(arg1)-1);
remove_quotes(arg1);
new mapName[MAX_MAPNAME_LEN+5]; // map name is 31 (i.e. MAX_MAPNAME_LEN), ".bsp" is 4, string terminator is 1.
new dir, file, mapCnt, lenMapName;
dir = open_dir("maps", mapName, sizeof(mapName)-1);
if (dir)
{
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/%s", DIR_CONFIGS, arg1);
file = fopen(filename, "wt");
if (file)
{
mapCnt = 0;
while (next_file(dir, mapName, sizeof(mapName)-1))
{
lenMapName = strlen(mapName);
if (lenMapName > 4 && equali(mapName[lenMapName - 4], ".bsp", 4))
{
mapName[lenMapName- 4] = '^0';
if (is_map_valid(mapName))
{
mapCnt++;
fprintf(file, "%s^n", mapName);
}
}
}
fclose(file);
con_print(id, "%L", LANG_SERVER, "GAL_CREATIONSUCCESS", filename, mapCnt);
}
else
{
con_print(id, "%L", LANG_SERVER, "GAL_CREATIONFAILED", filename);
}
close_dir(dir);
}
else
{
// directory not found, wtf?
con_print(id, "%L", LANG_SERVER, "GAL_MAPSFOLDERMISSING");
}
}
default:
{
// inform of correct usage
con_print(id, "%L", id, "GAL_CMD_CREATEFILE_USAGE1");
con_print(id, "%L", id, "GAL_CMD_CREATEFILE_USAGE2");
}
}
return PLUGIN_HANDLED;
}
public map_loadPrefixList()
{
new filename[256];
formatex(filename, sizeof(filename)-1, "%s/prefixes.ini", DIR_CONFIGS);
new file = fopen(filename, "rt");
if (file)
{
new buffer[16];
while (!feof(file))
{
fgets(file, buffer, sizeof(buffer)-1);
if (buffer[0] && !equal(buffer, "//", 2))
{
if (g_mapPrefixCnt <= MAX_PREFIX_CNT)
{
trim(buffer);
copy(g_mapPrefix[g_mapPrefixCnt++], sizeof(buffer)-1, buffer);
}
else
{
log_error(AMX_ERR_BOUNDS, "%L", LANG_SERVER, "GAL_PREFIXES_TOOMANY", MAX_PREFIX_CNT, filename);
break;
}
}
}
fclose(file);
}
else
{
log_error(AMX_ERR_NOTFOUND, "%L", LANG_SERVER, "GAL_PREFIXES_NOTFOUND", filename);
}
return PLUGIN_HANDLED;
}
map_loadEmptyCycleList()
{
new filename[256];
get_pcvar_string(cvar_emptyMapFile, filename, sizeof(filename)-1);
g_emptyMapCnt = map_populateList(g_emptyCycleMap, filename);
}
public map_manageEnd()
{
dbg_log(2, "%32s mp_timelimit: %f", "map_manageEnd(in)", get_cvar_float("mp_timelimit"));
g_pauseMapEndManagerTask = true;
if (get_realplayersnum() <= 1)
{
// at most there is only one player on the server, so no need to stay around
map_change();
}
else
{
if (get_pcvar_num(cvar_endOnRound) && g_wasLastRound == false)
{
// let the server know it's the last round
g_wasLastRound = true;
// let the players know it's the last round
if (g_voteStatus & VOTE_FORCED)
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_CHANGE_NEXTROUND");
}
else
{
client_print(0, print_chat, "%L %L", LANG_PLAYER, "GAL_CHANGE_TIMEEXPIRED", LANG_PLAYER, "GAL_CHANGE_NEXTROUND");
}
// prevent the map from ending automatically
server_cmd("mp_timelimit 0");
}
else
{
// freeze the game and show the scoreboard
message_begin(MSG_ALL, SVC_INTERMISSION);
message_end();
//new chatTime = floatround(get_cvar_float("mp_chattime"), floatround_floor);
// display intermission expiration countdown
//set_task(1.0, "intermission_displayTimer", chatTime, _, _, "a", chatTime);
// change the map after "chattime" is over
set_task(floatmax(get_cvar_float("mp_chattime"), 2.0), "map_change");
}
new map[MAX_MAPNAME_LEN + 1];
get_cvar_string("amx_nextmap", map, sizeof(map)-1);
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_NEXTMAP", map);
}
dbg_log(2, "%32s mp_timelimit: %f", "map_manageEnd(out)", get_cvar_float("mp_timelimit"));
}
/*
public intermission_displayTimer(originalChatTime)
{
static secondsLeft = -1;
if (secondsLeft == -1)
{
secondsLeft = originalChatTime;
}
secondsLeft--;
client_print(0, print_center, "Intermission ends in %i seconds.", secondsLeft);
client_print(0, print_chat, "%i seconds", secondsLeft);
set_hudmessage(255, 0, 90, 0.80, 0.20, 0, 1.0, 2.0, 0.1, 0.1, -1);
// set_hudmessage(0, 222, 50, -1.0, 0.13, 0, 1.0, 0.94, 0.0, 0.0, -1);
show_hudmessage(0, "Intermission ends in %i seconds.", secondsLeft);
// use audio since visual doesn't seem to work
// something like "map will change in 2 seconds"
}
*/
public event_round_start()
{
if (g_wasLastRound)
{
map_manageEnd();
}
}
public event_game_commencing()
{
// make sure the reset time is the original time limit
// (can be skewed if map was previously extended)
map_restoreOriginalTimeLimit();
}
public event_intermission()
{
// don't let the normal end interfere
g_pauseMapEndManagerTask = true;
// change the map after "chattime" is over
set_task(floatmax(get_cvar_float("mp_chattime"), 2.0), "map_change");
return PLUGIN_CONTINUE;
}
map_getIdx(text[])
{
new map[MAX_MAPNAME_LEN + 1];
new mapIdx;
new nominationMap[32];
for (new prefixIdx = 0; prefixIdx < g_mapPrefixCnt; ++prefixIdx)
{
formatex(map, sizeof(map)-1, "%s%s", g_mapPrefix[prefixIdx], text);
for (mapIdx = 0; mapIdx < g_nominationMapCnt; ++mapIdx)
{
ArrayGetString(g_nominationMap, mapIdx, nominationMap, sizeof(nominationMap)-1);
if (equal(map, nominationMap))
{
return mapIdx;
}
}
}
return -1;
}
public cmd_say(id)
{
//-----
// generic say handler to determine if we need to act on what was said
//-----
static text[70], arg1[32], arg2[32], arg3[2];
read_args(text, sizeof(text)-1);
remove_quotes(text);
arg1[0] = '^0';
arg2[0] = '^0';
arg3[0] = '^0';
parse(text, arg1, sizeof(arg1)-1, arg2, sizeof(arg2)-1, arg3, sizeof(arg3)-1);
// if the chat line has more than 2 words, we're not interested at all
if (arg3[0] == 0)
{
new idxMap;
// if the chat line contains 1 word, it could be a map or a one-word command
if (arg2[0] == 0) // "say [rtv|rockthe<anything>vote]"
{
if ((get_pcvar_num(cvar_rtvCommands) & RTV_CMD_SHORTHAND && equali(arg1, "rtv")) || ((get_pcvar_num(cvar_rtvCommands) & RTV_CMD_DYNAMIC && equali(arg1, "rockthe", 7) && equali(arg1[strlen(arg1)-4], "vote"))))
{
vote_rock(id);
return PLUGIN_HANDLED;
}
else if (get_pcvar_num(cvar_nomPlayerAllowance))
{
if (equali(arg1, "noms"))
{
nomination_list(id);
return PLUGIN_HANDLED;
}
else
{
idxMap = map_getIdx(arg1);
if (idxMap >= 0)
{
nomination_toggle(id, idxMap);
return PLUGIN_HANDLED;
}
}
}
}
else if (get_pcvar_num(cvar_nomPlayerAllowance)) // "say <nominate|nom|cancel> <map>"
{
if (equali(arg1, "nominate") || equali(arg1, "nom"))
{
nomination_attempt(id, arg2);
return PLUGIN_HANDLED;
}
else if (equali(arg1, "cancel"))
{
// bpj -- allow ambiguous cancel in which case a menu of their nominations is shown
idxMap = map_getIdx(arg2);
if (idxMap >= 0)
{
nomination_cancel(id, idxMap);
return PLUGIN_HANDLED;
}
}
}
}
return PLUGIN_CONTINUE;
}
nomination_attempt(id, nomination[]) // (playerName[], &phraseIdx, matchingSegment[])
{
// all map names are stored as lowercase, so normalize the nomination
strtolower(nomination);
// assume there'll be more than one match (because we're lazy) and starting building the match menu
//menu_destroy(g_nominationMatchesMenu[id]);
g_nominationMatchesMenu[id] = menu_create("Nominate Map", "nomination_handleMatchChoice");
// gather all maps that match the nomination
new mapIdx, nominationMap[32], matchCnt = 0, matchIdx = -1, info[1], choice[64], disabledReason[16];
for (mapIdx = 0; mapIdx < g_nominationMapCnt && matchCnt <= MAX_NOM_MATCH_CNT; ++mapIdx)
{
ArrayGetString(g_nominationMap, mapIdx, nominationMap, sizeof(nominationMap)-1);
if (contain(nominationMap, nomination) > -1)
{
matchCnt++;
matchIdx = mapIdx; // store in case this is the only match
// there may be a much better way of doing this, but I didn't feel like
// storing the matches and mapIdx's only to loop through them again
info[0] = mapIdx;
// in most cases, the map will be available for selection, so assume that's the case here
disabledReason[0] = 0;
// disable if the map has already been nominated
if (nomination_getPlayer(mapIdx))
{
formatex(disabledReason, sizeof(disabledReason)-1, "%L", id, "GAL_MATCH_NOMINATED");
}
// disable if the map is too recent
else if (map_isTooRecent(nominationMap))
{
formatex(disabledReason, sizeof(disabledReason)-1, "%L", id, "GAL_MATCH_TOORECENT");
}
else if (equal(g_currentMap, nominationMap))
{
formatex(disabledReason, sizeof(disabledReason)-1, "%L", id, "GAL_MATCH_CURRENTMAP");
}
formatex(choice, sizeof(choice)-1, "%s %s", nominationMap, disabledReason);
menu_additem(g_nominationMatchesMenu[id], choice, info, (disabledReason[0] == 0) ? 0 : (1<<26));
}
}
// handle the number of matches
switch (matchCnt)
{
case 0:
{
// no matches; pity the poor fool
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_NOMATCHES", nomination);
}
case 1:
{
// one match?! omg, this is just like awesome
map_nominate(id, matchIdx);
}
default:
{
// this is kinda sexy; we put up a menu of the matches for them to pick the right one
client_print(id, print_chat, "%L", id, "GAL_NOM_MATCHES", nomination);
if (matchCnt == MAX_NOM_MATCH_CNT)
{
client_print(id, print_chat, "%L", id, "GAL_NOM_MATCHES_MAX", MAX_NOM_MATCH_CNT, MAX_NOM_MATCH_CNT);
}
menu_display(id, g_nominationMatchesMenu[id]);
}
}
}
public nomination_handleMatchChoice(id, menu, item)
{
if( item < 0 ) return PLUGIN_CONTINUE;
// Get item info
new mapIdx, info[1];
new access, callback;
menu_item_getinfo(g_nominationMatchesMenu[id], item, access, info, 1, _, _, callback);
mapIdx = info[0];
map_nominate(id, mapIdx);
return PLUGIN_HANDLED;
}
nomination_getPlayer(idxMap)
{
// check if the map has already been nominated
new idxNomination;
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
for (new idPlayer = 1; idPlayer <= MAX_PLAYER_CNT; ++idPlayer)
{
for (idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
if (idxMap == g_nomination[idPlayer][idxNomination])
{
return idPlayer;
}
}
}
return 0;
}
nomination_toggle(id, idxMap)
{
new idNominator = nomination_getPlayer(idxMap);
if (idNominator == id)
{
nomination_cancel(id, idxMap);
}
else
{
map_nominate(id, idxMap, idNominator);
}
}
nomination_cancel(id, idxMap)
{
// cancellations can only be made if a vote isn't already in progress
if (g_voteStatus & VOTE_IN_PROGRESS)
{
client_print(id, print_chat, "%L", id, "GAL_CANCEL_FAIL_INPROGRESS");
return;
}
// and if the outcome of the vote hasn't already been determined
else if (g_voteStatus & VOTE_IS_OVER)
{
client_print(id, print_chat, "%L", id, "GAL_CANCEL_FAIL_VOTEOVER");
return;
}
new bool:nominationFound, idxNomination;
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
for (idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
if (g_nomination[id][idxNomination] == idxMap)
{
nominationFound = true;
break;
}
}
new mapName[32];
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
if (nominationFound)
{
g_nomination[id][idxNomination] = -1;
g_nominationCnt--;
nomination_announceCancellation(mapName);
}
else
{
new idNominator = nomination_getPlayer(idxMap);
if (idNominator)
{
new name[32];
get_user_name(idNominator, name, 31);
client_print(id, print_chat, "%L", id, "GAL_CANCEL_FAIL_SOMEONEELSE", mapName, name);
}
else
{
client_print(id, print_chat, "%L", id, "GAL_CANCEL_FAIL_WASNOTYOU", mapName);
}
}
}
map_nominate(id, idxMap, idNominator = -1)
{
// nominations can only be made if a vote isn't already in progress
if (g_voteStatus & VOTE_IN_PROGRESS)
{
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_INPROGRESS");
return;
}
// and if the outcome of the vote hasn't already been determined
else if (g_voteStatus & VOTE_IS_OVER)
{
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_VOTEOVER");
return;
}
new mapName[32];
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
// players can not nominate the current map
if (equal(g_currentMap, mapName))
{
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_CURRENTMAP", g_currentMap);
return;
}
// players may not be able to nominate recently played maps
if (map_isTooRecent(mapName))
{
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_TOORECENT", mapName);
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_TOORECENT_HLP");
return;
}
// check if the map has already been nominated
if (idNominator == -1)
{
idNominator = nomination_getPlayer(idxMap);
}
if (idNominator == 0)
{
// determine the number of nominations the player already made
// and grab an open slot with the presumption that the player can make the nomination
new nominationCnt = 0, idxNominationOpen, idxNomination;
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
for (idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
if (g_nomination[id][idxNomination] >= 0)
{
nominationCnt++;
}
else
{
idxNominationOpen = idxNomination;
}
}
if (nominationCnt == playerNominationMax)
{
new nominatedMaps[256], buffer[32];
for (idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
idxMap = g_nomination[id][idxNomination];
ArrayGetString(g_nominationMap, idxMap, buffer, sizeof(buffer)-1);
format(nominatedMaps, sizeof(nominatedMaps)-1, "%s%s%s", nominatedMaps, (idxNomination == 1) ? "" : ", ", buffer);
}
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_TOOMANY", playerNominationMax, nominatedMaps);
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_TOOMANY_HLP");
}
else
{
// otherwise, allow the nomination
g_nomination[id][idxNominationOpen] = idxMap;
g_nominationCnt++;
map_announceNomination(id, mapName);
client_print(id, print_chat, "%L", id, "GAL_NOM_GOOD_HLP");
}
}
else if (idNominator == id)
{
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_ALREADY", mapName);
}
else
{
new name[32];
get_user_name(idNominator, name, 31);
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_SOMEONEELSE", mapName, name);
client_print(id, print_chat, "%L", id, "GAL_NOM_FAIL_SOMEONEELSE_HLP");
}
}
public nomination_list(id)
{
new idxNomination, idxMap; //, hudMessage[512];
new msg[101], mapCnt;
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
new mapName[32];
for (new idPlayer = 1; idPlayer <= MAX_PLAYER_CNT; ++idPlayer)
{
for (idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
idxMap = g_nomination[idPlayer][idxNomination];
if (idxMap >= 0)
{
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
format(msg, sizeof(msg)-1, "%s, %s", msg, mapName);
if (++mapCnt == 4) // list 4 maps per chat line
{
client_print(0, print_chat, "%L: %s", LANG_PLAYER, "GAL_NOMINATIONS", msg[2]);
mapCnt = 0;
msg[0] = 0;
}
// construct the HUD message
// format(hudMessage, sizeof(hudMessage)-1, "%s^n%s", hudMessage, mapName);
// construct the console message
}
}
}
if (msg[0])
{
client_print(0, print_chat, "%L: %s", LANG_PLAYER, "GAL_NOMINATIONS", msg[2]);
}
else
{
client_print(0, print_chat, "%L: %L", LANG_PLAYER, "GAL_NOMINATIONS", LANG_PLAYER, "NONE");
}
// set_hudmessage(255, 0, 90, 0.80, 0.20, 0, 1.0, 12.0, 0.1, 0.1, -1);
// ShowSyncHudMsg(id, g_nonOverlapHudSync, hudMessage);
}
public vote_startDirector(bool:forced)
{
new choicesLoaded, voteDuration;
if (g_voteStatus & VOTE_IS_RUNOFF)
{
choicesLoaded = vote_loadRunoffChoices();
voteDuration = get_pcvar_num(cvar_runoffDuration);
if (get_realplayersnum())
{
dbg_log(4, " [RUNOFF VOTE CHOICES (%i)]", choicesLoaded);
}
}
else
{
// make it known that a vote is in progress
g_voteStatus |= VOTE_IN_PROGRESS;
// stop RTV reminders
remove_task(TASKID_REMINDER);
// set nextmap to "voting"
if (forced || get_pcvar_num(cvar_endOfMapVote))
{
new nextMap[32];
formatex(nextMap, sizeof(nextMap)-1, "%L", LANG_SERVER, "GAL_NEXTMAP_VOTING");
map_setNext(nextMap);
}
// pause the "end of map" tasks so they don't interfere
g_pauseMapEndVoteTask = true;
g_pauseMapEndManagerTask = true;
if (forced)
{
g_voteStatus |= VOTE_FORCED;
}
choicesLoaded = vote_loadChoices();
voteDuration = get_pcvar_num(cvar_voteDuration);
if (get_realplayersnum())
{
dbg_log(4, " [PRIMARY VOTE CHOICES (%i)]", choicesLoaded);
}
if (choicesLoaded)
{
// clear all nominations
nomination_clearAll();
}
}
if (choicesLoaded)
{
// alphabetize the maps
SortCustom2D(g_mapChoice, choicesLoaded, "sort_stringsi");
// dbg code ----
if (get_realplayersnum())
{
for (new dbgChoice = 0; dbgChoice < choicesLoaded; dbgChoice++)
{
dbg_log(4, " %i. %s", dbgChoice+1, g_mapChoice[dbgChoice]);
}
}
//--------------
// mark the players who are in this vote for use later
new player[32], playerCnt;
get_players(player, playerCnt, "ch"); // skip bots and hltv
for (new idxPlayer = 0; idxPlayer < playerCnt; ++idxPlayer)
{
g_voted[player[idxPlayer]] = false;
}
// make perfunctory announcement: "get ready to choose a map"
if (!(get_pcvar_num(cvar_soundsMute) & SOUND_GETREADYTOCHOOSE))
{
//client_cmd(0, "spk ^"get red(e80) ninety(s45) to check(e20) use bay(s18) mass(e42) cap(s50)^"");
}
// announce the pending vote countdown from 7 to 1
set_task(1.0, "vote_countdownPendingVote", _, _, _, "a", 7);
// display the map choices
set_task(8.5, "vote_handleDisplay");
// display the vote outcome
if (get_pcvar_num(cvar_voteStatus))
{
new arg[3] = {-1, -1, false}; // indicates it's the end of vote display
set_task(8.5 + float(voteDuration) + 1.0, "vote_display", _, arg, 3);
set_task(8.5 + float(voteDuration) + 6.0, "vote_expire");
}
else
{
set_task(8.5 + float(voteDuration) + 3.0, "vote_expire");
}
}
else
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_VOTE_NOMAPS");
}
if (get_realplayersnum())
{
dbg_log(4, "");
dbg_log(4, " [PLAYER CHOICES]");
}
}
public vote_countdownPendingVote()
{
static countdown = 7;
// visual countdown
set_hudmessage(0, 222, 50, -1.0, 0.13, 0, 1.0, 0.94, 0.0, 0.0, -1);
show_hudmessage(0, "%L", LANG_PLAYER, "GAL_VOTE_COUNTDOWN", countdown);
// audio countdown
if (!(get_pcvar_num(cvar_soundsMute) & SOUND_COUNTDOWN))
{
new word[6];
num_to_word(countdown, word, 5);
client_cmd(0, "spk ^"fvox/%s^"", word);
}
// decrement the countdown
countdown--;
if (countdown == 0)
{
countdown = 7;
}
}
vote_addNominations()
{
// dbg code ----
if (get_realplayersnum())
{
dbg_log(4, " [NOMINATIONS (%i)]", g_nominationCnt);
}
//--------------
if (g_nominationCnt)
{
// set how many total nominations we can use in this vote
new maxNominations = get_pcvar_num(cvar_nomQtyUsed);
new slotsAvailable = g_choiceMax - g_choiceCnt;
new voteNominationMax = (maxNominations) ? min(maxNominations, slotsAvailable) : slotsAvailable;
// set how many total nominations each player is allowed
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
// add as many nominations as we can
// [TODO: develop a better method of determining which nominations make the cut; either FIFO or random]
new idxMap, id, mapName[32];
// dbg code ----
if (get_realplayersnum())
{
new nominator_id, playerName[32];
for (new idxNomination = playerNominationMax; idxNomination >= 1; --idxNomination)
{
for (id = 1; id <= MAX_PLAYER_CNT; ++id)
{
idxMap = g_nomination[id][idxNomination];
if (idxMap >= 0)
{
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
nominator_id = nomination_getPlayer(idxMap);
get_user_name(nominator_id, playerName, sizeof(playerName)-1);
dbg_log(4, " %-32s %s", mapName, playerName);
}
}
}
dbg_log(4, "");
}
//--------------
for (new idxNomination = playerNominationMax; idxNomination >= 1; --idxNomination)
{
for (id = 1; id <= MAX_PLAYER_CNT; ++id)
{
idxMap = g_nomination[id][idxNomination];
if (idxMap >= 0)
{
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
copy(g_mapChoice[g_choiceCnt++], sizeof(g_mapChoice[])-1, mapName);
if (g_choiceCnt == voteNominationMax)
{
break;
}
}
}
if (g_choiceCnt == voteNominationMax)
{
break;
}
}
}
}
vote_addFiller()
{
if (g_choiceCnt == g_choiceMax)
{
return;
}
// grab the name of the filler file
new filename[256];
get_pcvar_string(cvar_voteMapFile, filename, sizeof(filename)-1);
// create an array of files that will be pulled from
new fillerFile[8][256];
new mapsPerGroup[8], groupCnt;
if (!equal(filename, "*"))
{
// determine what kind of file it's being used as
new file = fopen(filename, "rt");
if (file)
{
new buffer[16];
fgets(file, buffer, sizeof(buffer)-1);
trim(buffer);
fclose(file);
if (equali(buffer, "[groups]"))
{
dbg_log(8, " ");
dbg_log(8, "this is a [groups] file");
// read the filler file to determine how many groups there are (max of 8)
new groupIdx;
file = fopen(filename, "rt");
while (!feof(file))
{
fgets(file, buffer, sizeof(buffer)-1);
trim(buffer);
// dbg_log(8, "buffer: %s isdigit: %i groupCnt: %i ", buffer, isdigit(buffer[0]), groupCnt);
if (isdigit(buffer[0]))
{
if (groupCnt < 8)
{
groupIdx = groupCnt++;
mapsPerGroup[groupIdx] = str_to_num(buffer);
formatex(fillerFile[groupIdx], sizeof(fillerFile[])-1, "%s/%i.ini", DIR_CONFIGS, groupCnt);
// dbg_log(8, "fillerFile: %s", fillerFile[groupIdx]);
}
else
{
log_error(AMX_ERR_BOUNDS, "%L", LANG_SERVER, "GAL_GRP_FAIL_TOOMANY", filename);
break;
}
}
}
fclose(file);
if (groupCnt == 0)
{
log_error(AMX_ERR_GENERAL, "%L", LANG_SERVER, "GAL_GRP_FAIL_NOCOUNTS", filename);
return;
}
}
else
{
// we presume it's a listing of maps, ala mapcycle1.txt
copy(fillerFile[0], sizeof(filename)-1, filename);
mapsPerGroup[0] = 8;
groupCnt = 1;
}
}
else
{
log_error(AMX_ERR_NOTFOUND, "%L", LANG_SERVER, "GAL_FILLER_NOTFOUND", fillerFile);
}
}
else
{
// we'll be loading all maps in the /maps folder
copy(fillerFile[0], sizeof(filename)-1, filename);
mapsPerGroup[0] = 8;
groupCnt = 1;
}
// fill remaining slots with random maps from each filler file, as much as possible
new mapCnt, mapKey, allowedCnt, unsuccessfulCnt, choiceIdx, mapName[32];
for (new groupIdx = 0; groupIdx < groupCnt; ++groupIdx)
{
mapCnt = map_loadFillerList(fillerFile[groupIdx]);
dbg_log(8, "[%i] groupCnt:%i mapCnt: %i g_choiceCnt: %i g_choiceMax: %i fillerFile: %s", groupIdx, groupCnt, mapCnt, g_choiceCnt, g_choiceMax, fillerFile[groupIdx]);
if (g_choiceCnt < g_choiceMax && mapCnt)
{
unsuccessfulCnt = 0;
allowedCnt = min(min(mapsPerGroup[groupIdx], g_choiceMax - g_choiceCnt), mapCnt);
dbg_log(8, "[%i] allowedCnt: %i mapsPerGroup: %i Max-Cnt: %i", groupIdx, allowedCnt, mapsPerGroup[groupIdx], g_choiceMax - g_choiceCnt);
for (choiceIdx = 0; choiceIdx < allowedCnt; ++choiceIdx)
{
mapKey = random_num(0, mapCnt - 1);
ArrayGetString(g_fillerMap, mapKey, mapName, sizeof(mapName)-1);
dbg_log(8, "[%i] choiceIdx: %i allowedCnt: %i mapKey: %i mapName: %s", groupIdx, choiceIdx, allowedCnt, mapKey, mapName);
unsuccessfulCnt = 0;
while ((map_isInMenu(mapName) || equal(g_currentMap, mapName) || map_isTooRecent(mapName) || prefix_isInMenu(mapName)) && unsuccessfulCnt < mapCnt)
{
unsuccessfulCnt++;
if (++mapKey == mapCnt)
{
mapKey = 0;
}
ArrayGetString(g_fillerMap, mapKey, mapName, sizeof(mapName)-1);
}
if (unsuccessfulCnt == mapCnt)
{
//client_print(0, print_chat, "unsuccessfulCnt: %i mapCnt: %i", unsuccessfulCnt, mapCnt);
// there aren't enough maps in this filler file to continue adding anymore
break;
}
//client_print(0, print_chat, "mapIdx: %i map: %s", mapIdx, mapName);
copy(g_mapChoice[g_choiceCnt++], sizeof(g_mapChoice[])-1, mapName);
dbg_log(8, "[%i] mapName: %s unsuccessfulCnt: %i mapCnt: %i g_choiceCnt: %i", groupIdx, mapName, unsuccessfulCnt, mapCnt, g_choiceCnt);
}
}
}
}
vote_loadChoices()
{
vote_addNominations();
vote_addFiller();
return g_choiceCnt;
}
vote_loadRunoffChoices()
{
new choiceCnt;
new runoffChoice[2][MAX_MAPNAME_LEN+1];
copy(runoffChoice[0], sizeof(runoffChoice[])-1, g_mapChoice[g_runoffChoice[0]]);
copy(runoffChoice[1], sizeof(runoffChoice[])-1, g_mapChoice[g_runoffChoice[1]]);
new mapIdx;
if (g_runoffChoice[0] != g_choiceCnt)
{
copy(g_mapChoice[mapIdx++], sizeof(g_mapChoice[])-1, runoffChoice[0]);
choiceCnt++;
}
if (g_runoffChoice[1] != g_choiceCnt)
{
choiceCnt++;
}
copy(g_mapChoice[mapIdx], sizeof(g_mapChoice[])-1, runoffChoice[1]);
g_choiceCnt = choiceCnt;
return choiceCnt;
}
public vote_handleDisplay()
{
// announce: "time to choose"
if (!(get_pcvar_num(cvar_soundsMute) & SOUND_TIMETOCHOOSE))
{
client_cmd(0, "spk Gman/Gman_Choose%i", random_num(1, 2));
}
if (g_voteStatus & VOTE_IS_RUNOFF)
{
g_voteDuration = get_pcvar_num(cvar_runoffDuration);
}
else
{
g_voteDuration = get_pcvar_num(cvar_voteDuration);
}
if (get_pcvar_num(cvar_voteStatus) && get_pcvar_num(cvar_voteStatusType) == SHOWSTATUSTYPE_PERCENTAGE)
{
copy(g_voteTallyType, sizeof(g_voteTallyType)-1, "%");
}
if (get_cvar_num("gal_debug") & 4)
{
set_task(2.0, "dbg_fakeVotes");
}
// make sure the display is contructed from scratch
g_refreshVoteStatus = true;
// ensure the vote status doesn't indicate expired
g_voteStatus &= ~VOTE_HAS_EXPIRED;
new arg[3];
arg[0] = true;
arg[1] = 0;
arg[2] = false;
if (get_pcvar_num(cvar_voteStatus) == SHOWSTATUS_VOTE)
{
set_task(1.0, "vote_display", _, arg, sizeof(arg), "a", g_voteDuration);
}
else
{
set_task(1.0, "vote_display", _, arg, sizeof(arg));
}
}
public vote_display(arg[3])
{
static allKeys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9|MENU_KEY_0;
static keys, voteStatus[512], voteTally[16];
new updateTimeRemaining = arg[0];
new id = arg[1];
// dbg code ----
if (get_realplayersnum())
{
new snuff = (id > 0) ? g_snuffDisplay[id] : -1;
dbg_log(4, " [votedisplay()] id: %i updateTimeRemaining: %i unsnuffDisplay: %i g_snuffDisplay: %i g_refreshVoteStatus: %i g_choiceCnt: %i len(g_vote): %i len(voteStatus): %i", arg[1], arg[0], arg[2], snuff, g_refreshVoteStatus, g_choiceCnt, strlen(g_vote), strlen(voteStatus));
}
if (id > 0 && g_snuffDisplay[id])
{
new unsnuffDisplay = arg[2];
if (unsnuffDisplay)
{
g_snuffDisplay[id] = false;
}
else
{
return;
}
}
new isVoteOver = (updateTimeRemaining == -1 && id == -1);
new charCnt;
if (g_refreshVoteStatus || isVoteOver)
{
// wipe the previous vote status clean
voteStatus[0] = 0;
keys = MENU_KEY_0;
new voteCnt;
new allowStay = (g_voteStatus & VOTE_IS_EARLY);
new isRunoff = (g_voteStatus & VOTE_IS_RUNOFF);
new bool:allowExtend = !allowStay && ((isRunoff && g_choiceCnt == 1) || (!(g_voteStatus & VOTE_FORCED) && !isRunoff && get_cvar_float("mp_timelimit") < get_pcvar_float(cvar_extendmapMax)));
if (get_cvar_num("gal_debug") & 4)
{
allowExtend = !allowStay && ((isRunoff && g_choiceCnt == 1) || (!isRunoff && get_cvar_float("mp_timelimit") < get_pcvar_float(cvar_extendmapMax)));
}
// add the header
if (isVoteOver)
{
charCnt = formatex(voteStatus, sizeof(voteStatus)-1, "%s%L^n", CLR_YELLOW, LANG_SERVER, "GAL_RESULT");
}
else
{
charCnt = formatex(voteStatus, sizeof(voteStatus)-1, "%s%L^n", CLR_YELLOW, LANG_SERVER, "GAL_CHOOSE");
}
// add maps to the menu
for (new choiceIdx = 0; choiceIdx < g_choiceCnt; ++choiceIdx)
{
voteCnt = g_mapVote[choiceIdx];
vote_getTallyStr(voteTally, sizeof(voteTally)-1, voteCnt);
charCnt += formatex(voteStatus[charCnt], sizeof(voteStatus)-1-charCnt, "^n%s%i. %s%s%s", CLR_RED, choiceIdx+1, CLR_WHITE, g_mapChoice[choiceIdx], voteTally);
keys |= (1<<choiceIdx);
}
// add optional menu item
if (allowExtend || allowStay)
{
// if it's not a runoff vote, add a space between the maps and the additional option
if (g_voteStatus & VOTE_IS_RUNOFF == 0)
{
charCnt += formatex(voteStatus[charCnt], sizeof(voteStatus)-1-charCnt, "^n");
}
vote_getTallyStr(voteTally, sizeof(voteTally)-1, g_mapVote[g_choiceCnt]);
if (allowExtend)
{
// add the "Extend Map" menu item.
charCnt += formatex(voteStatus[charCnt], sizeof(voteStatus)-1-charCnt, "^n%s%i. %s%L%s", CLR_RED, g_choiceCnt+1, CLR_WHITE, LANG_SERVER, "GAL_OPTION_EXTEND", g_currentMap, floatround(get_pcvar_float(cvar_extendmapStep)), voteTally);
}
else
{
// add the "Stay Here" menu item
charCnt += formatex(voteStatus[charCnt], sizeof(voteStatus)-1-charCnt, "^n%s%i. %s%L%s", CLR_RED, g_choiceCnt+1, CLR_WHITE, LANG_SERVER, "GAL_OPTION_STAY", voteTally);
}
keys |= (1<<g_choiceCnt);
}
// make a copy of the virgin menu
if (g_vote[0] == 0)
{
new cleanCharCnt = copy(g_vote, sizeof(g_vote)-1, voteStatus);
// append a "None" option on for people to choose if they don't like any other choice
formatex(g_vote[cleanCharCnt], sizeof(g_vote)-1-cleanCharCnt, "^n^n%s0. %s%L", CLR_RED, CLR_WHITE, LANG_SERVER, "GAL_OPTION_NONE");
}
charCnt += formatex(voteStatus[charCnt], sizeof(voteStatus)-1-charCnt, "^n^n");
g_refreshVoteStatus = false;
}
static voteFooter[32];
if (updateTimeRemaining && get_pcvar_num(cvar_voteExpCountdown))
{
charCnt = copy(voteFooter, sizeof(voteFooter)-1, "^n^n");
if (--g_voteDuration <= 10)
{
formatex(voteFooter[charCnt], sizeof(voteFooter)-1-charCnt, "%s%L: %s%i", CLR_GREY, LANG_SERVER, "GAL_TIMELEFT", CLR_RED, g_voteDuration);
}
}
// create the different displays
static menuClean[512], menuDirty[512];
menuClean[0] = 0;
menuDirty[0] = 0;
formatex(menuClean, sizeof(menuClean)-1, "%s%s", g_vote, voteFooter);
if (!isVoteOver)
{
formatex(menuDirty, sizeof(menuDirty)-1, "%s%s", voteStatus, voteFooter);
}
else
{
formatex(menuDirty, sizeof(menuDirty)-1, "%s^n^n%s%L", voteStatus, CLR_YELLOW, LANG_SERVER, "GAL_VOTE_ENDED");
}
new menuid, menukeys;
// display the vote
new showStatus = get_pcvar_num(cvar_voteStatus);
if (id > 0)
{
// optionally display to single player that just voted
if (showStatus == SHOWSTATUS_VOTE)
{
// dbg code ----
new name[32];
get_user_name(id, name, 31);
dbg_log(4, " [%s (dirty, just voted)]", name);
dbg_log(4, " %s", menuDirty);
//--------------
get_user_menu(id, menuid, menukeys);
if (menuid == 0 || menuid == g_menuChooseMap)
{
show_menu(id, allKeys, menuDirty, max(1, g_voteDuration), MENU_CHOOSEMAP);
}
}
}
else
{
// display to everyone
new players[32], playerCnt;
get_players(players, playerCnt, "ch"); // skip bots and hltv
for (new playerIdx = 0; playerIdx < playerCnt; ++playerIdx)
{
id = players[playerIdx];
if (g_voted[id] == false && !isVoteOver)
{
// dbg code ----
if (playerIdx == 0)
{
new name[32];
get_user_name(id, name, 31);
dbg_log(4, " [%s (clean)]", name);
dbg_log(4, " %s", menuClean);
}
//--------------
get_user_menu(id, menuid, menukeys);
if (menuid == 0 || menuid == g_menuChooseMap)
{
show_menu(id, keys, menuClean, g_voteDuration, MENU_CHOOSEMAP);
}
}
else
{
if ((isVoteOver && showStatus) || (showStatus == SHOWSTATUS_VOTE && g_voted[id]))
{
// dbg code ----
if (playerIdx == 0)
{
new name[32];
get_user_name(id, name, 31);
dbg_log(4, " [%s (dirty)]", name);
dbg_log(4, " %s", menuDirty);
}
//--------------
get_user_menu(id, menuid, menukeys);
if (menuid == 0 || menuid == g_menuChooseMap)
{
show_menu(id, allKeys, menuDirty, (isVoteOver) ? 5 : max(1, g_voteDuration), MENU_CHOOSEMAP);
}
}
}
// dbg code ----
if (id == 1)
{
dbg_log(4, "");
}
//--------------
}
}
}
vote_getTallyStr(voteTally[], voteTallyLen, voteCnt)
{
if (voteCnt && get_pcvar_num(cvar_voteStatusType) == SHOWSTATUSTYPE_PERCENTAGE)
{
voteCnt = percent(voteCnt, g_votesCast);
}
if (get_pcvar_num(cvar_voteStatus) && voteCnt)
{
formatex(voteTally, voteTallyLen, " %s(%i%s)", CLR_GREY, voteCnt, g_voteTallyType);
}
else
{
voteTally[0] = 0;
}
}
public vote_expire()
{
g_voteStatus |= VOTE_HAS_EXPIRED;
// dbg code ----
if (get_realplayersnum())
{
dbg_log(4, "");
dbg_log(4, " [VOTE RESULT]");
new voteTally[16];
for (new idxChoice = 0; idxChoice <= g_choiceCnt; ++idxChoice)
{
vote_getTallyStr(voteTally, sizeof(voteTally)-1, g_mapVote[idxChoice]);
dbg_log(4, " %2i/%3i %i. %s", g_mapVote[idxChoice], voteTally, idxChoice, g_mapChoice[idxChoice]);
}
dbg_log(4, "");
}
//--------------
g_vote[0] = 0;
// determine the number of votes for 1st and 2nd place
new firstPlaceVoteCnt, secondPlaceVoteCnt, totalVotes;
for (new idxChoice = 0; idxChoice <= g_choiceCnt; ++idxChoice)
{
totalVotes += g_mapVote[idxChoice];
if (firstPlaceVoteCnt < g_mapVote[idxChoice])
{
secondPlaceVoteCnt = firstPlaceVoteCnt;
firstPlaceVoteCnt = g_mapVote[idxChoice];
}
else if (secondPlaceVoteCnt < g_mapVote[idxChoice])
{
secondPlaceVoteCnt = g_mapVote[idxChoice];
}
}
// determine which maps are in 1st and 2nd place
new firstPlace[MAX_MAPS_IN_VOTE + 1], firstPlaceCnt;
new secondPlace[MAX_MAPS_IN_VOTE + 1], secondPlaceCnt;
for (new idxChoice = 0; idxChoice <= g_choiceCnt; ++idxChoice)
{
if (g_mapVote[idxChoice] == firstPlaceVoteCnt)
{
firstPlace[firstPlaceCnt++] = idxChoice;
}
else if (g_mapVote[idxChoice] == secondPlaceVoteCnt)
{
secondPlace[secondPlaceCnt++] = idxChoice;
}
}
// announce the outcome
new idxWinner;
if (firstPlaceVoteCnt)
{
// start a runoff vote, if needed
if (get_pcvar_num(cvar_runoffEnabled) && !(g_voteStatus & VOTE_IS_RUNOFF))
{
// if the top vote getting map didn't receive over 50% of the votes cast, start runoff vote
if (firstPlaceVoteCnt <= totalVotes / 2)
{
// announce runoff voting requirement
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_RUNOFF_REQUIRED");
if (!(get_pcvar_num(cvar_soundsMute) & SOUND_RUNOFFREQUIRED))
{
//client_cmd(0, "spk ^"run officer(e40) voltage(e30) accelerating(s70) is required^"");
}
// let the server know the next vote will be a runoff
g_voteStatus |= VOTE_IS_RUNOFF;
// determine the two choices that will be facing off
new choice1Idx, choice2Idx;
if (firstPlaceCnt > 2)
{
choice1Idx = random_num(0, firstPlaceCnt - 1);
choice2Idx = random_num(0, firstPlaceCnt - 1);
if (choice2Idx == choice1Idx)
{
choice2Idx = (choice2Idx == firstPlaceCnt - 1) ? 0 : ++choice2Idx;
}
g_runoffChoice[0] = firstPlace[choice1Idx];
g_runoffChoice[1] = firstPlace[choice2Idx];
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_RESULT_TIED1", firstPlaceCnt);
}
else if (firstPlaceCnt == 2)
{
g_runoffChoice[0] = firstPlace[0];
g_runoffChoice[1] = firstPlace[1];
}
else if (secondPlaceCnt == 1)
{
g_runoffChoice[0] = firstPlace[0];
g_runoffChoice[1] = secondPlace[0];
}
else
{
g_runoffChoice[0] = firstPlace[0];
g_runoffChoice[1] = secondPlace[random_num(0, secondPlaceCnt - 1)];
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_RESULT_TIED2", secondPlaceCnt);
}
/*
// dbg
new dbg1 = g_runoffChoice[0];
new dbg2 = g_runoffChoice[1];
client_print(0, print_chat, "%s, %s", g_mapChoice[dbg1], g_mapChoice[dbg2]);
*/
// clear all the votes
vote_resetStats();
// start the runoff vote
set_task(5.0, "vote_startDirector");
return;
}
}
// if there is a tie for 1st, randomly select one as the winner
if (firstPlaceCnt > 1)
{
idxWinner = firstPlace[random_num(0, firstPlaceCnt - 1)];
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_WINNER_TIED", firstPlaceCnt);
}
else
{
idxWinner = firstPlace[0];
}
if (idxWinner == g_choiceCnt)
{
if (get_pcvar_num(cvar_endOfMapVote))
{
new nextMap[32];
formatex(nextMap, sizeof(nextMap)-1, "%L", LANG_SERVER, "GAL_NEXTMAP_UNKNOWN");
map_setNext(nextMap);
}
// restart map end vote task
g_pauseMapEndVoteTask = false;
if (g_voteStatus & VOTE_IS_EARLY)
{
// "stay here" won
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_WINNER_STAY");
// clear all the votes
vote_resetStats();
// no longer is an early vote
g_voteStatus &= ~VOTE_IS_EARLY;
}
else
{
// "extend map" won
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_WINNER_EXTEND", floatround(get_pcvar_float(cvar_extendmapStep)));
map_extend();
}
}
else
{
map_setNext(g_mapChoice[idxWinner]);
server_exec();
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_NEXTMAP", g_mapChoice[idxWinner]);
g_voteStatus |= VOTE_IS_OVER;
}
}
else
{
// nobody voted. pick a random map from the choices provided.
idxWinner = random_num(0, g_choiceCnt - 1);
map_setNext(g_mapChoice[idxWinner]);
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_WINNER_RANDOM", g_mapChoice[idxWinner]);
g_voteStatus |= VOTE_IS_OVER;
}
g_refreshVoteStatus = true;
new playerCnt = get_realplayersnum();
// vote is no longer in progress
g_voteStatus &= ~VOTE_IN_PROGRESS;
if (g_handleMapChange)
{
if ((g_voteStatus & VOTE_FORCED || (playerCnt == 1 && idxWinner < g_choiceCnt) || playerCnt == 0) && !(get_cvar_num("gal_debug") & 4))
{
// tell the map we need to finish up
set_task(2.0, "map_manageEnd");
}
else
{
// restart map end task
g_pauseMapEndManagerTask = false;
}
}
}
map_extend()
{
dbg_log(2, "%32s mp_timelimit: %f g_rtvWait: %f extendmapStep: %f", "map_extend(in)", get_cvar_float("mp_timelimit"), g_rtvWait, get_pcvar_float(cvar_extendmapStep));
// reset the "rtv wait" time, taking into consideration the map extension
if (g_rtvWait)
{
g_rtvWait = get_cvar_float("mp_timelimit") + g_rtvWait;
}
// do that actual map extension
set_cvar_float("mp_timelimit", get_cvar_float("mp_timelimit") + get_pcvar_float(cvar_extendmapStep));
server_exec();
// clear vote stats
vote_resetStats();
// if we were in a runoff mode, get out of it
g_voteStatus &= ~VOTE_IS_RUNOFF;
dbg_log(2, "%32s mp_timelimit: %f g_rtvWait: %f extendmapStep: %f", "map_extend(out)", get_cvar_float("mp_timelimit"), g_rtvWait, get_pcvar_float(cvar_extendmapStep));
}
vote_resetStats()
{
// g_vote[0] = 0;
g_votesCast = 0;
arrayset(g_mapVote, 0, MAX_MAPS_IN_VOTE + 1);
// reset everyones' rocks
arrayset(g_rockedVote, false, sizeof(g_rockedVote));
g_rockedVoteCnt = 0;
// reset everyones' votes
// arrayset(g_voted, false, sizeof(g_voted));
}
map_isInMenu(map[])
{
for (new idxChoice = 0; idxChoice < g_choiceCnt; ++idxChoice)
{
if (equal(map, g_mapChoice[idxChoice]))
{
return true;
}
}
return false;
}
prefix_isInMenu(map[])
{
if (get_pcvar_num(cvar_voteUniquePrefixes))
{
new tentativePrefix[8], existingPrefix[8], junk[8];
strtok(map, tentativePrefix, sizeof(tentativePrefix)-1, junk, sizeof(junk)-1, '_', 1);
for (new idxChoice = 0; idxChoice < g_choiceCnt; ++idxChoice)
{
strtok(g_mapChoice[idxChoice], existingPrefix, sizeof(existingPrefix)-1, junk, sizeof(junk)-1, '_', 1);
if (equal(tentativePrefix, existingPrefix))
{
return true;
}
}
}
return false;
}
map_isTooRecent(map[])
{
if (get_pcvar_num(cvar_banRecent))
{
for (new idxBannedMap = 0; idxBannedMap < g_cntRecentMap; ++idxBannedMap)
{
if (equal(map, g_recentMap[idxBannedMap]))
{
return true;
}
}
}
return false;
}
public vote_handleChoice(id, key)
{
if (g_voteStatus & VOTE_HAS_EXPIRED)
{
client_cmd(id, "^"slot%i^"", key + 1);
return;
}
g_snuffDisplay[id] = true;
if (g_voted[id] == false)
{
new name[32];
if (get_pcvar_num(cvar_voteAnnounceChoice))
{
get_user_name(id, name, sizeof(name)-1);
}
// dbg code ----
get_user_name(id, name, sizeof(name)-1);
//--------------
// confirm the player's choice
if (key == 9)
{
dbg_log(4, " %-32s (none)", name);
if (get_pcvar_num(cvar_voteAnnounceChoice))
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_CHOICE_NONE_ALL", name);
}
else
{
client_print(id, print_chat, "%L", id, "GAL_CHOICE_NONE");
}
}
else
{
// increment votes cast count
g_votesCast++;
if (key == g_choiceCnt)
{
// only display the "none" vote if we haven't already voted (we can make it here from the vote status menu too)
if (g_voted[id] == false)
{
dbg_log(4, " %-32s (extend)", name);
if (get_pcvar_num(cvar_voteAnnounceChoice))
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_CHOICE_EXTEND_ALL", name);
}
else
{
client_print(id, print_chat, "%L", id, "GAL_CHOICE_EXTEND");
}
}
}
else
{
dbg_log(4, " %-32s %s", name, g_mapChoice[key]);
if (get_pcvar_num(cvar_voteAnnounceChoice))
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_CHOICE_MAP_ALL", name, g_mapChoice[key]);
}
else
{
client_print(id, print_chat, "%L", id, "GAL_CHOICE_MAP", g_mapChoice[key]);
}
}
// register the player's choice giving extra weight to admin votes
new voteWeight = get_pcvar_num(cvar_voteWeight);
if (voteWeight > 1 && has_flag(id, g_voteWeightFlags))
{
g_mapVote[key] += voteWeight;
g_votesCast += (voteWeight - 1);
client_print(id, print_chat, "%L", id, "GAL_VOTE_WEIGHTED", voteWeight);
}
else
{
g_mapVote[key]++;
}
}
g_voted[id] = true;
g_refreshVoteStatus = true;
}
else
{
client_cmd(id, "^"slot%i^"", key + 1);
}
// display the vote again, with status
if (get_pcvar_num(cvar_voteStatus) == SHOWSTATUS_VOTE)
{
new arg[3];
arg[0] = false;
arg[1] = id;
arg[2] = true;
set_task(0.1, "vote_display", _, arg, sizeof(arg));
//vote_display(arg);
}
}
public map_change()
{
// restore the map's timelimit, just in case we had changed it
map_restoreOriginalTimeLimit();
// grab the name of the map we're changing to
new map[MAX_MAPNAME_LEN + 1];
get_cvar_string("amx_nextmap", map, sizeof(map)-1);
// verify we're changing to a valid map
if (!is_map_valid(map))
{
// probably admin did something dumb like changed the map time limit below
// the time remaining in the map, thus making the map over immediately.
// since the next map is unknown, just restart the current map.
copy(map, sizeof(map)-1, g_currentMap);
}
// change to the map
server_cmd("changelevel %s", map);
}
Float:map_getMinutesElapsed()
{
dbg_log(2, "%32s mp_timelimit: %f", "map_getMinutesElapsed(in/out)", get_cvar_float("mp_timelimit"));
return get_cvar_float("mp_timelimit") - (float(get_timeleft()) / 60.0);
}
public vote_rock(id)
{
// if an early vote is pending, don't allow any rocks
if (g_voteStatus & VOTE_IS_EARLY)
{
client_print(id, print_chat, "%L", id, "GAL_ROCK_FAIL_PENDINGVOTE");
return;
}
new Float:minutesElapsed = map_getMinutesElapsed();
// if the player is the only one on the server, bring up the vote immediately
if (get_realplayersnum() == 1 && minutesElapsed > floatmin(2.0, g_rtvWait))
{
vote_startDirector(true);
return;
}
// make sure enough time has gone by on the current map
if (g_rtvWait)
{
if (minutesElapsed < g_rtvWait)
{
client_print(id, print_chat, "%L", id, "GAL_ROCK_FAIL_TOOSOON", floatround(g_rtvWait - minutesElapsed, floatround_ceil));
return;
}
}
// rocks can only be made if a vote isn't already in progress
if (g_voteStatus & VOTE_IN_PROGRESS)
{
client_print(id, print_chat, "%L", id, "GAL_ROCK_FAIL_INPROGRESS");
return;
}
// and if the outcome of the vote hasn't already been determined
else if (g_voteStatus & VOTE_IS_OVER)
{
client_print(id, print_chat, "%L", id, "GAL_ROCK_FAIL_VOTEOVER");
return;
}
// determine how many total rocks are needed
new rocksNeeded = vote_getRocksNeeded();
// make sure player hasn't already rocked the vote
if (g_rockedVote[id])
{
client_print(id, print_chat, "%L", id, "GAL_ROCK_FAIL_ALREADY", rocksNeeded - g_rockedVoteCnt);
rtv_remind(TASKID_REMINDER + id);
return;
}
// allow the player to rock the vote
g_rockedVote[id] = true;
client_print(id, print_chat, "%L", id, "GAL_ROCK_SUCCESS");
// make sure the rtv reminder timer has stopped
if (task_exists(TASKID_REMINDER))
{
remove_task(TASKID_REMINDER);
}
// determine if there have been enough rocks for a vote yet
if (++g_rockedVoteCnt >= rocksNeeded)
{
// announce that the vote has been rocked
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_ROCK_ENOUGH");
// start up the vote director
vote_startDirector(true);
}
else
{
// let the players know how many more rocks are needed
rtv_remind(TASKID_REMINDER);
if (get_pcvar_num(cvar_rtvReminder))
{
// initialize the rtv reminder timer to repeat how many rocks are still needed, at regular intervals
set_task(get_pcvar_float(cvar_rtvReminder) * 60.0, "rtv_remind", TASKID_REMINDER, _, _, "b");
}
}
}
vote_unrock(id)
{
if (g_rockedVote[id])
{
g_rockedVote[id] = false;
g_rockedVoteCnt--;
// and such
}
}
vote_getRocksNeeded()
{
return floatround(get_pcvar_float(cvar_rtvRatio) * float(get_realplayersnum()), floatround_ceil);
}
public rtv_remind(param)
{
new who = param - TASKID_REMINDER;
// let the players know how many more rocks are needed
client_print(who, print_chat, "%L", LANG_PLAYER, "GAL_ROCK_NEEDMORE", vote_getRocksNeeded() - g_rockedVoteCnt);
}
public cmd_listmaps(id)
{
// new arg1[8];
// new start = read_argv(1, arg1, 7) ? str_to_num(arg1) : 1;
map_listAll(id);
return PLUGIN_HANDLED;
}
public cmd_HL1_votemap(id)
{
if (get_pcvar_num(cvar_cmdVotemap) == 0)
{
con_print(id, "%L", id, "GAL_DISABLED");
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
public cmd_HL1_listmaps(id)
{
switch (get_pcvar_num(cvar_cmdListmaps))
{
case 0:
{
con_print(id, "%L", id, "GAL_DISABLED");
}
case 2:
{
map_listAll(id);
}
default:
{
return PLUGIN_CONTINUE;
}
}
return PLUGIN_HANDLED;
}
map_listAll(id)
{
static lastMapDisplayed[MAX_PLAYER_CNT + 1][2];
// determine if the player has requested a listing before
new userid = get_user_userid(id);
if (userid != lastMapDisplayed[id][LISTMAPS_USERID])
{
lastMapDisplayed[id][LISTMAPS_USERID] = 0;
}
new command[32];
read_argv(0, command, sizeof(command)-1);
new arg1[8], start;
new mapCount = get_pcvar_num(cvar_listmapsPaginate);
if (mapCount)
{
if (read_argv(1, arg1, sizeof(arg1)-1))
{
if (arg1[0] == '*')
{
// if the last map previously displayed belongs to the current user,
// start them off there, otherwise, start them at 1
if (lastMapDisplayed[id][LISTMAPS_USERID])
{
start = lastMapDisplayed[id][LISTMAPS_LAST] + 1;
}
else
{
start = 1;
}
}
else
{
start = str_to_num(arg1);
}
}
else
{
start = 1;
}
if (id == 0 && read_argc() == 3 && read_argv(2, arg1, sizeof(arg1)-1))
{
mapCount = str_to_num(arg1);
}
}
if (start < 1)
{
start = 1;
}
if (start >= g_nominationMapCnt)
{
start = g_nominationMapCnt - 1;
}
new end = mapCount ? start + mapCount - 1 : g_nominationMapCnt;
if (end > g_nominationMapCnt)
{
end = g_nominationMapCnt;
}
// this enables us to use 'command *' to get the next group of maps, when paginated
lastMapDisplayed[id][LISTMAPS_USERID] = userid;
lastMapDisplayed[id][LISTMAPS_LAST] = end - 1;
con_print(id, "^n----- %L -----", id, "GAL_LISTMAPS_TITLE", g_nominationMapCnt);
new nominated[64], nominator_id, name[32], mapName[32], idx;
for (idx = start - 1; idx < end; idx++)
{
nominator_id = nomination_getPlayer(idx);
if (nominator_id)
{
get_user_name(nominator_id, name, sizeof(name)-1);
formatex(nominated, sizeof(nominated)-1, "%L", id, "GAL_NOMINATEDBY", name);
}
else
{
nominated[0] = 0;
}
ArrayGetString(g_nominationMap, idx, mapName, sizeof(mapName)-1);
con_print(id, "%3i: %s %s", idx + 1, mapName, nominated);
}
if (mapCount && mapCount < g_nominationMapCnt)
{
con_print(id, "----- %L -----", id, "GAL_LISTMAPS_SHOWING", start, idx, g_nominationMapCnt);
if (end < g_nominationMapCnt)
{
con_print(id, "----- %L -----", id, "GAL_LISTMAPS_MORE", command, end + 1, command);
}
}
}
/*
map_listMatches(id, match[])
{
strtolower(match);
con_print(id, "%L", id, "GAL_MATCHING", match);
con_print(id, "------------------------------------------");
new mapName[32], matchCnt;
new nominated[64], nominator_id, name[32];
for (new idx = 1; idx <= g_nominationMapCnt; ++idx)
{
copy(mapName, sizeof(mapName)-1, g_nominationMap[idx]);
strtolower(mapName);
if (containi(mapName, match) > -1)
{
nominator_id = nomination_getPlayer(idx);
if (nominator_id)
{
get_user_name(nominator_id, name, sizeof(name)-1);
formatex(nominated, sizeof(nominated)-1, "(nominated by %s)", name);
}
else
{
nominated[0] = 0;
}
con_print(id, "%3i: %s %s", ++matchCnt, g_nominationMap[idx], nominated);
}
}
}
*/
con_print(id, message[], {Float,Sql,Result,_}:...)
{
new consoleMessage[256];
vformat(consoleMessage, sizeof(consoleMessage)-1, message, 3);
if (id)
{
new authid[32];
get_user_authid(id, authid, 31);
if (!equal(authid, "STEAM_ID_LAN"))
{
console_print(id, consoleMessage);
return;
}
}
server_print(consoleMessage);
}
public client_disconnect(id)
{
g_voted[id] = false;
// un-rock the vote
vote_unrock(id);
// cancel player's nominations
new playerNominationMax = min(get_pcvar_num(cvar_nomPlayerAllowance), MAX_NOMINATION_CNT);
new nominatedMaps[256], nominationCnt, idxMap, mapName[32];
for (new idxNomination = 1; idxNomination <= playerNominationMax; ++idxNomination)
{
idxMap = g_nomination[id][idxNomination];
if (idxMap >= 0)
{
ArrayGetString(g_nominationMap, idxMap, mapName, sizeof(mapName)-1);
nominationCnt++;
format(nominatedMaps, sizeof(nominatedMaps)-1, "%s%s, ", nominatedMaps, mapName);
g_nomination[id][idxNomination] = -1;
}
}
if (nominationCnt)
{
// strip the extraneous ", " from the string
nominatedMaps[strlen(nominatedMaps) - 2] = 0;
// inform the masses that the maps are no longer nominated
nomination_announceCancellation(nominatedMaps);
}
new dbg_playerCnt = get_realplayersnum()-1;
dbg_log(2, "%32s dbg_playerCnt:%i", "client_disconnect()", dbg_playerCnt);
if (dbg_playerCnt == 0)
{
srv_handleEmpty();
}
}
public client_connect(id)
{
set_pcvar_num(cvar_emptyCycle, 0);
vote_unrock(id);
}
public client_putinserver(id)
{
if ((g_voteStatus & VOTE_IS_EARLY) && !is_user_bot(id) && !is_user_hltv(id))
{
set_task(20.0, "srv_announceEarlyVote", id);
}
}
srv_handleEmpty()
{
dbg_log(2, "%32s mp_timelimit: %f g_originalTimelimit: %f", "srv_handleEmpty(in)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
if (g_originalTimelimit != get_cvar_float("mp_timelimit"))
{
// it's possible that the map has been extended at least once. that
// means that if someone comes into the server, the time limit will
// be the extended time limit rather than the normal time limit. bad.
// reset the original time limit
map_restoreOriginalTimeLimit();
}
// might be utilizing "empty server" feature
if (g_isUsingEmptyCycle && g_emptyMapCnt)
{
srv_startEmptyCountdown();
}
dbg_log(2, "%32s mp_timelimit: %f g_originalTimelimit: %f", "srv_handleEmpty(out)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
}
public srv_announceEarlyVote(id)
{
if (is_user_connected(id))
{
//client_print(id, print_chat, "%L", id, "GAL_VOTE_EARLY");
new text[101];
formatex(text, sizeof(text)-1, "^x04%L", id, "GAL_VOTE_EARLY");
print_color(id, text);
}
}
public srv_initEmptyCheck()
{
if (get_pcvar_num(cvar_emptyWait))
{
if ((get_realplayersnum()) == 0 && !get_pcvar_num(cvar_emptyCycle))
{
srv_startEmptyCountdown();
}
g_isUsingEmptyCycle = true;
}
}
srv_startEmptyCountdown()
{
new waitMinutes = get_pcvar_num(cvar_emptyWait);
if (waitMinutes)
{
set_task(float(waitMinutes * 60), "srv_startEmptyCycle", TASKID_EMPTYSERVER);
}
}
public srv_startEmptyCycle()
{
set_pcvar_num(cvar_emptyCycle, 1);
// set the next map from the empty cycle list,
// or the first one, if the current map isn't part of the cycle
new nextMap[32], mapIdx;
mapIdx = map_getNext(g_emptyCycleMap, g_currentMap, nextMap);
map_setNext(nextMap);
// if the current map isn't part of the empty cycle,
// immediately change to next map that is
if (mapIdx == -1)
{
map_change();
}
}
nomination_announceCancellation(nominations[])
{
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_CANCEL_SUCCESS", nominations);
}
nomination_clearAll()
{
for (new idxPlayer = 1; idxPlayer <= MAX_PLAYER_CNT; idxPlayer++)
{
for (new idxNomination = 1; idxNomination <= MAX_NOMINATION_CNT; idxNomination++)
{
g_nomination[idxPlayer][idxNomination] = -1;
}
}
g_nominationCnt = 0;
}
map_announceNomination(id, map[])
{
new name[32];
get_user_name(id, name, sizeof(name)-1);
client_print(0, print_chat, "%L", LANG_PLAYER, "GAL_NOM_SUCCESS", name, map);
}
#if AMXX_VERSION_NUM < 180
has_flag(id, flags[])
{
return (get_user_flags(id) & read_flags(flags));
}
#endif
public sort_stringsi(const elem1[], const elem2[], const array[], data[], data_size)
{
return strcmp(elem1, elem2, 1);
}
stock get_realplayersnum()
{
new players[32], playerCnt;
get_players(players, playerCnt, "ch");
return playerCnt;
}
stock percent(is, of)
{
return (of != 0) ? floatround(floatmul(float(is)/float(of), 100.0)) : 0;
}
print_color(id, text[])
{
message_begin(MSG_ONE, get_user_msgid("SayText"), {0, 0, 0}, id);
write_byte(id);
write_string(text);
message_end();
}
map_restoreOriginalTimeLimit()
{
dbg_log(2, "%32s mp_timelimit: %f g_originalTimelimit: %f", "map_restoreOriginalTimeLimit(in)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
if (g_originalTimelimit != TIMELIMIT_NOT_SET)
{
server_cmd("mp_timelimit %f", g_originalTimelimit);
server_exec();
}
dbg_log(2, "%32s mp_timelimit: %f g_originalTimelimit: %f", "map_restoreOriginalTimeLimit(out)", get_cvar_float("mp_timelimit"), g_originalTimelimit);
}
dbg_log(const mode, const text[] = "", {Float,Sql,Result,_}:...)
{
new dbg = get_cvar_num("gal_debug");
if (mode & dbg)
{
// format the text as needed
new formattedText[1024];
format_args(formattedText, 1023, 1);
// grab the current game time
new Float:gameTime = get_gametime();
// log text to file
log_to_file("_galileo.log", "{%3.4f} %s", gameTime, formattedText);
if (dbg & 1 && formattedText[0])
{
// make quotes in log text palatable to 3rd party chat log viewers
new isFound = 1;
while (isFound) isFound = replace(formattedText, 1023, "^"", "'");
// print to the server log so as to be picked up by programs such as HLSW
log_message("^"<><><>^" triggered ^"amx_chat^" (text ^"[GAL] %s^")", formattedText);
}
}
// not needed but gets rid of stupid compiler error
if (text[0] == 0) return;
}
|
|