Advertisement
IsaacSin

Limited Play Again

Dec 14th, 2013
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.45 KB | None | 0 0
  1. --
  2. -- racemidvote_server.lua
  3. --
  4. -- Mid-race random map vote and
  5. -- NextMapVote handled in this file
  6. --
  7.  
  8. local lastVoteStarterName = ''
  9. local lastVoteStarterCount = 0
  10.  
  11. ----------------------------------------------------------------------------
  12. -- displayHilariarseMessage
  13. --
  14. -- Comedy gold
  15. ----------------------------------------------------------------------------
  16. function displayHilariarseMessage( player )
  17.     if not player then
  18.         lastVoteStarterName = ''
  19.     else
  20.         local playerName = getPlayerName(player)
  21.         local msg = ''
  22.         if playerName == lastVoteStarterName then
  23.             lastVoteStarterCount = lastVoteStarterCount + 1
  24.             if lastVoteStarterCount == 5 then
  25.                 msg = playerName .. ' started a vote. Hardly a suprise.'
  26.             elseif lastVoteStarterCount == 10 then
  27.                 msg = 'Guess what! '..playerName .. ' started ANOTHER vote!'
  28.             elseif lastVoteStarterCount < 5 then
  29.                 msg = playerName .. ' started another vote.'
  30.             else
  31.                 msg = playerName .. ' continues to abuse the vote system.'
  32.             end
  33.         else
  34.             lastVoteStarterCount = 0
  35.             lastVoteStarterName = playerName
  36.             msg = playerName .. ' started a vote.'
  37.         end
  38.         outputRace( msg )
  39.     end
  40. end
  41.  
  42.  
  43. ----------------------------------------------------------------------------
  44. -- displayKillerPunchLine
  45. --
  46. -- Sewing kits available in the foyer
  47. ----------------------------------------------------------------------------
  48. function displayKillerPunchLine( player )
  49.     if lastVoteStarterName ~= '' then
  50.         outputRace( 'Offical news: Everybody hates ' .. lastVoteStarterName )
  51.     end
  52. end
  53.  
  54.  
  55. ----------------------------------------------------------------------------
  56. -- startMidMapVoteForRandomMap
  57. --
  58. -- Start the vote menu if during a race and more than 30 seconds from the end
  59. -- No messages if this was not started by a player
  60. ----------------------------------------------------------------------------
  61. function startMidMapVoteForRandomMap(player)
  62.  
  63.     -- Check state and race time left
  64.     if not stateAllowsRandomMapVote() or g_CurrentRaceMode:getTimeRemaining() < 30000 then
  65.         if player then
  66.             outputRace( "I'm afraid I can't let you do that, " .. getPlayerName(player) .. ".", player )
  67.         end
  68.         return
  69.     end
  70.  
  71.     displayHilariarseMessage( player )
  72.     exports.votemanager:stopPoll()
  73.  
  74.     -- Actual vote started here
  75.     local pollDidStart = exports.votemanager:startPoll {
  76.             title='Do you want to change to a random map?',
  77.             percentage=51,
  78.             timeout=15,
  79.             allowchange=true,
  80.             visibleTo=getRootElement(),
  81.             [1]={'Yes', 'midMapVoteResult', getRootElement(), true},
  82.             [2]={'No', 'midMapVoteResult', getRootElement(), false;default=true},
  83.     }
  84.  
  85.     -- Change state if vote did start
  86.     if pollDidStart then
  87.         gotoState('MidMapVote')
  88.     end
  89.  
  90. end
  91. addCommandHandler('new',startMidMapVoteForRandomMap)
  92.  
  93.  
  94. ----------------------------------------------------------------------------
  95. -- event midMapVoteResult
  96. --
  97. -- Called from the votemanager when the poll has completed
  98. ----------------------------------------------------------------------------
  99. addEvent('midMapVoteResult')
  100. addEventHandler('midMapVoteResult', getRootElement(),
  101.     function( votedYes )
  102.         -- Change state back
  103.         if stateAllowsRandomMapVoteResult() then
  104.             gotoState('Running')
  105.             if votedYes then
  106.                 g_playAgainCount = 0
  107.                 startRandomMap()
  108.             else
  109.                 displayKillerPunchLine()
  110.             end
  111.         end
  112.     end
  113. )
  114.  
  115.  
  116.  
  117. ----------------------------------------------------------------------------
  118. -- startRandomMap
  119. --
  120. -- Changes the current map to a random race map
  121. ----------------------------------------------------------------------------
  122. function startRandomMap()
  123.  
  124.     -- Handle forced nextmap setting
  125.     if maybeApplyForcedNextMap() then
  126.         return
  127.     end
  128.  
  129.     -- Get a random map chosen from the 10% of least recently player maps, with enough spawn points for all the players (if required)
  130.     local map = getRandomMapCompatibleWithGamemode( getThisResource(), 10, g_GameOptions.ghostmode and 0 or getTotalPlayerCount() )
  131.     if map then
  132.         g_IgnoreSpawnCountProblems = map    -- Uber hack 4000
  133.         if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  134.             problemChangingMap()
  135.         end
  136.     else
  137.         outputWarning( 'startRandomMap failed' )
  138.     end
  139. end
  140.  
  141.  
  142. ----------------------------------------------------------------------------
  143. -- outputRace
  144. --
  145. -- Race color is defined in the settings
  146. ----------------------------------------------------------------------------
  147. function outputRace(message, toElement)
  148.     toElement = toElement or g_Root
  149.     local r, g, b = getColorFromString(string.upper(get("color")))
  150.     if getElementType(toElement) == 'console' then
  151.         outputServerLog(message)
  152.     else
  153.         if toElement == rootElement then
  154.             outputServerLog(message)
  155.         end
  156.         if getElementType(toElement) == 'player' then
  157.             message = '[PM] ' .. message
  158.         end
  159.         outputChatBox(message, toElement, r, g, b)
  160.     end
  161. end
  162.  
  163.  
  164. ----------------------------------------------------------------------------
  165. -- problemChangingMap
  166. --
  167. -- Sort it
  168. ----------------------------------------------------------------------------
  169. function problemChangingMap()
  170.     outputRace( 'Changing to random map in 5 seconds' )
  171.     local currentMap = exports.mapmanager:getRunningGamemodeMap()
  172.     TimerManager.createTimerFor("resource","mapproblem"):setTimer(
  173.         function()
  174.             -- Check that something else hasn't already changed the map
  175.             if currentMap == exports.mapmanager:getRunningGamemodeMap() then
  176.                 startRandomMap()
  177.             end
  178.         end,
  179.         math.random(4500,5500), 1 )
  180. end
  181.  
  182.  
  183.  
  184. --
  185. --
  186. -- NextMapVote
  187. --
  188. --
  189. --
  190.  
  191. local g_Poll
  192.  
  193. ----------------------------------------------------------------------------
  194. -- startNextMapVote
  195. --
  196. -- Start a votemap for the next map. Should only be called during the
  197. -- race state 'NextMapSelect'
  198. ----------------------------------------------------------------------------
  199. function startNextMapVote()
  200.  
  201.     exports.votemanager:stopPoll()
  202.  
  203.     -- Handle forced nextmap setting
  204.     if maybeApplyForcedNextMap() then
  205.         return
  206.     end
  207.  
  208.     -- Get all maps
  209.     local compatibleMaps = exports.mapmanager:getMapsCompatibleWithGamemode(getThisResource())
  210.    
  211.     -- limit it to eight random maps
  212.     if #compatibleMaps > 5 then
  213.         math.randomseed(getTickCount())
  214.         repeat
  215.             table.remove(compatibleMaps, math.random(1, #compatibleMaps))
  216.         until #compatibleMaps == 5
  217.     elseif #compatibleMaps < 2 then
  218.         return false, errorCode.onlyOneCompatibleMap
  219.     end
  220.  
  221.     -- mix up the list order
  222.     for i,map in ipairs(compatibleMaps) do
  223.         local swapWith = math.random(1, #compatibleMaps)
  224.         local temp = compatibleMaps[i]
  225.         compatibleMaps[i] = compatibleMaps[swapWith]
  226.         compatibleMaps[swapWith] = temp
  227.     end
  228.    
  229.     local poll = {
  230.         title="Choose the next map:",
  231.         visibleTo=getRootElement(),
  232.         percentage=51,
  233.         timeout=15,
  234.         allowchange=true;
  235.         }
  236.    
  237.     for index, map in ipairs(compatibleMaps) do
  238.         local mapName = getResourceInfo(map, "name") or getResourceName(map)
  239.         table.insert(poll, {mapName, 'nextMapVoteResult', getRootElement(), map})
  240.     end
  241.    
  242.     if not g_playAgainCount then
  243.         g_playAgainCount = 0
  244.     end
  245.    
  246.     g_currentMap = exports.mapmanager:getRunningGamemodeMap()
  247.     if g_currentMap then
  248.         -- Modify this to change play again limit. Obviously 2 PlayAgains = 3 plays of the map total
  249.         if g_playAgainCount < 2 then
  250.             table.insert(poll, {"Play again (" .. g_playAgainCount + 1 .. "/2)", 'nextMapVoteResult', getRootElement(), g_currentMap})
  251.         end
  252.     end
  253.  
  254.     -- Allow addons to modify the poll
  255.     g_Poll = poll
  256.     triggerEvent('onPollStarting', g_Root, poll )
  257.     poll = g_Poll
  258.     g_Poll = nil
  259.  
  260.     local pollDidStart = exports.votemanager:startPoll(poll)
  261.  
  262.     if pollDidStart then
  263.         gotoState('NextMapVote')
  264.         addEventHandler("onPollEnd", getRootElement(), chooseRandomMap)
  265.     end
  266.  
  267.     return pollDidStart
  268. end
  269.  
  270.  
  271. -- Used by addons in response to onPollStarting
  272. addEvent('onPollModified')
  273. addEventHandler('onPollModified', getRootElement(),
  274.     function( poll )
  275.         g_Poll = poll
  276.     end
  277. )
  278.  
  279.  
  280. function chooseRandomMap (chosen)
  281.     if not chosen then
  282.         cancelEvent()
  283.         math.randomseed(getTickCount())
  284.         exports.votemanager:finishPoll(1)
  285.     end
  286.     removeEventHandler("onPollEnd", getRootElement(), chooseRandomMap)
  287. end
  288.  
  289.  
  290.  
  291. ----------------------------------------------------------------------------
  292. -- event nextMapVoteResult
  293. --
  294. -- Called from the votemanager when the poll has completed
  295. ----------------------------------------------------------------------------
  296. addEvent('nextMapVoteResult')
  297. addEventHandler('nextMapVoteResult', getRootElement(),
  298.     function( map )
  299.         if map == g_currentMap then
  300.             g_playAgainCount = g_playAgainCount + 1
  301.         else
  302.             g_playAgainCount = 0
  303.         end
  304.         if stateAllowsNextMapVoteResult() then
  305.             if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  306.                 problemChangingMap()
  307.             end
  308.         end
  309.     end
  310. )
  311.  
  312.  
  313.  
  314. ----------------------------------------------------------------------------
  315. -- startMidMapVoteForRestartMap
  316. --
  317. -- Start the vote menu to restart the current map if during a race
  318. -- No messages if this was not started by a player
  319. ----------------------------------------------------------------------------
  320. function startMidMapVoteForRestartMap(player)
  321.  
  322.     -- Check state and race time left
  323.     if not stateAllowsRestartMapVote() then
  324.         if player then
  325.             outputRace( "I'm afraid I can't let you do that, " .. getPlayerName(player) .. ".", player )
  326.         end
  327.         return
  328.     end
  329.  
  330.     displayHilariarseMessage( player )
  331.     exports.votemanager:stopPoll()
  332.  
  333.     -- Actual vote started here
  334.     local pollDidStart = exports.votemanager:startPoll {
  335.             title='Do you want to restart the current map?',
  336.             percentage=51,
  337.             timeout=15,
  338.             allowchange=true,
  339.             visibleTo=getRootElement(),
  340.             [1]={'Yes', 'midMapRestartVoteResult', getRootElement(), true},
  341.             [2]={'No', 'midMapRestartVoteResult', getRootElement(), false;default=true},
  342.     }
  343.  
  344.     -- Change state if vote did start
  345.     if pollDidStart then
  346.         gotoState('MidMapVote')
  347.     end
  348.  
  349. end
  350. addCommandHandler('voteredo',startMidMapVoteForRestartMap)
  351.  
  352.  
  353. ----------------------------------------------------------------------------
  354. -- event midMapRestartVoteResult
  355. --
  356. -- Called from the votemanager when the poll has completed
  357. ----------------------------------------------------------------------------
  358. addEvent('midMapRestartVoteResult')
  359. addEventHandler('midMapRestartVoteResult', getRootElement(),
  360.     function( votedYes )
  361.         -- Change state back
  362.         if stateAllowsRandomMapVoteResult() then
  363.             gotoState('Running')
  364.             if votedYes then
  365.                 if not exports.mapmanager:changeGamemodeMap ( exports.mapmanager:getRunningGamemodeMap(), nil, true ) then
  366.                     problemChangingMap()
  367.                 end
  368.             else
  369.                 displayKillerPunchLine()
  370.             end
  371.         end
  372.     end
  373. )
  374.  
  375. addCommandHandler('redo',
  376.     function( player, command, value )
  377.         if isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  378.             local currentMap = exports.mapmanager:getRunningGamemodeMap()
  379.             if currentMap then
  380.                 outputChatBox('Map restarted by ' .. getPlayerName(player), g_Root, 0, 240, 0)
  381.                 if not exports.mapmanager:changeGamemodeMap (currentMap, nil, true) then
  382.                     problemChangingMap()
  383.                 end
  384.             else
  385.                 outputRace("You can't restart the map because no map is running", player)
  386.             end
  387.         else
  388.             outputRace("You are not an Admin", player)
  389.         end
  390.     end
  391. )
  392.  
  393.  
  394. addCommandHandler('random',
  395.     function( player, command, value )
  396.         if isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  397.             if not stateAllowsRandomMapVote() or g_CurrentRaceMode:getTimeRemaining() < 1000 then
  398.                 outputRace( "Random command only works during a race and when no polls are running.", player )
  399.             else
  400.                 local choice = {'curtailed', 'cut short', 'terminated', 'given the heave ho', 'dropkicked', 'expunged', 'put out of our misery', 'got rid of'}
  401.                 outputChatBox('Current map ' .. choice[math.random( 1, #choice )] .. ' by ' .. getPlayerName(player), g_Root, 0, 240, 0)
  402.                 startRandomMap()
  403.             end
  404.         end
  405.     end
  406. )
  407.  
  408.  
  409. ----------------------------------------------------------------------------
  410. -- maybeApplyForcedNextMap
  411. --
  412. -- Returns true if nextmap did override
  413. ----------------------------------------------------------------------------
  414. function maybeApplyForcedNextMap()
  415.     if g_ForcedNextMap then
  416.         local map = g_ForcedNextMap
  417.         g_ForcedNextMap = nil
  418.         g_IgnoreSpawnCountProblems = map    -- Uber hack 4000
  419.         if not exports.mapmanager:changeGamemodeMap ( map, nil, true ) then
  420.             outputWarning( 'Forced next map failed' )
  421.             return false
  422.         end
  423.         return true
  424.     end
  425.     return false
  426. end
  427.  
  428. ---------------------------------------------------------------------------
  429. --
  430. -- Testing
  431. --
  432. --
  433. --
  434. ---------------------------------------------------------------------------
  435. addCommandHandler('forcevote',
  436.     function( player, command, value )
  437.         if not _TESTING and not isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  438.             return
  439.         end
  440.         startNextMapVote()
  441.     end
  442. )
  443.  
  444.  
  445. ---------------------------------------------------------------------------
  446. --
  447. -- getRandomMapCompatibleWithGamemode
  448. --
  449. -- This should go in mapmanager, but ACL needs doing
  450. --
  451. ---------------------------------------------------------------------------
  452.  
  453. addEventHandler('onResourceStart', getRootElement(),
  454.     function( res )
  455.         if exports.mapmanager:isMap( res ) then
  456.             setMapLastTimePlayed( res )
  457.         end
  458.     end
  459. )
  460.  
  461. function getRandomMapCompatibleWithGamemode( gamemode, oldestPercentage, minSpawnCount )
  462.  
  463.     -- Get all relevant maps
  464.     local compatibleMaps = exports.mapmanager:getMapsCompatibleWithGamemode( gamemode )
  465.  
  466.     if #compatibleMaps == 0 then
  467.         outputDebugString( 'getRandomMapCompatibleWithGamemode: No maps.', 1 )
  468.         return false
  469.     end
  470.  
  471.     -- Sort maps by time since played
  472.     local sortList = {}
  473.     for i,map in ipairs(compatibleMaps) do
  474.         sortList[i] = {}
  475.         sortList[i].map = map
  476.         sortList[i].lastTimePlayed = getMapLastTimePlayed( map )
  477.     end
  478.  
  479.     table.sort( sortList, function(a, b) return a.lastTimePlayed > b.lastTimePlayed end )
  480.  
  481.     -- Use the bottom n% of maps as the initial selection pool
  482.     local cutoff = #sortList - math.floor( #sortList * oldestPercentage / 100 )
  483.  
  484.     outputDebug( 'RANDMAP', 'getRandomMapCompatibleWithGamemode' )
  485.     outputDebug( 'RANDMAP', ''
  486.             .. ' minSpawns:' .. tostring( minSpawnCount )
  487.             .. ' nummaps:' .. tostring( #sortList )
  488.             .. ' cutoff:' .. tostring( cutoff )
  489.             .. ' poolsize:' .. tostring( #sortList - cutoff + 1 )
  490.             )
  491.  
  492.     math.randomseed( getTickCount() % 50000 )
  493.     local fallbackMap
  494.     while #sortList > 0 do
  495.         -- Get random item from range
  496.         local idx = math.random( cutoff, #sortList )
  497.         local map = sortList[idx].map
  498.  
  499.         if not minSpawnCount or minSpawnCount <= getMapSpawnPointCount( map ) then
  500.             outputDebug( 'RANDMAP', ''
  501.                     .. ' ++ using map:' .. tostring( getResourceName( map ) )
  502.                     .. ' spawns:' .. tostring( getMapSpawnPointCount( map ) )
  503.                     .. ' age:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( map ) )
  504.                     )
  505.             return map
  506.         end
  507.  
  508.         -- Remember best match incase we cant find any with enough spawn points
  509.         if not fallbackMap or getMapSpawnPointCount( fallbackMap ) < getMapSpawnPointCount( map ) then
  510.             fallbackMap = map
  511.         end
  512.  
  513.         outputDebug( 'RANDMAP', ''
  514.                 .. ' skip:' .. tostring( getResourceName( map ) )
  515.                 .. ' spawns:' .. tostring( getMapSpawnPointCount( map ) )
  516.                 .. ' age:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( map ) )
  517.                 )
  518.  
  519.         -- If map not good enough, remove from the list and try another
  520.         table.remove( sortList, idx )
  521.         -- Move cutoff up the list if required
  522.         cutoff = math.min( cutoff, #sortList )
  523.     end
  524.  
  525.     -- No maps found - use best match
  526.     outputDebug( 'RANDMAP', ''
  527.             .. ' ** fallback map:' .. tostring( getResourceName( fallbackMap ) )
  528.             .. ' spawns:' .. tostring( getMapSpawnPointCount( fallbackMap ) )
  529.             .. ' ageLstPlyd:' .. tostring( getRealTimeSeconds() - getMapLastTimePlayed( fallbackMap ) )
  530.             )
  531.     return fallbackMap
  532. end
  533.  
  534. -- Look for spawnpoints in map file
  535. -- Not very quick as it loads the map file everytime
  536. function countSpawnPointsInMap(res)
  537.     local count = 0
  538.     local meta = xmlLoadFile(':' .. getResourceName(res) .. '/' .. 'meta.xml')
  539.     if meta then
  540.         local mapnode = xmlFindChild(meta, 'map', 0) or xmlFindChild(meta, 'race', 0)
  541.         local filename = mapnode and xmlNodeGetAttribute(mapnode, 'src')
  542.         xmlUnloadFile(meta)
  543.         if filename then
  544.             local map = xmlLoadFile(':' .. getResourceName(res) .. '/' .. filename)
  545.             if map then
  546.                 while xmlFindChild(map, 'spawnpoint', count) do
  547.                     count = count + 1
  548.                 end
  549.                 xmlUnloadFile(map)
  550.             end
  551.         end
  552.     end
  553.     return count
  554. end
  555.  
  556. ---------------------------------------------------------------------------
  557. -- g_MapInfoList access
  558. ---------------------------------------------------------------------------
  559. local g_MapInfoList
  560.  
  561. function getMapLastTimePlayed( map )
  562.     local mapInfo = getMapInfo( map )
  563.     return mapInfo.lastTimePlayed or 0
  564. end
  565.  
  566. function setMapLastTimePlayed( map, time )
  567.     time = time or getRealTimeSeconds()
  568.     local mapInfo = getMapInfo( map )
  569.     mapInfo.lastTimePlayed = time
  570.     mapInfo.playedCount = ( mapInfo.playedCount or 0 ) + 1
  571.     saveMapInfoItem( map, mapInfo )
  572. end
  573.  
  574. function getMapSpawnPointCount( map )
  575.     local mapInfo = getMapInfo( map )
  576.     if not mapInfo.spawnPointCount then
  577.         mapInfo.spawnPointCount = countSpawnPointsInMap( map )
  578.         saveMapInfoItem( map, mapInfo )
  579.     end
  580.     return mapInfo.spawnPointCount
  581. end
  582.  
  583. function getMapInfo( map )
  584.     if not g_MapInfoList then
  585.         loadMapInfoAll()
  586.     end
  587.     if not g_MapInfoList[map] then
  588.         g_MapInfoList[map] = {}
  589.     end
  590.     local mapInfo = g_MapInfoList[map]
  591.     if mapInfo.loadTime ~= getResourceLoadTime(map) then
  592.         -- Reset or clear data that may change between loads
  593.         mapInfo.loadTime = getResourceLoadTime( map )
  594.         mapInfo.spawnPointCount = false
  595.     end
  596.     return mapInfo
  597. end
  598.  
  599.  
  600. ---------------------------------------------------------------------------
  601. -- g_MapInfoList <-> database
  602. ---------------------------------------------------------------------------
  603. function sqlString(value)
  604.     value = tostring(value) or ''
  605.     return "'" .. value:gsub( "(['])", "''" ) .. "'"
  606. end
  607.  
  608. function sqlInt(value)
  609.     return tonumber(value) or 0
  610. end
  611.  
  612. function getTableName(value)
  613.     return sqlString( 'race_mapmanager_maps' )
  614. end
  615.  
  616. function ensureTableExists()
  617.     local cmd = ( 'CREATE TABLE IF NOT EXISTS ' .. getTableName() .. ' ('
  618.                      .. 'resName TEXT UNIQUE'
  619.                      .. ', infoName TEXT '
  620.                      .. ', spawnPointCount INTEGER'
  621.                      .. ', playedCount INTEGER'
  622.                      .. ', lastTimePlayedText TEXT'
  623.                      .. ', lastTimePlayed INTEGER'
  624.             .. ')' )
  625.     executeSQLQuery( cmd )
  626. end
  627.  
  628. -- Load all rows into g_MapInfoList
  629. function loadMapInfoAll()
  630.     ensureTableExists()
  631.     local rows = executeSQLQuery( 'SELECT * FROM ' .. getTableName() )
  632.     g_MapInfoList = {}
  633.     for i,row in ipairs(rows) do
  634.         local map = getResourceFromName( row.resName )
  635.         if map then
  636.             local mapInfo = getMapInfo( map )
  637.             mapInfo.playedCount = row.playedCount
  638.             mapInfo.lastTimePlayed = row.lastTimePlayed
  639.         end
  640.     end
  641. end
  642.  
  643. -- Save one row
  644. function saveMapInfoItem( map, info )
  645.     executeSQLQuery( 'BEGIN TRANSACTION' )
  646.  
  647.     ensureTableExists()
  648.  
  649.     local cmd = ( 'INSERT OR IGNORE INTO ' .. getTableName() .. ' VALUES ('
  650.                     .. ''       .. sqlString( getResourceName( map ) )
  651.                     .. ','      .. sqlString( "" )
  652.                     .. ','      .. sqlInt( 0 )
  653.                     .. ','      .. sqlInt( 0 )
  654.                     .. ','      .. sqlString( "" )
  655.                     .. ','      .. sqlInt( 0 )
  656.             .. ')' )
  657.     executeSQLQuery( cmd )
  658.  
  659.     cmd = ( 'UPDATE ' .. getTableName() .. ' SET '
  660.                     .. 'infoName='              .. sqlString( getResourceInfo( map, "name" ) )
  661.                     .. ',spawnPointCount='      .. sqlInt( info.spawnPointCount )
  662.                     .. ',playedCount='          .. sqlInt( info.playedCount )
  663.                     .. ',lastTimePlayedText='   .. sqlString( info.lastTimePlayed and info.lastTimePlayed > 0 and getRealDateTimeString(getRealTime(info.lastTimePlayed)) or "-" )
  664.                     .. ',lastTimePlayed='       .. sqlInt( info.lastTimePlayed )
  665.             .. ' WHERE '
  666.                     .. 'resName='               .. sqlString( getResourceName( map ) )
  667.              )
  668.     executeSQLQuery( cmd )
  669.  
  670.     executeSQLQuery( 'END TRANSACTION' )
  671. end
  672.  
  673.  
  674.  
  675. ---------------------------------------------------------------------------
  676. --
  677. -- More things that should go in mapmanager
  678. --
  679. ---------------------------------------------------------------------------
  680.  
  681. addCommandHandler('checkmap',
  682.     function( player, command, ... )
  683.         local query = #{...}>0 and table.concat({...},' ') or nil
  684.         if query then
  685.             local map, errormsg = findMap( query )
  686.             outputRace( errormsg, player )
  687.         end
  688.     end
  689. )
  690.  
  691. addCommandHandler('nextmap',
  692.     function( player, command, ... )
  693.         local query = #{...}>0 and table.concat({...},' ') or nil
  694.         if not query then
  695.             if g_ForcedNextMap then
  696.                 outputRace( 'Next map is ' .. getMapName( g_ForcedNextMap ), player )
  697.             else
  698.                 outputRace( 'Next map is not set', player )
  699.             end
  700.             return
  701.         end
  702.         if not _TESTING and not isPlayerInACLGroup(player, g_GameOptions.admingroup) then
  703.             return
  704.         end
  705.         local map, errormsg = findMap( query )
  706.         if not map then
  707.             outputRace( errormsg, player )
  708.             return
  709.         end
  710.         if g_ForcedNextMap == map then
  711.             outputRace( 'Next map is already set to ' .. getMapName( g_ForcedNextMap ), player )
  712.             return
  713.         end
  714.         g_ForcedNextMap = map
  715.         outputChatBox('Next map set to ' .. getMapName( g_ForcedNextMap ) .. ' by ' .. getPlayerName( player ), g_Root, 0, 240, 0)
  716.     end
  717. )
  718.  
  719. --Find a map which matches, or nil and a text message if there is not one match
  720. function findMap( query )
  721.     local maps = findMaps( query )
  722.  
  723.     -- Make status string
  724.     local status = "Found " .. #maps .. " match" .. ( #maps==1 and "" or "es" )
  725.     for i=1,math.min(5,#maps) do
  726.         status = status .. ( i==1 and ": " or ", " ) .. "'" .. getMapName( maps[i] ) .. "'"
  727.     end
  728.     if #maps > 5 then
  729.         status = status .. " (" .. #maps - 5 .. " more)"
  730.     end
  731.  
  732.     if #maps == 0 then
  733.         return nil, status .. " for '" .. query .. "'"
  734.     end
  735.     if #maps == 1 then
  736.         return maps[1], status
  737.     end
  738.     if #maps > 1 then
  739.         return nil, status
  740.     end
  741. end
  742.  
  743. -- Find all maps which match the query string
  744. function findMaps( query )
  745.     local results = {}
  746.     --escape all meta chars
  747.     query = string.gsub(query, "([%*%+%?%.%(%)%[%]%{%}%\%/%|%^%$%-])","%%%1")
  748.     -- Loop through and find matching maps
  749.     for i,resource in ipairs(exports.mapmanager:getMapsCompatibleWithGamemode(getThisResource())) do
  750.         local resName = getResourceName( resource )
  751.         local infoName = getMapName( resource  )
  752.  
  753.         -- Look for exact match first
  754.         if query == resName or query == infoName then
  755.             return {resource}
  756.         end
  757.  
  758.         -- Find match for query within infoName
  759.         if string.find( infoName:lower(), query:lower() ) then
  760.             table.insert( results, resource )
  761.         end
  762.     end
  763.     return results
  764. end
  765.  
  766. function getMapName( map )
  767.     return getResourceInfo( map, "name" ) or getResourceName( map ) or "unknown"
  768. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement