Advertisement
Guest User

Untitled

a guest
Sep 13th, 2012
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.40 KB | None | 0 0
  1. /**
  2. * vim: set ts=4 :
  3. * =============================================================================
  4. * SourceMod Mapchooser Plugin
  5. * Creates a map vote at appropriate times, setting sm_nextmap to the winning
  6. * vote
  7. *
  8. * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
  9. * =============================================================================
  10. *
  11. * This program is free software; you can redistribute it and/or modify it under
  12. * the terms of the GNU General Public License, version 3.0, as published by the
  13. * Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  17. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU General Public License along with
  21. * this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. * As a special exception, AlliedModders LLC gives you permission to link the
  24. * code of this program (as well as its derivative works) to "Half-Life 2," the
  25. * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
  26. * by the Valve Corporation. You must obey the GNU General Public License in
  27. * all respects for all other code used. Additionally, AlliedModders LLC grants
  28. * this exception to all derivative works. AlliedModders LLC defines further
  29. * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
  30. * or <http://www.sourcemod.net/license.php>.
  31. *
  32. * Version: $Id$
  33. */
  34.  
  35. #define DEBUG
  36.  
  37. #if defined DEBUG
  38. #define assert(%1) if (!(%1)) ThrowError("Debug Assertion Failed");
  39. #define assert_msg(%1,%2) if (!(%1)) ThrowError(%2);
  40. #else
  41. #define assert(%1)
  42. #define assert_msg(%1,%2)
  43. #endif
  44.  
  45. #pragma semicolon 1
  46. #include <sourcemod>
  47. #include <mapchooser>
  48. #include <nextmap>
  49.  
  50. public Plugin:myinfo =
  51. {
  52. name = "MapChooser",
  53. author = "AlliedModders LLC",
  54. description = "Automated Map Voting",
  55. version = SOURCEMOD_VERSION,
  56. url = "http://www.sourcemod.net/"
  57. };
  58.  
  59. /* Valve ConVars */
  60. new Handle:g_Cvar_Winlimit = INVALID_HANDLE;
  61. new Handle:g_Cvar_Maxrounds = INVALID_HANDLE;
  62. new Handle:g_Cvar_Fraglimit = INVALID_HANDLE;
  63. new Handle:g_Cvar_Bonusroundtime = INVALID_HANDLE;
  64. new Handle:g_Cvar_MatchClinch = INVALID_HANDLE;
  65.  
  66. /* Plugin ConVars */
  67. new Handle:g_Cvar_StartTime = INVALID_HANDLE;
  68. new Handle:g_Cvar_StartRounds = INVALID_HANDLE;
  69. new Handle:g_Cvar_StartFrags = INVALID_HANDLE;
  70. new Handle:g_Cvar_ExtendTimeStep = INVALID_HANDLE;
  71. new Handle:g_Cvar_ExtendRoundStep = INVALID_HANDLE;
  72. new Handle:g_Cvar_ExtendFragStep = INVALID_HANDLE;
  73. new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE;
  74. new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE;
  75. new Handle:g_Cvar_NoVoteMode = INVALID_HANDLE;
  76. new Handle:g_Cvar_Extend = INVALID_HANDLE;
  77. new Handle:g_Cvar_DontChange = INVALID_HANDLE;
  78. new Handle:g_Cvar_EndOfMapVote = INVALID_HANDLE;
  79. new Handle:g_Cvar_VoteDuration = INVALID_HANDLE;
  80. new Handle:g_Cvar_RunOff = INVALID_HANDLE;
  81. new Handle:g_Cvar_RunOffPercent = INVALID_HANDLE;
  82.  
  83. new Handle:g_VoteTimer = INVALID_HANDLE;
  84. new Handle:g_RetryTimer = INVALID_HANDLE;
  85.  
  86. /* Data Handles */
  87. new Handle:g_MapList = INVALID_HANDLE;
  88. new Handle:g_NominateList = INVALID_HANDLE;
  89. new Handle:g_NominateOwners = INVALID_HANDLE;
  90. new Handle:g_OldMapList = INVALID_HANDLE;
  91. new Handle:g_NextMapList = INVALID_HANDLE;
  92. new Handle:g_VoteMenu = INVALID_HANDLE;
  93.  
  94. new g_Extends;
  95. new g_TotalRounds;
  96. new bool:g_HasVoteStarted;
  97. new bool:g_WaitingForVote;
  98. new bool:g_MapVoteCompleted;
  99. new bool:g_ChangeMapAtRoundEnd;
  100. new bool:g_ChangeMapInProgress;
  101. new bool:g_HasIntermissionStarted = false;
  102. new g_mapFileSerial = -1;
  103.  
  104. new MapChange:g_ChangeTime;
  105.  
  106. new Handle:g_NominationsResetForward = INVALID_HANDLE;
  107. new Handle:g_MapVoteStartedForward = INVALID_HANDLE;
  108.  
  109. /* Upper bound of how many team there could be */
  110. #define MAXTEAMS 10
  111. new g_winCount[MAXTEAMS];
  112.  
  113. #define VOTE_EXTEND "##extend##"
  114. #define VOTE_DONTCHANGE "##dontchange##"
  115.  
  116. public OnPluginStart()
  117. {
  118. LoadTranslations("mapchooser.phrases");
  119. LoadTranslations("common.phrases");
  120.  
  121. new arraySize = ByteCountToCells(33);
  122. g_MapList = CreateArray(arraySize);
  123. g_NominateList = CreateArray(arraySize);
  124. g_NominateOwners = CreateArray(1);
  125. g_OldMapList = CreateArray(arraySize);
  126. g_NextMapList = CreateArray(arraySize);
  127.  
  128. g_Cvar_EndOfMapVote = CreateConVar("sm_mapvote_endvote", "1", "Specifies if MapChooser should run an end of map vote", _, true, 0.0, true, 1.0);
  129. g_Cvar_StartTime = CreateConVar("sm_mapvote_start", "3.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0);
  130. 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);
  131. g_Cvar_StartFrags = CreateConVar("sm_mapvote_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0);
  132. g_Cvar_ExtendTimeStep = CreateConVar("sm_extendmap_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0);
  133. g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 1.0);
  134. g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0);
  135. g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0);
  136. g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0);
  137. 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);
  138. g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "0", "Number of extensions allowed each map.", _, true, 0.0);
  139. g_Cvar_DontChange = CreateConVar("sm_mapvote_dontchange", "1", "Specifies if a 'Don't Change' option should be added to early votes", _, true, 0.0);
  140. g_Cvar_VoteDuration = CreateConVar("sm_mapvote_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0);
  141. g_Cvar_RunOff = CreateConVar("sm_mapvote_runoff", "0", "Hold run of votes if winning choice is less than a certain margin", _, true, 0.0, true, 1.0);
  142. g_Cvar_RunOffPercent = CreateConVar("sm_mapvote_runoffpercent", "50", "If winning choice has less than this percent of votes, hold a runoff", _, true, 0.0, true, 100.0);
  143.  
  144. RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now.");
  145. RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>");
  146.  
  147. g_Cvar_Winlimit = FindConVar("mp_winlimit");
  148. g_Cvar_Maxrounds = FindConVar("mp_maxrounds");
  149. g_Cvar_Fraglimit = FindConVar("mp_fraglimit");
  150. g_Cvar_Bonusroundtime = FindConVar("mp_bonusroundtime");
  151. g_Cvar_MatchClinch = FindConVar("mp_match_can_clinch");
  152.  
  153. if (g_Cvar_Winlimit != INVALID_HANDLE || g_Cvar_Maxrounds != INVALID_HANDLE)
  154. {
  155. decl String:folder[64];
  156. GetGameFolderName(folder, sizeof(folder));
  157.  
  158. if (strcmp(folder, "tf") == 0)
  159. {
  160. HookEvent("teamplay_win_panel", Event_TeamPlayWinPanel);
  161. HookEvent("teamplay_restart_round", Event_TFRestartRound);
  162. HookEvent("arena_win_panel", Event_TeamPlayWinPanel);
  163. }
  164. else if (strcmp(folder, "nucleardawn") == 0)
  165. {
  166. HookEvent("round_win", Event_RoundEnd);
  167. }
  168. else if (strcmp(folder, "csgo") == 0)
  169. {
  170. HookEvent("round_end", Event_RoundEnd);
  171. HookEvent("cs_intermission", Event_Intermission);
  172. HookEvent("announce_phase_end", Event_PhaseEnd);
  173. }
  174. else
  175. {
  176. HookEvent("round_end", Event_RoundEnd);
  177. }
  178. }
  179.  
  180. if (g_Cvar_Fraglimit != INVALID_HANDLE)
  181. {
  182. HookEvent("player_death", Event_PlayerDeath);
  183. }
  184.  
  185. AutoExecConfig(true, "mapchooser");
  186.  
  187. //Change the mp_bonusroundtime max so that we have time to display the vote
  188. //If you display a vote during bonus time good defaults are 17 vote duration and 19 mp_bonustime
  189. if (g_Cvar_Bonusroundtime != INVALID_HANDLE)
  190. {
  191. SetConVarBounds(g_Cvar_Bonusroundtime, ConVarBound_Upper, true, 30.0);
  192. }
  193.  
  194. g_NominationsResetForward = CreateGlobalForward("OnNominationRemoved", ET_Ignore, Param_String, Param_Cell);
  195. g_MapVoteStartedForward = CreateGlobalForward("OnMapVoteStarted", ET_Ignore);
  196. }
  197.  
  198. public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
  199. {
  200. RegPluginLibrary("mapchooser");
  201.  
  202. CreateNative("NominateMap", Native_NominateMap);
  203. CreateNative("RemoveNominationByMap", Native_RemoveNominationByMap);
  204. CreateNative("RemoveNominationByOwner", Native_RemoveNominationByOwner);
  205. CreateNative("InitiateMapChooserVote", Native_InitiateVote);
  206. CreateNative("CanMapChooserStartVote", Native_CanVoteStart);
  207. CreateNative("HasEndOfMapVoteFinished", Native_CheckVoteDone);
  208. CreateNative("GetExcludeMapList", Native_GetExcludeMapList);
  209. CreateNative("GetNominatedMapList", Native_GetNominatedMapList);
  210. CreateNative("EndOfMapVoteEnabled", Native_EndOfMapVoteEnabled);
  211.  
  212. return APLRes_Success;
  213. }
  214.  
  215. public OnConfigsExecuted()
  216. {
  217. if (ReadMapList(g_MapList,
  218. g_mapFileSerial,
  219. "mapchooser",
  220. MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER)
  221. != INVALID_HANDLE)
  222.  
  223. {
  224. if (g_mapFileSerial == -1)
  225. {
  226. LogError("Unable to create a valid map list.");
  227. }
  228. }
  229.  
  230. CreateNextVote();
  231. SetupTimeleftTimer();
  232.  
  233. g_TotalRounds = 0;
  234.  
  235. g_Extends = 0;
  236.  
  237. g_MapVoteCompleted = false;
  238.  
  239. ClearArray(g_NominateList);
  240. ClearArray(g_NominateOwners);
  241.  
  242. for (new i=0; i<MAXTEAMS; i++)
  243. {
  244. g_winCount[i] = 0;
  245. }
  246.  
  247. /* Check if mapchooser will attempt to start mapvote during bonus round time - TF2 Only */
  248. if ((g_Cvar_Bonusroundtime != INVALID_HANDLE) && !GetConVarInt(g_Cvar_StartRounds))
  249. {
  250. if (GetConVarFloat(g_Cvar_Bonusroundtime) <= GetConVarFloat(g_Cvar_VoteDuration))
  251. {
  252. LogError("Warning - Bonus Round Time shorter than Vote Time. Votes during bonus round may not have time to complete");
  253. }
  254. }
  255. }
  256.  
  257. public OnMapEnd()
  258. {
  259. g_HasVoteStarted = false;
  260. g_WaitingForVote = false;
  261. g_ChangeMapAtRoundEnd = false;
  262. g_ChangeMapInProgress = false;
  263. g_HasIntermissionStarted = false;
  264.  
  265. g_VoteTimer = INVALID_HANDLE;
  266. g_RetryTimer = INVALID_HANDLE;
  267.  
  268. decl String:map[32];
  269. GetCurrentMap(map, sizeof(map));
  270. PushArrayString(g_OldMapList, map);
  271.  
  272. if (GetArraySize(g_OldMapList) > GetConVarInt(g_Cvar_ExcludeMaps))
  273. {
  274. RemoveFromArray(g_OldMapList, 0);
  275. }
  276. }
  277.  
  278. public OnClientDisconnect(client)
  279. {
  280. new index = FindValueInArray(g_NominateOwners, client);
  281.  
  282. if (index == -1)
  283. {
  284. return;
  285. }
  286.  
  287. new String:oldmap[33];
  288. GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap));
  289. Call_StartForward(g_NominationsResetForward);
  290. Call_PushString(oldmap);
  291. Call_PushCell(GetArrayCell(g_NominateOwners, index));
  292. Call_Finish();
  293.  
  294. RemoveFromArray(g_NominateOwners, index);
  295. RemoveFromArray(g_NominateList, index);
  296. }
  297.  
  298. public Action:Command_SetNextmap(client, args)
  299. {
  300. if (args < 1)
  301. {
  302. ReplyToCommand(client, "[SM] Usage: sm_setnextmap <map>");
  303. return Plugin_Handled;
  304. }
  305.  
  306. decl String:map[64];
  307. GetCmdArg(1, map, sizeof(map));
  308.  
  309. if (!IsMapValid(map))
  310. {
  311. ReplyToCommand(client, "[SM] %t", "Map was not found", map);
  312. return Plugin_Handled;
  313. }
  314.  
  315. ShowActivity(client, "%t", "Changed Next Map", map);
  316. LogAction(client, -1, "\"%L\" changed nextmap to \"%s\"", client, map);
  317.  
  318. SetNextMap(map);
  319. g_MapVoteCompleted = true;
  320.  
  321. return Plugin_Handled;
  322. }
  323.  
  324. public OnMapTimeLeftChanged()
  325. {
  326. if (GetArraySize(g_MapList))
  327. {
  328. SetupTimeleftTimer();
  329. }
  330. }
  331.  
  332. SetupTimeleftTimer()
  333. {
  334. new time;
  335. if (GetMapTimeLeft(time) && time > 0)
  336. {
  337. new startTime = GetConVarInt(g_Cvar_StartTime) * 60;
  338. if (time - startTime < 0 && GetConVarBool(g_Cvar_EndOfMapVote) && !g_MapVoteCompleted && !g_HasVoteStarted)
  339. {
  340. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  341. }
  342. else
  343. {
  344. if (g_VoteTimer != INVALID_HANDLE)
  345. {
  346. KillTimer(g_VoteTimer);
  347. g_VoteTimer = INVALID_HANDLE;
  348. }
  349.  
  350. //g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE);
  351. new Handle:data;
  352. g_VoteTimer = CreateDataTimer(float(time - startTime), Timer_StartMapVote, data, TIMER_FLAG_NO_MAPCHANGE);
  353. WritePackCell(data, _:MapChange_MapEnd);
  354. WritePackCell(data, _:INVALID_HANDLE);
  355. ResetPack(data);
  356. }
  357. }
  358. }
  359.  
  360. public Action:Timer_StartMapVote(Handle:timer, Handle:data)
  361. {
  362. if (timer == g_RetryTimer)
  363. {
  364. g_WaitingForVote = false;
  365. g_RetryTimer = INVALID_HANDLE;
  366. }
  367. else
  368. {
  369. g_VoteTimer = INVALID_HANDLE;
  370. }
  371.  
  372. if (!GetArraySize(g_MapList) || !GetConVarBool(g_Cvar_EndOfMapVote) || g_MapVoteCompleted || g_HasVoteStarted)
  373. {
  374. return Plugin_Stop;
  375. }
  376.  
  377. new MapChange:mapChange = MapChange:ReadPackCell(data);
  378. new Handle:hndl = Handle:ReadPackCell(data);
  379.  
  380. InitiateVote(mapChange, hndl);
  381.  
  382. return Plugin_Stop;
  383. }
  384.  
  385. public Event_TFRestartRound(Handle:event, const String:name[], bool:dontBroadcast)
  386. {
  387. /* Game got restarted - reset our round count tracking */
  388. g_TotalRounds = 0;
  389. }
  390.  
  391. public Event_TeamPlayWinPanel(Handle:event, const String:name[], bool:dontBroadcast)
  392. {
  393. if (g_ChangeMapAtRoundEnd)
  394. {
  395. g_ChangeMapAtRoundEnd = false;
  396. CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE);
  397. g_ChangeMapInProgress = true;
  398. }
  399.  
  400. new bluescore = GetEventInt(event, "blue_score");
  401. new redscore = GetEventInt(event, "red_score");
  402.  
  403. if(GetEventInt(event, "round_complete") == 1 || StrEqual(name, "arena_win_panel"))
  404. {
  405. g_TotalRounds++;
  406.  
  407. if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted || !GetConVarBool(g_Cvar_EndOfMapVote))
  408. {
  409. return;
  410. }
  411.  
  412. CheckMaxRounds(g_TotalRounds);
  413.  
  414. switch(GetEventInt(event, "winning_team"))
  415. {
  416. case 3:
  417. {
  418. CheckWinLimit(bluescore);
  419. }
  420. case 2:
  421. {
  422. CheckWinLimit(redscore);
  423. }
  424. //We need to do nothing on winning_team == 0 this indicates stalemate.
  425. default:
  426. {
  427. return;
  428. }
  429. }
  430. }
  431. }
  432.  
  433. public Event_Intermission(Handle:event, const String:name[], bool:dontBroadcast)
  434. {
  435. g_HasIntermissionStarted = true;
  436. }
  437.  
  438. public Event_PhaseEnd(Handle:event, const String:name[], bool:dontBroadcast)
  439. {
  440. /* announce_phase_end fires for both half time and the end of the map, but intermission fires first for end of the map. */
  441. if (g_HasIntermissionStarted)
  442. {
  443. return;
  444. }
  445.  
  446. /* No intermission yet, so this must be half time. Swap the score counters. */
  447. new t_score = g_winCount[2];
  448. g_winCount[2] = g_winCount[3];
  449. g_winCount[3] = t_score;
  450. }
  451.  
  452. /* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */
  453. public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
  454. {
  455. if (g_ChangeMapAtRoundEnd)
  456. {
  457. g_ChangeMapAtRoundEnd = false;
  458. CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE);
  459. g_ChangeMapInProgress = true;
  460. }
  461.  
  462. new winner;
  463. if (strcmp(name, "round_win") == 0)
  464. {
  465. // Nuclear Dawn
  466. winner = GetEventInt(event, "team");
  467. }
  468. else
  469. {
  470. winner = GetEventInt(event, "winner");
  471. }
  472.  
  473. if (winner == 0 || winner == 1 || !GetConVarBool(g_Cvar_EndOfMapVote))
  474. {
  475. return;
  476. }
  477.  
  478. if (winner >= MAXTEAMS)
  479. {
  480. SetFailState("Mod exceed maximum team count - Please file a bug report.");
  481. }
  482.  
  483. g_TotalRounds++;
  484.  
  485. g_winCount[winner]++;
  486.  
  487. if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted)
  488. {
  489. return;
  490. }
  491.  
  492. CheckWinLimit(g_winCount[winner]);
  493. CheckMaxRounds(g_TotalRounds);
  494. }
  495.  
  496. public CheckWinLimit(winner_score)
  497. {
  498. if (g_Cvar_Winlimit != INVALID_HANDLE)
  499. {
  500. new winlimit = GetConVarInt(g_Cvar_Winlimit);
  501.  
  502. if (winlimit)
  503. {
  504. if (winner_score >= (winlimit - GetConVarInt(g_Cvar_StartRounds)))
  505. {
  506. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  507. }
  508. }
  509. }
  510.  
  511. if (g_Cvar_MatchClinch != INVALID_HANDLE && g_Cvar_Maxrounds != INVALID_HANDLE)
  512. {
  513. new clinch = GetConVarInt(g_Cvar_MatchClinch);
  514.  
  515. if (clinch)
  516. {
  517. new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
  518. new winlimit = maxrounds / 2;
  519.  
  520. if(winner_score > (winlimit - GetConVarInt(g_Cvar_StartRounds)))
  521. {
  522. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  523. }
  524. }
  525.  
  526. }
  527. }
  528.  
  529. public CheckMaxRounds(roundcount)
  530. {
  531. if (g_Cvar_Maxrounds != INVALID_HANDLE)
  532. {
  533. new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
  534. if (maxrounds)
  535. {
  536. if (roundcount >= (maxrounds - GetConVarInt(g_Cvar_StartRounds)))
  537. {
  538. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  539. }
  540. }
  541. }
  542. }
  543.  
  544. public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
  545. {
  546. if (!GetArraySize(g_MapList) || g_Cvar_Fraglimit == INVALID_HANDLE || g_HasVoteStarted)
  547. {
  548. return;
  549. }
  550.  
  551. if (!GetConVarInt(g_Cvar_Fraglimit) || !GetConVarBool(g_Cvar_EndOfMapVote))
  552. {
  553. return;
  554. }
  555.  
  556. if (g_MapVoteCompleted)
  557. {
  558. return;
  559. }
  560.  
  561. new fragger = GetClientOfUserId(GetEventInt(event, "attacker"));
  562.  
  563. if (!fragger)
  564. {
  565. return;
  566. }
  567.  
  568. if (GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags)))
  569. {
  570. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  571. }
  572. }
  573.  
  574. public Action:Command_Mapvote(client, args)
  575. {
  576. InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
  577.  
  578. return Plugin_Handled;
  579. }
  580.  
  581. /**
  582. * Starts a new map vote
  583. *
  584. * @param when When the resulting map change should occur.
  585. * @param inputlist Optional list of maps to use for the vote, otherwise an internal list of nominations + random maps will be used.
  586. * @param noSpecials Block special vote options like extend/nochange (upgrade this to bitflags instead?)
  587. */
  588. InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
  589. {
  590. g_WaitingForVote = true;
  591.  
  592. if (IsVoteInProgress())
  593. {
  594. // Can't start a vote, try again in 5 seconds.
  595. //g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE);
  596.  
  597. new Handle:data;
  598. g_RetryTimer = CreateDataTimer(5.0, Timer_StartMapVote, data, TIMER_FLAG_NO_MAPCHANGE);
  599. WritePackCell(data, _:when);
  600. WritePackCell(data, _:inputlist);
  601. ResetPack(data);
  602. return;
  603. }
  604.  
  605. /* If the main map vote has completed (and chosen result) and its currently changing (not a delayed change) we block further attempts */
  606. if (g_MapVoteCompleted && g_ChangeMapInProgress)
  607. {
  608. return;
  609. }
  610.  
  611. g_ChangeTime = when;
  612.  
  613. g_WaitingForVote = false;
  614.  
  615. g_HasVoteStarted = true;
  616. g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
  617. SetMenuTitle(g_VoteMenu, "Vote Nextmap");
  618. SetVoteResultCallback(g_VoteMenu, Handler_MapVoteFinished);
  619.  
  620. /* Call OnMapVoteStarted() Forward */
  621. Call_StartForward(g_MapVoteStartedForward);
  622. Call_Finish();
  623.  
  624. /**
  625. * TODO: Make a proper decision on when to clear the nominations list.
  626. * Currently it clears when used, and stays if an external list is provided.
  627. * Is this the right thing to do? External lists will probably come from places
  628. * like sm_mapvote from the adminmenu in the future.
  629. */
  630.  
  631. decl String:map[32];
  632.  
  633. /* No input given - User our internal nominations and maplist */
  634. if (inputlist == INVALID_HANDLE)
  635. {
  636. new nominateCount = GetArraySize(g_NominateList);
  637. new voteSize = GetConVarInt(g_Cvar_IncludeMaps);
  638.  
  639. /* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
  640. new nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount;
  641.  
  642.  
  643. for (new i=0; i<nominationsToAdd; i++)
  644. {
  645. GetArrayString(g_NominateList, i, map, sizeof(map));
  646. AddMenuItem(g_VoteMenu, map, map);
  647. RemoveStringFromArray(g_NextMapList, map);
  648.  
  649. /* Notify Nominations that this map is now free */
  650. Call_StartForward(g_NominationsResetForward);
  651. Call_PushString(map);
  652. Call_PushCell(GetArrayCell(g_NominateOwners, i));
  653. Call_Finish();
  654. }
  655.  
  656. /* Clear out the rest of the nominations array */
  657. for (new i=nominationsToAdd; i<nominateCount; i++)
  658. {
  659. GetArrayString(g_NominateList, i, map, sizeof(map));
  660. /* These maps shouldn't be excluded from the vote as they weren't really nominated at all */
  661.  
  662. /* Notify Nominations that this map is now free */
  663. Call_StartForward(g_NominationsResetForward);
  664. Call_PushString(map);
  665. Call_PushCell(GetArrayCell(g_NominateOwners, i));
  666. Call_Finish();
  667. }
  668.  
  669. /* There should currently be 'nominationsToAdd' unique maps in the vote */
  670.  
  671. new i = nominationsToAdd;
  672. new count = 0;
  673. new availableMaps = GetArraySize(g_NextMapList);
  674.  
  675. while (i < voteSize)
  676. {
  677. GetArrayString(g_NextMapList, count, map, sizeof(map));
  678. count++;
  679.  
  680. /* Insert the map and increment our count */
  681. AddMenuItem(g_VoteMenu, map, map);
  682. i++;
  683.  
  684. if (count >= availableMaps)
  685. {
  686. //Run out of maps, this will have to do.
  687. break;
  688. }
  689. }
  690.  
  691. /* Wipe out our nominations list - Nominations have already been informed of this */
  692. ClearArray(g_NominateOwners);
  693. ClearArray(g_NominateList);
  694. }
  695. else //We were given a list of maps to start the vote with
  696. {
  697. new size = GetArraySize(inputlist);
  698.  
  699. for (new i=0; i<size; i++)
  700. {
  701. GetArrayString(inputlist, i, map, sizeof(map));
  702.  
  703. if (IsMapValid(map))
  704. {
  705. AddMenuItem(g_VoteMenu, map, map);
  706. }
  707. }
  708. }
  709.  
  710. /* Do we add any special items? */
  711. if ((when == MapChange_Instant || when == MapChange_RoundEnd) && GetConVarBool(g_Cvar_DontChange))
  712. {
  713. AddMenuItem(g_VoteMenu, VOTE_DONTCHANGE, "Don't Change");
  714. }
  715. else if (GetConVarBool(g_Cvar_Extend) && g_Extends < GetConVarInt(g_Cvar_Extend))
  716. {
  717. AddMenuItem(g_VoteMenu, VOTE_EXTEND, "Extend Map");
  718. }
  719.  
  720. new voteDuration = GetConVarInt(g_Cvar_VoteDuration);
  721.  
  722. SetMenuExitButton(g_VoteMenu, false);
  723. VoteMenuToAll(g_VoteMenu, voteDuration);
  724.  
  725. LogAction(-1, -1, "Voting for next map has started.");
  726. PrintToChatAll("[SM] %t", "Nextmap Voting Started");
  727. }
  728.  
  729. public Handler_VoteFinishedGeneric(Handle:menu,
  730. num_votes,
  731. num_clients,
  732. const client_info[][2],
  733. num_items,
  734. const item_info[][2])
  735. {
  736. decl String:map[32];
  737. GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map));
  738.  
  739. if (strcmp(map, VOTE_EXTEND, false) == 0)
  740. {
  741. g_Extends++;
  742.  
  743. new time;
  744. if (GetMapTimeLimit(time))
  745. {
  746. if (time > 0)
  747. {
  748. ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60);
  749. }
  750. }
  751.  
  752. if (g_Cvar_Winlimit != INVALID_HANDLE)
  753. {
  754. new winlimit = GetConVarInt(g_Cvar_Winlimit);
  755. if (winlimit)
  756. {
  757. SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep));
  758. }
  759. }
  760.  
  761. if (g_Cvar_Maxrounds != INVALID_HANDLE)
  762. {
  763. new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
  764. if (maxrounds)
  765. {
  766. SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep));
  767. }
  768. }
  769.  
  770. if (g_Cvar_Fraglimit != INVALID_HANDLE)
  771. {
  772. new fraglimit = GetConVarInt(g_Cvar_Fraglimit);
  773. if (fraglimit)
  774. {
  775. SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep));
  776. }
  777. }
  778.  
  779. PrintToChatAll("[SM] %t", "Current Map Extended", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes);
  780. LogAction(-1, -1, "Voting for next map has finished. The current map has been extended.");
  781.  
  782. // We extended, so we'll have to vote again.
  783. g_HasVoteStarted = false;
  784. CreateNextVote();
  785. SetupTimeleftTimer();
  786.  
  787. }
  788. else if (strcmp(map, VOTE_DONTCHANGE, false) == 0)
  789. {
  790. PrintToChatAll("[SM] %t", "Current Map Stays", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes);
  791. LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner");
  792.  
  793. g_HasVoteStarted = false;
  794. CreateNextVote();
  795. SetupTimeleftTimer();
  796. }
  797. else
  798. {
  799. if (g_ChangeTime == MapChange_MapEnd)
  800. {
  801. SetNextMap(map);
  802. }
  803. else if (g_ChangeTime == MapChange_Instant)
  804. {
  805. new Handle:data;
  806. CreateDataTimer(2.0, Timer_ChangeMap, data);
  807. WritePackString(data, map);
  808. g_ChangeMapInProgress = false;
  809. }
  810. else // MapChange_RoundEnd
  811. {
  812. SetNextMap(map);
  813. g_ChangeMapAtRoundEnd = true;
  814. }
  815.  
  816. g_HasVoteStarted = false;
  817. g_MapVoteCompleted = true;
  818.  
  819. PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes);
  820. LogAction(-1, -1, "Voting for next map has finished. Nextmap: %s.", map);
  821. }
  822. }
  823.  
  824. public Handler_MapVoteFinished(Handle:menu,
  825. num_votes,
  826. num_clients,
  827. const client_info[][2],
  828. num_items,
  829. const item_info[][2])
  830. {
  831. if (GetConVarBool(g_Cvar_RunOff) && num_items > 1)
  832. {
  833. new Float:winningvotes = float(item_info[0][VOTEINFO_ITEM_VOTES]);
  834. new Float:required = num_votes * (GetConVarFloat(g_Cvar_RunOffPercent) / 100.0);
  835.  
  836. if (winningvotes <= required)
  837. {
  838. /* Insufficient Winning margin - Lets do a runoff */
  839. g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
  840. SetMenuTitle(g_VoteMenu, "Runoff Vote Nextmap");
  841. SetVoteResultCallback(g_VoteMenu, Handler_VoteFinishedGeneric);
  842.  
  843. decl String:map[32];
  844. decl String:info1[32];
  845. decl String:info2[32];
  846.  
  847. GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info1, sizeof(info1));
  848. AddMenuItem(g_VoteMenu, map, info1);
  849. GetMenuItem(menu, item_info[1][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info2, sizeof(info2));
  850. AddMenuItem(g_VoteMenu, map, info2);
  851.  
  852. new voteDuration = GetConVarInt(g_Cvar_VoteDuration);
  853. SetMenuExitButton(g_VoteMenu, false);
  854. VoteMenuToAll(g_VoteMenu, voteDuration);
  855.  
  856. /* Notify */
  857. new Float:map1percent = float(item_info[0][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
  858. new Float:map2percent = float(item_info[1][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
  859.  
  860.  
  861. PrintToChatAll("[SM] %t", "Starting Runoff", GetConVarFloat(g_Cvar_RunOffPercent), info1, map1percent, info2, map2percent);
  862. LogMessage("Voting for next map was indecisive, beginning runoff vote");
  863.  
  864. return;
  865. }
  866. }
  867.  
  868. Handler_VoteFinishedGeneric(menu, num_votes, num_clients, client_info, num_items, item_info);
  869. }
  870.  
  871. public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
  872. {
  873. switch (action)
  874. {
  875. case MenuAction_End:
  876. {
  877. g_VoteMenu = INVALID_HANDLE;
  878. CloseHandle(menu);
  879. }
  880.  
  881. case MenuAction_Display:
  882. {
  883. decl String:buffer[255];
  884. Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1);
  885.  
  886. new Handle:panel = Handle:param2;
  887. SetPanelTitle(panel, buffer);
  888. }
  889.  
  890. case MenuAction_DisplayItem:
  891. {
  892. if (GetMenuItemCount(menu) - 1 == param2)
  893. {
  894. decl String:map[64], String:buffer[255];
  895. GetMenuItem(menu, param2, map, sizeof(map));
  896. if (strcmp(map, VOTE_EXTEND, false) == 0)
  897. {
  898. Format(buffer, sizeof(buffer), "%T", "Extend Map", param1);
  899. return RedrawMenuItem(buffer);
  900. }
  901. else if (strcmp(map, VOTE_DONTCHANGE, false) == 0)
  902. {
  903. Format(buffer, sizeof(buffer), "%T", "Dont Change", param1);
  904. return RedrawMenuItem(buffer);
  905. }
  906. }
  907. }
  908.  
  909. case MenuAction_VoteCancel:
  910. {
  911. // If we receive 0 votes, pick at random.
  912. if (param1 == VoteCancel_NoVotes && GetConVarBool(g_Cvar_NoVoteMode))
  913. {
  914. new count = GetMenuItemCount(menu);
  915. new item = GetRandomInt(0, count - 1);
  916. decl String:map[32];
  917. GetMenuItem(menu, item, map, sizeof(map));
  918.  
  919. while (strcmp(map, VOTE_EXTEND, false) == 0)
  920. {
  921. item = GetRandomInt(0, count - 1);
  922. GetMenuItem(menu, item, map, sizeof(map));
  923. }
  924.  
  925. SetNextMap(map);
  926. }
  927. else
  928. {
  929. // We were actually cancelled. I guess we do nothing.
  930. }
  931.  
  932. g_HasVoteStarted = false;
  933. g_MapVoteCompleted = true;
  934. }
  935. }
  936.  
  937. return 0;
  938. }
  939.  
  940. public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp)
  941. {
  942. g_ChangeMapInProgress = false;
  943.  
  944. new String:map[65];
  945.  
  946. if (dp == INVALID_HANDLE)
  947. {
  948. if (!GetNextMap(map, sizeof(map)))
  949. {
  950. //No passed map and no set nextmap. fail!
  951. return Plugin_Stop;
  952. }
  953. }
  954. else
  955. {
  956. ResetPack(dp);
  957. ReadPackString(dp, map, sizeof(map));
  958. }
  959.  
  960. ForceChangeLevel(map, "Map Vote");
  961.  
  962. return Plugin_Stop;
  963. }
  964.  
  965. bool:RemoveStringFromArray(Handle:array, String:str[])
  966. {
  967. new index = FindStringInArray(array, str);
  968. if (index != -1)
  969. {
  970. RemoveFromArray(array, index);
  971. return true;
  972. }
  973.  
  974. return false;
  975. }
  976.  
  977. CreateNextVote()
  978. {
  979. assert(g_NextMapList)
  980. ClearArray(g_NextMapList);
  981.  
  982. decl String:map[32];
  983. new Handle:tempMaps = CloneArray(g_MapList);
  984.  
  985. if (GetArraySize(tempMaps) > 1)
  986. {
  987. GetCurrentMap(map, sizeof(map));
  988. RemoveStringFromArray(tempMaps, map);
  989.  
  990. if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps))
  991. {
  992. for (new i = 0; i < GetArraySize(g_OldMapList); i++)
  993. {
  994. GetArrayString(g_OldMapList, i, map, sizeof(map));
  995. RemoveStringFromArray(tempMaps, map);
  996. }
  997. }
  998.  
  999. new limit = (GetConVarInt(g_Cvar_IncludeMaps) < GetArraySize(tempMaps) ? GetConVarInt(g_Cvar_IncludeMaps) : GetArraySize(tempMaps));
  1000. for (new i = 0; i < limit; i++)
  1001. {
  1002. new b = GetRandomInt(0, GetArraySize(tempMaps) - 1);
  1003. GetArrayString(tempMaps, b, map, sizeof(map));
  1004. PushArrayString(g_NextMapList, map);
  1005. RemoveFromArray(tempMaps, b);
  1006. }
  1007. }
  1008. else
  1009. {
  1010. GetArrayString(tempMaps, 0, map, sizeof(map));
  1011. PushArrayString(g_NextMapList, map);
  1012. }
  1013.  
  1014. CloseHandle(tempMaps);
  1015. }
  1016.  
  1017. bool:CanVoteStart()
  1018. {
  1019. if (g_WaitingForVote || g_HasVoteStarted)
  1020. {
  1021. return false;
  1022. }
  1023.  
  1024. return true;
  1025. }
  1026.  
  1027. NominateResult:InternalNominateMap(String:map[], bool:force, owner)
  1028. {
  1029. if (!IsMapValid(map))
  1030. {
  1031. return Nominate_InvalidMap;
  1032. }
  1033.  
  1034. new index;
  1035.  
  1036. /* Look to replace an existing nomination by this client - Nominations made with owner = 0 aren't replaced */
  1037. if (owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1))
  1038. {
  1039. new String:oldmap[33];
  1040. GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap));
  1041. Call_StartForward(g_NominationsResetForward);
  1042. Call_PushString(oldmap);
  1043. Call_PushCell(owner);
  1044. Call_Finish();
  1045.  
  1046. SetArrayString(g_NominateList, index, map);
  1047. return Nominate_Replaced;
  1048. }
  1049.  
  1050. /* Too many nominated maps. */
  1051. if (GetArraySize(g_NominateList) >= GetConVarInt(g_Cvar_IncludeMaps) && !force)
  1052. {
  1053. return Nominate_VoteFull;
  1054. }
  1055.  
  1056. /* Map already in the vote */
  1057. if (FindStringInArray(g_NominateList, map) != -1)
  1058. {
  1059. return Nominate_AlreadyInVote;
  1060. }
  1061.  
  1062.  
  1063. PushArrayString(g_NominateList, map);
  1064. PushArrayCell(g_NominateOwners, owner);
  1065.  
  1066. while (GetArraySize(g_NominateList) > GetConVarInt(g_Cvar_IncludeMaps))
  1067. {
  1068. new String:oldmap[33];
  1069. GetArrayString(g_NominateList, 0, oldmap, sizeof(oldmap));
  1070. Call_StartForward(g_NominationsResetForward);
  1071. Call_PushString(oldmap);
  1072. Call_PushCell(GetArrayCell(g_NominateOwners, 0));
  1073. Call_Finish();
  1074.  
  1075. RemoveFromArray(g_NominateList, 0);
  1076. RemoveFromArray(g_NominateOwners, 0);
  1077. }
  1078.  
  1079. return Nominate_Added;
  1080. }
  1081.  
  1082. /* Add natives to allow nominate and initiate vote to be call */
  1083.  
  1084. /* native bool:NominateMap(const String:map[], bool:force, &NominateError:error); */
  1085. public Native_NominateMap(Handle:plugin, numParams)
  1086. {
  1087. new len;
  1088. GetNativeStringLength(1, len);
  1089.  
  1090. if (len <= 0)
  1091. {
  1092. return false;
  1093. }
  1094.  
  1095. new String:map[len+1];
  1096. GetNativeString(1, map, len+1);
  1097.  
  1098. return _:InternalNominateMap(map, GetNativeCell(2), GetNativeCell(3));
  1099. }
  1100.  
  1101. bool:InternalRemoveNominationByMap(String:map[])
  1102. {
  1103. for (new i = 0; i < GetArraySize(g_NominateList); i++)
  1104. {
  1105. new String:oldmap[33];
  1106. GetArrayString(g_NominateList, i, oldmap, sizeof(oldmap));
  1107.  
  1108. if(strcmp(map, oldmap, false) == 0)
  1109. {
  1110. Call_StartForward(g_NominationsResetForward);
  1111. Call_PushString(oldmap);
  1112. Call_PushCell(GetArrayCell(g_NominateOwners, i));
  1113. Call_Finish();
  1114.  
  1115. RemoveFromArray(g_NominateList, i);
  1116. RemoveFromArray(g_NominateOwners, i);
  1117.  
  1118. return true;
  1119. }
  1120. }
  1121.  
  1122. return false;
  1123. }
  1124.  
  1125. /* native bool:RemoveNominationByMap(const String:map[]); */
  1126. public Native_RemoveNominationByMap(Handle:plugin, numParams)
  1127. {
  1128. new len;
  1129. GetNativeStringLength(1, len);
  1130.  
  1131. if (len <= 0)
  1132. {
  1133. return false;
  1134. }
  1135.  
  1136. new String:map[len+1];
  1137. GetNativeString(1, map, len+1);
  1138.  
  1139. return _:InternalRemoveNominationByMap(map);
  1140. }
  1141.  
  1142. bool:InternalRemoveNominationByOwner(owner)
  1143. {
  1144. new index;
  1145.  
  1146. if (owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1))
  1147. {
  1148. new String:oldmap[33];
  1149. GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap));
  1150.  
  1151. Call_StartForward(g_NominationsResetForward);
  1152. Call_PushString(oldmap);
  1153. Call_PushCell(owner);
  1154. Call_Finish();
  1155.  
  1156. RemoveFromArray(g_NominateList, index);
  1157. RemoveFromArray(g_NominateOwners, index);
  1158.  
  1159. return true;
  1160. }
  1161.  
  1162. return false;
  1163. }
  1164.  
  1165. /* native bool:RemoveNominationByOwner(owner); */
  1166. public Native_RemoveNominationByOwner(Handle:plugin, numParams)
  1167. {
  1168. return _:InternalRemoveNominationByOwner(GetNativeCell(1));
  1169. }
  1170.  
  1171. /* native InitiateMapChooserVote(); */
  1172. public Native_InitiateVote(Handle:plugin, numParams)
  1173. {
  1174. new MapChange:when = MapChange:GetNativeCell(1);
  1175. new Handle:inputarray = Handle:GetNativeCell(2);
  1176.  
  1177. LogAction(-1, -1, "Starting map vote because outside request");
  1178. InitiateVote(when, inputarray);
  1179. }
  1180.  
  1181. public Native_CanVoteStart(Handle:plugin, numParams)
  1182. {
  1183. return CanVoteStart();
  1184. }
  1185.  
  1186. public Native_CheckVoteDone(Handle:plugin, numParams)
  1187. {
  1188. return g_MapVoteCompleted;
  1189. }
  1190.  
  1191. public Native_EndOfMapVoteEnabled(Handle:plugin, numParams)
  1192. {
  1193. return GetConVarBool(g_Cvar_EndOfMapVote);
  1194. }
  1195.  
  1196. public Native_GetExcludeMapList(Handle:plugin, numParams)
  1197. {
  1198. new Handle:array = Handle:GetNativeCell(1);
  1199.  
  1200. if (array == INVALID_HANDLE)
  1201. {
  1202. return;
  1203. }
  1204. new size = GetArraySize(g_OldMapList);
  1205. decl String:map[33];
  1206.  
  1207. for (new i=0; i<size; i++)
  1208. {
  1209. GetArrayString(g_OldMapList, i, map, sizeof(map));
  1210. PushArrayString(array, map);
  1211. }
  1212.  
  1213. return;
  1214. }
  1215.  
  1216. public Native_GetNominatedMapList(Handle:plugin, numParams)
  1217. {
  1218. new Handle:maparray = Handle:GetNativeCell(1);
  1219. new Handle:ownerarray = Handle:GetNativeCell(2);
  1220.  
  1221. if (maparray == INVALID_HANDLE)
  1222. return;
  1223.  
  1224. decl String:map[33];
  1225.  
  1226. for (new i = 0; i < GetArraySize(g_NominateList); i++)
  1227. {
  1228. GetArrayString(g_NominateList, i, map, sizeof(map));
  1229. PushArrayString(maparray, map);
  1230.  
  1231. // If the optional parameter for an owner list was passed, then we need to fill that out as well
  1232. if(ownerarray != INVALID_HANDLE)
  1233. {
  1234. new index = GetArrayCell(g_NominateOwners, i);
  1235. PushArrayCell(ownerarray, index);
  1236. }
  1237. }
  1238.  
  1239. return;
  1240. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement