• 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!

Generating maps?

Why don't you implement this to RME or another map e

Oh, sweet! I'll check it out later tonight.


Care to publish code so we can work on it as a community? I would like to make some additions to a system like this.
I published one generator already, nobody worked on it yet except me. We both know that you don't want to work on that code. Just say you want it, I will understand. Teamworking always slowed everything down. I just hope someone care to write and post mods for my system after posting it.

Currently I'm working on basic functions such as improving perlin-based generator, adding commands to manage it and rewriting functions from old generator and loader for lua maps made by other generators so if they work in console mode they will be usable as extension. I will post that after adding functions to convert and handle rme brushes.

Adding system entirely written in lua to RME would be pointless. I'll just add to libs function to save map(it can be found somewhere on otland).
 
Added support for @Crypton3's generator.
areas.lua is config file, here is what things do:
Code:
      [1] = {LAYER_SCRIPT, -- type of action to be taken currently only base and script can be handled
function() return WORLDGEN_CORE.loadExternalGen( -- you may put your custom function between "return" and "end"
'data\\lib\\WORLDGEN\\mods\\island_gen\\', -- generator path
'generator.exe', -- generator filename
'-S 256 -F map -O LUA', -- size 256x256, map name will be map.lua(do not add .lua here), map output lua
'map.lua', -- file name(used to read only, needs ".lua" there)
64432, -- id used in cache, should be different for every layer
{ -- generator settings (values of generated map are between -1 and 1
{-0.9, 231}, -- values higher than -0.9 will be id 231 on map
{-0.5, 598},
{0, 493},
{0.5, 919} -- values higher than 0.5 will be id 919 on map
}, 1) -- cave id, should be same as id defined in WORLDGEN_AREAS
end},

command to draw: /worldgen reset 1

known bugs:
currently reset command doesn't reset anything yet so you need to restart your ot to clear the map
huge lag appears if /reload is used during generating proccess

Current version of thing I'm currently working on(TFS 1.0, I can write compat lib for 0.4 if someone needs it):

download:
https://drive.google.com/file/d/0B77EtBbnvIOhUnYwNDhlZ2xGbDQ/view?usp=sharing
https://mega.co.nz/#!Dc8jRDyB!xVXRq0Wzi9yWNdLF7hoE9VhqO-A0QOHJfdW-_X4v3K0

scan:
https://www.virustotal.com/pl/file/...026f9b47f2190cbd3c95b85b/analysis/1422480544/
 
Last edited:
Funny, i forget to backup my debug data directory while migrating to vps :D
Lost my config xmls...
Doesnt matter lets write it again in better form XD
If my new generating method works ill try post something.
Glad that i posted some parts there ;D
 
currently working on this:
Code:
map_lib_cfg = {
	prefix = "[Generator]: ",
	msgType = MESSAGE_INFO_DESCR
}

MAP_STATUS_NONE = 0
-- unused
MAP_STATUS_OPEN = 1
MAP_STATUS_CLOSED = 2
MAP_STATUS_RENDERING = 3
MAP_STATUS_LOCKED = 4
MAP_STATUS_END = 5

if not Map then
	Map = setmetatable({
		instances = {}
	}, {
		__call = function (self, id, fromPosition, toPosition)
			local object = self.instances[id]
			if not object then
				self.instances[id] = setmetatable({
					id = id,
					exist = true,
					layers = {},
					delay = 100,
					status = MAP_STATUS_NONE
				}, {
					__index = Map
				})
				object = self.instances[id]
				object:setPosition(fromPosition, toPosition)
			end
			return object
		end
	})
end

function Map:getId()
	return self.exist and self.id
end

function Map:remove()
	if not self.exist then return false end
	local from = self.fromPosition
	local to = self.toPosition
	
	if from and to then
		from:iterateArea(to, function(position)
			local tile = Tile(position)
			if tile then
				local items = tile:getItems()
				for index = 1, #items do
					items[index]:remove()
				end
				
				local creatures = tile:getCreatures()
				
				for index = 1, #creatures do
					local creature = creatures[index]
					if creature:isPlayer() then
						creature:teleportTo(creature:getTown():getTemplePosition())
						creature:sendTextMessage(map_lib_cfg.msgType, map_lib_cfg.prefix .. "Area closed.")
					else
						creature:remove()
					end
				end
				tile:getGround():remove()
			end		
		end
		)
	end
	
	self.exist = false
end

function Map:reset()
	self.exist = true
	self.layers = {}
	self.delay = 100
	self.status = MAP_STATUS_NONE
	self.seed = nil
end

function Map:setPosition(fromPosition, toPosition)
	self.fromPosition = Position(fromPosition) or Position()
	self.toPosition = Position(toPosition) or Position()
end

function Map:setSeed(seed)
	if not seed then return false end

	local strseed = tostring(seed)
	local numseed = tonumber(seed)
	if numseed then
		self.seed = numseed
		return true
	elseif strseed then
		self.seed = strseed:toSeed()
		return true
	end
end

function Map:getSeed()
	return self.exist and self.seed
end

function string:toSeed()
	local seed = ""
	for i = 1, #self do seed = seed .. self:byte(i) end
	return tonumber(seed)
end

function Map:setStatus(status)
	self.status = status
end

function Map:getStatus()
	return self.exist and self.status
end

function Map:addLayer(callback, arguments)
	if not self.exist then return nil end
	local layers = self.layers
	layers[#layers + 1] = {callback = callback, arguments = arguments}
end

function Map:removeLayer(layer_index)
	table.remove(self.layers, layer_index)
end

function Map:getLayers()
	return self.exist and self.layers
end

function newGround(pos, id)
	Game.createTile(pos)
	return Game.createItem(id, 1, pos)
end

-- chunk size 16x16
function Map:base(grounds)
	local from = self.fromPosition
	local to = self.toPosition
	from:iterateArea(to, function(pos) addEvent(newGround, self.delay, pos, grounds[math.random(1, #grounds)]) self.delay = self.delay + 1 end)
end

function Map:draw()
	if not self.exist then return false end
	local from = self.fromPosition
	local to = self.toPosition

	local x_chunksize = math.floor((to.x - from.x) / 16)
	local y_chunksize = math.floor((to.y - from.y) / 16)
	for a = 0, x_chunksize do
	for b = 0, y_chunksize do
		-- print(a, b)
		-- todo: split generating to chunks
	end
	end
	
	if not (from and to) then
		return false
	end

	for i = 1, #self.layers do
		local layer = self.layers[i]
		layer.callback(unpack(layer.arguments))
	end
	-- from:iterateArea(to, function(pos) self:drawTile(pos) end)
	return true
end

-- from: otland.net/threads/226401
function Position:iterateArea(topos, func)
	for z = self.z, topos.z do
	for y = self.y, topos.y do
	for x = self.x, topos.x do
		func(Position(x, y, z))
	end
	end
	end
end


--[[

function map_example(id, from, to)
	local map = Map(4, {x = 922, y = 1174, z = 8}, {x = 1749, y = 1701, z = 15})
	map:setSeed(os.time())
	map:addLayer(Map.base, {map, {101, 407}})
	map:draw()
	map:reset()
end

]]
any suggestions?
 
currently working on this:
Code:
map_lib_cfg = {
    prefix = "[Generator]: ",
    msgType = MESSAGE_INFO_DESCR
}

MAP_STATUS_NONE = 0
-- unused
MAP_STATUS_OPEN = 1
MAP_STATUS_CLOSED = 2
MAP_STATUS_RENDERING = 3
MAP_STATUS_LOCKED = 4
MAP_STATUS_END = 5

if not Map then
    Map = setmetatable({
        instances = {}
    }, {
        __call = function (self, id, fromPosition, toPosition)
            local object = self.instances[id]
            if not object then
                self.instances[id] = setmetatable({
                    id = id,
                    exist = true,
                    layers = {},
                    delay = 100,
                    status = MAP_STATUS_NONE
                }, {
                    __index = Map
                })
                object = self.instances[id]
                object:setPosition(fromPosition, toPosition)
            end
            return object
        end
    })
end

function Map:getId()
    return self.exist and self.id
end

function Map:remove()
    if not self.exist then return false end
    local from = self.fromPosition
    local to = self.toPosition
   
    if from and to then
        from:iterateArea(to, function(position)
            local tile = Tile(position)
            if tile then
                local items = tile:getItems()
                for index = 1, #items do
                    items[index]:remove()
                end
               
                local creatures = tile:getCreatures()
               
                for index = 1, #creatures do
                    local creature = creatures[index]
                    if creature:isPlayer() then
                        creature:teleportTo(creature:getTown():getTemplePosition())
                        creature:sendTextMessage(map_lib_cfg.msgType, map_lib_cfg.prefix .. "Area closed.")
                    else
                        creature:remove()
                    end
                end
                tile:getGround():remove()
            end       
        end
        )
    end
   
    self.exist = false
end

function Map:reset()
    self.exist = true
    self.layers = {}
    self.delay = 100
    self.status = MAP_STATUS_NONE
    self.seed = nil
end

function Map:setPosition(fromPosition, toPosition)
    self.fromPosition = Position(fromPosition) or Position()
    self.toPosition = Position(toPosition) or Position()
end

function Map:setSeed(seed)
    if not seed then return false end

    local strseed = tostring(seed)
    local numseed = tonumber(seed)
    if numseed then
        self.seed = numseed
        return true
    elseif strseed then
        self.seed = strseed:toSeed()
        return true
    end
end

function Map:getSeed()
    return self.exist and self.seed
end

function string:toSeed()
    local seed = ""
    for i = 1, #self do seed = seed .. self:byte(i) end
    return tonumber(seed)
end

function Map:setStatus(status)
    self.status = status
end

function Map:getStatus()
    return self.exist and self.status
end

function Map:addLayer(callback, arguments)
    if not self.exist then return nil end
    local layers = self.layers
    layers[#layers + 1] = {callback = callback, arguments = arguments}
end

function Map:removeLayer(layer_index)
    table.remove(self.layers, layer_index)
end

function Map:getLayers()
    return self.exist and self.layers
end

function newGround(pos, id)
    Game.createTile(pos)
    return Game.createItem(id, 1, pos)
end

-- chunk size 16x16
function Map:base(grounds)
    local from = self.fromPosition
    local to = self.toPosition
    from:iterateArea(to, function(pos) addEvent(newGround, self.delay, pos, grounds[math.random(1, #grounds)]) self.delay = self.delay + 1 end)
end

function Map:draw()
    if not self.exist then return false end
    local from = self.fromPosition
    local to = self.toPosition

    local x_chunksize = math.floor((to.x - from.x) / 16)
    local y_chunksize = math.floor((to.y - from.y) / 16)
    for a = 0, x_chunksize do
    for b = 0, y_chunksize do
        -- print(a, b)
        -- todo: split generating to chunks
    end
    end
   
    if not (from and to) then
        return false
    end

    for i = 1, #self.layers do
        local layer = self.layers[i]
        layer.callback(unpack(layer.arguments))
    end
    -- from:iterateArea(to, function(pos) self:drawTile(pos) end)
    return true
end

-- from: otland.net/threads/226401
function Position:iterateArea(topos, func)
    for z = self.z, topos.z do
    for y = self.y, topos.y do
    for x = self.x, topos.x do
        func(Position(x, y, z))
    end
    end
    end
end


--[[

function map_example(id, from, to)
    local map = Map(4, {x = 922, y = 1174, z = 8}, {x = 1749, y = 1701, z = 15})
    map:setSeed(os.time())
    map:addLayer(Map.base, {map, {101, 407}})
    map:draw()
    map:reset()
end

]]
any suggestions?

It looks great so far! I'm more and more impressed by your work every time I see you release something new! ;)

Red
 
actually iz @Dalkon
Helped me with setting up map metatable

@Simon Here
I still do it, but very slowly, from scratch. Some pieces of a new map(work in progress) can be seen in cat mages ai script preview.
 
Last edited:
-- from: otland.net/threads/226401 function Position:iterateArea(topos, func) for z = self.z, topos.z do for y = self.y, topos.y do for x = self.x, topos.x do func(Position(x, y, z)) end end end end

You said that function would help get rid of many lines of code, and bam, started using it! LOL, nice work btw. I was curious, I have already downloaded your final release of EvoRPG, and looked at the map generator part, but since it was so huge, and integrated into many different parts of the server (ie, channelscripts, libs, creaturescripts, or w/e, ect.), and so complex, I decided to not try to mess with it for now, but I see you are working on this new way.

This new one, that isn't an extentsion to the old is it? It kind of looks like you are starting back over from scratch, is that what you are doing here? Because if so, kudos to you man. This new one's api does look very nice and clean. I like it!
 
Not as many as changing style to metatables.
There won't be any configs anymore, maps will be handled this way:
Code:
	local map = Map(id, from, to)
	map:setSeed(seed) -- seed, supports numbers and strings
	map:addLayer(Map.base, {map, {101, 5711, 5712, 5713, 5714, 5715, 5716, 5717, 5718, 5719, 5720, 5721, 5722, 5723, 5724, 5725, 5726}}) -- grounds
	map:addLayer(Map.caves, {map, {351, 352, 353, 354, 355}, 75, 100, 4, 5}) -- 0.025% startchance, 0.25% stopchance, 4 min radius, 5 max radius
	map:draw()

It's a folder like "lib" with functions, mods are easy to install. Yep, working on it from scratch, but I have plenty of examples to make it faster.
 
That's great work. If you decide to release this one too, I will definitely use it! Maybe make some mods for it whenever I get some time, right now, AI is priority :D
 
I won't use it for generating dungeons, but when I see the code I might create handle to use it as mapping tool, to make better starting scenary.
 
Finally release gz;D
Now should be my turn
But now im struggling with another fancy problem(tfs suprises never ends :D)

Code:
>> Starting SQL connection
>> Running Database Manager
> Optimizing table: account_viplist... Failed connecting to database - MYSQL ERROR: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111) (2002)
Failed connecting to database - MYSQL ERROR: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111) (2002)

Loses connection after handshake :D
Only tfs have this problem ;p

But nevermind...
Since my code is cpp based can somebody tell me (and give me source) of most used tfs version?
My playground is on 0.3.6-r96.
If i want start developing stable release i need most used version as target.
 
Finally release gz;D
Now should be my turn
But now im struggling with another fancy problem(tfs suprises never ends :D)

Code:
>> Starting SQL connection
>> Running Database Manager
> Optimizing table: account_viplist... Failed connecting to database - MYSQL ERROR: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111) (2002)
Failed connecting to database - MYSQL ERROR: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111) (2002)

Loses connection after handshake :D
Only tfs have this problem ;p

But nevermind...
Since my code is cpp based can somebody tell me (and give me source) of most used tfs version?
My playground is on 0.3.6-r96.
If i want start developing stable release i need most used version as target.


https://github.com/otland/forgottenserver

And I used to have mysql connection issues when using 0.3.6, I chalked it up as my shitty internet, since I switched to that, no problems with the database connection have ever occured
 
Reinstalled mysql and it works :D
@zbizu
Can u name all TFS methods you used in your generating system?
I mean getThingfromPos etc.
and is your generating only lua based? no "mods/" etc ?
Dont have time to study it all :D
I need to know how "portable" is your code.
 
it's intended to work on clean 1.1

methods used so far:
creature:isPlayer()
creature:teleportTo()
creature:sendTextMessage()
creature:remove()
tile:getGround() -- returns Item
item:remove()
Game.createItem()

it will be moddable using lua files, I'm working on a loader. <- done
 
Last edited:
Back
Top