Map event data
Hi there. Really appreciate this project. I do some research as well and found something about map event data in the XMap_data.amb files.
@nicode I write this as an issue cause I am not sure how you want to integrate this into the wiki and it is still WIP.
You mentioned the data as:
map_3 {
uint16_t field_0;
uint8_t field_2[field_0][2];
};
map_4 {
uint16_t field_0;
[field_0] {
uint8_t field_0;
uint8_t field_1;
uint8_t field_2;
uint8_t field_3;
uint8_t field_4;
uint8_t field_5;
uint8_t field_6;
uint8_t field_7;
uint8_t field_8;
uint8_t field_9;
uint16_t field_A;
}
};
Actually it is the map event data:
// this is map_3 from above
map_event_dictionary {
// this is the amount of map events used inside the map (referenced by the ID 1 to num_entries)
uint16_t num_entries;
// index (0-based) in the map_events data below
// as each map event has 12 bytes of data one has to multiply the index by 12 to get the real byte offset
// note that the first map event starts after the num_map_events value
uint16_t indices[num_entries];
};
// this is map_4 from above
map_events {
// total amount of map events (there can be multiple map events on one tile)
uint16_t num_map_events;
map_event_t map_events[num_map_events];
};
map_event_t {
// 1: map change
// 3: chest
// 4: text events / text popup (uses texts for XMap_texts.amb)
// 6: most likely hurting stuff (like fire, traps, etc)
// 8: riddlemouth
// 10: change tile appearance (most likely only the front/overlay tile)
// 13: condition
// 14: action
// rest unknown yet
uint8_t type;
// data depends on event type (see below)
uint8_t event_data[9];
// map events are organized as linked lists so they have a reference to
// the next map event in the list here. 0xffff means no more map events in the list.
// so the map event dictionary above references map event lists that can be used
// by map tiles. for example the left fireplace in grandfathers living room has a
// fire hurt event and a map change event.
uint16_t next_map_event;
};
// examples for map event data
map_change_event_data {
uint8_t x; // new map x coordinate in tiles (1-based so 1 is the first tile column)
uint8_t y; // new map y coordinate in tiles (1-based so 1 is the first tile row)
uint8_t direction; // direction to look at after map change, 0: up, 1: right, 2: down, 3: left
uint8_t unknown_1[2];
uint16_t map_index; // new map index
uint8_t unknown_2[2];
};
chest_event_data {
// 0x00: open
// 0x01: locked chest that can be opened by a lockpick
// 0x64: locked with special key
// not 100% sure yet
uint8_t lock_flags;
uint16_t unknown_1;
uint8_t chest_index;
uint8_t remove_when_empty; // 0: statonary chest, 1: pile, magic picture etc
uint16_t key_index; // key index for locked chests
uint16_t unknown_2;
};
text_event_data {
uint8_t unknown_1[4];
uint8_t text_index; // if the map has a name, the name will have index 0
uint8_t unknown_2[4];
};
riddlemouth_event_data {
uint8_t intro_text_index; // text index for introduction / question / riddle
uint8_t solution_text_index; // text index used when the riddle is solved
uint8_t unknown[7];
};
change_tile_data {
uint8_t x; // x coordinate of the tile to change (1-based)
uint8_t y; // y coordinate of the tile to change (1-based)
uint8_t unknown_1[3];
uint16_t new_overlay_index; // this is the tile index of the foreground layer
uint8_t unknown_2[2];
};
// Note: It seems that the next map event in the linked list is only executed
// if the condition is fulfilled.
// There can be multiple conditions chained in the linked list which acts as
// a logical AND operator. So all conditions in a row have to be fulfilled to
// execute the following events.
condition_event_data {
// 0x0: map variable
// 0x1: global variable
// 0x7: use item (from inventory)
// 0x9: treasure looted (is chained after chest events with chests that can be completely looted)
// 0xe: hand cursor interaction
// rest unknown yet
uint8_t condition_type;
uint8_t value; // e.g. expected variable value
uint8_t unknown_1[4];
// depends on condition type (e.g. item index or variable index)
uint8_t object_index;
uint8_t unknown_2[2];
};
// Actions are very similar to conditions but they change
// things like variable values instead of checking them.
action_event_data {
// 0x0: set map variable
// 0x1: set global variable
// rest unknown yet
uint8_t action_type;
uint8_t value; // e.g. new variable value
uint8_t unknown_1[4];
// depends on action type (e.g. variable index)
uint8_t object_index;
uint8_t unknown_2[2];
};
More research is needed by looking at several maps. But I think it's a good starting point.
Here is how tiles in maps reference the map events:
map_2[mapHeight][mapWidth] {
if (mapType == 2) { // 2D
uint8_t tile_data[4];
} else { // 3D
uint8_t tile_data[2];
}
}
if (mapType == 2) { // 2D
back_tile_index = ((tile_data[1] & 0xe0) << 3) | tile_data[0];
overlay_tile_index = ((tile_data[2] & 0x07) << 8) | tile_data[3];
map_event_index = tile_data[1] & 0x1f;
} else { // 3D
map_event_index = tile_data[1] & 0x1f;
// not sure about the tile_index yet in 3D
}
Edited by Pyrdacor