[Ace] Map Format Code Dev Notes

darkgriffin

Villager
Member
Joined
Sep 3, 2013
Messages
23
Reaction score
3
First Language
English
Primarily Uses
I'm not sure this is the correct place for this.  I apologize if it goes somewhere else, I'm not sure where else to post it though.

This isn't so much a question as just some information on the map data that I've worked out through trial and error this afternoon.  

I figured if the information is posted somewhere, it might save someone else some time figuring out how this ticks.  The help files are not very clear on this system, lacking key info such as how deep the tile array is.  I've been running p() commands all afternoon collecting data and figuring this out myself.

Bear with me, this is a work in progress and is being filled out and edited as I work on my project that needs the info.  I'll edit this later, and hopefully this will become a pretty useful reference for coders altering or adding onto map tiles/event data.

Spoilered, as this will get pretty long.  Also, I haven't had time to format this, so it's a bit hard to read right now.

Edit log(since I'm going to randomly pop in, clean up, and correct this post, I'll keep a changelog here for sanity's sake):

Last edit: 12/29/2013 - corrected "encounters" to "region paint" to avoid any confusion.  The encounters list itself is actually stored in the map data with the music and such, but not in the tile data.  I'll document the @map object later, as it has much useful data when working with maps such as width and height properties.
Map tile data, what it means and how to access it.

The map data for all events and tiles seem to be stored in $game_map.map  It doesn't have an attr_reader, so you will need to add one to the class Game_Map to get the data from any other objects.

 

From the Game_Map class, you can get the general event map data by calling @map

 

This seems to mostly contain a list of all the events on the map, including all their event code.  It also has all the settings for the map in the editor, like what tileset to use, what music to play, region paint, and so on.

------------

The actual tile data is found in the @map.data object.

 

The map tile data lives in $game_map.map.data during runtime.

 

Note: The map normally doesn't have an attr_reader, you will need to add one if you want to access it from other script objects.  If you do not add one, the only object that can get to the data is the class Game_Map.

 

In Game_Map's script, access the map data with @map.data

 

The map.data array seems to be a 4 dimensional array, accessed with [X, Y, Z].  It contains the map tile data and region paint settings.

-----------

Z level 0 seems to have the tile data.  

 

I'm not sure entirely how this works yet.  Some tiles seem to use Z level 1 as well, and I have yet to test auto tiling situations properly.

 

My best guess is that Z level 0 tells it what auto tile to use as a base, and Z level 1 tells it what tile to "stack" or "mix" with it.  If you look at the data below, all 4 water tiles have the same Z 0 level ID, but obviously they look different as they are the two water depth levels and then the rocks and iceburgs.  All these tiles have the same basic blue water base, so I think the 0 slot is a sort of "use this as a base or for auto tiling", and the Z 1 is "display this tile instead of the one in Z 0".

 

overworld tile data output for example/analysis purposes:

 

tile number in editor - level 0 number - level 1 number

row 1 Tile 1 - 2048 - 0

row 1 Tile 2 - 2048 - 2096

row 1 Tile 3 - 2048 - 2144

row 1 tile 4 - 2048 - 2230

row 1 tile 5 - 2278 - 0

row 1 tile 6 - 2288 - 0

row 1 tile 7 - 2374 - 0

row 1 tile 8 - 2384 - 0

row 2 tile 1 - 2470 - 0

------------------------------

Z level 2 is the id of the B,C,D,E, tile that is mixed on top of the terrain tile.  They seem to start at 0 and just go up by 1 each tile.  Each tab in the default tilesets has 256 tiles and the ids start at 0, so:

 

ID 0 to 255 is tab B's tiles.

 

ID 256 to 511 is tab C's tiles.

 

and so on.  Pretty straight forward compared to the other two numbers.

--------------------------------

Z level 3 is for shadowing and region paint.

 

This data is only accurate with no shadows.  I need to do some research to figure out exactly which numbers match which shadow/regions.  So far an offset of 256 seems to indicate the next region paint number.

 

Values are:

 

Code Number = Editor Encounter Paint Number

0 = 0

256 = 1

512 = 2

768 = 3

 

It seems to be intervals of 256 all the way through.  The last number is 16128 for region paint 63, which is 256 * 63.

 

There doesn't appear to be anything beyond z level 3 in the default, and the editor cannot access anything past that point.  I guess technically one could extend this further, but what's here seems to cover everything needed.

------------------

 

The Game_Map class loads the map data by calling 

 

@map = load_data(sprintf("Data/Map%03d.rvdata2", @map_id))

 

So long as you pass a valid ID to this function, any code object in the game can call data from the editor data, and get map data in memory.  The data this pulls in will be in the same format as the Game_Map's @map.

 

To actually write data to the editor map data, you would probably call save_data() with presumably the same variables.  I haven't tested to see if this works though.  It's rather useless for now, as you'll be overwriting all the editor work, and potentially crashing the editor itself(I don't know how stable RPG ace is with invalid map data), so I'd recommend strongly against doing it.
 

Event data:

 

-To be done when I get further on my own project and need to start copying events.

 

-----------------
 
Last edited by a moderator:

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
31,355
Reaction score
7,668
First Language
German
Primarily Uses
RMMV
What is this supposed to be?


Support is if you have questions about how to solve a specific problem.


But it reads like you're trying to give info to someone else - in that case, a completed topic would go to tutorials, and until it is completed it should remain on your computer, and you come here only to ask questions about what you want to do (for example to learn what you want to teach in the tutorial.)


And one more thing:


If you want to collect info on how to create map with scripts, then you're probably thinking too complex - most maps are better created in the editor.


So please tell us:


What is the purpose of this topic?


Then we can help you improve it.
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
The map has 3 layers, and each layer is stored in its own dimension. That is why the map data table is 4-dimensional.


z = 3 is for region and shadow. It's stored as a 2-byte integer, where the lower 4 bits are used for the shadow (1 bit per 16x16 square of a tile), and the higher 6 bits are used for the region. The rest of the bits in between are unused.


Encounters are not stored with the tilemap, they are a separate array.
 
Last edited by a moderator:

darkgriffin

Villager
Member
Joined
Sep 3, 2013
Messages
23
Reaction score
3
First Language
English
Primarily Uses
What is this supposed to be?

Support is if you have questions about how to solve a specific problem.

But it reads like you're trying to give info to someone else - in that case, a completed topic would go to tutorials, and until it is completed it should remain on your computer, and you come here only to ask questions about what you want to do (for example to learn what you want to teach in the tutorial.)

And one more thing:

If you want to collect info on how to create map with scripts, then you're probably thinking too complex - most maps are better created in the editor.

So please tell us:

What is the purpose of this topic?

Then we can help you improve it.
Ok, since I need to explain a purpose to the thread...

Just to make this clear, my purpose was both to open the map format for discussion, and also create a useful resource to be found when people search later when it's all done.

It won't become a tutorial, per say, because I'm not doing any one particular thing.  What I have in mind is more like a documentation reference, because the help files for Ace leave a lot to be desired about the formats and object structuring when dealing with the database, especially for handling map files.

For what I'm personally doing, just to prove I am doing something that needs this low level access: I'm writing a full blown Mystery Dungeon Room Based Generator, driven entirely by editor maps being set to "be a room" through editor set tags, and other maps being flagged as "generate stuff using this dungeon's ruleset".  It's rather complicated to explain but the basic idea is that unlike the standard rouge-like map generator, the Mystery Dungeon games have a lot of creator-created content that it builds things out of, instead of pure random generation.  (If you've ever played one of the more recent ones, you'll know that it's built with rooms on a "grid" of sorts, with connecting Z hallways, and the rooms are often hand created with chances of things appearing in them.)  I don't know how far I will get, but if I can get it working well enough I'll probably make a separate release thread about that.  I haven't liked the currently available generators much as they lack an easy way to add room data and made different "flavors" of dungeon room arrangements.

This thread is mostly because I was trying to find any sort of detailed documentation on the maps and such, and couldn't find much besides what was in the help manual.  It's posted incomplete, because if I wait for it to be all written on my computer, well, first of all, it wouldn't be much of a tutorial, and secondly, I work very sporadically and might never get the time to clean it up.  I figured even half baked documentation would be more useful to other coders then the next to nothing I found searching early this afternoon. ;)

My big hope with this thread is to create a resource of quick info on what the map format is and other useful stuff, so other programmers can use this info if they ever want to build their own generators or map tools later.  I know the forums don't really have a section for such a thing, but maybe we should have one in the future.  Not everything can be boiled down into tutorials, sometimes as a coder you just need to look something up instead.

The map has 3 layers, and each layer is stored in its own dimension. That is why the map data table is 4-dimensional.z = 3 is for region and shadow. It's stored as a 2-byte integer, where the lower 4 bits are used for the shadow (1 bit per 16x16 square of a tile), and the higher 6 bits are used for the region. The rest of the bits in between are unused.

Encounters are not stored with the tilemap, they are a separate array.
Tsukihime, thanks for the info on the region and shadow stuff. 

I'll have to test out some more later...to be honest I totally forgot about shadowing when I was testing, but I noticed the region paint numbers offset the value by 255.  Could be because I'm using p(@map.data[0,0,3]), which is probably converting the byte integer into an int or a string somehow.  I'm more of a javascript user so I'm new to how ruby behaves when outputting to the console.

I know the encounters themselves are stored separate.  I meant to refer to the region paint.  I'll have to go back and edit that when I get a chance.
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
31,355
Reaction score
7,668
First Language
German
Primarily Uses
RMMV
Good idea, I hope you can pull it off - it has been requested several times, and there appearantly is one script that tried to do the same, but had limitations.


Search for "random dungeon" on this forum and you'll find several topic where such an idea was discussed, and where that other script was linked - it might help you find out what you need to proceed.


You also might want to change the title (use edit, more edit options on your first post) to something like "collecting note for a dungeon generator" or so - that way you'll probably get more help faster.
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
I'll have to test out some more later...to be honest I totally forgot about shadowing when I was testing, but I noticed the region paint numbers offset the value by 255.  Could be because I'm using p(@map.data[0,0,3]), which is probably converting the byte integer into an int or a string somehow.  I'm more of a javascript user so I'm new to how ruby behaves when outputting to the console.
I was wrong, it's not the 6 upper bits.

You have your two bytes for each tile for that dimension (because a Table stores all data as 2-byte integers).

The lower byte is for the shadow, of which the 4 lower bits are used and the higher 4 bits are ignored

The higher byte is for the region, of which the 6 lower bits are used, the higher 2 bits are ignored.

Getting the value of a region can be done by simply right-shifting it by 8 bits

map.data[0, 0, 3] >> 8Returns the region for the tile at location (0, 0)There is also this reference which gives you all the other tile information.

http://forums.rpgmakerweb.com/index.php?/topic/2829-autotile-tile-ids/
 
Last edited by a moderator:

darkgriffin

Villager
Member
Joined
Sep 3, 2013
Messages
23
Reaction score
3
First Language
English
Primarily Uses
Ok, I think I worked out most of how shadows and tile regions work, thanks to Tsukihime. (You rock!) I'll update the main post when I can get to it, for now I think Tsukihime explained the basics decently in the above post.

I'm a bit lost on event structure. The events appear to be there when I run a

p(@map.events)

They, and their contents, are all listed in that object.

But calling something like

p(@map.events[1])

is returning a nil, when I should think it should be returning the first event in the map.

The structure seems to be different then an array, even though I'm pretty sure it is one. I'm trying to make a way to loop over them, get their ids, their names, basically access/read/write the data of events and eventually replace/add new ones to the map in the generator code.

EDIT: The second call above actually does work just like that, I had made a mistake elsewhere in my code that broke it.  I'm not sure what I did, but it's working now.  Tired me is not a good coder. x_x
 
Last edited by a moderator:

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
It's a hash. Maybe your map doesn't have an event with ID 1.

Map events. A hash that represents RPG::Event instances as values, using event IDs as the keys.
It's in the help file under RPG::Map
 
Last edited by a moderator:

darkgriffin

Villager
Member
Joined
Sep 3, 2013
Messages
23
Reaction score
3
First Language
English
Primarily Uses
Ah ha!

I never have worked with a hash before(my other work is usually a bit higher level then this), so I didn't understand what was being output. After a bit of research on google, I think I'm starting to get the hang of them(they seem mostly like basic arrays, except with keys instead of raw array number references).

I kept getting errors or nils because I was using it like an array in a for.each loop. After looking at what a hash is in ruby, I now know to do something like this instead:
 

name = "Test Name"found_id = nil@map.events.each{ | key, value | if(value.name == name) found_id = key end}The above checks every key/value pair for a match with the variable name.  It then sets found_id to the key, which will let me access that exact event entry by key.  (One catch I've discovered, in the case of multiple same named events, it only gets the last id.  For now that's all I need.)

Looks like there are a lot of other handy things hashes can do, like replace(hash key) for cloning events, or getting the length so that I can know what the next event to add should be.  Sweet!
 
Last edited by a moderator:

darkgriffin

Villager
Member
Joined
Sep 3, 2013
Messages
23
Reaction score
3
First Language
English
Primarily Uses
Ok, is there a catch to making events redraw themselves?  I have this code to create a new event as part of the Game_Map object:

def copy_event_id(event_id, new_position_x, new_position_y) #get the map event to copy copy = @map.events[event_id] #get the next empty id for events new_empty_id = get_empty_event_ID # make the event #@map.events[new_empty_id] = Game_Event.new(@map_id, copy) #copy the event @map.events[new_empty_id] = copy #setup the id of the event to the proper id value @map.events[new_empty_id].id = new_empty_id #setup the x and y to the requested x and y positions @map.events[new_empty_id].x = new_position_x @map.events[new_empty_id].y = new_position_y #call a refresh next loop @need_refresh = true #debug calls below p("event copied. ID, name, position x, position y:") p(@map.events[new_empty_id].id) p(@map.events[new_empty_id].name) p(@map.events[new_empty_id].x) p(@map.events[new_empty_id].y) p("full output of copied event data") p(@map.events[new_empty_id]) endThe data outputs ok for all the debug lines.  The ID is set to the latest empty event slot.  The name is the same as the old event's name.  The x and y position values are updated as well.

However, the new event doesn't graphically show up at the requested spot on the map.  I think something else must need to be called as well to cause the map to update the events.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

How many parameters is 'too many'??
Yay, now back in action Happy Christmas time, coming back!






Back in action to develop the indie game that has been long overdue... Final Fallacy. A game that keeps on giving! The development never ends as the developer thinks to be the smart cookie by coming back and beginning by saying... "Oh bother, this indie game has been long overdue..." How could one resist such? No-one c
So I was playing with filters and this looked interesting...

Versus the normal look...

Kind of gives a very different feel. :LZSexcite:
To whom ever person or persons who re-did the DS/DS+ asset packs for MV (as in, they are all 48x48, and not just x2 the pixel scale) .... THANK-YOU!!!!!!!!! XwwwwX

Forum statistics

Threads
105,849
Messages
1,016,975
Members
137,563
Latest member
cexojow
Top