-- loosely based on MTA's https://code.google.com/p/mtasa-resources/source/browse/trunk/%5Bmanagers%5D/mapmanager/mapmanager_main.lua maps = {} gametypes = {} AddEventHandler('getResourceInitFuncs', function(isPreParse, add) add('resource_type', function(type) return function(params) local resourceName = GetInvokingResource() if type == 'map' then maps[resourceName] = params elseif type == 'gametype' then gametypes[resourceName] = params end end end) add('map', function(file) AddAuxFile(file) end) end) 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)) if type == 'map' then maps[resource] = params elseif type == 'gametype' then gametypes[resource] = params end end end end AddEventHandler('onResourceListRefresh', function() refreshResources() end) refreshResources() AddEventHandler('onResourceStarting', function(resource) if GetNumResourceMetadata(resource, 'map') then -- todo: add file 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) TriggerClientEvent('onClientGameTypeStart', -1, getCurrentGameType()) 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 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 > 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) 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 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