331 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			331 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| -- loosely based on MTA's https://code.google.com/p/mtasa-resources/source/browse/trunk/%5Bmanagers%5D/mapmanager/mapmanager_main.lua
 | |
| 
 | |
| local maps = {}
 | |
| local gametypes = {}
 | |
| 
 | |
| local function refreshResources()
 | |
|     local numResources = GetNumResources()
 | |
| 
 | |
|     for i = 0, numResources - 1 do
 | |
|         local resource = GetResourceByFindIndex(i)
 | |
| 
 | |
|         if GetNumResourceMetadata(resource, 'resource_type') > 0 then
 | |
|             local type = GetResourceMetadata(resource, 'resource_type', 0)
 | |
|             local params = json.decode(GetResourceMetadata(resource, 'resource_type_extra', 0))
 | |
|             
 | |
|             local valid = false
 | |
|             
 | |
|             local games = GetNumResourceMetadata(resource, 'game')
 | |
|             if games > 0 then
 | |
| 				for j = 0, games - 1 do
 | |
| 					local game = GetResourceMetadata(resource, 'game', j)
 | |
| 				
 | |
| 					if game == GetConvar('gamename', 'gta5') or game == 'common' then
 | |
| 						valid = true
 | |
| 					end
 | |
| 				end
 | |
|             end
 | |
| 
 | |
| 			if valid then
 | |
| 				if type == 'map' then
 | |
| 					maps[resource] = params
 | |
| 				elseif type == 'gametype' then
 | |
| 					gametypes[resource] = params
 | |
| 				end
 | |
| 			end
 | |
|         end
 | |
|     end
 | |
| end
 | |
| 
 | |
| AddEventHandler('onResourceListRefresh', function()
 | |
|     refreshResources()
 | |
| end)
 | |
| 
 | |
| refreshResources()
 | |
| 
 | |
| AddEventHandler('onResourceStarting', function(resource)
 | |
|     local num = GetNumResourceMetadata(resource, 'map')
 | |
| 
 | |
|     if num then
 | |
|         for i = 0, num-1 do
 | |
|             local file = GetResourceMetadata(resource, 'map', i)
 | |
| 
 | |
|             if file then
 | |
|                 addMap(file, resource)
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     if maps[resource] then
 | |
|         if getCurrentMap() and getCurrentMap() ~= resource then
 | |
|             if doesMapSupportGameType(getCurrentGameType(), resource) then
 | |
|                 print("Changing map from " .. getCurrentMap() .. " to " .. resource)
 | |
| 
 | |
|                 changeMap(resource)
 | |
|             else
 | |
|                 -- check if there's only one possible game type for the map
 | |
|                 local map = maps[resource]
 | |
|                 local count = 0
 | |
|                 local gt
 | |
| 
 | |
|                 for type, flag in pairs(map.gameTypes) do
 | |
|                     if flag then
 | |
|                         count = count + 1
 | |
|                         gt = type
 | |
|                     end
 | |
|                 end
 | |
| 
 | |
|                 if count == 1 then
 | |
|                     print("Changing map from " .. getCurrentMap() .. " to " .. resource .. " (gt " .. gt .. ")")
 | |
| 
 | |
|                     changeGameType(gt)
 | |
|                     changeMap(resource)
 | |
|                 end
 | |
|             end
 | |
| 
 | |
|             CancelEvent()
 | |
|         end
 | |
|     elseif gametypes[resource] then
 | |
|         if getCurrentGameType() and getCurrentGameType() ~= resource then
 | |
|             print("Changing gametype from " .. getCurrentGameType() .. " to " .. resource)
 | |
| 
 | |
|             changeGameType(resource)
 | |
| 
 | |
|             CancelEvent()
 | |
|         end
 | |
|     end
 | |
| end)
 | |
| 
 | |
| math.randomseed(GetInstanceId())
 | |
| 
 | |
| local currentGameType = nil
 | |
| local currentMap = nil
 | |
| 
 | |
| AddEventHandler('onResourceStart', function(resource)
 | |
|     if maps[resource] then
 | |
|         if not getCurrentGameType() then
 | |
|             for gt, _ in pairs(maps[resource].gameTypes) do
 | |
|                 changeGameType(gt)
 | |
|                 break
 | |
|             end
 | |
|         end
 | |
| 
 | |
|         if getCurrentGameType() and not getCurrentMap() then
 | |
|             if doesMapSupportGameType(currentGameType, resource) then
 | |
|                 if TriggerEvent('onMapStart', resource, maps[resource]) then
 | |
|                     if maps[resource].name then
 | |
|                         print('Started map ' .. maps[resource].name)
 | |
|                         SetMapName(maps[resource].name)
 | |
|                     else
 | |
|                         print('Started map ' .. resource)
 | |
|                         SetMapName(resource)
 | |
|                     end
 | |
| 
 | |
|                     currentMap = resource
 | |
|                 else
 | |
|                     currentMap = nil
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|     elseif gametypes[resource] then
 | |
|         if not getCurrentGameType() then
 | |
|             if TriggerEvent('onGameTypeStart', resource, gametypes[resource]) then
 | |
|                 currentGameType = resource
 | |
| 
 | |
|                 local gtName = gametypes[resource].name or resource
 | |
| 
 | |
|                 SetGameType(gtName)
 | |
| 
 | |
|                 print('Started gametype ' .. gtName)
 | |
| 
 | |
|                 SetTimeout(50, function()
 | |
|                     if not currentMap then
 | |
|                         local possibleMaps = {}
 | |
| 
 | |
|                         for map, data in pairs(maps) do
 | |
|                             if data.gameTypes[currentGameType] then
 | |
|                                 table.insert(possibleMaps, map)
 | |
|                             end
 | |
|                         end
 | |
| 
 | |
|                         if #possibleMaps > 0 then
 | |
|                             local rnd = math.random(#possibleMaps)
 | |
|                             changeMap(possibleMaps[rnd])
 | |
|                         end
 | |
|                     end
 | |
|                 end)
 | |
|             else
 | |
|                 currentGameType = nil
 | |
|             end
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     -- handle starting
 | |
|     loadMap(resource)
 | |
| end)
 | |
| 
 | |
| local function handleRoundEnd()
 | |
| 	local possibleMaps = {}
 | |
| 
 | |
| 	for map, data in pairs(maps) do
 | |
| 		if data.gameTypes[currentGameType] then
 | |
| 			table.insert(possibleMaps, map)
 | |
| 		end
 | |
|     end
 | |
| 
 | |
|     if #possibleMaps > 1 then
 | |
|         local mapname = currentMap
 | |
| 
 | |
|         while mapname == currentMap do
 | |
|             local rnd = math.random(#possibleMaps)
 | |
|             mapname = possibleMaps[rnd]
 | |
|         end
 | |
| 
 | |
|         changeMap(mapname)
 | |
|     elseif #possibleMaps > 0 then
 | |
|         local rnd = math.random(#possibleMaps)
 | |
|         changeMap(possibleMaps[rnd])
 | |
| 	end
 | |
| end
 | |
| 
 | |
| AddEventHandler('mapmanager:roundEnded', function()
 | |
|     -- set a timeout as we don't want to return to a dead environment
 | |
|     SetTimeout(50, handleRoundEnd) -- not a closure as to work around some issue in neolua?
 | |
| end)
 | |
| 
 | |
| function roundEnded()
 | |
|     SetTimeout(50, handleRoundEnd)
 | |
| end
 | |
| 
 | |
| AddEventHandler('onResourceStop', function(resource)
 | |
|     if resource == currentGameType then
 | |
|         TriggerEvent('onGameTypeStop', resource)
 | |
| 
 | |
|         currentGameType = nil
 | |
| 
 | |
|         if currentMap then
 | |
|             StopResource(currentMap)
 | |
|         end
 | |
|     elseif resource == currentMap then
 | |
|         TriggerEvent('onMapStop', resource)
 | |
| 
 | |
|         currentMap = nil
 | |
|     end
 | |
| 
 | |
|     -- unload the map
 | |
|     unloadMap(resource)
 | |
| end)
 | |
| 
 | |
| AddEventHandler('rconCommand', function(commandName, args)
 | |
|     if commandName == 'map' then
 | |
|         if #args ~= 1 then
 | |
|             RconPrint("usage: map [mapname]\n")
 | |
|         end
 | |
| 
 | |
|         if not maps[args[1]] then
 | |
|             RconPrint('no such map ' .. args[1] .. "\n")
 | |
|             CancelEvent()
 | |
| 
 | |
|             return
 | |
|         end
 | |
| 
 | |
|         if currentGameType == nil or not doesMapSupportGameType(currentGameType, args[1]) then
 | |
|             local map = maps[args[1]]
 | |
|             local count = 0
 | |
|             local gt
 | |
| 
 | |
|             for type, flag in pairs(map.gameTypes) do
 | |
|                 if flag then
 | |
|                     count = count + 1
 | |
|                     gt = type
 | |
|                 end
 | |
|             end
 | |
| 
 | |
|             if count == 1 then
 | |
|                 print("Changing map from " .. getCurrentMap() .. " to " .. args[1] .. " (gt " .. gt .. ")")
 | |
| 
 | |
|                 changeGameType(gt)
 | |
|                 changeMap(args[1])
 | |
| 
 | |
|                 RconPrint('map ' .. args[1] .. "\n")
 | |
|             else
 | |
|                 RconPrint('map ' .. args[1] .. ' does not support ' .. currentGameType .. "\n")
 | |
|             end
 | |
| 
 | |
|             CancelEvent()
 | |
| 
 | |
|             return
 | |
|         end
 | |
| 
 | |
|         changeMap(args[1])
 | |
| 
 | |
|         RconPrint('map ' .. args[1] .. "\n")
 | |
| 
 | |
|         CancelEvent()
 | |
|     elseif commandName == 'gametype' then
 | |
|         if #args ~= 1 then
 | |
|             RconPrint("usage: gametype [name]\n")
 | |
|         end
 | |
| 
 | |
|         if not gametypes[args[1]] then
 | |
|             RconPrint('no such gametype ' .. args[1] .. "\n")
 | |
|             CancelEvent()
 | |
| 
 | |
|             return
 | |
|         end
 | |
| 
 | |
|         changeGameType(args[1])
 | |
| 
 | |
|         RconPrint('gametype ' .. args[1] .. "\n")
 | |
| 
 | |
|         CancelEvent()
 | |
|     end
 | |
| end)
 | |
| 
 | |
| function getCurrentGameType()
 | |
|     return currentGameType
 | |
| end
 | |
| 
 | |
| function getCurrentMap()
 | |
|     return currentMap
 | |
| end
 | |
| 
 | |
| function getMaps()
 | |
|     return maps
 | |
| end
 | |
| 
 | |
| function changeGameType(gameType)
 | |
|     if currentMap and not doesMapSupportGameType(gameType, currentMap) then
 | |
|         StopResource(currentMap)
 | |
|     end
 | |
| 
 | |
|     if currentGameType then
 | |
|         StopResource(currentGameType)
 | |
|     end
 | |
| 
 | |
|     StartResource(gameType)
 | |
| end
 | |
| 
 | |
| function changeMap(map)
 | |
|     if currentMap then
 | |
|         StopResource(currentMap)
 | |
|     end
 | |
| 
 | |
|     StartResource(map)
 | |
| end
 | |
| 
 | |
| function doesMapSupportGameType(gameType, map)
 | |
|     if not gametypes[gameType] then
 | |
|         return false
 | |
|     end
 | |
| 
 | |
|     if not maps[map] then
 | |
|         return false
 | |
|     end
 | |
| 
 | |
|     if not maps[map].gameTypes then
 | |
|         return true
 | |
|     end
 | |
| 
 | |
|     return maps[map].gameTypes[gameType]
 | |
| end
 | 
