diff --git a/plugins/include/mapchooser.inc b/plugins/include/mapchooser.inc new file mode 100644 index 00000000..d1608b86 --- /dev/null +++ b/plugins/include/mapchooser.inc @@ -0,0 +1,80 @@ +#if defined _mapchooser_included_ + #endinput +#endif +#define _mapchooser_included_ + +enum NominateResult +{ + Nominate_Added, /** The map was added to the nominate list */ + Nominate_Replaced, /** A clients existing nomination was replaced */ + Nominate_AlreadyInVote, /** Specified map was already in the vote */ + Nominate_InvalidMap, /** Mapname specifed wasn't a valid map */ + Nominate_VoteFull, /** This will only occur if force was set to false */ +}; + +enum MapChange +{ + MapChange_Instant, /** Change map as soon as the voting results have come in */ + MapChange_RoundEnd, /** Change map at the end of the round */ + MapChange_MapEnd, /** Change the sm_nextmap cvar */ +}; + +/** + * Attempt to add a map to the mapchooser map list. + * + * @param map Map to add. + * @param force Should we force the map in even if it requires overwriting an existing nomination? + * @param owner Client index of the nominater. If the client disconnects the nomination will be removed. Use 0 for constant nominations + * @return Nominate Result of the outcome + */ +native NominateResult:NominateMap(const String:map[], bool:force, owner); + +/** + * Gets the current list of excluded maps. + * + * @param array An ADT array handle to add the map strings to. Needs to be + * @noreturn + */ +native GetExcludeMapList(Handle:array); + +/** + * Checks if MapChooser will allow a vote + * + * @return True if a vote can be held, or false if mapchooser is already holding a vote. + */ +native bool:CanMapChooserStartVote(); + +/** + * Initiates a MapChooser map vote + * + * Note: If no input array is specified mapchooser will use its internal list. This includes + * any nominations and excluded maps (as per mapchoosers convars). + * + * @param when MapChange consant of when the resulting mapchange should occur. + * @param inputarray ADT array list of maps to add to the vote. + */ +native InitiateMapChooserVote(MapChange:when, Handle:inputarray=INVALID_HANDLE); + + +/** + * A horribly named native that checks if MapChooser's end of map vote has completed. + */ +native bool:HasEndOfMapVoteFinished(); + +/** + * Called when mapchooser removes a nomination from its list. + * Nominations cleared on map start will not trigger this forward + */ +forward OnNominationRemoved(String:map[], owner); + + +public SharedPlugin:__pl_mapchooser = +{ + name = "mapchooser", + file = "mapchooser.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; \ No newline at end of file diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index edf90d03..d7ababb2 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -72,7 +72,7 @@ struct Plugin #include #include #include -//#include +#include /** * Declare this as a struct in your plugin to expose its information. diff --git a/plugins/mapchooser.sp b/plugins/mapchooser.sp index 4ab55071..bd6b1e98 100644 --- a/plugins/mapchooser.sp +++ b/plugins/mapchooser.sp @@ -34,6 +34,11 @@ #pragma semicolon 1 #include +#include +#include +#undef REQUIRE_EXTENSIONS +#include +#define REQUIRE_EXTENSIONS public Plugin:myinfo = { @@ -44,12 +49,13 @@ public Plugin:myinfo = url = "http://www.sourcemod.net/" }; +/* Valve ConVars */ new Handle:g_Cvar_Winlimit = INVALID_HANDLE; new Handle:g_Cvar_Maxrounds = INVALID_HANDLE; new Handle:g_Cvar_Fraglimit = INVALID_HANDLE; +new Handle:g_Cvar_Bonusroundtime = INVALID_HANDLE; -new Handle:g_Cvar_Nextmap = INVALID_HANDLE; - +/* Plugin ConVars */ new Handle:g_Cvar_StartTime = INVALID_HANDLE; new Handle:g_Cvar_StartRounds = INVALID_HANDLE; new Handle:g_Cvar_StartFrags = INVALID_HANDLE; @@ -60,22 +66,39 @@ new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE; new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE; new Handle:g_Cvar_NoVoteMode = INVALID_HANDLE; new Handle:g_Cvar_Extend = INVALID_HANDLE; - +new Handle:g_Cvar_DontChange = INVALID_HANDLE; +new Handle:g_Cvar_EndOfMapVote = INVALID_HANDLE; +new Handle:g_Cvar_VoteDuration = INVALID_HANDLE; new Handle:g_VoteTimer = INVALID_HANDLE; new Handle:g_RetryTimer = INVALID_HANDLE; +/* Data Handles */ new Handle:g_MapList = INVALID_HANDLE; +new Handle:g_NominateList = INVALID_HANDLE; +new Handle:g_NominateOwners = INVALID_HANDLE; new Handle:g_OldMapList = INVALID_HANDLE; new Handle:g_NextMapList = INVALID_HANDLE; -new Handle:g_TeamScores = INVALID_HANDLE; new Handle:g_VoteMenu = INVALID_HANDLE; new g_Extends; new g_TotalRounds; new bool:g_HasVoteStarted; +new bool:g_WaitingForVote; +new bool:g_MapVoteCompleted; +new bool:g_ChangeMapAtRoundEnd; new g_mapFileSerial = -1; +new g_NominateCount = 0; +new MapChange:g_ChangeTime; + +new Handle:g_NominationsResetForward = INVALID_HANDLE; + +/* Upper bound of how many team there could be */ +#define MAXTEAMS 10 +new g_winCount[MAXTEAMS]; + #define VOTE_EXTEND "##extend##" +#define VOTE_DONTCHANGE "##dontchange##" public OnPluginStart() { @@ -83,30 +106,38 @@ public OnPluginStart() new arraySize = ByteCountToCells(33); g_MapList = CreateArray(arraySize); + g_NominateList = CreateArray(arraySize); + g_NominateOwners = CreateArray(1); g_OldMapList = CreateArray(arraySize); g_NextMapList = CreateArray(arraySize); + + g_Cvar_EndOfMapVote = CreateConVar("sm_mapvote_endvote", "1", "Specifies if MapChooser should run an end of map vote", _, true, 0.0, true, 1.0); + HookConVarChange(g_Cvar_EndOfMapVote, EndVoteChanged); g_Cvar_StartTime = CreateConVar("sm_mapvote_start", "3.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0); - g_Cvar_StartRounds = CreateConVar("sm_mapvote_startround", "2.0", "Specifies when to start the vote based on rounds remaining.", _, true, 1.0); + g_Cvar_StartRounds = CreateConVar("sm_mapvote_startround", "2.0", "Specifies when to start the vote based on rounds remaining. Use 0 on TF2 to start vote during bonus round time", _, true, 0.0); g_Cvar_StartFrags = CreateConVar("sm_mapvote_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0); g_Cvar_ExtendTimeStep = CreateConVar("sm_extendmap_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0); - g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 5.0); + g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 1.0); g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0); g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0); g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0); g_Cvar_NoVoteMode = CreateConVar("sm_mapvote_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0); g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "0", "Number of extensions allowed each map.", _, true, 0.0); - + g_Cvar_DontChange = CreateConVar("sm_mapvote_dontchange", "1", "Specifies if a 'Don't Change' option should be added to early votes", _, true, 0.0); + g_Cvar_VoteDuration = CreateConVar("sm_mapvote_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0, true, 25.0); RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now."); g_Cvar_Winlimit = FindConVar("mp_winlimit"); g_Cvar_Maxrounds = FindConVar("mp_maxrounds"); g_Cvar_Fraglimit = FindConVar("mp_fraglimit"); + g_Cvar_Bonusroundtime = FindConVar("mp_bonusroundtime"); if (g_Cvar_Winlimit != INVALID_HANDLE || g_Cvar_Maxrounds != INVALID_HANDLE) { HookEvent("round_end", Event_RoundEnd); - HookEventEx("teamplay_round_win", Event_TeamPlayRoundWin); + HookEventEx("teamplay_win_panel", Event_TeamPlayWinPanel); + HookEventEx("teamplay_restart_round", Event_TFRestartRound); } if (g_Cvar_Fraglimit != INVALID_HANDLE) @@ -115,18 +146,37 @@ public OnPluginStart() } AutoExecConfig(true, "mapchooser"); + + //Change the mp_bonusroundtime max so that we have time to display the vote + //If you display a vote during bonus time good defaults are 17 vote duration and 19 mp_bonustime + if (g_Cvar_Bonusroundtime != INVALID_HANDLE) + { + SetConVarBounds(g_Cvar_Bonusroundtime, ConVarBound_Upper, true, 30.0); + } + + RegPluginLibrary("mapchooser"); + + g_NominationsResetForward = CreateGlobalForward("OnNominationRemoved", ET_Ignore, Param_String, Param_Cell); +} + +public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) +{ + CreateNative("NominateMap", Native_NominateMap); + CreateNative("InitiateMapChooserVote", Native_InitiateVote); + CreateNative("CanMapChooserStartVote", Native_CanVoteStart); + CreateNative("HasEndOfMapVoteFinished", Native_CheckVoteDone); + CreateNative("GetExcludeMapList", Native_GetExcludeMapList); + + return true; +} + +public OnMapStart() +{ + Call_Cancel(); } public OnConfigsExecuted() { - g_Cvar_Nextmap = FindConVar("sm_nextmap"); - - if (g_Cvar_Nextmap == INVALID_HANDLE) - { - LogError("FATAL: Cannot find sm_nextmap cvar. Mapchooser not loaded."); - SetFailState("sm_nextmap not found"); - } - if (ReadMapList(g_MapList, g_mapFileSerial, "mapchooser", @@ -142,22 +192,37 @@ public OnConfigsExecuted() CreateNextVote(); SetupTimeleftTimer(); - SetConVarString(g_Cvar_Nextmap, "Pending Vote"); - if (g_TeamScores != INVALID_HANDLE) - { - CloseHandle(g_TeamScores); - } - - g_TeamScores = CreateArray(2); g_TotalRounds = 0; g_Extends = 0; + + g_MapVoteCompleted = false; + + g_NominateCount = 0; + ClearArray(g_NominateList); + ClearArray(g_NominateOwners); + + for (new i=0; i GetConVarInt(g_Cvar_ExcludeMaps)) + { + RemoveFromArray(g_OldMapList, 0); + } +} + +public OnClientDisconnect(client) +{ + new index = FindValueInArray(g_NominateOwners, client); + + if (index == -1) + { + return; + } + + new String:oldmap[33]; + GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap)); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(GetArrayCell(g_NominateOwners, index)); + Call_Finish(); + + RemoveFromArray(g_NominateOwners, index); + RemoveFromArray(g_NominateList, index); + g_NominateCount--; +} + +public EndVoteChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if (newValue[0] == '1') + { + SetNextMap("Pending Vote"); + } + else + { + SetNextMap(""); + } } public OnMapTimeLeftChanged() @@ -186,9 +293,9 @@ SetupTimeleftTimer() if (GetMapTimeLeft(time) && time > 0) { new startTime = GetConVarInt(g_Cvar_StartTime) * 60; - if (time - startTime < 0) + if (time - startTime < 0 && GetConVarBool(g_Cvar_EndOfMapVote) && !g_MapVoteCompleted && !g_HasVoteStarted) { - InitiateVote(); + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); } else { @@ -205,7 +312,7 @@ SetupTimeleftTimer() public Action:Timer_StartMapVote(Handle:timer) { - if (!GetArraySize(g_MapList)) + if (!GetArraySize(g_MapList) || !GetConVarBool(g_Cvar_EndOfMapVote) || g_MapVoteCompleted || g_HasVoteStarted) { return Plugin_Stop; } @@ -218,87 +325,116 @@ public Action:Timer_StartMapVote(Handle:timer) { g_VoteTimer = INVALID_HANDLE; } - - InitiateVote(); + + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); return Plugin_Stop; } -public Event_TeamPlayRoundWin(Handle:event, const String:name[], bool:dontBroadcast) +public Event_TFRestartRound(Handle:event, const String:name[], bool:dontBroadcast) { - new isFull = GetEventInt(event, "full_round"); - new winningTeam = GetEventInt(event, "team"); - - if (isFull == 1) + /* Game got restarted - reset our round count tracking */ + g_TotalRounds = 0; +} + +public Event_TeamPlayWinPanel(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (g_ChangeMapAtRoundEnd) { - RoundCompleted(winningTeam); + g_ChangeMapAtRoundEnd = false; + CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE); + } + + if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted || !GetConVarBool(g_Cvar_EndOfMapVote)) + { + return; + } + + new bluescore = GetEventInt(event, "blue_score"); + new redscore = GetEventInt(event, "red_score"); + + if(GetEventInt(event, "round_complete") == 1) + { + switch(GetEventInt(event, "winning_team")) + { + case TFTeam_Blue: + { + CheckWinLimit(bluescore); + } + case TFTeam_Red: + { + CheckWinLimit(redscore); + } + //We need to do nothing on winning_team == 0 this indicates stalemate. + default: + { + return; + } + } + + g_TotalRounds++; + CheckMaxRounds(g_TotalRounds); } } /* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */ public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { - if (!GetArraySize(g_MapList) || g_HasVoteStarted) + if (g_ChangeMapAtRoundEnd) + { + g_ChangeMapAtRoundEnd = false; + CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE); + } + + if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted) { return; } new winner = GetEventInt(event, "winner"); - RoundCompleted(winner); -} - -public RoundCompleted(winner) -{ - if (winner == 0 || winner == 1) + if (winner == 0 || winner == 1 || !GetConVarBool(g_Cvar_EndOfMapVote)) { return; } + + if (winner >= MAXTEAMS) + { + SetFailState("Mod exceed maximum team count - Please file a bug report."); + } g_TotalRounds++; - new team[2], teamPos = -1; - for (new i; i < GetArraySize(g_TeamScores); i++) - { - GetArrayArray(g_TeamScores, i, team); - if (team[0] == winner) - { - teamPos = i; - break; - } - } - - if (teamPos == -1) - { - team[0] = winner; - team[1] = 1; - PushArrayArray(g_TeamScores, team); - } - else - { - team[1]++; - SetArrayArray(g_TeamScores, teamPos, team); - } + g_winCount[winner]++; + CheckWinLimit(g_winCount[winner]); + CheckMaxRounds(g_TotalRounds); +} + +public CheckWinLimit(winner_score) +{ if (g_Cvar_Winlimit != INVALID_HANDLE) { new winlimit = GetConVarInt(g_Cvar_Winlimit); if (winlimit) - { - if (team[1] >= (winlimit - GetConVarInt(g_Cvar_StartRounds))) + { + if (winner_score >= (winlimit - GetConVarInt(g_Cvar_StartRounds))) { - InitiateVote(); + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); } } } - +} + +public CheckMaxRounds(roundcount) +{ if (g_Cvar_Maxrounds != INVALID_HANDLE) { new maxrounds = GetConVarInt(g_Cvar_Maxrounds); if (maxrounds) { - if (g_TotalRounds >= (maxrounds - GetConVarInt(g_Cvar_StartRounds))) + if (roundcount >= (maxrounds - GetConVarInt(g_Cvar_StartRounds))) { - InitiateVote(); + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); } } } @@ -311,7 +447,7 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) return; } - if (!GetConVarInt(g_Cvar_Fraglimit)) + if (!GetConVarInt(g_Cvar_Fraglimit) || !GetConVarBool(g_Cvar_EndOfMapVote)) { return; } @@ -319,54 +455,249 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) new fragger = GetClientOfUserId(GetEventInt(event, "attacker")); if (fragger && GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags))) { - InitiateVote(); + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); } } public Action:Command_Mapvote(client, args) { - InitiateVote(); + InitiateVote(MapChange_MapEnd, INVALID_HANDLE); return Plugin_Handled; } -InitiateVote() +InitiateVote(MapChange:when, Handle:inputlist) { - if (g_HasVoteStarted || g_RetryTimer != INVALID_HANDLE) + if (!CanVoteStart()) { return; } + g_WaitingForVote = true; + if (IsVoteInProgress()) { // Can't start a vote, try again in 5 seconds. g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote); return; - } + } + g_ChangeTime = when; + + g_WaitingForVote = false; + g_HasVoteStarted = true; g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL); SetMenuTitle(g_VoteMenu, "Vote Nextmap"); - + SetVoteResultCallback(g_VoteMenu, Handler_MapVoteFinished); + + /** + * TODO: Make a proper decision on when to clear the nominations list. + * Currently it clears when used, and stays if an external list is provided. + * Is this the right thing to do? External lists will probably come from places + * like sm_mapvote from the adminmenu in the future. + */ + decl String:map[32]; - for (new i = 0; i < GetArraySize(g_NextMapList); i++) + + /* No input given - User our internal nominations and maplist */ + if (inputlist == INVALID_HANDLE) { - GetArrayString(g_NextMapList, i, map, sizeof(map)); - AddMenuItem(g_VoteMenu, map, map); + new nominateCount = GetArraySize(g_NominateList); + new voteSize = GetConVarInt(g_Cvar_IncludeMaps); + + /* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */ + new nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount; + + + for (new i=0; i= availableMaps) + { + //Run out of maps, this will have to do. + break; + } + } + + /* Wipe out our nominations list - Nominations have already been informed of this */ + ClearArray(g_NominateOwners); + ClearArray(g_NominateList); } - - if (GetConVarBool(g_Cvar_Extend) && g_Extends < GetConVarInt(g_Cvar_Extend)) + else //We were given a list of maps to start the vote with + { + new size = GetArraySize(inputlist); + + for (new i=0; i 0) + { + ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60); + } + } + + if (g_Cvar_Winlimit != INVALID_HANDLE) + { + new winlimit = GetConVarInt(g_Cvar_Winlimit); + if (winlimit) + { + SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep)); + } + } + + if (g_Cvar_Maxrounds != INVALID_HANDLE) + { + new maxrounds = GetConVarInt(g_Cvar_Maxrounds); + if (maxrounds) + { + SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep)); + } + } + + if (g_Cvar_Fraglimit != INVALID_HANDLE) + { + new fraglimit = GetConVarInt(g_Cvar_Fraglimit); + if (fraglimit) + { + SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); + } + } + + PrintToChatAll("[SM] %t", "Current Map Extended", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogMessage("Voting for next map has finished. The current map has been extended."); + + // We extended, so we'll have to vote again. + g_HasVoteStarted = false; + CreateNextVote(); + SetupTimeleftTimer(); + + } + else if (strcmp(map, VOTE_DONTCHANGE, false) == 0) + { + PrintToChatAll("[SM] %t", "Current Map Stays", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogMessage("Voting for next map has finished. 'No Change' was the winner"); + + g_HasVoteStarted = false; + CreateNextVote(); + SetupTimeleftTimer(); + } + else + { + if (g_ChangeTime == MapChange_MapEnd) + { + SetNextMap(map); + } + else if (g_ChangeTime == MapChange_Instant) + { + new Handle:data; + CreateDataTimer(2.0, Timer_ChangeMap, data); + WritePackString(data, map); + } + else // MapChange_RoundEnd + { + SetNextMap(map); + g_ChangeMapAtRoundEnd = true; + } + + g_HasVoteStarted = false; + g_MapVoteCompleted = true; + + PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogMessage("Voting for next map has finished. Nextmap: %s.", map); + } +} + public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2) { switch (action) @@ -397,20 +728,14 @@ public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2) Format(buffer, sizeof(buffer), "%T", "Extend Map", param1); return RedrawMenuItem(buffer); } + else if (strcmp(map, VOTE_DONTCHANGE, false) == 0) + { + Format(buffer, sizeof(buffer), "%T", "Dont Change", param1); + return RedrawMenuItem(buffer); + } } } - - // Why am I commented out? Because BAIL hasn't decided yet if - // vote notification will be built into the Vote API. - /*case MenuAction_Select: - { - decl String:Name[32], String:Map[32]; - GetClientName(param1, Name, sizeof(Name)); - GetMenuItem(menu, param2, Map, sizeof(Map)); - - PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map); - }*/ - + case MenuAction_VoteCancel: { // If we receive 0 votes, pick at random. @@ -432,84 +757,37 @@ public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2) else { // We were actually cancelled. What should we do? - } - } - - case MenuAction_VoteEnd: - { - decl String:map[32]; - GetMenuItem(menu, param1, map, sizeof(map)); - - if (strcmp(map, VOTE_EXTEND, false) == 0) - { - g_Extends++; - - new time; - if (GetMapTimeLimit(time)) - { - if (time > 0) - { - ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60); - } - } - - if (g_Cvar_Winlimit != INVALID_HANDLE) - { - new winlimit = GetConVarInt(g_Cvar_Winlimit); - if (winlimit) - { - SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep)); - } - } - - if (g_Cvar_Maxrounds != INVALID_HANDLE) - { - new maxrounds = GetConVarInt(g_Cvar_Maxrounds); - if (maxrounds) - { - SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep)); - } - } - - if (g_Cvar_Fraglimit != INVALID_HANDLE) - { - new fraglimit = GetConVarInt(g_Cvar_Fraglimit); - if (fraglimit) - { - SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); - } - } - - PrintToChatAll("[SM] %t", "Current Map Extended"); - LogMessage("Voting for next map has finished. The current map has been extended."); - - // We extended, so we'll have to vote again. g_HasVoteStarted = false; CreateNextVote(); SetupTimeleftTimer(); } - else - { - SetNextMap(map); - } } } return 0; } -SetNextMap(const String:map[]) +public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp) { - SetConVarString(g_Cvar_Nextmap, map); - PushArrayString(g_OldMapList, map); - - if (GetArraySize(g_OldMapList) > GetConVarInt(g_Cvar_ExcludeMaps)) + new String:map[65]; + + if (dp == INVALID_HANDLE) { - RemoveFromArray(g_OldMapList, 0); + if (!GetNextMap(map, sizeof(map))) + { + //No passed map and no set nextmap. fail! + return Plugin_Stop; + } } - - PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map); - LogMessage("Voting for next map has finished. Nextmap: %s.", map); + else + { + ResetPack(dp); + ReadPackString(dp, map, sizeof(map)); + } + + ServerCommand("changelevel \"%s\"", map); + + return Plugin_Stop; } CreateNextVote() @@ -552,4 +830,131 @@ CreateNextVote() } CloseHandle(tempMaps); +} + +bool:CanVoteStart() +{ + if (g_WaitingForVote || g_HasVoteStarted) + { + return false; + } + + return true; +} + +NominateResult:InternalNominateMap(String:map[], bool:force, owner) +{ + if (!IsMapValid(map)) + { + return Nominate_InvalidMap; + } + + new index; + + if ((index = FindValueInArray(g_NominateOwners, owner)) != -1) + { + new String:oldmap[33]; + GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap)); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(owner); + Call_Finish(); + + + SetArrayString(g_NominateList, index, map); + return Nominate_Replaced; + } + + /* Too many nominated maps. */ + if (g_NominateCount >= GetConVarInt(g_Cvar_IncludeMaps) && !force) + { + return Nominate_VoteFull; + } + + /* Map already in the vote */ + if (FindStringInArray(g_NominateList, map) != -1) + { + return Nominate_AlreadyInVote; + } + + + PushArrayString(g_NominateList, map); + PushArrayCell(g_NominateOwners, owner); + g_NominateCount++; + + while (GetArraySize(g_NominateList) > GetConVarInt(g_Cvar_IncludeMaps)) + { + new String:oldmap[33]; + GetArrayString(g_NominateList, 0, oldmap, sizeof(oldmap)); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(GetArrayCell(g_NominateOwners, 0)); + Call_Finish(); + + RemoveFromArray(g_NominateList, 0); + RemoveFromArray(g_NominateOwners, 0); + } + + return Nominate_Added; +} + +/* Add natives to allow nominate and initiate vote to be call */ + +/* native bool:NominateMap(const String:map[], bool:force, &NominateError:error); */ +public Native_NominateMap(Handle:plugin, numParams) +{ + new len; + GetNativeStringLength(1, len); + + if (len <= 0) + { + return false; + } + + new String:map[len+1]; + GetNativeString(1, map, len+1); + + return _:InternalNominateMap(map, GetNativeCell(2), GetNativeCell(3)); +} + +/* native InitiateMapChooserVote(); */ +public Native_InitiateVote(Handle:plugin, numParams) +{ + new MapChange:when = MapChange:GetNativeCell(1); + new Handle:inputarray = Handle:GetNativeCell(2); + + LogMessage("Starting map vote because outside request"); + InitiateVote(when, inputarray); +} + +public Native_CanVoteStart(Handle:plugin, numParams) +{ + return CanVoteStart(); +} + +public Native_CheckVoteDone(Handle:plugin, numParams) +{ + return g_MapVoteCompleted; +} + +public Native_GetExcludeMapList(Handle:plugin, numParams) +{ + new Handle:array = Handle:GetNativeCell(1); + + if (array == INVALID_HANDLE) + { + return; + } + + + new size = GetArraySize(g_OldMapList); + decl String:map[33]; + + for (new i=0; i. - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#pragma semicolon 1 -#include -#undef REQUIRE_PLUGIN -#include - -public Plugin:myinfo = -{ - name = "Map Manager", - author = "AlliedModders LLC", - description = "Map Management", - version = SOURCEMOD_VERSION, - url = "http://www.sourcemod.net/" -}; - -#include "mapmanager/globals.sp" -#include "mapmanager/commands.sp" -#include "mapmanager/events.sp" -#include "mapmanager/functions.sp" -#include "mapmanager/functions_menu.sp" -#include "mapmanager/menus.sp" -#include "mapmanager/timers.sp" -#include "mapmanager/votes.sp" - -public OnPluginStart() -{ - LoadTranslations("mapmanager.phrases"); - - // Prepare nextmap functionality. - g_VGUIMenu = GetUserMessageId("VGUIMenu"); - if (g_VGUIMenu == INVALID_MESSAGE_ID) - { - LogError("FATAL: Cannot find VGUIMenu user message id. MapManager crippled."); - g_NextMapEnabled = false; - } - HookUserMessage(g_VGUIMenu, UserMsg_VGUIMenu); - - // Create all of the arrays, sized for a 64 character string. - new arraySize = ByteCountToCells(64); - g_MapCycle = CreateArray(arraySize); - g_MapList = CreateArray(arraySize); - g_MapHistory = CreateArray(arraySize); - g_NextVoteMaps = CreateArray(arraySize); - g_SelectedMaps = CreateArray(arraySize); - g_NominatedMaps = CreateArray(arraySize); - - g_TeamScores = CreateArray(2); - - // Hook say - RegConsoleCmd("say", Command_Say); - RegConsoleCmd("say_team", Command_Say); - - // Register all commands. - RegAdminCmd("sm_map", Command_Map, ADMFLAG_CHANGEMAP, "sm_map [r/e]"); - RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap "); - RegAdminCmd("sm_votemap", Command_Votemap, ADMFLAG_VOTE|ADMFLAG_CHANGEMAP, "sm_votemap [mapname2] ... [mapname5] "); - RegAdminCmd("sm_maplist", Command_List, ADMFLAG_GENERIC, "sm_maplist"); - RegAdminCmd("sm_nominate", Command_Nominate, ADMFLAG_CHANGEMAP, "sm_nominate - Nominates a map for RockTheVote and MapChooser. Overrides existing nominations."); - RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces the MapChooser vote to occur."); - - if (GetCommandFlags("nextmap") == INVALID_FCVAR_FLAGS) - { - RegServerCmd("nextmap", Command_Nextmap); - } - - // Register all convars - g_Cvar_NextMap = CreateConVar("sm_nextmap", "", "Sets the Next Map", FCVAR_NOTIFY); - - g_Cvar_MapCount = CreateConVar("sm_mm_maps", "4", "Number of maps to be voted on at end of map or RTV. 2 to 6. (Def 4)", 0, true, 2.0, true, 6.0); - g_Cvar_Excludes = CreateConVar("sm_mm_exclude", "5", "Specifies how many past maps to exclude from end of map vote and RTV.", _, true, 0.0); - - g_Cvar_MapChooser = CreateConVar("sm_mm_mapchooser", "0", "Enables MapChooser (End of Map voting)", 0, true, 0.0, true, 1.0); - g_Cvar_RockTheVote = CreateConVar("sm_mm_rockthevote", "0", "Enables RockTheVote (Player initiated map votes)", 0, true, 0.0, true, 1.0); - g_Cvar_Randomize = CreateConVar("sm_mm_randomize", "0", "Enabled Randomizer (Randomly picks the next map)", 0, true, 0.0, true, 1.0); - g_Cvar_Nominate = CreateConVar("sm_mm_nominate", "1", "Enables nomination system.", 0, true, 0.0, true, 1.0); - - g_Cvar_VoteMap = CreateConVar("sm_mm_votemap", "0.60", "Percentage required for successful sm_votemap.", 0, true, 0.05, true, 1.0); - g_Cvar_RTVLimit = CreateConVar("sm_mm_rtvlimit", "0.60", "Required percentage of players needed to rockthevote", 0, true, 0.05, true, 1.0); - g_Cvar_MinPlayers = CreateConVar("sm_mm_minplayers", "0", "Number of players required before RTV will be enabled.", 0, true, 0.0, true, float(MAXPLAYERS)); - - g_Cvar_StartTime = CreateConVar("sm_mapvote_start", "3.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0); - g_Cvar_StartRounds = CreateConVar("sm_mapvote_startround", "2.0", "Specifies when to start the vote based on rounds remaining.", _, true, 1.0); - g_Cvar_StartFrags = CreateConVar("sm_mapvote_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0); - g_Cvar_ExtendTimeMax = CreateConVar("sm_extendmap_maxtime", "90", "Specifies the maximum amount of time a map can be extended", _, true, 0.0); - g_Cvar_ExtendTimeStep = CreateConVar("sm_extendmap_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0); - g_Cvar_ExtendRoundMax = CreateConVar("sm_extendmap_maxrounds", "30", "Specfies the maximum amount of rounds a map can be extended", _, true, 0.0); - g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 5.0); - g_Cvar_ExtendFragMax = CreateConVar("sm_extendmap_maxfrags", "150", "Specfies the maximum frags allowed that a map can be extended.", _, true, 0.0); - g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0); - g_Cvar_Mapfile = CreateConVar("sm_mapvote_file", "configs/maps.ini", "Map file to use. (Def sourcemod/configs/maps.ini)"); - g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0); - g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0); - g_Cvar_NoVoteMode = CreateConVar("sm_mapvote_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0); - g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "1", "Specifies whether or not MapChooser will allow the map to be extended.", _, true, 0.0, true, 1.0); - - - // Find game convars - g_Cvar_Chattime = FindConVar("mp_chattime"); - g_Cvar_Winlimit = FindConVar("mp_winlimit"); - g_Cvar_Maxrounds = FindConVar("mp_maxrounds"); - g_Cvar_Fraglimit = FindConVar("mp_fraglimit"); - - if (GetCommandFlags("nextmap") == INVALID_FCVAR_FLAGS) - { - RegServerCmd("nextmap", Command_Nextmap); - } - - // Hook events - HookEvent("round_end", Event_RoundEnd); // We always require round_end - if (g_Cvar_Fraglimit != INVALID_HANDLE) - { - HookEvent("player_death", Event_PlayerDeath); - } - - // Set to the current map so OnMapStart() will know what to do - decl String:currentMap[64]; - GetCurrentMap(currentMap, 64); - SetNextMap(currentMap); - - // Create necessary menus for TopMenu - g_Menu_Map = CreateMenu(MenuHandler_Map); - SetMenuTitle(g_Menu_Map, "Please select a map"); - SetMenuExitBackButton(g_Menu_Map, true); - - g_Menu_Votemap = CreateMenu(MenuHandler_VoteMap, MenuAction_DrawItem); - SetMenuTitle(g_Menu_Votemap, "Please select a map"); - SetMenuExitBackButton(g_Menu_Votemap, true); - - // Bind TopMenu commands to adminmenu_maplist.ini, in cases it doesn't exist in maplists.cfg - decl String:mapListPath[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, mapListPath, sizeof(mapListPath), "configs/adminmenu_maplist.ini"); - SetMapListCompatBind("sm_map menu", mapListPath); - SetMapListCompatBind("sm_votemap menu", mapListPath); - - // Account for late loading - new Handle:topmenu; - if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) - { - OnAdminMenuReady(topmenu); - } - - AutoExecConfig(true, "mapmanager"); -} - -public OnAdminMenuReady(Handle:topmenu) -{ - /* Block us from being called twice */ - if (topmenu == hTopMenu) - { - return; - } - - /* Save the Handle */ - hTopMenu = topmenu; - - new TopMenuObject:server_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS); - - if (server_commands != INVALID_TOPMENUOBJECT) - { - AddToTopMenu(hTopMenu, - "sm_map", - TopMenuObject_Item, - AdminMenu_Map, - server_commands, - "sm_map", - ADMFLAG_CHANGEMAP); - } - - new TopMenuObject:voting_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_VOTINGCOMMANDS); - - if (voting_commands != INVALID_TOPMENUOBJECT) - { - AddToTopMenu(hTopMenu, - "sm_votemap", - TopMenuObject_Item, - AdminMenu_VoteMap, - voting_commands, - "sm_votemap", - ADMFLAG_VOTE|ADMFLAG_CHANGEMAP); - } -} - -public OnLibraryRemoved(const String:name[]) -{ - if (strcmp(name, "adminmenu") == 0) - { - hTopMenu = INVALID_HANDLE; - } -} - -public OnConfigsExecuted() -{ - // Add map logic here - - // Get the current and last maps. - decl String:lastMap[64], String:currentMap[64]; - GetConVarString(g_Cvar_NextMap, lastMap, 64); - GetCurrentMap(currentMap, 64); - - // Why am I doing this? If we switched to a new map, but it wasn't what we expected (Due to sm_map, sm_votemap, or - // some other plugin/command), we don't want to scramble the map cycle. Or for example, admin switches to a custom map - // not in mapcyclefile. So we keep it set to the last expected nextmap. - ferret - if (strcmp(lastMap, currentMap) == 0) - { - FindAndSetNextMap(); - } - - // Build map menus for sm_map, sm_votemap, and RTV. - /* TODO: Figure out wtf I'm supposed to do here */ - BuildMapMenu(g_Menu_Map); - BuildMapMenu(g_Menu_Votemap); - - - // If the Randomize option is on, randomize! - if (GetConVarBool(g_Cvar_Randomize)) - { - CreateTimer(5.0, Timer_RandomizeNextmap); - } - - // If MapChooser is active, start it up! - if (GetConVarBool(g_Cvar_MapChooser)) - { - SetupTimeleftTimer(); - SetConVarString(g_Cvar_NextMap, "Pending Vote"); - } - - /* - // If RockTheVote is active, start it up! - if (GetConVarBool(g_Cvar_RockTheVote)) - { - BuildMapMenu(g_Menu_RTV, list); - CreateTimer(30.0, Timer_DelayRTV); - } - */ -} - -// Reinitialize all our various globals -public OnMapStart() -{ - if (g_Menu_Nominate != INVALID_HANDLE) - { - ClearArray(g_Menu_Nominate); - } - - if (g_TeamScores != INVALID_HANDLE) - { - ClearArray(g_TeamScores); - } - - g_TotalRounds = 0; - - g_RTV_Voters = 0; - g_RTV_Votes = 0; - g_RTV_VotesNeeded = 0; - g_RTV_Started = false; - g_RTV_Ended = false; -} - -// Reset globals as necessary and kill timers -public OnMapEnd() -{ - g_IntermissionCalled = false; - g_HasVoteStarted = false; - - g_RTV_Allowed = false; - - if (g_VoteTimer != INVALID_HANDLE) - { - KillTimer(g_VoteTimer); - g_VoteTimer = INVALID_HANDLE; - } - - if (g_RetryTimer != INVALID_HANDLE) - { - KillTimer(g_RetryTimer); - g_RetryTimer = INVALID_HANDLE; - } -} - -public bool:OnClientConnect(client, String:rejectmsg[], maxlen) -{ - if (IsFakeClient(client)) - { - return true; - } - - // If RTV is active, deal with vote counting. - if (GetConVarBool(g_Cvar_RockTheVote)) - { - g_RTV_Voted[client] = false; - g_RTV_Voters++; - g_RTV_VotesNeeded = RoundToFloor(float(g_RTV_Voters) * GetConVarFloat(g_Cvar_RTVLimit)); - } - - // If Nominate is active, let the new client nominate - if (GetConVarBool(g_Cvar_Nominate)) - { - g_Nominated[client] = false; - } - - return true; -} - -public OnClientDisconnect(client) -{ - if (IsFakeClient(client)) - { - return; - } - - // If RTV is active, deal with vote counting. - if (GetConVarBool(g_Cvar_RockTheVote)) - { - if(g_RTV_Voted[client]) - { - g_RTV_Votes--; - } - - g_RTV_Voters--; - g_RTV_VotesNeeded = RoundToFloor(float(g_RTV_Voters) * GetConVarFloat(g_Cvar_RTVLimit)); - - // If this client caused us to fall below the RTV threshold and its allowed be started, start it. - if (g_RTV_Votes && g_RTV_Voters && g_RTV_Votes >= g_RTV_VotesNeeded && g_RTV_Allowed && !g_RTV_Started) - { - g_RTV_Started = true; - CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); - } - } -} - -public OnMapTimeLeftChanged() -{ - if (GetConVarBool(g_Cvar_MapChooser)) - { - SetupTimeleftTimer(); - } -} \ No newline at end of file diff --git a/plugins/mapmanager/commands.sp b/plugins/mapmanager/commands.sp deleted file mode 100644 index 30199406..00000000 --- a/plugins/mapmanager/commands.sp +++ /dev/null @@ -1,398 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains callbacks for commands - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - - public Action:Command_Say(client, args) - { - decl String:text[192]; - if (GetCmdArgString(text, sizeof(text)) < 1) - { - return Plugin_Continue; - } - - new startidx; - if (text[strlen(text)-1] == '"') - { - text[strlen(text)-1] = '\0'; - startidx = 1; - } - - decl String:message[8]; - BreakString(text[startidx], message, sizeof(message)); - - if (strcmp(message, "nextmap", false) == 0) - { - decl String:map[32]; - GetConVarString(g_Cvar_Nextmap, map, sizeof(map)); - - PrintToChat(client, "%t", "Next Map", map); - } - else - { - if (GetConVarBool(g_Cvar_RockTheVote) && (strcmp(text[startidx], "rtv", false) == 0 || strcmp(text[startidx], "rockthevote", false) == 0)) - { - if (g_MapChanged) - { - ReplyToCommand(client, "[SM] %t", "Map change in progress"); - return Plugin_Continue; - } - - if (!g_RTV_Allowed) - { - PrintToChat(client, "[SM] %t", "RTV Not Allowed"); - return Plugin_Continue; - } - - if (g_RTV_Ended) - { - PrintToChat(client, "[SM] %t", "RTV Ended"); - return Plugin_Continue; - } - - if (g_RTV_Started) - { - PrintToChat(client, "[SM] %t", "RTV Started"); - return Plugin_Continue; - } - - if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers) && g_RTV_Votes == 0) // Should we keep checking g_Votes here? - { - PrintToChat(client, "[SM] %t", "Minimal Players Not Met"); - return Plugin_Continue; - } - - if (g_RTV_Voted[client]) - { - PrintToChat(client, "[SM] %t", "Already Voted"); - return Plugin_Continue; - } - - new String:name[64]; - GetClientName(client, name, sizeof(name)); - - g_RTV_Votes++; - g_RTV_Voted[client] = true; - - PrintToChatAll("[SM] %t", "RTV Requested", name, g_RTV_Votes, g_RTV_VotesNeeded); - - if (g_RTV_Votes >= g_RTV_VotesNeeded) - { - g_RTV_Started = true; - CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); - } - } - else if (GetConVarBool(g_Cvar_Nominate) && strcmp(text[startidx], "nominate", false) == 0) - { - if (g_MapChanged) - { - ReplyToCommand(client, "[SM] %t", "Map change in progress"); - return Plugin_Continue; - } - - if (g_RTV_Started || g_HasVoteStarted) - { - ReplyToCommand(client, "[SM] %t", "Map vote in progress"); - return Plugin_Continue; - } - - if (g_Nominated[client]) - { - PrintToChat(client, "[SM] %t", "Already Nominated"); - return Plugin_Continue; - } - - if (GetArraySize(g_Nominate) >= GetConVarInt(g_Cvar_Maps)) - { - PrintToChat(client, "[SM] %t", "Max Nominations"); - return Plugin_Continue; - } - - DisplayMenu(g_Menu_Nominate, client, MENU_TIME_FOREVER); - } - } - - return Plugin_Continue; -} - -public Action:Command_Mapvote(client, args) -{ - InitiateVote(); - - return Plugin_Handled; -} - -public Action:Command_Nextmap(args) -{ - decl String:map[64]; - - GetConVarString(g_Cvar_Nextmap, map, sizeof(map)); - - ReplyToCommand(0, "%t", "Next Map", map); - - return Plugin_Handled; -} - -public Action:Command_List(client, args) -{ - PrintToConsole(client, "Map Cycle:"); - - decl String:currentMap[64]; - GetCurrentMap(currentMap, 64); - - decl String:mapName[64]; - for (new i = 0; i < GetArraySize(g_MapCycle); i++) - { - GetArrayString(g_MapCycle, i, mapName, sizeof(mapName)); - if (strcmp(mapName, currentMap) == 0) - { - PrintToConsole(client, "%s <========= Current map", mapName); - } - else if (strcmp(mapName, g_NextMap) == 0) - { - PrintToConsole(client, "%s <========= Next map", mapName); - } - else - { - PrintToConsole(client, "%s", mapName); - } - } - - return Plugin_Handled; -} - -public Action:Command_SetNextmap(client, args) -{ - if (args < 1) - { - ReplyToCommand(client, "[SM] Usage: sm_setnextmap "); - return Plugin_Handled; - } - - if (g_MapChanged) - { - ReplyToCommand(client, "[SM] %t", "Map change in progress"); - return Plugin_Handled; - } - - decl String:map[64]; - GetCmdArg(1, map, sizeof(map)); - - if (!IsMapValid(map)) - { - ReplyToCommand(client, "[SM] %t", "Map was not found", map); - return Plugin_Handled; - } - - ShowActivity(client, "%t", "Cvar changed", "sm_nextmap", map); - LogMessage("\"%L\" changed sm_nextmap to \"%s\"", client, map); - - SetNextMap(map); - - return Plugin_Handled; -} - - public Action:Command_Map(client, args) - { - if (args < 1) - { - ReplyToCommand(client, "[SM] Usage: sm_map [r/e]"); - return Plugin_Handled; - } - - if (g_MapChanged) - { - ReplyToCommand(client, "[SM] %t", "Map change in progress"); - return Plugin_Handled; - } - - decl String:map[64]; - GetCmdArg(1, map, sizeof(map)); - - if (!IsMapValid(map)) - { - ReplyToCommand(client, "[SM] %t", "Map was not found", map); - return Plugin_Handled; - } - - decl String:when[2]; - if (args > 1) - { - GetCmdArg(2, when, sizeof(when)); - - when[0] = CharToLower(when[0]); - if (when[0] != 'r' && when[0] != 'e') - { - when[0] = 'i'; - } - } - - SetMapChange(client, map, when); - - return Plugin_Handled; -} - -public Action:Command_Votemap(client, args) -{ - if (args < 1) - { - ReplyToCommand(client, "[SM] Usage: sm_votemap [r/e] [mapname2] ... [mapname5]"); - return Plugin_Handled; - } - - if (g_MapChanged) - { - ReplyToCommand(client, "[SM] %t", "Map change in progress"); - return Plugin_Handled; - } - - if (IsVoteInProgress()) - { - ReplyToCommand(client, "[SM] %t", "Vote in Progress"); - return Plugin_Handled; - } - - if (!TestVoteDelay(client)) - { - return Plugin_Handled; - } - - decl String:text[256]; - GetCmdArgString(text, sizeof(text)); - - decl String:maps[5][64]; - new mapCount; - new len, pos; - - // Find out if the user specified "when" - decl String:when[64]; - pos = BreakString(text[len], when, sizeof(when)); - if (!IsMapValid(when)) - { - when[0] = CharToLower(when[0]); - if (when[0] != 'r' && when[0] != 'e') - { - ReplyToCommand(client, "[SM] %t", "Map was not found", maps[mapCount]); - return Plugin_Handled; - } - } - else - { - strcpy(maps[mapCount], sizeof(maps[]), when); - mapCount++; - when[0] = 'i'; - } - - len += pos; - - while (pos != -1 && mapCount < 5) - { - pos = BreakString(text[len], maps[mapCount], sizeof(maps[])); - - if (!IsMapValid(maps[mapCount])) - { - ReplyToCommand(client, "[SM] %t", "Map was not found", maps[mapCount]); - return Plugin_Handled; - } - - mapCount++; - - len += pos; - } - - g_VoteMapInUse = client; - g_Client_Data[client][0] = when[0]; - - DisplayVoteMapMenu(client, mapCount, maps); - - return Plugin_Handled; -} - -public Action:Command_Nominate(client, args) -{ - if (args < 1) - { - ReplyToCommand(client, "[SM] Usage: sm_nominate "); - return Plugin_Handled; - } - - if (!GetConVarBool(g_Cvar_Nominate)) - { - ReplyToCommand(client, "[SM] Nominations are currently disabled."); - return Plugin_Handled; - } - - decl String:mapname[64]; - GetCmdArg(1, mapname, sizeof(mapname)); - - if (FindStringInArray(g_MapList, mapname) == -1) - { - ReplyToCommand(client, "%t", "Map was not found", mapname); - return Plugin_Handled; - } - - if (GetArraySize(g_Nominated) > 0) - { - if (FindStringInArray(g_Nominated, mapname) != -1) - { - ReplyToCommand(client, "%t", "Map Already In Vote", mapname); - return Plugin_Handled; - } - - ShiftArrayUp(g_Nominated, 0); - SetArrayString(g_Nominated, 0, mapname); - - while (GetArraySize(g_Nominated) > GetConVarInt(g_Cvar_Maps)) - { - RemoveFromArray(g_Nominated, GetConVarInt(g_Cvar_Maps)); - } - } - else - { - PushArrayString(g_Nominated, mapname); - } - - decl String:item[64]; - for (new i = 0; i < GetMenuItemCount(g_Menu_Nominate); i++) - { - GetMenuItem(g_Menu_Nominate, i, item, sizeof(item)); - if (strcmp(item, mapname) == 0) - { - RemoveMenuItem(g_Menu_Nominate, i); - break; - } - } - - ReplyToCommand(client, "%t", "Map Inserted", mapname); - LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); - - return Plugin_Handled; -} \ No newline at end of file diff --git a/plugins/mapmanager/events.sp b/plugins/mapmanager/events.sp deleted file mode 100644 index 0d868310..00000000 --- a/plugins/mapmanager/events.sp +++ /dev/null @@ -1,166 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains event callbacks - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -public Action:UserMsg_VGUIMenu(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init) -{ - if (g_IntermissionCalled) - { - return Plugin_Handled; - } - - decl String:type[15]; - - /* If we don't get a valid string, bail out. */ - if (BfReadString(bf, type, sizeof(type)) < 0) - { - return Plugin_Handled; - } - - if (BfReadByte(bf) == 1 && BfReadByte(bf) == 0 && (strcmp(type, "scores", false) == 0)) - { - g_IntermissionCalled = true; - - decl String:map[32]; - new Float:fChatTime = GetConVarFloat(g_Cvar_Chattime); - - if (fChatTime < 2.0) - { - SetConVarFloat(g_Cvar_Chattime, 2.0); - } - - LogMessage("[MapManager] Changing map to '%s' due to map ending.", g_NextMap); - - g_MapChanged = true; - CreateTimer(fChatTime - 1.0, Timer_ChangeMap); - } - - return Plugin_Handled; -} - -public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (g_MapChanged) - { - return; - } - - if (g_MapChangeSet && g_MapChangeWhen == 'r') - { - LogMessage("[MapManager] Changing map to '%s' due to round ending.", g_NextMap); - - g_MapChanged = true; - CreateTimer(1.0, Timer_ChangeMap); - - return; - } - - if (g_HasVoteStarted) - { - return; - } - - new winner = GetEventInt(event, "winner"); - - if (winner == 0 || winner == 1) - { - return; - } - - g_TotalRounds++; - - new team[2], teamPos = -1; - for (new i; i < GetArraySize(g_TeamScores); i++) - { - GetArrayArray(g_TeamScores, i, team); - if (team[0] == winner) - { - teamPos = i; - break; - } - } - - if (teamPos == -1) - { - team[0] = winner; - team[1] = 1; - PushArrayArray(g_TeamScores, team); - } - else - { - team[1]++; - SetArrayArray(g_TeamScores, teamPos, team); - } - - if (g_Cvar_Winlimit != INVALID_HANDLE) - { - new winlimit = GetConVarInt(g_Cvar_Winlimit); - if (winlimit) - { - if (team[1] >= (winlimit - GetConVarInt(g_Cvar_StartRounds))) - { - InitiateVote(); - } - } - } - - if (g_Cvar_Maxrounds != INVALID_HANDLE) - { - new maxrounds = GetConVarInt(g_Cvar_Maxrounds); - if (maxrounds) - { - if (g_TotalRounds >= (maxrounds - GetConVarInt(g_Cvar_StartRounds))) - { - InitiateVote(); - } - } - } -} - -public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) -{ - if (g_MapChanged || g_HasVoteStarted || g_Cvar_Fraglimit == INVALID_HANDLE) - { - return; - } - - if (!GetConVarInt(g_Cvar_Fraglimit)) - { - return; - } - - new fragger = GetClientOfUserId(GetEventInt(event, "attacker")); - if (fragger && GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags))) - { - InitiateVote(); - } -} \ No newline at end of file diff --git a/plugins/mapmanager/functions.sp b/plugins/mapmanager/functions.sp deleted file mode 100644 index 365c004e..00000000 --- a/plugins/mapmanager/functions.sp +++ /dev/null @@ -1,335 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Management Plugin - * Contains misc functions. - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -SetNextMap(String:map[]) -{ - strcopy(g_NextMap, sizeof(g_NextMap), map); - SetConVarString(g_Cvar_Nextmap, map); -} - -SetMapChange(client, map, when, Float:time = 3.0) -{ - g_MapChangeSet = true; - g_MapChangeWhen = when[0]; - SetNextMap(map); - - if (when[0] == 'r') - { - ShowActivity2(client, "[SM] ", "%t", "Changing map end of round", map); - LogAction(client, -1, "\"%L\" set end of round map change to \"%s\"", client, map); - } - else if (when[0] == 'e') - { - ShowActivity2(client, "[SM] ", "%t", "Set nextmap", map); - LogAction(client, -1, "\"%L\" set the next map to \"%s\"", client, map); - } - else - { - ShowActivity2(client, "[SM] ", "%t", "Change map", map); - LogAction(client, -1, "\"%L\" changed map to \"%s\"", client, map); - - g_MapChanged = true; - CreateTimer(3.0, Timer_ChangeMap); - } -} - -FindAndSetNextMap() -{ - if (ReadMapList(g_MapList, - g_MapListSerial, - "mapcyclefile", - MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT) - == INVALID_HANDLE) - { - if (g_MapListSerial == -1) - { - LogError("FATAL: Cannot load map cycle. Nextmap not loaded."); - SetFailState("Mapcycle Not Found"); - } - } - - new mapCount = GetArraySize(g_MapList); - decl String:mapName[32]; - - if (g_MapPos == -1) - { - decl String:current[64]; - GetCurrentMap(current, 64); - - for (new i = 0; i < mapCount; i++) - { - GetArrayString(g_MapList, i, mapName, sizeof(mapName)); - if (strcmp(current, mapName, false) == 0) - { - g_MapPos = i; - break; - } - } - - if (g_MapPos == -1) - g_MapPos = 0; - } - - g_MapPos++; - if (g_MapPos >= mapCount) - g_MapPos = 0; - - GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName)); - SetConVarString(g_Cvar_Nextmap, mapName); -} - -Float:GetVotePercent(votes, totalVotes) -{ - return FloatDiv(float(votes),float(totalVotes)); -} - -bool:TestVoteDelay(client) -{ - new delay = CheckVoteDelay(); - - if (delay > 0) - { - if (delay > 60) - { - ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60); - } - else - { - ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay); - } - - return false; - } - - return true; -} - -BuildMapMenu() -{ - if (g_MapMenu != INVALID_HANDLE) - { - CloseHandle(g_MapMenu); - g_MapMenu = INVALID_HANDLE; - } - - g_MapMenu = CreateMenu(Handler_MapSelectMenu); - SetMenuTitle(g_MapMenu, "%t", "Nominate Title"); - - decl String:map[64]; - for (new i = 0; i < GetArraySize(g_MapList); i++) - { - GetArrayString(g_MapList, i, map, sizeof(map)); - AddMenuItem(g_MapMenu, map, map); - } - - SetMenuExitButton(g_MapMenu, false); -} - -SetupTimeleftTimer() -{ - new time; - if (GetMapTimeLeft(time) && time > 0) - { - new startTime = GetConVarInt(g_Cvar_StartTime) * 60; - if (time - startTime < 0) - { - InitiateVote(); - } - else - { - if (g_VoteTimer != INVALID_HANDLE) - { - KillTimer(g_VoteTimer); - g_VoteTimer = INVALID_HANDLE; - } - - g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVote); - } - } -} - -InitiateVote() -{ - if (g_HasVoteStarted || g_RetryTimer != INVALID_HANDLE) - { - return; - } - - if (IsVoteInProgress()) - { - // Can't start a vote, try again in 5 seconds. - g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote); - return; - } - - g_HasVoteStarted = true; - g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL); - SetMenuTitle(g_VoteMenu, "Vote Nextmap"); - - decl String:map[32]; - for (new i = 0; i < GetArraySize(g_NextMapList); i++) - { - GetArrayString(g_NextMapList, i, map, sizeof(map)); - AddMenuItem(g_VoteMenu, map, map); - } - - if (GetConVarBool(g_Cvar_Extend)) - { - new bool:allowExtend, time; - if (GetMapTimeLimit(time) && time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax)) - { - allowExtend = true; - } - - if (g_Cvar_Winlimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Winlimit) < GetConVarInt(g_Cvar_ExtendRoundMax)) - { - allowExtend = true; - } - - if (g_Cvar_Maxrounds != INVALID_HANDLE && GetConVarInt(g_Cvar_Maxrounds) < GetConVarInt(g_Cvar_ExtendRoundMax)) - { - allowExtend = true; - } - - if (g_Cvar_Fraglimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Fraglimit) < GetConVarInt(g_Cvar_ExtendFragMax)) - { - allowExtend = true; - } - - if (allowExtend) - { - AddMenuItem(g_VoteMenu, VOTE_EXTEND, "Extend Map"); - } - } - - SetMenuExitButton(g_VoteMenu, false); - VoteMenuToAll(g_VoteMenu, 20); - - LogMessage("Voting for next map has started."); - PrintToChatAll("[SM] %t", "Nextmap Voting Started"); -} - -SetNextMap(const String:map[]) -{ - SetConVarString(g_Cvar_Nextmap, map); - PushArrayString(g_OldMapList, map); - - if (GetArraySize(g_OldMapList) > GetConVarInt(g_Cvar_ExcludeMaps)) - { - RemoveFromArray(g_OldMapList, 0); - } - - PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map); - LogMessage("Voting for next map has finished. Nextmap: %s.", map); -} - -CreateNextVote() -{ - if(g_NextMapList != INVALID_HANDLE) - { - ClearArray(g_NextMapList); - } - - decl String:map[32]; - new index, Handle:tempMaps = CloneArray(g_MapList); - - GetCurrentMap(map, sizeof(map)); - index = FindStringInArray(tempMaps, map); - if (index != -1) - { - RemoveFromArray(tempMaps, index); - } - - if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps)) - { - for (new i = 0; i < GetArraySize(g_OldMapList); i++) - { - GetArrayString(g_OldMapList, i, map, sizeof(map)); - index = FindStringInArray(tempMaps, map); - if (index != -1) - { - RemoveFromArray(tempMaps, index); - } - } - } - - new limit = (GetConVarInt(g_Cvar_IncludeMaps) < GetArraySize(tempMaps) ? GetConVarInt(g_Cvar_IncludeMaps) : GetArraySize(tempMaps)); - for (new i = 0; i < limit; i++) - { - new b = GetRandomInt(0, GetArraySize(tempMaps) - 1); - GetArrayString(tempMaps, b, map, sizeof(map)); - PushArrayString(g_NextMapList, map); - RemoveFromArray(tempMaps, b); - } - - CloseHandle(tempMaps); -} - -/* - -new Handle:g_map_array = INVALID_HANDLE; -new g_map_serial = -1; - -LoadMapList(Handle:menu) -{ - new Handle:map_array; - - if ((map_array = ReadMapList(g_map_array, - g_map_serial, - "sm_map menu", - MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT|MAPLIST_FLAG_MAPSFOLDER)) - != INVALID_HANDLE) - { - g_map_array = map_array; - } - - if (g_map_array == INVALID_HANDLE) - { - return 0; - } - - RemoveAllMenuItems(menu); - - decl String:map_name[64]; - new map_count = GetArraySize(g_map_array); - - for (new i = 0; i < map_count; i++) - { - GetArrayString(g_map_array, i, map_name, sizeof(map_name)); - AddMenuItem(menu, map_name, map_name); - } - - return map_count; -} - -*/ \ No newline at end of file diff --git a/plugins/mapmanager/functions_menu.sp b/plugins/mapmanager/functions_menu.sp deleted file mode 100644 index 709f7764..00000000 --- a/plugins/mapmanager/functions_menu.sp +++ /dev/null @@ -1,115 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Management Plugin - * Contains misc functions. - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -DisplayWhenMenu(client, bool:vote = false) -{ - new Handle: - - if (!vote) - { - menu = CreateMenu(MenuHandler_ChangeMap); - } - else - { - menu = CreateMenu(MenuHandler_VoteWhen); - } - - decl String:title[100]; - Format(title, sizeof(title), "%T:", "Map Change When", client); - SetMenuTitle(menu, title); - SetMenuExitBackButton(menu, true); - - AddMenuItem(menu, "i", "Immediately"); - AddMenuItem(menu, "r", "Round End"); - AddMenuItem(menu, "e", "Map End"); - - DisplayMenu(menu, client, MENU_TIME_FOREVER); -} - -DisplayConfirmVoteMenu(client) -{ - new Handle:menu = CreateMenu(MenuHandler_Confirm); - - decl String:title[100]; - Format(title, sizeof(title), "%T:", "Confirm Vote", client); - SetMenuTitle(menu, title); - SetMenuExitBackButton(menu, true); - - AddMenuItem(menu, "Confirm", "Start the Vote"); - - DisplayMenu(menu, client, MENU_TIME_FOREVER); -} - -DisplayAcceptVoteMenu(String:map[]) -{ - new Handle:menu = CreateMenu(MenuHandler_Accept); - - decl String:title[100]; - Format(title, sizeof(title), "%T:", "Accept Vote", client); - SetMenuTitle(menu, title); - SetMenuExitBackButton(menu, true); - - AddMenuItem(menu, map, "Accept Vote"); - - DisplayMenu(menu, g_VoteMapInUse, MENU_TIME_FOREVER); -} - -DisplayVoteMapMenu(client, mapCount, String:maps[5][]) -{ - LogAction(client, -1, "\"%L\" initiated a map vote.", client); - ShowActivity2(client, "[SM] ", "%t", "Initiated Vote Map"); - - new Handle:menu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL); - - if (mapCount == 1) - { - //strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), maps[0]); - - SetMenuTitle(menu, "Change Map To"); - AddMenuItem(menu, maps[0], "Yes"); - AddMenuItem(menu, VOTE_NO, "No"); - } - else - { - //g_voteInfo[VOTE_NAME][0] = '\0'; - - SetMenuTitle(menu, "Map Vote"); - for (new i = 0; i < mapCount; i++) - { - AddMenuItem(menu, maps[i], maps[i]); - } - } - - SetMenuExitButton(menu, false); - VoteMenuToAll(menu, 20); -} diff --git a/plugins/mapmanager/globals.sp b/plugins/mapmanager/globals.sp deleted file mode 100644 index db917957..00000000 --- a/plugins/mapmanager/globals.sp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains globals and defines - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#define VOTE_EXTEND "##extend##" -#define VOTE_YES "###yes###" -#define VOTE_NO "###no###" - -new Handle:hTopMenu = INVALID_HANDLE; // TopMenu - -new Handle:g_MapCycle = INVALID_HANDLE; // mapcyclefile maps -new Handle:g_MapList = INVALID_HANDLE; // maplist.txt maps -new Handle:g_MapHistory = INVALID_HANDLE; // History of maps played -new Handle:g_NextVoteMaps = INVALID_HANDLE; // Array of maps for next RTV or MC vote -new Handle:g_NominatedMaps = INVALID_HANDLE; // Array of maps that have been nominated - -new Handle:g_Menu_Map = INVALID_HANDLE; // Menu of maps used by sm_map in admin menu -new Handle:g_Menu_Votemap = INVALID_HANDLE; // Menu of maps used by sm_votemap in admin menu -new Handle:g_Menu_Nominate = INVALID_HANDLE; // Menu of maps used by Nomination system - -new Handle:g_SelectedMaps; // List of maps chosen so far by a user in sm_votemap admin menu -new g_VoteMapInUse; // Client index of admin using sm_votemap -new String:g_Client_Data[MAXCLIENTS+1][64]; // Used to hold bits of client data during sm_votemap - -new bool:g_MapChangeSet; // True if a command or vote has set the map -new bool:g_MapChanged; // True if a map change has been issued -new g_MapChangeWhen; // Either 'i' for immediate, 'r' for round end, or 'e' for end of map. - -new UserMsg:g_VGUIMenu; // VGUI usermsg id for nextmap -new bool:g_NextMapEnabled = true // If set to false, all features requiring nextmap are disabled. -new bool:g_IntermissionCalled; // Has the end of map intermission begun? -new String:g_NextMap[64]; // All important! This is the next map! -new g_MapPos = -1; // Position in mapcycle - -new bool:g_RTV_Voted[MAXPLAYERS+1] = {false, ...}; // Whether or not a player has voted for RTV -new bool:g_RTV_Allowed = false; // True if RTV is available to players. Used to delay rtv votes. -new bool:g_RTV_Started = false; // Indicates that the actual map vote has started -new bool:g_RTV_Ended = false; // Indicates that the actual map vote has concluded -new g_RTV_Voters = 0; // Total voters connected. Doesn't include fake clients. -new g_RTV_Votes = 0; // Total number of "say rtv" votes -new g_RTV_VotesNeeded = 0; // Necessary votes before map vote begins. (voters * percent_needed) - -new bool:g_Nominated[MAXPLAYERS+1] = {false, ...}; // Whether or not a player has nominated a map - -new Handle:g_TeamScores = INVALID_HANDLE; // Array of team scores -new g_TotalRounds; // Total rounds played this map -new bool:g_HasVoteStarted; // Whether or not MapChooser has begun - -// ConVar handles -new Handle:g_Cvar_NextMap = INVALID_HANDLE; -new Handle:g_Cvar_VoteMap = INVALID_HANDLE; -new Handle:g_Cvar_Excludes = INVALID_HANDLE; -new Handle:g_Cvar_StartTime = INVALID_HANDLE; -new Handle:g_Cvar_StartRounds = INVALID_HANDLE; -new Handle:g_Cvar_StartFrags = INVALID_HANDLE; -new Handle:g_Cvar_ExtendTimeMax = INVALID_HANDLE; -new Handle:g_Cvar_ExtendTimeStep = INVALID_HANDLE; -new Handle:g_Cvar_ExtendRoundMax = INVALID_HANDLE; -new Handle:g_Cvar_ExtendRoundStep = INVALID_HANDLE; -new Handle:g_Cvar_ExtendFragMax = INVALID_HANDLE; -new Handle:g_Cvar_ExtendFragStep = INVALID_HANDLE; -new Handle:g_Cvar_Mapfile = INVALID_HANDLE; -new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE; -new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE; -new Handle:g_Cvar_NoVoteMode = INVALID_HANDLE; -new Handle:g_Cvar_Extend = INVALID_HANDLE; - -new Handle:g_VoteTimer = INVALID_HANDLE; -new Handle:g_RetryTimer = INVALID_HANDLE; - -// VALVe ConVars -new Handle:g_Cvar_Chattime = INVALID_HANDLE; -new Handle:g_Cvar_Winlimit = INVALID_HANDLE; -new Handle:g_Cvar_Maxrounds = INVALID_HANDLE; -new Handle:g_Cvar_Fraglimit = INVALID_HANDLE; diff --git a/plugins/mapmanager/menus.sp b/plugins/mapmanager/menus.sp deleted file mode 100644 index 3157f16c..00000000 --- a/plugins/mapmanager/menus.sp +++ /dev/null @@ -1,263 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains menu callbacks - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -// Following callbacks are for sm_map -public AdminMenu_Map(Handle:topmenu, - TopMenuAction:action, - TopMenuObject:object_id, - param, - String:buffer[], - maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - Format(buffer, maxlength, "%T", "Choose Map", param); - } - else if (action == TopMenuAction_SelectOption) - { - DisplayMenu(g_Menu_Map, param, MENU_TIME_FOREVER); - } -} - -public MenuHandler_Map(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) - { - DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_Select) - { - GetMenuItem(menu, param2, g_Client_Data[param1], sizeof(g_Client_Data[])); - DisplayWhenMenu(param1); - } -} - -public MenuHandler_ChangeMap(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) - { - DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_Select) - { - decl String:when[2]; - GetMenuItem(menu, param2, when, sizeof(when)); - SetMapChange(client, g_Client_Data[param1], when[0]) - } -} - -// Following callbacks are for sm_votemap -public AdminMenu_VoteMap(Handle:topmenu, - TopMenuAction:action, - TopMenuObject:object_id, - param, - String:buffer[], - maxlength) -{ - if (action == TopMenuAction_DisplayOption) - { - Format(buffer, maxlength, "%T", "Map vote", param); - } - else if (action == TopMenuAction_SelectOption) - { - g_VoteMapInUse = param; - ClearArray(g_SelectedMaps); - DisplayMenu(g_Menu_Votemap, param, MENU_TIME_FOREVER); - } - else if (action == TopMenuAction_DrawOption) - { - /* disable this option if a vote is already running, theres no maps listed or someone else has already accessed this menu */ - buffer[0] = (!IsNewVoteAllowed() || g_VoteMapInUse) ? ITEMDRAW_IGNORE : ITEMDRAW_DEFAULT; - } -} - -public MenuHandler_VoteMap(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) - { - DisplayWhenMenu(param1, true); - } - else // no action was selected. - { - /* Re-enable the menu option */ - g_VoteMapInUse = 0; - } - } - else if (action == MenuAction_DrawItem) - { - decl String:info[32]; - - GetMenuItem(menu, param2, info, sizeof(info)); - - if (FindStringInArray(g_SelectedMaps, info) != -1) - { - return ITEMDRAW_IGNORE; - } - else - { - return ITEMDRAW_DEFAULT; - } - } - else if (action == MenuAction_Select) - { - decl String:info[32]; - - GetMenuItem(menu, param2, info, sizeof(info)); - - PushArrayString(g_SelectedMaps, info); - - /* Redisplay the list */ - if (GetArraySize(g_SelectedMaps) < 5) - { - DisplayMenu(g_MapList, param1, MENU_TIME_FOREVER); - } - else - { - DisplayWhenMenu(param1, true); - } - } - - return 0; -} - -public MenuHandler_VoteWhen(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_End) - { - CloseHandle(menu); - } - else if (action == MenuAction_Cancel) - { - if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) - { - g_Menu_Info[param1][0] = 'i'; - DisplayConfirmVoteMenu(param1); - } - else - { - g_VoteMapInUse = 0; - } - } - else if (action == MenuAction_Select) - { - GetMenuItem(menu, param2, g_Menu_Info[param1], sizeof(g_Menu_Info[])); - - DisplayConfirmVoteMenu(param1); - } -} - -public MenuHandler_Confirm(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_End) - { - CloseHandle(menu); - } - else if (action == MenuAction_Cancel) - { - g_VoteMapInUse = 0; - - if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE) - { - DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory); - } - } - else if (action == MenuAction_Select) - { - decl String:maps[5][64]; - new selectedmaps = GetArraySize(g_SelectedMaps); - - for (new i = 0; i < selectedmaps; i++) - { - GetArrayString(g_SelectedMaps, i, maps[i], sizeof(maps[])); - } - - DisplayVoteMapMenu(param1, selectedmaps, maps); - } -} - -public MenuHandler_Accept(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_End) - { - CloseHandle(menu); - g_VoteMapInUse = 0; - } - else if (action == MenuAction_Select) - { - decl String:map[64] - GetMenuItem(menu, 1, map, sizeof(map)); - - SetMapChange(param1, map, g_Client_Data[param1][0]) - } -} - -public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) -{ - switch (action) - { - case MenuAction_Select: - { - if (GetArraySize(g_RTVMapList) >= GetConVarInt(g_Cvar_Maps)) - { - PrintToChat(param1, "[SM] %t", "Max Nominations"); - return; - } - - decl String:map[64], String:name[64]; - GetMenuItem(menu, param2, map, sizeof(map)); - - if (FindStringInArray(g_RTVMapList, map) != -1) - { - PrintToChat(param1, "[SM] %t", "Map Already Nominated"); - return; - } - - GetClientName(param1, name, 64); - - PushArrayString(g_RTVMapList, map); - RemoveMenuItem(menu, param2); - - g_Nominated[param1] = true; - - PrintToChatAll("[SM] %t", "Map Nominated", name, map); - } - } -} \ No newline at end of file diff --git a/plugins/mapmanager/timers.sp b/plugins/mapmanager/timers.sp deleted file mode 100644 index bfef0f27..00000000 --- a/plugins/mapmanager/timers.sp +++ /dev/null @@ -1,166 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains timer callbacks - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -public Action:Timer_ChangeMap(Handle:timer) -{ - ServerCommand("changelevel \"%s\"", g_NextMap); - PushArrayString(g_MapHistory, g_NextMap); - - return Plugin_Stop; -} - -public Action:Timer_RandomizeNextmap(Handle:timer) -{ - decl String:map[64]; - - new exclusion = GetConVarInt(g_Cvar_ExcludeMaps); - if (exclusion > GetArraySize(g_MapCycle)) - { - exclusion = GetArraySize(g_MapCycle) - 1; - } - - new b = GetRandomInt(0, GetArraySize(g_MapCycle) - 1); - GetArrayString(g_MapCycle, b, map, sizeof(map)); - - while (FindStringInArray(g_MapHistory, map) != -1) - { - b = GetRandomInt(0, GetArraySize(g_MapCycle) - 1); - GetArrayString(g_MapCycle, b, map, sizeof(map)); - } - - SetNextmap(map); - - LogMessage("[MapManager] Randomizer has chosen '%s' as the next map.", map); - - return Plugin_Stop; -} - -public Action:Timer_DelayRTV(Handle:timer) -{ - g_RTVAllowed = true; - g_RTVStarted = false; - g_RTVEnded = false; -} - -public Action:Timer_StartRTV(Handle:timer) -{ - if (timer == g_RetryTimer) - { - g_RetryTimer = INVALID_HANDLE; - } - - if (g_RetryTimer != INVALID_HANDLE) - { - return; - } - - if (IsVoteInProgress()) - { - // Can't start a vote, try again in 5 seconds. - g_RetryTimer = CreateTimer(5.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); - return; - } - - PrintToChatAll("[SM] %t", "RTV Vote Ready"); - - new Handle:MapVoteMenu = CreateMenu(Handler_MapMapVoteMenu, MenuAction:MENU_ACTIONS_ALL); - SetMenuTitle(MapVoteMenu, "Rock The Vote"); - - new Handle:tempMaps = CloneArray(g_MapList); - decl String:map[32]; - - GetCurrentMap(map, sizeof(map)); - new index = FindStringInArray(tempMaps, map); - if (index != -1) - { - RemoveFromArray(tempMaps, index); - } - - // We assume that g_RTVMapList is within the correct limits, based on the logic for nominations - for (new i = 0; i < GetArraySize(g_RTVMapList); i++) - { - GetArrayString(g_RTVMapList, i, map, sizeof(map)); - AddMenuItem(MapVoteMenu, map, map); - - index = FindStringInArray(tempMaps, map); - if (index != -1) - { - RemoveFromArray(tempMaps, index); - } - } - - new limit = GetConVarInt(g_Cvar_Maps) - GetArraySize(g_RTVMapList); - if (limit > GetArraySize(tempMaps)) - { - limit = GetArraySize(tempMaps); - } - - for (new i = 0; i < limit; i++) - { - new b = GetRandomInt(0, GetArraySize(tempMaps) - 1); - GetArrayString(tempMaps, b, map, sizeof(map)); - PushArrayString(g_RTVMapList, map); - AddMenuItem(MapVoteMenu, map, map); - RemoveFromArray(tempMaps, b); - } - - CloseHandle(tempMaps); - - AddMenuItem(MapVoteMenu, "Don't Change", "Don't Change"); - - SetMenuExitButton(MapVoteMenu, false); - VoteMenuToAll(MapVoteMenu, 20); - - LogMessage("[SM] Rockthevote was successfully started."); -} - -public Action:Timer_StartMapVote(Handle:timer) -{ - if (!GetArraySize(g_MapList)) - { - return Plugin_Stop; - } - - if (timer == g_RetryTimer) - { - g_RetryTimer = INVALID_HANDLE; - } - else - { - g_VoteTimer = INVALID_HANDLE; - } - - InitiateVote(); - - return Plugin_Stop; -} \ No newline at end of file diff --git a/plugins/mapmanager/votes.sp b/plugins/mapmanager/votes.sp deleted file mode 100644 index 4f7a9849..00000000 --- a/plugins/mapmanager/votes.sp +++ /dev/null @@ -1,318 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Map Manager Plugin - * Contains vote callbacks - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * 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 . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -// sm_votemap -public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) -{ - if (action == MenuAction_End) - { - CloseHandle(menu); - } - else if (action == MenuAction_Display) - { - decl String:title[64]; - GetMenuTitle(menu, title, sizeof(title)); - - decl String:map[64]; - GetMenuItem(menu, 1, map, sizeof(map)); - - decl String:buffer[255]; - Format(buffer, sizeof(buffer), "%T", title, param1, map); - - new Handle:panel = Handle:param2; - SetPanelTitle(panel, buffer); - } - else if (action == MenuAction_DisplayItem) - { - decl String:display[64]; - GetMenuItem(menu, param2, "", 0, _, display, sizeof(display)); - - if (strcmp(display, "No") == 0 || strcmp(display, "Yes") == 0) - { - decl String:buffer[255]; - Format(buffer, sizeof(buffer), "%T", display, param1); - - return RedrawMenuItem(buffer); - } - } - else if (action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes) - { - PrintToChatAll("[SM] %t", "No Votes Cast"); - } - else if (action == MenuAction_VoteEnd) - { - decl String:item[64], String:display[64]; - new Float:percent, Float:limit, votes, totalVotes; - - GetMenuVoteInfo(param2, votes, totalVotes); - GetMenuItem(menu, param1, item, sizeof(item), _, display, sizeof(display)); - - if (strcmp(item, VOTE_NO) == 0 && param1 == 1) - { - votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option. - } - - percent = GetVotePercent(votes, totalVotes); - - limit = GetConVarFloat(g_Cvar_VoteMap); - - // A multi-argument vote is "always successful", but have to check if its a Yes/No vote. - if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1)) - { - LogAction(-1, -1, "Vote failed."); - PrintToChatAll("[SM] %t", "Votemap Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes); - } - else - { - PrintToChatAll("[SM] %t", "Votemap Successful", RoundToNearest(100.0*percent), totalVotes); - - if (g_VoteMapInUse && IsClientInGame(g_VoteMapInUse)) - { - DisplayAcceptVoteMenu(item); - } - else - { - LogAction(-1, -1, "Changing map to %s due to vote.", item); - PrintToChatAll("[SM] %t", "Changing map", item); - SetMapChange(0, item, g_Client_Data[g_VoteMapInUse][0]) - } - } - } - - return 0; -} - -public Handler_MapMapVoteMenu(Handle:menu, MenuAction:action, param1, param2) -{ - switch (action) - { - case MenuAction_End: - { - CloseHandle(menu); - } - - case MenuAction_Display: - { - decl String:oldTitle[255], String:buffer[255]; - GetMenuTitle(menu, oldTitle, sizeof(oldTitle)); - Format(buffer, sizeof(buffer), "%T", oldTitle, param1); - - new Handle:panel = Handle:param2; - SetPanelTitle(panel, buffer); - } - - case MenuAction_DisplayItem: - { - if (GetMenuItemCount(menu) - 1 == param2) - { - decl String:buffer[255]; - Format(buffer, sizeof(buffer), "%T", "Don't Change", param1); - return RedrawMenuItem(buffer); - } - } - - // Why am I commented out? Because BAIL hasn't decided yet if - // vote notification will be built into the Vote API. - /*case MenuAction_Select: - { - decl String:Name[32], String:Map[32]; - GetClientName(param1, Name, sizeof(Name)); - GetMenuItem(menu, param2, Map, sizeof(Map)); - - PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map); - }*/ - - case MenuAction_VoteCancel: - { - if (param1 == VoteCancel_NoVotes) - { - PrintToChatAll("[SM] %t", "No Votes"); - g_RTVEnded = true; - } - } - - case MenuAction_VoteEnd: - { - new String:map[64]; - - GetMenuItem(menu, param1, map, sizeof(map)); - - if (GetMenuItemCount(menu) - 1 == param1) // This should always match the "Keep Current" option - { - PrintToChatAll("[SM] %t", "Current Map Stays"); - LogMessage("[SM] Rockthevote has ended, current map kept."); - } - else - { - PrintToChatAll("[SM] %t", "Changing Maps", map); - LogMessage("[SM] Rockthevote has ended, changing to map %s.", map); - new Handle:dp; - CreateDataTimer(5.0, Timer_ChangeMap, dp); - WritePackString(dp, map); - } - - g_RTVEnded = true; - } - } - - return 0; -} - -public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2) -{ - switch (action) - { - case MenuAction_End: - { - g_VoteMenu = INVALID_HANDLE; - CloseHandle(menu); - } - - case MenuAction_Display: - { - decl String:buffer[255]; - Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1); - - new Handle:panel = Handle:param2; - SetPanelTitle(panel, buffer); - } - - case MenuAction_DisplayItem: - { - if (GetMenuItemCount(menu) - 1 == param2) - { - decl String:map[64], String:buffer[255]; - GetMenuItem(menu, param2, map, sizeof(map)); - if (strcmp(map, VOTE_EXTEND, false) == 0) - { - Format(buffer, sizeof(buffer), "%T", "Extend Map", param1); - return RedrawMenuItem(buffer); - } - } - } - - // Why am I commented out? Because BAIL hasn't decided yet if - // vote notification will be built into the Vote API. - /*case MenuAction_Select: - { - decl String:Name[32], String:Map[32]; - GetClientName(param1, Name, sizeof(Name)); - GetMenuItem(menu, param2, Map, sizeof(Map)); - - PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map); - }*/ - - case MenuAction_VoteCancel: - { - // If we receive 0 votes, pick at random. - if (param1 == VoteCancel_NoVotes && GetConVarBool(g_Cvar_NoVoteMode)) - { - new count = GetMenuItemCount(menu); - new item = GetRandomInt(0, count - 1); - decl String:map[32]; - GetMenuItem(menu, item, map, sizeof(map)); - - while (strcmp(map, VOTE_EXTEND, false) == 0) - { - item = GetRandomInt(0, count - 1); - GetMenuItem(menu, item, map, sizeof(map)); - } - - SetNextMap(map); - } - else - { - // We were actually cancelled. What should we do? - } - } - - case MenuAction_VoteEnd: - { - decl String:map[32]; - GetMenuItem(menu, param1, map, sizeof(map)); - - if (strcmp(map, VOTE_EXTEND, false) == 0) - { - new time; - if (GetMapTimeLimit(time)) - { - if (time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax)) - { - ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60); - } - } - - if (g_Cvar_Winlimit != INVALID_HANDLE) - { - new winlimit = GetConVarInt(g_Cvar_Winlimit); - if (winlimit && winlimit < GetConVarInt(g_Cvar_ExtendRoundMax)) - { - SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep)); - } - } - - if (g_Cvar_Maxrounds != INVALID_HANDLE) - { - new maxrounds = GetConVarInt(g_Cvar_Maxrounds); - if (maxrounds && maxrounds < GetConVarInt(g_Cvar_ExtendRoundMax)) - { - SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep)); - } - } - - if (g_Cvar_Fraglimit != INVALID_HANDLE) - { - new fraglimit = GetConVarInt(g_Cvar_Fraglimit); - if (fraglimit && fraglimit < GetConVarInt(g_Cvar_ExtendFragMax)) - { - SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); - } - } - - PrintToChatAll("[SM] %t", "Current Map Extended"); - LogMessage("Voting for next map has finished. The current map has been extended."); - - // We extended, so we'll have to vote again. - g_HasVoteStarted = false; - CreateNextVote(); - SetupTimeleftTimer(); - } - else - { - SetNextMap(map); - } - } - } - - return 0; -} \ No newline at end of file diff --git a/plugins/nominations.sp b/plugins/nominations.sp new file mode 100644 index 00000000..f1070d91 --- /dev/null +++ b/plugins/nominations.sp @@ -0,0 +1,327 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Rock The Vote Plugin + * Creates a map vote when the required number of players have requested one. + * + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * 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 . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include +#include + +#pragma semicolon 1 + +public Plugin:myinfo = +{ + name = "Map Nominations", + author = "AlliedModders LLC", + description = "Provides Map Nominations", + version = SOURCEMOD_VERSION, + url = "http://www.sourcemod.net/" +}; + +new Handle:g_Cvar_ExcludeOld = INVALID_HANDLE; +new Handle:g_Cvar_ExcludeCurrent = INVALID_HANDLE; + +new Handle:g_MapList = INVALID_HANDLE; +new Handle:g_MapMenu = INVALID_HANDLE; +new g_mapFileSerial = -1; + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + LoadTranslations("nominations.phrases"); + + new arraySize = ByteCountToCells(33); + g_MapList = CreateArray(arraySize); + + g_Cvar_ExcludeOld = CreateConVar("sm_nominate_excludeold", "1", "Specifies if the current map should be excluded from the Nominations list", 0, true, 0.00, true, 1.0); + g_Cvar_ExcludeCurrent = CreateConVar("sm_nominate_excludecurrent", "1", "Specifies if the MapChooser excluded maps should also be excluded from Nominations", 0, true, 0.00, true, 1.0); + + RegConsoleCmd("say", Command_Say); + RegConsoleCmd("say_team", Command_Say); + + RegConsoleCmd("sm_nominate", Command_Nominate); + + RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap - Forces a map to be on the next mapvote."); +} + +public OnConfigsExecuted() +{ + if (ReadMapList(g_MapList, + g_mapFileSerial, + "nominations", + MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) + == INVALID_HANDLE) + { + if (g_mapFileSerial == -1) + { + SetFailState("Unable to create a valid map list."); + } + } + + BuildMapMenu(); +} + +public OnNominationRemoved(String:map[], owner) +{ + AddMenuItem(g_MapMenu, map, map); +} + +public Action:Command_Addmap(client, args) +{ + if (args < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_nominate_addmap "); + return Plugin_Handled; + } + + decl String:mapname[64]; + GetCmdArg(1, mapname, sizeof(mapname)); + + if (FindStringInArray(g_MapList, mapname) == -1) + { + ReplyToCommand(client, "%t", "Map was not found", mapname); + return Plugin_Handled; + } + + new NominateResult:result = NominateMap(mapname, true, 0); + + if (result > Nominate_Replaced) + { + /* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it can't be full */ + ReplyToCommand(client, "%t", "Map Already In Vote", mapname); + + return Plugin_Handled; + } + + decl String:item[64]; + for (new i = 0; i < GetMenuItemCount(g_MapMenu); i++) + { + GetMenuItem(g_MapMenu, i, item, sizeof(item)); + if (strcmp(item, mapname) == 0) + { + RemoveMenuItem(g_MapMenu, i); + break; + } + } + + ReplyToCommand(client, "%t", "Map Inserted", mapname); + LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); + + return Plugin_Handled; +} + +public Action:Command_Say(client, args) +{ + if (!client) + { + return Plugin_Continue; + } + + decl String:text[192]; + if (!GetCmdArgString(text, sizeof(text))) + { + return Plugin_Continue; + } + + new startidx = 0; + if(text[strlen(text)-1] == '"') + { + text[strlen(text)-1] = '\0'; + startidx = 1; + } + + new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); + + if (strcmp(text[startidx], "nominate", false) == 0) + { + AttemptNominate(client); + } + + SetCmdReplySource(old); + + return Plugin_Continue; +} + +public Action:Command_Nominate(client, args) +{ + if (!client) + { + return Plugin_Continue; + } + + if (args == 0) + { + AttemptNominate(client); + return Plugin_Continue; + } + + decl String:mapname[64]; + GetCmdArg(1, mapname, sizeof(mapname)); + + if (FindStringInArray(g_MapList, mapname) == -1) + { + ReplyToCommand(client, "%t", "Map was not found", mapname); + return Plugin_Handled; + } + + new NominateResult:result = NominateMap(mapname, false, client); + + if (result > Nominate_Replaced) + { + if (result == Nominate_AlreadyInVote) + { + ReplyToCommand(client, "%t", "Map Already In Vote", mapname); + } + else + { + ReplyToCommand(client, "[SM] %t", "Map Already Nominated"); + } + + return Plugin_Handled; + } + + decl String:item[64]; + for (new i = 0; i < GetMenuItemCount(g_MapMenu); i++) + { + GetMenuItem(g_MapMenu, i, item, sizeof(item)); + if (strcmp(item, mapname) == 0) + { + RemoveMenuItem(g_MapMenu, i); + break; + } + } + + decl String:name[64]; + GetClientName(client, name, sizeof(name)); + + PrintToChatAll("[SM] %t", "Map Nominated", name, mapname); + + return Plugin_Continue; +} + +AttemptNominate(client) +{ + SetMenuTitle(g_MapMenu, "%t", "Nominate Title", client); + DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER); + + return; +} + +BuildMapMenu() +{ + if (g_MapMenu != INVALID_HANDLE) + { + CloseHandle(g_MapMenu); + g_MapMenu = INVALID_HANDLE; + } + + g_MapMenu = CreateMenu(Handler_MapSelectMenu); + + decl String:map[64]; + + new Handle:excludeMaps; + decl String:currentMap[32]; + + if (GetConVarBool(g_Cvar_ExcludeOld)) + { + excludeMaps = CreateArray(ByteCountToCells(33)); + GetExcludeMapList(excludeMaps); + } + + if (GetConVarBool(g_Cvar_ExcludeCurrent)) + { + GetCurrentMap(currentMap, sizeof(currentMap)); + } + + for (new i = 0; i < GetArraySize(g_MapList); i++) + { + GetArrayString(g_MapList, i, map, sizeof(map)); + + if (GetConVarBool(g_Cvar_ExcludeOld)) + { + if (FindStringInArray(excludeMaps, map) != -1) + { + continue; + } + } + + if (GetConVarBool(g_Cvar_ExcludeCurrent)) + { + if (StrEqual(map, currentMap)) + { + continue; + } + } + + AddMenuItem(g_MapMenu, map, map); + } + + SetMenuExitButton(g_MapMenu, true); +} + +public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) +{ + switch (action) + { + case MenuAction_Select: + { + decl String:map[64], String:name[64]; + GetMenuItem(menu, param2, map, sizeof(map)); + + + GetClientName(param1, name, 64); + + + new NominateResult:result = NominateMap(map, false, param1); + + /* Don't need to check for InvalidMap because the menu did that already */ + if (result == Nominate_AlreadyInVote) + { + PrintToChat(param1, "[SM] %t", "Map Already Nominated"); + return; + } + else if (result == Nominate_VoteFull) + { + PrintToChat(param1, "[SM] %t", "Max Nominations"); + return; + } + + RemoveMenuItem(menu, param2); + + if (result == Nominate_Replaced) + { + PrintToChatAll("[SM] %t", "Map Nomination Changed", name, map); + return; + } + + PrintToChatAll("[SM] %t", "Map Nominated", name, map); + } + } +} \ No newline at end of file diff --git a/plugins/reservedslots.sp b/plugins/reservedslots.sp index de4e9e15..eacbf1b1 100644 --- a/plugins/reservedslots.sp +++ b/plugins/reservedslots.sp @@ -150,7 +150,7 @@ public OnClientPostAdminCheck(client) else if (type == 1) { if (clients > limit) - { + { if (flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION) { new target = SelectKickClient(); diff --git a/plugins/rockthevote.sp b/plugins/rockthevote.sp index 3d3a0287..d05364d9 100644 --- a/plugins/rockthevote.sp +++ b/plugins/rockthevote.sp @@ -32,6 +32,8 @@ */ #include +#include +#include #pragma semicolon 1 @@ -45,44 +47,37 @@ public Plugin:myinfo = }; new Handle:g_Cvar_Needed = INVALID_HANDLE; -new Handle:g_Cvar_Maps = INVALID_HANDLE; -new Handle:g_Cvar_Nominate = INVALID_HANDLE; new Handle:g_Cvar_MinPlayers = INVALID_HANDLE; - -new Handle:g_MapList = INVALID_HANDLE; -new Handle:g_RTVMapList = INVALID_HANDLE; -new Handle:g_MapMenu = INVALID_HANDLE; -new Handle:g_RetryTimer = INVALID_HANDLE; -new g_mapFileSerial = -1; +new Handle:g_Cvar_InitialDelay = INVALID_HANDLE; +new Handle:g_Cvar_Interval = INVALID_HANDLE; +new Handle:g_Cvar_ChangeTime = INVALID_HANDLE; +new Handle:g_Cvar_RTVPostVoteAction = INVALID_HANDLE; new bool:g_CanRTV = false; // True if RTV loaded maps and is active. new bool:g_RTVAllowed = false; // True if RTV is available to players. Used to delay rtv votes. -new bool:g_RTVStarted = false; // Indicates that the actual map vote has started -new bool:g_RTVEnded = false; // Indicates that the actual map vote has concluded new g_Voters = 0; // Total voters connected. Doesn't include fake clients. new g_Votes = 0; // Total number of "say rtv" votes new g_VotesNeeded = 0; // Necessary votes before map vote begins. (voters * percent_needed) new bool:g_Voted[MAXPLAYERS+1] = {false, ...}; -new bool:g_Nominated[MAXPLAYERS+1] = {false, ...}; + +new bool:g_InChange = false; public OnPluginStart() { LoadTranslations("common.phrases"); LoadTranslations("rockthevote.phrases"); - new arraySize = ByteCountToCells(33); - g_MapList = CreateArray(arraySize); - g_RTVMapList = CreateArray(arraySize); - g_Cvar_Needed = CreateConVar("sm_rtv_needed", "0.60", "Percentage of players needed to rockthevote (Def 60%)", 0, true, 0.05, true, 1.0); - g_Cvar_Maps = CreateConVar("sm_rtv_maps", "4", "Number of maps to be voted on. 2 to 6. (Def 4)", 0, true, 2.0, true, 6.0); - g_Cvar_Nominate = CreateConVar("sm_rtv_nominate", "1", "Enables nomination system.", 0, true, 0.0, true, 1.0); g_Cvar_MinPlayers = CreateConVar("sm_rtv_minplayers", "0", "Number of players required before RTV will be enabled.", 0, true, 0.0, true, float(MAXPLAYERS)); + g_Cvar_InitialDelay = CreateConVar("sm_rtv_initialdelay", "30.0", "Time before first RTV can be held", 0, true, 0.00); + g_Cvar_Interval = CreateConVar("sm_rtv_interval", "240.0", "Time after a failed RTV before another can be held", 0, true, 0.00); + g_Cvar_ChangeTime = CreateConVar("sm_rtv_changetime", "0", "When to change the map after a succesful RTV: 0 - Instant, 1 - RoundEnd, 2 - MapEnd", _, true, 0.0, true, 2.0); + g_Cvar_RTVPostVoteAction = CreateConVar("sm_rtv_postvoteaction", "0", "What to do with RTV's after a mapvote has completed. 0 - Allow, success = instant change, 1 - Deny", _, true, 0.0, true, 1.0); RegConsoleCmd("say", Command_Say); RegConsoleCmd("say_team", Command_Say); - RegAdminCmd("sm_rtv_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_rtv_addmap - Forces a map to be on the RTV, and lowers the allowed nominations."); + RegConsoleCmd("sm_rtv", Command_RTV); AutoExecConfig(true, "rtv"); } @@ -92,8 +87,17 @@ public OnMapStart() g_Voters = 0; g_Votes = 0; g_VotesNeeded = 0; - g_RTVStarted = false; - g_RTVEnded = false; + g_InChange = false; + + /* Handle late load */ + new maxclients = GetMaxClients(); + for (new i=1; i<=maxclients; i++) + { + if (IsClientConnected(i)) + { + OnClientConnect(i, "", 0); + } + } } public OnMapEnd() @@ -103,36 +107,18 @@ public OnMapEnd() } public OnConfigsExecuted() -{ - if (g_RTVMapList != INVALID_HANDLE) - { - ClearArray(g_RTVMapList); - } - - if (ReadMapList(g_MapList, - g_mapFileSerial, - "rockthevote", - MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) - == INVALID_HANDLE) - { - if (g_mapFileSerial == -1) - { - LogError("Unable to create a valid map list."); - } - } - - BuildMapMenu(); +{ g_CanRTV = true; - CreateTimer(30.0, Timer_DelayRTV); + g_RTVAllowed = false; + CreateTimer(GetConVarFloat(g_Cvar_InitialDelay), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); } public bool:OnClientConnect(client, String:rejectmsg[], maxlen) { - if(!g_CanRTV || IsFakeClient(client)) + if(IsFakeClient(client)) return true; g_Voted[client] = false; - g_Nominated[client] = false; g_Voters++; g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); @@ -154,72 +140,30 @@ public OnClientDisconnect(client) g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); - if (g_Votes && g_Voters && g_Votes >= g_VotesNeeded && g_RTVAllowed && !g_RTVStarted) + if (g_Votes && + g_Voters && + g_Votes >= g_VotesNeeded && + g_RTVAllowed ) { - g_RTVStarted = true; - CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); + if (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished()) + { + return; + } + + StartRTV(); } } -public Action:Command_Addmap(client, args) +public Action:Command_RTV(client, args) { - if (args < 1) + if (!g_CanRTV || !client) { - ReplyToCommand(client, "[SM] Usage: sm_rtv_addmap "); - return Plugin_Handled; + return Plugin_Continue; } - if (!g_CanRTV) - { - ReplyToCommand(client, "[SM] RockTheVote is not available."); - return Plugin_Handled; - } + AttemptRTV(client); - decl String:mapname[64]; - GetCmdArg(1, mapname, sizeof(mapname)); - - if (FindStringInArray(g_MapList, mapname) == -1) - { - ReplyToCommand(client, "%t", "Map was not found", mapname); - return Plugin_Handled; - } - - if (GetArraySize(g_RTVMapList) > 0) - { - if (FindStringInArray(g_RTVMapList, mapname) != -1) - { - ReplyToCommand(client, "%t", "Map Already In Vote", mapname); - return Plugin_Handled; - } - - ShiftArrayUp(g_RTVMapList, 0); - SetArrayString(g_RTVMapList, 0, mapname); - - while (GetArraySize(g_RTVMapList) > GetConVarInt(g_Cvar_Maps)) - { - RemoveFromArray(g_RTVMapList, GetConVarInt(g_Cvar_Maps)); - } - } - else - { - PushArrayString(g_RTVMapList, mapname); - } - - decl String:item[64]; - for (new i = 0; i < GetMenuItemCount(g_MapMenu); i++) - { - GetMenuItem(g_MapMenu, i, item, sizeof(item)); - if (strcmp(item, mapname) == 0) - { - RemoveMenuItem(g_MapMenu, i); - break; - } - } - - ReplyToCommand(client, "%t", "Map Inserted", mapname); - LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); - - return Plugin_Handled; + return Plugin_Continue; } public Action:Command_Say(client, args) @@ -228,7 +172,7 @@ public Action:Command_Say(client, args) { return Plugin_Continue; } - + decl String:text[192]; if (!GetCmdArgString(text, sizeof(text))) { @@ -242,301 +186,120 @@ public Action:Command_Say(client, args) startidx = 1; } + new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); + if (strcmp(text[startidx], "rtv", false) == 0 || strcmp(text[startidx], "rockthevote", false) == 0) { - if (!g_RTVAllowed) - { - PrintToChat(client, "[SM] %t", "RTV Not Allowed"); - return Plugin_Continue; - } - - if (g_RTVEnded) - { - PrintToChat(client, "[SM] %t", "RTV Ended"); - return Plugin_Continue; - } - - if (g_RTVStarted) - { - PrintToChat(client, "[SM] %t", "RTV Started"); - return Plugin_Continue; - } - - if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers) && g_Votes == 0) // Should we keep checking g_Votes here? - { - PrintToChat(client, "[SM] %t", "Minimal Players Not Met"); - return Plugin_Continue; - } - - if (g_Voted[client]) - { - PrintToChat(client, "[SM] %t", "Already Voted"); - return Plugin_Continue; - } - - new String:name[64]; - GetClientName(client, name, sizeof(name)); - - g_Votes++; - g_Voted[client] = true; - - PrintToChatAll("[SM] %t", "RTV Requested", name, g_Votes, g_VotesNeeded); - - if (g_Votes >= g_VotesNeeded) - { - g_RTVStarted = true; - CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); - } - } - else if (GetConVarBool(g_Cvar_Nominate) && strcmp(text[startidx], "nominate", false) == 0) - { - if (g_RTVEnded) - { - PrintToChat(client, "[SM] %t", "RTV Ended"); - return Plugin_Continue; - } - - if (g_RTVStarted) - { - PrintToChat(client, "[SM] %t", "RTV Started"); - return Plugin_Continue; - } - - if (g_Nominated[client]) - { - PrintToChat(client, "[SM] %t", "Already Nominated"); - return Plugin_Continue; - } - - if (GetArraySize(g_RTVMapList) >= GetConVarInt(g_Cvar_Maps)) - { - PrintToChat(client, "[SM] %t", "Max Nominations"); - return Plugin_Continue; - } - - DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER); + AttemptRTV(client); } + SetCmdReplySource(old); + return Plugin_Continue; } +AttemptRTV(client) +{ + if (!g_RTVAllowed || (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished())) + { + ReplyToCommand(client, "[SM] %t", "RTV Not Allowed"); + return; + } + + if (!CanMapChooserStartVote()) + { + ReplyToCommand(client, "[SM] %t", "RTV Started"); + return; + } + + if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers)) + { + ReplyToCommand(client, "[SM] %t", "Minimal Players Not Met"); + return; + } + + if (g_Voted[client]) + { + ReplyToCommand(client, "[SM] %t", "Already Voted"); + return; + } + + new String:name[64]; + GetClientName(client, name, sizeof(name)); + + g_Votes++; + g_Voted[client] = true; + + PrintToChatAll("[SM] %t", "RTV Requested", name, g_Votes, g_VotesNeeded); + + if (g_Votes >= g_VotesNeeded) + { + StartRTV(); + } +} + public Action:Timer_DelayRTV(Handle:timer) { g_RTVAllowed = true; - g_RTVStarted = false; - g_RTVEnded = false; } -public Action:Timer_StartRTV(Handle:timer) +StartRTV() { - if (timer == g_RetryTimer) + if (g_InChange) { - g_RetryTimer = INVALID_HANDLE; + return; } - if (g_RetryTimer != INVALID_HANDLE) + if (HasEndOfMapVoteFinished()) { - return; - } - - if (IsVoteInProgress()) - { - // Can't start a vote, try again in 5 seconds. - g_RetryTimer = CreateTimer(5.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE); - return; - } - - PrintToChatAll("[SM] %t", "RTV Vote Ready"); - - new Handle:MapVoteMenu = CreateMenu(Handler_MapMapVoteMenu, MenuAction:MENU_ACTIONS_ALL); - SetMenuTitle(MapVoteMenu, "Rock The Vote"); - - new Handle:tempMaps = CloneArray(g_MapList); - decl String:map[32]; - - GetCurrentMap(map, sizeof(map)); - new index = FindStringInArray(tempMaps, map); - if (index != -1) - { - RemoveFromArray(tempMaps, index); - } - - // We assume that g_RTVMapList is within the correct limits, based on the logic for nominations - for (new i = 0; i < GetArraySize(g_RTVMapList); i++) - { - GetArrayString(g_RTVMapList, i, map, sizeof(map)); - AddMenuItem(MapVoteMenu, map, map); - - index = FindStringInArray(tempMaps, map); - if (index != -1) + /* Change right now then */ + new String:map[65]; + if (GetNextMap(map, sizeof(map))) { - RemoveFromArray(tempMaps, index); + PrintToChatAll("[SM] %t", "Changing Maps", map); + CreateTimer(5.0, Timer_ChangeMap, _, TIMER_FLAG_NO_MAPCHANGE); + g_InChange = true; + + ResetRTV(); + + g_RTVAllowed = false; } + return; } - new limit = GetConVarInt(g_Cvar_Maps) - GetArraySize(g_RTVMapList); - if (limit > GetArraySize(tempMaps)) + if (CanMapChooserStartVote()) { - limit = GetArraySize(tempMaps); + new MapChange:when = MapChange:GetConVarInt(g_Cvar_ChangeTime); + InitiateMapChooserVote(when); + + ResetRTV(); + + g_RTVAllowed = false; + CreateTimer(GetConVarFloat(g_Cvar_Interval), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); } - - for (new i = 0; i < limit; i++) - { - new b = GetRandomInt(0, GetArraySize(tempMaps) - 1); - GetArrayString(tempMaps, b, map, sizeof(map)); - PushArrayString(g_RTVMapList, map); - AddMenuItem(MapVoteMenu, map, map); - RemoveFromArray(tempMaps, b); - } - - CloseHandle(tempMaps); - - AddMenuItem(MapVoteMenu, "Don't Change", "Don't Change"); - - SetMenuExitButton(MapVoteMenu, false); - VoteMenuToAll(MapVoteMenu, 20); - - LogMessage("[SM] Rockthevote was successfully started."); } -public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp) +ResetRTV() { + g_Votes = 0; + + for (new i=1; i<=MAXPLAYERS; i++) + { + g_Voted[i] = false; + } +} + +public Action:Timer_ChangeMap(Handle:hTimer) +{ + g_InChange = false; + + LogMessage("RTV changing map manually"); + new String:map[65]; - - ResetPack(dp); - ReadPackString(dp, map, sizeof(map)); - - ServerCommand("changelevel \"%s\"", map); + if (GetNextMap(map, sizeof(map))) + { + ServerCommand("changelevel \"%s\"", map); + } return Plugin_Stop; -} - -public Handler_MapMapVoteMenu(Handle:menu, MenuAction:action, param1, param2) -{ - switch (action) - { - case MenuAction_End: - { - CloseHandle(menu); - } - - case MenuAction_Display: - { - decl String:oldTitle[255], String:buffer[255]; - GetMenuTitle(menu, oldTitle, sizeof(oldTitle)); - Format(buffer, sizeof(buffer), "%T", oldTitle, param1); - - new Handle:panel = Handle:param2; - SetPanelTitle(panel, buffer); - } - - case MenuAction_DisplayItem: - { - if (GetMenuItemCount(menu) - 1 == param2) - { - decl String:buffer[255]; - Format(buffer, sizeof(buffer), "%T", "Don't Change", param1); - return RedrawMenuItem(buffer); - } - } - - // Why am I commented out? Because BAIL hasn't decided yet if - // vote notification will be built into the Vote API. - /*case MenuAction_Select: - { - decl String:Name[32], String:Map[32]; - GetClientName(param1, Name, sizeof(Name)); - GetMenuItem(menu, param2, Map, sizeof(Map)); - - PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map); - }*/ - - case MenuAction_VoteCancel: - { - if (param1 == VoteCancel_NoVotes) - { - PrintToChatAll("[SM] %t", "No Votes"); - g_RTVEnded = true; - } - } - - case MenuAction_VoteEnd: - { - new String:map[64]; - - GetMenuItem(menu, param1, map, sizeof(map)); - - if (GetMenuItemCount(menu) - 1 == param1) // This should always match the "Keep Current" option - { - PrintToChatAll("[SM] %t", "Current Map Stays"); - LogMessage("[SM] Rockthevote has ended, current map kept."); - } - else - { - PrintToChatAll("[SM] %t", "Changing Maps", map); - LogMessage("[SM] Rockthevote has ended, changing to map %s.", map); - new Handle:dp; - CreateDataTimer(5.0, Timer_ChangeMap, dp); - WritePackString(dp, map); - } - - g_RTVEnded = true; - } - } - - return 0; -} - -public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) -{ - switch (action) - { - case MenuAction_Select: - { - if (GetArraySize(g_RTVMapList) >= GetConVarInt(g_Cvar_Maps)) - { - PrintToChat(param1, "[SM] %t", "Max Nominations"); - return; - } - - decl String:map[64], String:name[64]; - GetMenuItem(menu, param2, map, sizeof(map)); - - if (FindStringInArray(g_RTVMapList, map) != -1) - { - PrintToChat(param1, "[SM] %t", "Map Already Nominated"); - return; - } - - GetClientName(param1, name, 64); - - PushArrayString(g_RTVMapList, map); - RemoveMenuItem(menu, param2); - - g_Nominated[param1] = true; - - PrintToChatAll("[SM] %t", "Map Nominated", name, map); - } - } -} - -BuildMapMenu() -{ - if (g_MapMenu != INVALID_HANDLE) - { - CloseHandle(g_MapMenu); - g_MapMenu = INVALID_HANDLE; - } - - g_MapMenu = CreateMenu(Handler_MapSelectMenu); - SetMenuTitle(g_MapMenu, "%t", "Nominate Title"); - - decl String:map[64]; - for (new i = 0; i < GetArraySize(g_MapList); i++) - { - GetArrayString(g_MapList, i, map, sizeof(map)); - AddMenuItem(g_MapMenu, map, map); - } - - SetMenuExitButton(g_MapMenu, false); } \ No newline at end of file diff --git a/tools/builder/PkgCore.cs b/tools/builder/PkgCore.cs index 7dca19f5..bb8acab3 100644 --- a/tools/builder/PkgCore.cs +++ b/tools/builder/PkgCore.cs @@ -319,6 +319,7 @@ namespace builder plugins.Add(new Plugin("adminmenu")); plugins.Add(new Plugin("playercommands")); plugins.Add(new Plugin("clientprefs")); + plugins.Add(new Plugin("nominations"), true); return (Plugin [])plugins.ToArray(typeof(Plugin)); } diff --git a/translations/mapchooser.phrases.txt b/translations/mapchooser.phrases.txt index d722df6d..161645c2 100644 --- a/translations/mapchooser.phrases.txt +++ b/translations/mapchooser.phrases.txt @@ -12,17 +12,29 @@ "Nextmap Voting Finished" { - "#format" "{1:s}" - "en" "Map voting has finished. The next map will be {1}." + "#format" "{1:s},{2:i},{3:i}" + "en" "Map voting has finished. The next map will be {1}. (Received {2}%% of {3} votes)" } "Current Map Extended" { - "en" "The current map has been extended." + "#format" "{1:i},{2:i}" + "en" "The current map has been extended. (Received {1}%% of {2} votes)" } "Extend Map" { "en" "Extend Current Map" } + + "Dont Change" + { + "en" "Don't Change" + } + + "Current Map Stays" + { + "#format" "{1:i},{2:i}" + "en" "Current map continues! The Vote has spoken! (Received {1}%% of {2} votes)" + } } diff --git a/translations/nominations.phrases.txt b/translations/nominations.phrases.txt new file mode 100644 index 00000000..df17fe4a --- /dev/null +++ b/translations/nominations.phrases.txt @@ -0,0 +1,48 @@ +"Phrases" +{ + "Already Nominated" + { + "en" "You have already nominated a map." + + } + + "Max Nominations" + { + "en" "The maximum allowed nominations has been reached." + } + + + "Map Already In Vote" + { + "#format" "{1:s}" + "en" "Map '{1}' already in the Nominations list." + } + + "Map Inserted" + { + "#format" "{1:s}" + "en" "Map '{1}' added to the nominations list." + } + + "Map Already Nominated" + { + "en" "The map you chose has already been nominated." + } + + "Map Nominated" + { + "#format" "{1:s},{2:s}" + "en" "{1} has nominated {2}." + } + + "Map Nomination Changed" + { + "#format" "{1:s},{2:s}" + "en" "{1} has changed his nomination to {2}." + } + + "Nominate Title" + { + "en" "Nominate Map:" + } +} \ No newline at end of file diff --git a/translations/rockthevote.phrases.txt b/translations/rockthevote.phrases.txt index c169ead0..8899f81c 100644 --- a/translations/rockthevote.phrases.txt +++ b/translations/rockthevote.phrases.txt @@ -30,18 +30,7 @@ { "en" "The minimal number of players required has not been met." } - - "Map Already In Vote" - { - "#format" "{1:s}" - "en" "Map '{1}' already in the Rock the Vote list." - } - "Map Inserted" - { - "#format" "{1:s}" - "en" "Map '{1}' added to Rock the Vote." - } "RTV Requested" { @@ -60,16 +49,6 @@ "en" "Keep Current Map" } - "Already Nominated" - { - "en" "You have already nominated a map." - - } - - "Max Nominations" - { - "en" "The maximum allowed nominations has been reached." - } "Selected Map" { @@ -92,20 +71,4 @@ "#format" "{1:s}" "en" "Changing map to {1}! Rock the Vote has spoken!" } - - "Map Already Nominated" - { - "en" "The map you chose has already been nominated." - } - - "Map Nominated" - { - "#format" "{1:s},{2:s}" - "en" "{1} has nominated {2} for Rock the Vote." - } - - "Nominate Title" - { - "en" "Nominate Map:" - } } \ No newline at end of file