• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Change map for war server TFS 0.4

beenii

Well-Known Member
Joined
Jul 26, 2010
Messages
580
Solutions
1
Reaction score
57
Hi, I need help with the logic of this system.

I want my map to change every 4 hours, but always in a different order.

For example I have: map 1 / map 2 / map 3 / map 4

When the server starts, Start in map 3, then follow map 1, map 4 and map 2.

Whenever the server starts, it will be a different order.

And without restarting the server, if the cycle ends, change the map again, in a different order.

Suggestions for logic? It doesn't matter if we use mysql to have the values stored
 
Hello beenii,

You need a few tools to help you with that, in fact it's going to be using crontab and a little bash knowledge you can earn from reading stackoverflow pages.

Here you can find information about crontab: crontab(5): tables for driving cron - Linux man page (https://linux.die.net/man/5/crontab)

Here's a very hacky but very fast way to do this:
1. create 4 config.lua with different names, each of them containing the map you want to have. The order doesn't matter now.
2. set a cron job to stop your running server at specific times, you'll find more to it in the above link about crontab.
3. set a cron job to run a bash script that will rename the current config.lua to a name of your choice, and rename the "next config" to config.lua, that one you want to run. just mind timing it a few seconds between closing your server and restarting it :)
4. set a cron job to start your server again.

If you have further questions let me know, I maybe can help you with that.

Best Wishes,
Okke
 
Last edited:
Hello beenii,

You need a few tools to help you with that, in fact it's going to be using crontab and a little bash knowledge you can earn from reading stackoverflow pages.

Here you can find information about crontab: crontab(5): tables for driving cron - Linux man page (https://linux.die.net/man/5/crontab)

Here's a very hacky but very fast way to do this:
1. create 4 config.lua with different names, each of them containing the map you want to have. The order doesn't matter now.
2. set a cron job to stop your running server at specific times, you'll find more to it in the above link about crontab.
3. set a cron job to run a bash script that will rename the current config.lua to a name of your choice, and rename the "next config" to config.lua, that one you want to run. just mind timing it a few seconds between closing your server and restarting it :)
4. set a cron job to start your server again.

If you have further questions let me know, I maybe can help you with that.

Best Wishes,
Okke

I think I did not explain my problem well, An apology for that.

I will not change the map, I will change the players from townid, in total I will have 4 temples, where every certain hours they will be transported.


When the server starts, Players Start in town 3, then follow next houra teleport to town1, townid 4 and townid 2.

Whenever the server starts, it will be a different order.

And without restarting the server, if the cycle ends, change the townid again, in a different order.


This is normal system change town ID players online and offline

Lua:
local config, new = {
    minTownId = 1,
    maxTownId = 3
}, 0
function onThink(interval, lastExecution)
    for _, pid in ipairs(getPlayersOnline()) do
        local town = getPlayerTown(pid)
        new = town < config.maxTownId and town + 1 or config.minTownId
        doPlayerSetTown(pid, new)
        doTeleportThing(pid, getTownTemplePosition(new))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
            doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. new ..", posx = 0, posy = 0, posz = 0;")
    return true
end


I try to do the same, but that my 4 townids randomly without repeating themselves.

First townid 2 follow townid 4, next townid 1,next townid 3.

When finish cycle, have new order
 
hey, try this:


server lib:
Lua:
MAPCHANGER_towns = {
    ['thais'] = {id = 1},
    ['venore'] = {id = 2},
    ['carlin'] = {id = 3},
    ['darashia'] = {id = 4}
}

MAPCHANGER_used_towns = {}

function table.contains(table, element)
    for _, value in pairs(table) do
        if value == element then
            return true
        end
    end
    return false
end

onThink:
Lua:
function changeMap(id)
    for _, pid in ipairs(getPlayersOnline()) do
        doPlayerSetTown(pid, id)
        doTeleportThing(pid, getTownTemplePosition(id))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
        doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. id ..", posx = 0, posy = 0, posz = 0;") 
end

function chooseMap()
    -- reset maps if all have been used
    if #MAPCHANGER_used_towns == #MAPCHANGER_towns then
        MAPCHANGER_used_towns = {}
    end
  
    -- choose new different map
    for town, info in pairs(MAPCHANGER_towns) do
        if not table.contains(MAPCHANGER_used_towns, town) then
            table.insert(MAPCHANGER_used_towns, town)
            changeMap(info.id)
            break
        end
    end
end

function onThink(interval, lastExecution)
    chooseMap()
    return true
end

let me know how it works i made while cooking xd
 
Last edited:
hey, try this:


server lib:
Lua:
MAPCHANGER_towns = {
    ['thais'] = {id = 1},
    ['venore'] = {id = 2},
    ['carlin'] = {id = 3},
    ['darashia'] = {id = 4}
}

MAPCHANGER_used_towns = {}

function table.contains(table, element)
    for _, value in pairs(table) do
        if value == element then
            return true
        end
    end
    return false
end

onThink:
Lua:
function changeMap(id)
    for _, pid in ipairs(getPlayersOnline()) do
        doPlayerSetTown(pid, id)
        doTeleportThing(pid, getTownTemplePosition(id))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
        doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. id ..", posx = 0, posy = 0, posz = 0;")
end

function chooseMap()
    -- reset maps if all have been used
    if #MAPCHANGER_used_towns == #MAPCHANGER_towns then
        MAPCHANGER_used_towns = {}
    end
 
    -- choose new different map
    for town, info in pairs(MAPCHANGER_towns) do
        if not table.contains(MAPCHANGER_used_towns, town) then
            table.insert(MAPCHANGER_used_towns, town)
            changeMap(info.id)
            break
        end
    end
end

function onThink(interval, lastExecution)
    chooseMap()
    return true
end

let me know how it works i made while cooking xd
As soon as I get home I will test if it works, thanks for now
 
hey, try this:


server lib:
Lua:
MAPCHANGER_towns = {
    ['thais'] = {id = 1},
    ['venore'] = {id = 2},
    ['carlin'] = {id = 3},
    ['darashia'] = {id = 4}
}

MAPCHANGER_used_towns = {}

function table.contains(table, element)
    for _, value in pairs(table) do
        if value == element then
            return true
        end
    end
    return false
end

onThink:
Lua:
function changeMap(id)
    for _, pid in ipairs(getPlayersOnline()) do
        doPlayerSetTown(pid, id)
        doTeleportThing(pid, getTownTemplePosition(id))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
        doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. id ..", posx = 0, posy = 0, posz = 0;")
end

function chooseMap()
    -- reset maps if all have been used
    if #MAPCHANGER_used_towns == #MAPCHANGER_towns then
        MAPCHANGER_used_towns = {}
    end
 
    -- choose new different map
    for town, info in pairs(MAPCHANGER_towns) do
        if not table.contains(MAPCHANGER_used_towns, town) then
            table.insert(MAPCHANGER_used_towns, town)
            changeMap(info.id)
            break
        end
    end
end

function onThink(interval, lastExecution)
    chooseMap()
    return true
end

let me know how it works i made while cooking xd
next map.png

analyze the script in detail.

1.- the same order is always repeated
2.- and when the cycle ends, it doesn't make any more townid changes, until I restart the server

Hopefully you can help me, I want to implement the current map and the next map on the website.
if you can register the town order in mysql, and when the loop ends, another order.

i need send data of mysql for show in website
mapweb.png

When I imagined this system, I did not think that the logic would be so complicated xD
 
thats my bad, you can use:
Lua:
function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
  return tbl
end

and do like this:
Lua:
local MAPCHANGER_towns = {
    ['thais'] = {id = 1},
    ['venore'] = {id = 2},
    ['carlin'] = {id = 3},
    ['darashia'] = {id = 4}
}

MAPCHANGER_towns = shuffle(MAPCHANGER_towns)

this way, you will always get different order
Post automatically merged:

for the website, you can use this version:

- server lib
Lua:
function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
  return tbl
end

local MAPCHANGER_towns = {
    [1] = {town = 'thais'},
    [2] = {town = 'venore'},
    [3] = {town = 'carlin'},
    [4] = {town = 'darashia'}
}

-- sets a new map order
MAPCHANGER_towns = shuffle(MAPCHANGER_towns)

-- add map order to table and save it to use with website
MAPCHANGER_neworder = {}

-- onThink:
Lua:
function createNewOrder()
    -- reset maps if all have been used
    MAPCHANGER_neworder = {}
    -- choose new different map
    for i = 1, #MAPCHANGER_towns do
        MAPCHANGER_neworder[i] = MAPCHANGER_towns[i].town
    end
end

function changeMap(id)
    for _, pid in ipairs(getPlayersOnline()) do
        doPlayerSetTown(pid, id)
        doTeleportThing(pid, getTownTemplePosition(id))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
        doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. id ..", posx = 0, posy = 0, posz = 0;")
end

function chooseMap()
    for i = 1, #MAPCHANGER_neworder do
        if MAPCHANGER_neworder[i] then
            local new_town = getTownId(MAPCHANGER_neworder[i])
            if new_town then
                changeMap(new_town)
            end
            --remove new map
            MAPCHANGER_neworder[i] = nil
            break
        end
    end
end

function onThink(interval, lastExecution)
    if #MAPCHANGER_neworder < 1 then
        createNewOrder()
    end
    chooseMap()
    return true
end


you can use:
Lua:
MAPCHANGER_neworder = {}
to see the next map and send to db

havent tested it but should do the job
 
Last edited:
thats my bad, you can use:
Lua:
function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
  return tbl
end

and do like this:
Lua:
local MAPCHANGER_towns = {
    ['thais'] = {id = 1},
    ['venore'] = {id = 2},
    ['carlin'] = {id = 3},
    ['darashia'] = {id = 4}
}

MAPCHANGER_towns = shuffle(MAPCHANGER_towns)

this way, you will always get different order
Post automatically merged:

for the website, you can use this version:

- server lib
Lua:
function shuffle(tbl)
  for i = #tbl, 2, -1 do
    local j = math.random(i)
    tbl[i], tbl[j] = tbl[j], tbl[i]
  end
  return tbl
end

local MAPCHANGER_towns = {
    [1] = {town = 'thais'},
    [2] = {town = 'venore'},
    [3] = {town = 'carlin'},
    [4] = {town = 'darashia'}
}

-- sets a new map order
MAPCHANGER_towns = shuffle(MAPCHANGER_towns)

-- add map order to table and save it to use with website
MAPCHANGER_neworder = {}

-- onThink:
Lua:
function createNewOrder()
    -- reset maps if all have been used
    MAPCHANGER_neworder = {}
    -- choose new different map
    for i = 1, #MAPCHANGER_towns do
        MAPCHANGER_neworder[i] = MAPCHANGER_towns[i].town
    end
end

function changeMap(id)
    for _, pid in ipairs(getPlayersOnline()) do
        doPlayerSetTown(pid, id)
        doTeleportThing(pid, getTownTemplePosition(id))
        doRemoveConditions(pid)
        doCreatureAddHealth(pid, getCreatureMaxHealth(pid))
        doCreatureAddMana(pid, getCreatureMaxMana(pid))
        doBroadcastMessage("Map has been changed! Next map change will be in 25 minutes!", MESSAGE_STATUS_WARNING)
    end
    db.executeQuery("UPDATE players SET town_id = ".. id ..", posx = 0, posy = 0, posz = 0;")
end

function chooseMap()
    for i = 1, #MAPCHANGER_neworder do
        if MAPCHANGER_neworder[i] then
            local new_town = getTownId(MAPCHANGER_neworder[i])
            if new_town then
                changeMap(new_town)
            end
            --remove new map
            MAPCHANGER_neworder[i] = nil
            break
        end
    end
end

function onThink(interval, lastExecution)
    if #MAPCHANGER_neworder < 1 then
        createNewOrder()
    end
    chooseMap()
    return true
end


you can use:
Lua:
MAPCHANGER_neworder = {}
to see the next map and send to db

havent tested it but should do the job

I just ran several tests, if I improve, but still not working 100%

nextmap actu.png

the cycle repeats, but in the same order.

1.- only when i restart the server, or refresh the script changes the order.
2.- townid 1 never shows up
3.- when the cycle ends, in the next change the script does nothing, until it sends again a second time, the same cycle begins

I tried adding 2 extra town id, and the result was that now the loop was showing 2 townid

How get order from website with: MAPCHANGER_neworder = {} ?
- this is next map?
getTownId(MAPCHANGER_neworder)


I came up with a simpler function to solve this system:
we simply need a function that order numbers xD

for example put:
shuffle(1,2,3,4,5)
result:
shuffle.[1]=5
shuffle.[2]=2
shuffle.[3]=1
shuffle.[4]=3
shuffle.[5]=4

use again shuffle(1,2,3,4,5,6)
shuffle.[1]=2
shuffle.[2]=4
shuffle.[3]=6
shuffle.[4]=5
shuffle.[5]=1
shuffle.[6]=3

obtaining the numbers, everything else is the simplest, with some tables, the name of the town id is taken, and all the information.
 
I did not post the trick behind as i expect you to figure it out, but trust me its very easy to use the second version to be 100% as you want and also send the info to website.

anyway, as you asked here:
How get order from website with: MAPCHANGER_neworder = {} ?

solution:
the output of that table is the map order, which you can send by query to db. then use the php to read the db and list next map.

i like the fact you are playing with it, lua is funny and easy to learn.
 
I did not post the trick behind as i expect you to figure it out, but trust me its very easy to use the second version to be 100% as you want and also send the info to website.

anyway, as you asked here:
How get order from website with: MAPCHANGER_neworder = {} ?

solution:
the output of that table is the map order, which you can send by query to db. then use the php to read the db and list next map.

i like the fact you are playing with it, lua is funny and easy to learn.
Thanks for your help, I'll see how I solve that order :D
 
Eventually, you will get the same map twice in a row since there is no check for the current town id
 
Back
Top