plugins/mapchooser.sp
author Michael McKoy <ferret99gt@gmail.com>
Fri Oct 05 00:12:14 2007 +0000 (2007-10-05)
changeset 1530 be1fc1042aeb
parent 1529 af7995664ac4
child 1531 766b08c6e6c2
permissions -rw-r--r--
Fixed GetArraySize problem in mapchooser
     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 #pragma semicolon 1
    36 #include <sourcemod>
    37 
    38 public Plugin:myinfo =
    39 {
    40 	name = "MapChooser",
    41 	author = "AlliedModders LLC",
    42 	description = "Automated Map Voting",
    43 	version = SOURCEMOD_VERSION,
    44 	url = "http://www.sourcemod.net/"
    45 };
    46 
    47 new Handle:g_Cvar_Winlimit = INVALID_HANDLE;
    48 new Handle:g_Cvar_Maxrounds = INVALID_HANDLE;
    49 new Handle:g_Cvar_Fraglimit = INVALID_HANDLE;
    50 
    51 new Handle:g_Cvar_Nextmap = INVALID_HANDLE;
    52 
    53 new Handle:g_Cvar_StartTime = INVALID_HANDLE;
    54 new Handle:g_Cvar_StartRounds = INVALID_HANDLE;
    55 new Handle:g_Cvar_StartFrags = INVALID_HANDLE;
    56 new Handle:g_Cvar_ExtendTimeMax = INVALID_HANDLE;
    57 new Handle:g_Cvar_ExtendTimeStep = INVALID_HANDLE;
    58 new Handle:g_Cvar_ExtendRoundMax = INVALID_HANDLE;
    59 new Handle:g_Cvar_ExtendRoundStep = INVALID_HANDLE;
    60 new Handle:g_Cvar_ExtendFragMax = INVALID_HANDLE;
    61 new Handle:g_Cvar_ExtendFragStep = INVALID_HANDLE;
    62 new Handle:g_Cvar_Mapfile = INVALID_HANDLE;
    63 new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE;
    64 new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE;
    65 
    66 new Handle:g_VoteTimer = INVALID_HANDLE;
    67 new Handle:g_RetryTimer = INVALID_HANDLE;
    68 
    69 new Handle:g_MapList = INVALID_HANDLE;
    70 new Handle:g_OldMapList = INVALID_HANDLE;
    71 new Handle:g_NextMapList = INVALID_HANDLE;
    72 new Handle:g_VoteMenu = INVALID_HANDLE;
    73 new Handle:g_TeamScores = INVALID_HANDLE;
    74 
    75 new bool:g_HasVoteStarted;
    76 new g_mapFileTime;
    77 
    78 public OnPluginStart()
    79 {
    80 	LoadTranslations("mapchooser.phrases");
    81 	
    82 	g_MapList = CreateArray(33);
    83 	g_OldMapList = CreateArray(33);
    84 	g_NextMapList = CreateArray(33);
    85 	g_TeamScores = CreateArray(2);
    86 
    87 	g_Cvar_StartTime = CreateConVar("sm_mapvote_start", "3.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0);
    88 	g_Cvar_StartRounds = CreateConVar("sm_mapvote_startround", "2.0", "Specifies when to start the vote based on rounds remaining.", _, true, 1.0);
    89 	g_Cvar_StartFrags = CreateConVar("sm_mapvote_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0);
    90 	g_Cvar_ExtendTimeMax = CreateConVar("sm_extendmap_maxtime", "90", "Specifies the maximum amount of time a map can be extended", _, true, 0.0);
    91 	g_Cvar_ExtendTimeStep = CreateConVar("sm_extendmap_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0);
    92 	g_Cvar_ExtendRoundMax = CreateConVar("sm_extendmap_maxrounds", "30", "Specfies the maximum amount of rounds a map can be extended", _, true, 0.0);
    93 	g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 5.0);
    94 	g_Cvar_ExtendFragMax = CreateConVar("sm_extendmap_maxfrags", "150", "Specfies the maximum frags allowed that a map can be extended.", _, true, 0.0);
    95 	g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0);	
    96 	g_Cvar_Mapfile = CreateConVar("sm_mapvote_file", "configs/maps.ini", "Map file to use. (Def sourcemod/configs/maps.ini)");
    97 	g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0);
    98 	g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0);
    99 
   100 	RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now.");
   101 
   102 	g_Cvar_Winlimit = FindConVar("mp_winlimit");
   103 	g_Cvar_Maxrounds = FindConVar("mp_maxrounds");
   104 	g_Cvar_Fraglimit = FindConVar("mp_fraglimit");
   105 	
   106 	if (g_Cvar_Winlimit != INVALID_HANDLE || g_Cvar_Maxrounds != INVALID_HANDLE)
   107 	{
   108 		HookEvent("round_end", Event_RoundEnd);
   109 	}
   110 	
   111 	if (g_Cvar_Fraglimit != INVALID_HANDLE)
   112 	{
   113 		HookEvent("player_death", Event_PlayerDeath);		
   114 	}
   115 	
   116 	AutoExecConfig(true, "mapchooser");
   117 }
   118 
   119 public OnMapStart()
   120 {
   121 	g_Cvar_Nextmap = FindConVar("sm_nextmap");
   122 
   123 	if (g_Cvar_Nextmap == INVALID_HANDLE)
   124 	{
   125 		LogError("FATAL: Cannot find sm_nextmap cvar. Mapchooser not loaded.");
   126 		SetFailState("sm_nextmap not found");
   127 	}
   128 	
   129 	if (LoadMaps())
   130 	{
   131 		CreateNextVote();
   132 		SetupTimeleftTimer();
   133 	}
   134 }
   135 
   136 public OnMapEnd()
   137 {
   138 	g_HasVoteStarted = false;
   139 	g_RetryTimer = INVALID_HANDLE;
   140 	g_VoteTimer = INVALID_HANDLE;
   141 }
   142 
   143 public OnMapTimeLeftChanged()
   144 {
   145 	if (GetArraySize(g_MapList))
   146 	{
   147 		SetupTimeleftTimer();
   148 	}
   149 }
   150 
   151 SetupTimeleftTimer()
   152 {
   153 	new time;
   154 	if (GetMapTimeLeft(time) && time > 0)
   155 	{
   156 		new startTime = GetConVarInt(g_Cvar_StartTime) * 60;
   157 		if (time - startTime < 0)
   158 		{
   159 			InitiateVote();		
   160 		}
   161 		else
   162 		{
   163 			if (g_VoteTimer != INVALID_HANDLE)
   164 			{
   165 				KillTimer(g_VoteTimer);
   166 				g_VoteTimer = INVALID_HANDLE;
   167 			}	
   168 			
   169 			g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVote, TIMER_FLAG_NO_MAPCHANGE);
   170 		}		
   171 	}
   172 }
   173 
   174 public Action:Timer_StartMapVote(Handle:timer)
   175 {
   176 	if (!GetArraySize(g_MapList))
   177 	{
   178 		return Plugin_Stop;
   179 	}		
   180 	
   181 	if (timer == g_RetryTimer)
   182 	{
   183 		g_RetryTimer = INVALID_HANDLE;
   184 	}
   185 	else
   186 	{
   187 		g_VoteTimer = INVALID_HANDLE;
   188 	}
   189 
   190 	InitiateVote();
   191 
   192 	return Plugin_Stop;
   193 }
   194 
   195 /* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */
   196 public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
   197 {
   198 	if (!GetArraySize(g_MapList) || g_HasVoteStarted)
   199 	{
   200 		return;
   201 	}
   202 
   203 	new winner = GetEventInt(event, "winner");
   204 	
   205 	if (winner == 0 || winner == 1)
   206 	{
   207 		return;
   208 	}
   209 
   210 	static total;
   211 	total++;
   212 	
   213 	new team[2], teamPos = -1;
   214 	for (new i; i < GetArraySize(g_TeamScores); i++)
   215 	{
   216 		GetArrayArray(g_TeamScores, i, team);
   217 		if (team[0] == winner)
   218 		{
   219 			teamPos = i;
   220 			break;
   221 		}		
   222 	}
   223 	
   224 	if (teamPos == -1)
   225 	{
   226 		team[0] = winner;
   227 		team[1] = 1;
   228 		PushArrayArray(g_TeamScores, team);
   229 	}
   230 	else
   231 	{
   232 		team[1]++;
   233 		SetArrayArray(g_TeamScores, teamPos, team);
   234 	}	
   235 	
   236 	if (g_Cvar_Winlimit != INVALID_HANDLE)
   237 	{
   238 		new winlimit = GetConVarInt(g_Cvar_Winlimit);
   239 		if (winlimit)
   240 		{
   241 			if (team[1] >= (winlimit - GetConVarInt(g_Cvar_StartRounds)))
   242 			{
   243 				InitiateVote();
   244 			}
   245 		}
   246 	}
   247 	
   248 	if (g_Cvar_Maxrounds != INVALID_HANDLE)
   249 	{
   250 		new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
   251 		if (maxrounds)
   252 		{
   253 			if (total >= (maxrounds - GetConVarInt(g_Cvar_StartRounds)))
   254 			{
   255 				InitiateVote();
   256 			}			
   257 		}
   258 	}
   259 }
   260 
   261 public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
   262 {
   263 	if (!GetArraySize(g_MapList) || g_Cvar_Fraglimit == INVALID_HANDLE || g_HasVoteStarted)
   264 	{
   265 		return;
   266 	}
   267 	
   268 	if (!GetConVarInt(g_Cvar_Fraglimit))
   269 	{
   270 		return;
   271 	}
   272 
   273 	new fragger = GetClientOfUserId(GetEventInt(event, "attacker"));
   274 	if (fragger && GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags)))
   275 	{
   276 		InitiateVote();
   277 	}
   278 }
   279 
   280 public Action:Command_Mapvote(client, args)
   281 {
   282 	InitiateVote();
   283 
   284 	return Plugin_Handled;	
   285 }
   286 
   287 InitiateVote()
   288 {
   289 	if (g_HasVoteStarted || g_RetryTimer != INVALID_HANDLE)
   290 	{
   291 		return;
   292 	}
   293 	
   294 	if (IsVoteInProgress())
   295 	{
   296 		// Can't start a vote, try again in 5 seconds.
   297 		g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote, TIMER_FLAG_NO_MAPCHANGE);
   298 		return;
   299 	}		
   300 	
   301 	g_HasVoteStarted = true;
   302 	g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
   303 	SetMenuTitle(g_VoteMenu, "Vote Nextmap");
   304 
   305 	decl String:map[32];
   306 	for (new i = 0; i < GetArraySize(g_NextMapList); i++)
   307 	{
   308 		GetArrayString(g_NextMapList, i, map, sizeof(map));
   309 		AddMenuItem(g_VoteMenu, map, map);
   310 	}
   311 
   312 	new bool:allowExtend, time;
   313 	if (GetMapTimeLimit(time) && time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax))
   314 	{
   315 		allowExtend = true;
   316 	}
   317 	
   318 	if (g_Cvar_Winlimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Winlimit) < GetConVarInt(g_Cvar_ExtendRoundMax))
   319 	{
   320 		allowExtend = true;
   321 	}	
   322 	
   323 	if (g_Cvar_Maxrounds != INVALID_HANDLE && GetConVarInt(g_Cvar_Maxrounds) < GetConVarInt(g_Cvar_ExtendRoundMax))
   324 	{
   325 		allowExtend = true;
   326 	}
   327 	
   328 	if (g_Cvar_Fraglimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Fraglimit) < GetConVarInt(g_Cvar_ExtendFragMax))
   329 	{
   330 		allowExtend = true;
   331 	}
   332 
   333 	if (allowExtend)
   334 	{
   335 		AddMenuItem(g_VoteMenu, "##extend##", "Extend Map");
   336 	}
   337 
   338 	SetMenuExitButton(g_VoteMenu, false);
   339 	VoteMenuToAll(g_VoteMenu, 20);
   340 
   341 	LogMessage("Voting for next map has started.");
   342 	PrintToChatAll("[SM] %t", "Nextmap Voting Started");
   343 }
   344 
   345 public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
   346 {
   347 	switch (action)
   348 	{
   349 		case MenuAction_End:
   350 		{
   351 			g_VoteMenu = INVALID_HANDLE;
   352 			CloseHandle(menu);
   353 		}
   354 		
   355 		case MenuAction_Display:
   356 		{
   357 	 		decl String:buffer[255];
   358 			Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1);
   359 
   360 			new Handle:panel = Handle:param2;
   361 			SetPanelTitle(panel, buffer);
   362 		}		
   363 		
   364 		case MenuAction_DisplayItem:
   365 		{
   366 			if (GetMenuItemCount(menu) - 1 == param2)
   367 			{
   368 				decl String:map[64], String:buffer[255];
   369 				GetMenuItem(menu, param2, map, sizeof(map));
   370 				if (strcmp(map, "##extend##", false))
   371 				{
   372 					Format(buffer, sizeof(buffer), "%T", "Extend Map", param1);
   373 					return RedrawMenuItem(buffer);
   374 				}
   375 			}
   376 		}		
   377 
   378 		// Why am I commented out? Because BAIL hasn't decided yet if
   379 		// vote notification will be built into the Vote API.
   380 		/*case MenuAction_Select:
   381 		{
   382 			decl String:Name[32], String:Map[32];
   383 			GetClientName(param1, Name, sizeof(Name));
   384 			GetMenuItem(menu, param2, Map, sizeof(Map));
   385 
   386 			PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map);
   387 		}*/
   388 		
   389 		case MenuAction_VoteCancel:
   390 		{
   391 			// If we receive 0 votes, pick at random.
   392 			if (param1 == VoteCancel_NoVotes)
   393 			{
   394 				new count = GetMenuItemCount(menu);
   395 				new item = GetRandomInt(0, count - 1);
   396 				decl String:map[32];
   397 				GetMenuItem(menu, item, map, sizeof(map));
   398 				
   399 				while (strcmp(map, "##extend##", false) == 0)
   400 				{
   401 					item = GetRandomInt(0, count - 1);
   402 					GetMenuItem(menu, item, map, sizeof(map));
   403 				}
   404 				
   405 				SetNextMap(map);			
   406 			}
   407 			else
   408 			{
   409 				// We were actually cancelled. What should we do?
   410 			}
   411 		}
   412 
   413 		case MenuAction_VoteEnd:
   414 		{
   415 			decl String:map[32];
   416 			GetMenuItem(menu, param1, map, sizeof(map));
   417 
   418 			if (strcmp(map, "##extend##", false) == 0)
   419 			{
   420 				new time;
   421 				if (GetMapTimeLimit(time))
   422 				{
   423 					if (time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax))
   424 					{
   425 						ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60);						
   426 					}
   427 				}
   428 				
   429 				if (g_Cvar_Winlimit != INVALID_HANDLE)
   430 				{
   431 					new winlimit = GetConVarInt(g_Cvar_Winlimit);
   432 					if (winlimit && winlimit < GetConVarInt(g_Cvar_ExtendRoundMax))
   433 					{
   434 						SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep));
   435 					}					
   436 				}
   437 				
   438 				if (g_Cvar_Maxrounds != INVALID_HANDLE)
   439 				{
   440 					new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
   441 					if (maxrounds && maxrounds < GetConVarInt(g_Cvar_ExtendRoundMax))
   442 					{
   443 						SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep));
   444 					}
   445 				}
   446 				
   447 				if (g_Cvar_Fraglimit != INVALID_HANDLE)
   448 				{
   449 					new fraglimit = GetConVarInt(g_Cvar_Fraglimit);
   450 					if (fraglimit && fraglimit < GetConVarInt(g_Cvar_ExtendFragMax))
   451 					{
   452 						SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep));						
   453 					}
   454 				}
   455 
   456 				PrintToChatAll("[SM] %t", "Current Map Extended");
   457 				LogMessage("Voting for next map has finished. The current map has been extended.");
   458 				
   459 				// We extended, so we'll have to vote again.
   460 				g_HasVoteStarted = false;
   461 				CreateNextVote();
   462 				SetupTimeleftTimer();
   463 			}
   464 			else
   465 			{
   466 				SetNextMap(map);
   467 			}
   468 		}
   469 	}
   470 	
   471 	return 0;
   472 }
   473 
   474 SetNextMap(const String:map[])
   475 {
   476 	SetConVarString(g_Cvar_Nextmap, map);
   477 	PushArrayString(g_OldMapList, map);
   478 				
   479 	if (GetArraySize(g_OldMapList) > GetConVarInt(g_Cvar_ExcludeMaps))
   480 	{
   481 		RemoveFromArray(g_OldMapList, 0);
   482 	}
   483 		
   484 	PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map);
   485 	LogMessage("Voting for next map has finished. Nextmap: %s.", map);	
   486 }
   487 
   488 CreateNextVote()
   489 {
   490 	if(g_NextMapList != INVALID_HANDLE)
   491 	{
   492 		ClearArray(g_NextMapList);
   493 	}	
   494 	
   495 	decl String:map[32];
   496 	new limit = (GetConVarInt(g_Cvar_IncludeMaps) < GetArraySize(g_MapList) ? GetConVarInt(g_Cvar_IncludeMaps) : GetArraySize(g_MapList));
   497 	
   498 	new bool:oldMaps = false;
   499 	if (limit > GetConVarInt(g_Cvar_ExcludeMaps))
   500 	{
   501 		limit -= GetArraySize(g_OldMapList);
   502 		oldMaps = true;
   503 	}
   504 	
   505 	for (new i = 0; i < limit; i++)
   506 	{
   507 		new b = GetRandomInt(0, GetArraySize(g_MapList) - 1);
   508 		GetArrayString(g_MapList, b, map, sizeof(map));
   509 		
   510 		while (IsStringInArray(g_NextMapList, map) || (oldMaps && IsStringInArray(g_OldMapList, map)))
   511 		{
   512 			b = GetRandomInt(0, GetArraySize(g_MapList) - 1);
   513 			GetArrayString(g_MapList, b, map, sizeof(map));
   514 		}
   515 		
   516 		PushArrayString(g_NextMapList, map);		
   517 	}
   518 }
   519 
   520 LoadMaps()
   521 {
   522 	new bool:fileFound;
   523 
   524 	decl String:mapPath[256], String:mapFile[64];
   525 	GetConVarString(g_Cvar_Mapfile, mapFile, 64);
   526 	BuildPath(Path_SM, mapPath, sizeof(mapFile), mapFile);
   527 	fileFound = FileExists(mapPath);
   528 	if (!fileFound)
   529 	{
   530 		new Handle:mapCycleFile = FindConVar("mapcyclefile");
   531 		GetConVarString(mapCycleFile, mapPath, sizeof(mapPath));
   532 		fileFound = FileExists(mapPath);
   533 	}
   534 	
   535 	if (!fileFound)
   536 	{
   537 		LogError("Unable to locate sm_mapvote_file or mapcyclefile, no maps loaded.");
   538 		
   539 		if (g_MapList != INVALID_HANDLE)
   540 		{
   541 			ClearArray(g_MapList);
   542 		}
   543 		
   544 		return 0;		
   545 	}
   546 
   547 	// If the file hasn't changed, there's no reason to reload
   548 	// all of the maps.
   549 	new fileTime =  GetFileTime(mapPath, FileTime_LastChange);
   550 	if (g_mapFileTime == fileTime)
   551 	{
   552 		return GetArraySize(g_MapList);
   553 	}
   554 	
   555 	g_mapFileTime = fileTime;
   556 	
   557 	// Reset the array
   558 	if (g_MapList != INVALID_HANDLE)
   559 	{
   560 		ClearArray(g_MapList);
   561 	}
   562 
   563 	LogMessage("[SM] Loading mapchooser map file [%s]", mapPath);
   564 
   565 	new Handle:file = OpenFile(mapPath, "rt");
   566 	if (file == INVALID_HANDLE)
   567 	{
   568 		LogError("[SM] Could not open file: %s", mapPath);
   569 		return 0;
   570 	}
   571 
   572 	decl String:currentMap[32];
   573 	GetCurrentMap(currentMap, sizeof(currentMap));	
   574 	
   575 	decl String:buffer[64], len;
   576 	while (!IsEndOfFile(file) && ReadFileLine(file, buffer, sizeof(buffer)))
   577 	{
   578 		TrimString(buffer);
   579 
   580 		if ((len = StrContains(buffer, ".bsp", false)) != -1)
   581 		{
   582 			buffer[len] = '\0';
   583 		}
   584 
   585 		if (buffer[0] == '\0' || !IsValidConVarChar(buffer[0]) || !IsMapValid(buffer)
   586 			|| strcmp(currentMap, buffer, false) == 0)
   587 		{
   588 			continue;
   589 		}
   590 
   591 		PushArrayString(g_MapList, buffer);
   592 	}
   593 
   594 	CloseHandle(file);
   595 	return GetArraySize(g_MapList);
   596 }