name some previously-unknown fields
This commit is contained in:
@@ -5761,7 +5761,7 @@ struct G_UpdateShortStatuses_GC_Ep3_6xB4x04 {
|
||||
struct G_UpdateMap_GC_Ep3_6xB4x05 {
|
||||
G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateMap_GC_Ep3_6xB4x05) / 4, 0, 0x05, 0, 0, 0};
|
||||
Episode3::MapAndRulesState state;
|
||||
uint8_t unknown_a1 = 0;
|
||||
uint8_t start_battle = 0;
|
||||
parray<uint8_t, 3> unused;
|
||||
} __packed__;
|
||||
|
||||
|
||||
+82
-40
@@ -18,6 +18,43 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
const char* name_for_environment_number(uint8_t environment_number) {
|
||||
static constexpr array<const char*, 0x1C> names = {
|
||||
"Unguis Lapis",
|
||||
"Nebula Montana 1",
|
||||
"Lupus Silva 1",
|
||||
"Lupus Silva 2",
|
||||
"Molae Venti",
|
||||
"Nebula Montana 2",
|
||||
"Tener Sinus",
|
||||
"Mortis Fons",
|
||||
"Morgue (destroyed)",
|
||||
"Tower of Caelum",
|
||||
"MapMan",
|
||||
"Cyber",
|
||||
"Morgue (not destroyed)",
|
||||
"Castor/Pollux map",
|
||||
"Dolor Odor",
|
||||
"Ravum Aedes Sacra",
|
||||
"Amplum Umbra map",
|
||||
"Via Tubus",
|
||||
"Morgue",
|
||||
"TCardDemo",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"Battle Results",
|
||||
"Game Over",
|
||||
"Staff roll",
|
||||
"View Battle waiting room",
|
||||
"TCard00_Select",
|
||||
"blank",
|
||||
};
|
||||
if (environment_number >= names.size()) {
|
||||
return "unknown";
|
||||
}
|
||||
return names[environment_number];
|
||||
}
|
||||
|
||||
const char* name_for_link_color(uint8_t color) {
|
||||
switch (color) {
|
||||
case 1:
|
||||
@@ -1527,13 +1564,13 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
|
||||
lines.emplace_back(string_printf("Map %08" PRIX32 ": %hhux%hhu",
|
||||
this->map_number.load(), this->width, this->height));
|
||||
lines.emplace_back(string_printf(" a1=%08" PRIX32, this->unknown_a1.load()));
|
||||
lines.emplace_back(string_printf(" environment_number=%02hhX", this->environment_number));
|
||||
lines.emplace_back(string_printf(" num_camera_zones=%02hhX", this->num_camera_zones));
|
||||
lines.emplace_back(string_printf(" tag: %08" PRIX32, this->tag.load()));
|
||||
lines.emplace_back(string_printf(" environment_number: %02hhX (%s)", this->environment_number, name_for_environment_number(this->environment_number)));
|
||||
lines.emplace_back(string_printf(" num_camera_zones: %02hhX", this->num_camera_zones));
|
||||
lines.emplace_back(" tiles:");
|
||||
add_map(this->map_tiles);
|
||||
lines.emplace_back(string_printf(
|
||||
" start_tile_definitions=[1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX], [1p=%02hhX 2p=%02hhX,%02hhX 3p=%02hhX,%02hhX,%02hhX]",
|
||||
" start_tile_definitions: A:[1p: %02hhX; 2p: %02hhX,%02hhX; 3p: %02hhX,%02hhX,%02hhX], B:[1p: %02hhX; 2p: %02hhX,%02hhX; 3p: %02hhX,%02hhX,%02hhX]",
|
||||
this->start_tile_definitions[0][0], this->start_tile_definitions[0][1],
|
||||
this->start_tile_definitions[0][2], this->start_tile_definitions[0][3],
|
||||
this->start_tile_definitions[0][4], this->start_tile_definitions[0][5],
|
||||
@@ -1542,7 +1579,7 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
this->start_tile_definitions[1][4], this->start_tile_definitions[1][5]));
|
||||
for (size_t z = 0; z < this->num_camera_zones; z++) {
|
||||
for (size_t w = 0; w < 2; w++) {
|
||||
lines.emplace_back(string_printf(" camera zone %zu (team %zu):", z, w));
|
||||
lines.emplace_back(string_printf(" camera zone %zu (team %c):", z, w ? 'A' : 'B'));
|
||||
add_map(this->camera_zone_maps[w][z]);
|
||||
}
|
||||
for (size_t w = 0; w < 2; w++) {
|
||||
@@ -1552,39 +1589,39 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
for (size_t w = 0; w < 3; w++) {
|
||||
for (size_t z = 0; z < 2; z++) {
|
||||
string spec_str = this->overview_specs[w][z].str();
|
||||
lines.emplace_back(string_printf(" overview_specs[%zu][team %zu]=%s", w, z, spec_str.c_str()));
|
||||
lines.emplace_back(string_printf(" overview_specs[%zu][team %zu]: %s", w, z, spec_str.c_str()));
|
||||
}
|
||||
}
|
||||
lines.emplace_back(" modification tiles:");
|
||||
add_map(this->modification_tiles);
|
||||
for (size_t z = 0; z < 0x70; z += 0x10) {
|
||||
lines.emplace_back(string_printf(
|
||||
" a5[0x%02zX:0x%02zX]=%02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX", z, z + 0x10,
|
||||
" a5[0x%02zX:0x%02zX]: %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX", z, z + 0x10,
|
||||
this->unknown_a5[z + 0x00], this->unknown_a5[z + 0x01], this->unknown_a5[z + 0x02], this->unknown_a5[z + 0x03],
|
||||
this->unknown_a5[z + 0x04], this->unknown_a5[z + 0x05], this->unknown_a5[z + 0x06], this->unknown_a5[z + 0x07],
|
||||
this->unknown_a5[z + 0x08], this->unknown_a5[z + 0x09], this->unknown_a5[z + 0x0A], this->unknown_a5[z + 0x0B],
|
||||
this->unknown_a5[z + 0x0C], this->unknown_a5[z + 0x0D], this->unknown_a5[z + 0x0E], this->unknown_a5[z + 0x0F]));
|
||||
}
|
||||
lines.emplace_back(string_printf(
|
||||
" a5[0x70:0x74]=%02hhX %02hhX %02hhX %02hhX",
|
||||
" a5[0x70:0x74]: %02hhX %02hhX %02hhX %02hhX",
|
||||
this->unknown_a5[0x70], this->unknown_a5[0x71], this->unknown_a5[0x72], this->unknown_a5[0x73]));
|
||||
lines.emplace_back(" default_rules: " + this->default_rules.str());
|
||||
lines.emplace_back(" name: " + string(this->name));
|
||||
lines.emplace_back(" location_name: " + string(this->location_name));
|
||||
lines.emplace_back(" quest_name: " + string(this->quest_name));
|
||||
lines.emplace_back(" description: " + string(this->description));
|
||||
lines.emplace_back(" name: " + format_data_string(this->name));
|
||||
lines.emplace_back(" location_name: " + format_data_string(this->location_name));
|
||||
lines.emplace_back(" quest_name: " + format_data_string(this->quest_name));
|
||||
lines.emplace_back(" description: " + format_data_string(this->description));
|
||||
lines.emplace_back(string_printf(" map_xy: %hu %hu", this->map_x.load(), this->map_y.load()));
|
||||
for (size_t z = 0; z < 3; z++) {
|
||||
lines.emplace_back(string_printf(" npc_chars[%zu]:", z));
|
||||
lines.emplace_back(" name: " + string(this->npc_ai_params[z].name));
|
||||
lines.emplace_back(" name: " + format_data_string(this->npc_ai_params[z].name));
|
||||
lines.emplace_back(string_printf(
|
||||
" ai_params=(a1=%04hX %04hX, is_arkz=%02hhX, a2=%02hX %02hX %02hX)",
|
||||
" ai_params: (a1: %04hX %04hX, is_arkz: %02hhX, a2: %02hX %02hX %02hX)",
|
||||
this->npc_ai_params[z].unknown_a1[0].load(), this->npc_ai_params[z].unknown_a1[1].load(),
|
||||
this->npc_ai_params[z].is_arkz, this->npc_ai_params[z].unknown_a2[0],
|
||||
this->npc_ai_params[z].unknown_a2[1], this->npc_ai_params[z].unknown_a2[2]));
|
||||
for (size_t w = 0; w < 0x78; w += 0x08) {
|
||||
lines.emplace_back(string_printf(
|
||||
" ai_params.a3[0x%02zX:0x%02zX]=%04hX %04hX %04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
" ai_params.a3[0x%02zX:0x%02zX]: %04hX %04hX %04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
w, w + 0x08,
|
||||
this->npc_ai_params[z].params[w + 0x00].load(), this->npc_ai_params[z].params[w + 0x01].load(),
|
||||
this->npc_ai_params[z].params[w + 0x02].load(), this->npc_ai_params[z].params[w + 0x03].load(),
|
||||
@@ -1592,12 +1629,12 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
this->npc_ai_params[z].params[w + 0x06].load(), this->npc_ai_params[z].params[w + 0x07].load()));
|
||||
}
|
||||
lines.emplace_back(string_printf(
|
||||
" ai_params.a3[0x78:0x7E]=%04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
" ai_params.a3[0x78:0x7E]: %04hX %04hX %04hX %04hX %04hX %04hX",
|
||||
this->npc_ai_params[z].params[0x78].load(), this->npc_ai_params[z].params[0x79].load(),
|
||||
this->npc_ai_params[z].params[0x7A].load(), this->npc_ai_params[z].params[0x7B].load(),
|
||||
this->npc_ai_params[z].params[0x7C].load(), this->npc_ai_params[z].params[0x7D].load()));
|
||||
lines.emplace_back(string_printf(" npc_decks[%zu]:", z));
|
||||
lines.emplace_back(" name: " + string(this->npc_decks[z].name));
|
||||
lines.emplace_back(" name: " + format_data_string(this->npc_decks[z].name));
|
||||
for (size_t w = 0; w < 0x20; w++) {
|
||||
uint16_t card_id = this->npc_decks[z].card_ids[w];
|
||||
shared_ptr<const CardIndex::CardEntry> entry;
|
||||
@@ -1615,28 +1652,31 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
}
|
||||
}
|
||||
for (size_t x = 0; x < 0x10; x++) {
|
||||
lines.emplace_back(string_printf(" npc_dialogue[%zu][%zu]:", z, x));
|
||||
lines.emplace_back(string_printf(" a1=%04hX", this->dialogue_sets[z][x].unknown_a1.load()));
|
||||
lines.emplace_back(string_printf(" a2=%04hX", this->dialogue_sets[z][x].unknown_a2.load()));
|
||||
const auto& set = this->dialogue_sets[z][x];
|
||||
if (set.when == -1 && set.percent_chance == 0xFFFF) {
|
||||
continue;
|
||||
}
|
||||
lines.emplace_back(string_printf(" npc_dialogue[%zu][%zu] (when: %04hX, chance: %hu%%):",
|
||||
z, x, set.when.load(), set.percent_chance.load()));
|
||||
for (size_t w = 0; w < 4; w++) {
|
||||
if (this->dialogue_sets[z][x].strings[w][0] != 0 &&
|
||||
static_cast<uint8_t>(this->dialogue_sets[z][x].strings[w][0]) != 0xFF) {
|
||||
lines.emplace_back(string_printf(" strings[%zu]=", w) + string(this->dialogue_sets[z][x].strings[w]));
|
||||
if (set.strings[w][0] != 0 && static_cast<uint8_t>(set.strings[w][0]) != 0xFF) {
|
||||
string escaped = format_data_string(set.strings[w]);
|
||||
lines.emplace_back(string_printf(" strings[%zu]: %s", w, escaped.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lines.emplace_back(" a7=" + format_data_string(this->unknown_a7.data(), this->unknown_a7.bytes()));
|
||||
lines.emplace_back(string_printf(" npc_ai_params_entry_index=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "]",
|
||||
lines.emplace_back(" a7: " + format_data_string(this->unknown_a7.data(), this->unknown_a7.bytes()));
|
||||
lines.emplace_back(string_printf(" npc_ai_params_entry_index: [%08" PRIX32 ", %08" PRIX32 ", %08" PRIX32 "]",
|
||||
this->npc_ai_params_entry_index[0].load(), this->npc_ai_params_entry_index[1].load(), this->npc_ai_params_entry_index[2].load()));
|
||||
if (this->before_message[0]) {
|
||||
lines.emplace_back(" before_message: " + string(this->before_message));
|
||||
lines.emplace_back(" before_message: " + format_data_string(this->before_message));
|
||||
}
|
||||
if (this->after_message[0]) {
|
||||
lines.emplace_back(" after_message: " + string(this->after_message));
|
||||
lines.emplace_back(" after_message: " + format_data_string(this->after_message));
|
||||
}
|
||||
if (this->dispatch_message[0]) {
|
||||
lines.emplace_back(" dispatch_message: " + string(this->dispatch_message));
|
||||
lines.emplace_back(" dispatch_message: " + format_data_string(this->dispatch_message));
|
||||
}
|
||||
for (size_t z = 0; z < 0x10; z++) {
|
||||
uint16_t card_id = this->reward_card_ids[z];
|
||||
@@ -1654,12 +1694,12 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
lines.emplace_back(string_printf(" reward_cards[%02zu]: %04hX", z, card_id));
|
||||
}
|
||||
}
|
||||
lines.emplace_back(string_printf(" level_overrides=[win=%" PRId32 ", loss=%" PRId32 "]",
|
||||
lines.emplace_back(string_printf(" level_overrides: [win: %" PRId32 ", loss: %" PRId32 "]",
|
||||
this->win_level_override.load(), this->loss_level_override.load()));
|
||||
lines.emplace_back(string_printf(" field_offset=(x: %hd units, y:%hd units) (x: %lg tiles, y: %lg tiles)", this->field_offset_x.load(), this->field_offset_y.load(), static_cast<double>(this->field_offset_x) / 25.0, static_cast<double>(this->field_offset_y) / 25.0));
|
||||
lines.emplace_back(string_printf(" map_category=%02hhX", this->map_category));
|
||||
lines.emplace_back(string_printf(" cyber_block_type=%02hhX", this->cyber_block_type));
|
||||
lines.emplace_back(string_printf(" a11=%02hhX%02hhX", this->unknown_a11[0], this->unknown_a11[1]));
|
||||
lines.emplace_back(string_printf(" field_offset: (x: %hd units, y:%hd units) (x: %lg tiles, y: %lg tiles)", this->field_offset_x.load(), this->field_offset_y.load(), static_cast<double>(this->field_offset_x) / 25.0, static_cast<double>(this->field_offset_y) / 25.0));
|
||||
lines.emplace_back(string_printf(" map_category: %02hhX", this->map_category));
|
||||
lines.emplace_back(string_printf(" cyber_block_type: %02hhX", this->cyber_block_type));
|
||||
lines.emplace_back(string_printf(" a11: %02hhX%02hhX", this->unknown_a11[0], this->unknown_a11[1]));
|
||||
static const array<const char*, 0x18> sc_card_entry_names = {
|
||||
"00 (Guykild; 0005)",
|
||||
"01 (Kylria; 0006)",
|
||||
@@ -1686,12 +1726,12 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
"16 (K.C.; 011E)",
|
||||
"17 (Ohgun; 011F)",
|
||||
};
|
||||
string unavailable_sc_cards = " unavailable_sc_cards=[";
|
||||
string unavailable_sc_cards = " unavailable_sc_cards: [";
|
||||
for (size_t z = 0; z < 0x18; z++) {
|
||||
if (this->unavailable_sc_cards[z] == 0xFFFF) {
|
||||
continue;
|
||||
}
|
||||
if (unavailable_sc_cards.size() > 24) {
|
||||
if (unavailable_sc_cards.size() > 25) {
|
||||
unavailable_sc_cards += ", ";
|
||||
}
|
||||
if (this->unavailable_sc_cards[z] >= sc_card_entry_names.size()) {
|
||||
@@ -1743,13 +1783,13 @@ string MapDefinition::str(const CardIndex* card_index) const {
|
||||
break;
|
||||
}
|
||||
lines.emplace_back(string_printf(
|
||||
" entry_states[%zu] = %s / %s", z, player_type.c_str(), deck_type.c_str()));
|
||||
" entry_states[%zu]: %s / %s", z, player_type.c_str(), deck_type.c_str()));
|
||||
}
|
||||
return join(lines, "\n");
|
||||
}
|
||||
|
||||
MapDefinitionTrial::MapDefinitionTrial(const MapDefinition& map)
|
||||
: unknown_a1(map.unknown_a1),
|
||||
: tag(map.tag),
|
||||
map_number(map.map_number),
|
||||
width(map.width),
|
||||
height(map.height),
|
||||
@@ -1793,7 +1833,9 @@ MapDefinitionTrial::MapDefinitionTrial(const MapDefinition& map)
|
||||
|
||||
MapDefinitionTrial::operator MapDefinition() const {
|
||||
MapDefinition ret;
|
||||
ret.unknown_a1 = this->unknown_a1;
|
||||
// Trial Edition maps seem to have different tag values; we just always use
|
||||
// the value that the final version expects.
|
||||
ret.tag = 0x00000100;
|
||||
ret.map_number = this->map_number;
|
||||
ret.width = this->width;
|
||||
ret.height = this->height;
|
||||
@@ -1824,8 +1866,8 @@ MapDefinitionTrial::operator MapDefinition() const {
|
||||
for (size_t z = 0; z < ret.dialogue_sets.size(); z++) {
|
||||
ret.dialogue_sets[z].sub<8>(0) = this->dialogue_sets[z];
|
||||
for (size_t x = 8; x < ret.dialogue_sets[z].size(); x++) {
|
||||
ret.dialogue_sets[z][x].unknown_a1 = 0xFFFF;
|
||||
ret.dialogue_sets[z][x].unknown_a2 = 0xFFFF;
|
||||
ret.dialogue_sets[z][x].when = -1;
|
||||
ret.dialogue_sets[z][x].percent_chance = 0xFFFF;
|
||||
for (size_t w = 0; w < 4; w++) {
|
||||
ret.dialogue_sets[z][x].strings[w].clear(0xFF);
|
||||
ret.dialogue_sets[z][x].strings[w][0] = 0x00;
|
||||
|
||||
+35
-15
@@ -23,6 +23,7 @@ class CardIndex;
|
||||
class MapIndex;
|
||||
class COMDeckIndex;
|
||||
|
||||
const char* name_for_environment_number(uint8_t environment_number);
|
||||
const char* name_for_link_color(uint8_t color);
|
||||
|
||||
enum BehaviorFlag : uint32_t {
|
||||
@@ -721,6 +722,8 @@ struct CardDefinition {
|
||||
} __attribute__((packed)); // 0x128 bytes in total
|
||||
|
||||
struct CardDefinitionsFooter {
|
||||
// Technically the card definitions file is a REL file, so the last 0x20 bytes
|
||||
// here should be a separate structure.
|
||||
/* 00 */ be_uint32_t num_cards1;
|
||||
/* 04 */ be_uint32_t cards_offset; // == 0
|
||||
/* 08 */ be_uint32_t num_cards2;
|
||||
@@ -728,9 +731,9 @@ struct CardDefinitionsFooter {
|
||||
/* 18 */ parray<be_uint16_t, 0x10> relocations;
|
||||
/* 38 */ be_uint32_t relocations_offset;
|
||||
/* 3C */ be_uint32_t num_relocations;
|
||||
/* 40 */ parray<be_uint32_t, 2> unknown_a4;
|
||||
/* 40 */ parray<be_uint32_t, 2> unused1;
|
||||
/* 48 */ be_uint32_t footer_offset;
|
||||
/* 4C */ parray<be_uint32_t, 3> unknown_a5;
|
||||
/* 4C */ parray<be_uint32_t, 3> unused2;
|
||||
/* 58 */
|
||||
} __attribute__((packed));
|
||||
|
||||
@@ -771,6 +774,8 @@ struct PlayerConfig {
|
||||
// records structure and didn't remove the codepath that reads from this.
|
||||
/* 0138:---- */ PlayerRecords_Battle<true> unused_offline_records;
|
||||
/* 0150:---- */ parray<uint8_t, 4> unknown_a4;
|
||||
// The PlayerDataSegment structure begins here. In newserv, we combine this
|
||||
// structure into PlayerConfig since the two are always used together.
|
||||
/* 0154:0000 */ uint8_t is_encrypted;
|
||||
/* 0155:0001 */ uint8_t basis;
|
||||
/* 0156:0002 */ parray<uint8_t, 2> unused;
|
||||
@@ -819,15 +824,18 @@ struct PlayerConfig {
|
||||
/* 00 */ be_uint32_t guild_card_number;
|
||||
/* 04 */ ptext<char, 0x18> player_name;
|
||||
} __attribute__((packed));
|
||||
// TODO: What do these player references mean? When are entries added to or
|
||||
// removed from this list? It appears to happen sometime during processing of
|
||||
// the 6xB4x05 on the client, but the exact conditions aren't yet clear.
|
||||
/* 2128:1FD4 */ parray<PlayerReference, 10> unknown_a9;
|
||||
// This array is updated when a battle is started (via a 6xB4x05 command). The
|
||||
// client adds the opposing players' info to ths first two entries here if the
|
||||
// opponents are human. (The existing entries are always moved back by two
|
||||
// slots, but if either or both opponents are not humans, one or both of the
|
||||
// newly-vacated slots is not filled in.)
|
||||
/* 2128:1FD4 */ parray<PlayerReference, 10> recent_human_opponents;
|
||||
/* 2240:20EC */ parray<uint8_t, 0x28> unknown_a10;
|
||||
// TODO: These three fields are timestamps, but it's not clear what they're
|
||||
// used for.
|
||||
/* 2268:2114 */ be_uint32_t unknown_t1;
|
||||
/* 226C:2118 */ be_uint32_t unknown_t2;
|
||||
/* 2268:2114 */ be_uint32_t init_timestamp;
|
||||
/* 226C:2118 */ be_uint32_t last_online_battle_start_timestamp;
|
||||
// In a certain situation, unknown_t3 is set to init_timestamp plus a multiple
|
||||
// of two weeks (1209600 seconds). unknown_t3 appears never to be used for
|
||||
// anything, though.
|
||||
/* 2270:211C */ be_uint32_t unknown_t3;
|
||||
// This visual config is copied to the player's main visual config when the
|
||||
// player's name or proportions have changed, or when certain buttons on the
|
||||
@@ -991,8 +999,15 @@ struct CompressedMapHeader { // .mnm file format
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
|
||||
/* 0000 */ be_uint32_t unknown_a1; // Should be 0x00000100
|
||||
// If tag is not 0x00000100, the game considers the map to be corrupt in
|
||||
// offline mode and will delete it (if it's a download quest). The tag field
|
||||
// doesn't seem to have any other use.
|
||||
/* 0000 */ be_uint32_t tag;
|
||||
|
||||
/* 0004 */ be_uint32_t map_number; // Must be unique across all maps
|
||||
|
||||
// The maximum map size is 16 tiles in either dimension, since the various
|
||||
// tiles arrays below are fixed sizes.
|
||||
/* 0008 */ uint8_t width;
|
||||
/* 0009 */ uint8_t height;
|
||||
|
||||
@@ -1186,12 +1201,17 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
|
||||
/* 2760 */ ptext<char, 0x190> dispatch_message;
|
||||
|
||||
struct DialogueSet {
|
||||
/* 0000 */ be_uint16_t unknown_a1;
|
||||
/* 0002 */ be_uint16_t unknown_a2; // Always 0x0064 if valid, 0xFFFF if unused?
|
||||
/* 0000 */ be_int16_t when; // 0x00-0x0C, or FFFF if unused
|
||||
/* 0002 */ be_uint16_t percent_chance; // 0-100, or FFFF if unused
|
||||
// If the dialogue set activates, the game randomly chooses one of these
|
||||
// strings, excluding any that are empty or begin with the character '^'.
|
||||
/* 0004 */ parray<ptext<char, 0x40>, 4> strings;
|
||||
/* 0104 */
|
||||
} __attribute__((packed));
|
||||
/* 28F0 */ parray<parray<DialogueSet, 0x10>, 3> dialogue_sets; // Up to 0x10 per valid NPC
|
||||
// There are up to 0x10 of these per valid NPC, but only the first 13 of them
|
||||
// are used, since each one must have a unique value for .when and the values
|
||||
// there can only be 0-12.
|
||||
/* 28F0 */ parray<parray<DialogueSet, 0x10>, 3> dialogue_sets;
|
||||
|
||||
// These card IDs are always given to the player when they win a battle on
|
||||
// this map. Unused entries should be set to FFFF.
|
||||
@@ -1280,7 +1300,7 @@ struct MapDefinitionTrial {
|
||||
// This is the format of Episode 3 Trial Edition maps. See the comments in
|
||||
// MapDefinition for what each field means.
|
||||
|
||||
/* 0000 */ be_uint32_t unknown_a1;
|
||||
/* 0000 */ be_uint32_t tag;
|
||||
/* 0004 */ be_uint32_t map_number;
|
||||
/* 0008 */ uint8_t width;
|
||||
/* 0009 */ uint8_t height;
|
||||
|
||||
@@ -1514,7 +1514,7 @@ void Server::setup_and_start_battle() {
|
||||
|
||||
G_UpdateMap_GC_Ep3_6xB4x05 cmd05;
|
||||
cmd05.state = *this->map_and_rules;
|
||||
cmd05.unknown_a1 = 1;
|
||||
cmd05.start_battle = 1;
|
||||
this->send(cmd05);
|
||||
|
||||
this->battle_start_usecs = now();
|
||||
|
||||
Reference in New Issue
Block a user