Dragon Quest Monsters: Joker/RAM map

From Data Crystal
Jump to navigation Jump to search

Chip tiny.png The following article is a RAM map for Dragon Quest Monsters: Joker.

import std.io;

struct parent_monster {
    u16 species;
    u8 name[0x09];
    u16 unknown;
    u8 scout_name[11];
};

struct monster {
    u8 monster_name[12];
    u16 species; // Confirmed, but does not appear to auto update rank + traits + resistances, does update family
    u8 rank; // 1=F, 2=E, 3=D, 4=C, 5=B, 6=A, 7=S, 8=X, 9=???
    u8 family;
    u8 sex; // 0=+, 1=-, 2=+-
    u8 unknown_d[3];
    u8 synthesis_plus_number;
    u8 unknown_de[4];
    u8 unknown_e[24];
    u8 unknown_f[29];
    u8 unknown_f2[2];
    u8 unknown_g[29];
    u8 unknown_g2[5];
    
    u8 level; // Confirmed
    u8 level_limit;
    
    // Stats
    //
    // Stats are represented by two sets of values "base" stat values and
    // "adjusted" stat values.
    //
    // "base" stat values are the stat values without accounting for the
    // monster's current equipment. "adjusted" stat values are the stat
    // values after accounting for the effects of equipment.
    //
    // A monster will use its "adjusted" stat values. Once the monster's
    // equipment is removed, its "adjusted" stats values will be set back
    // to the corresponding "base" stat values.
    //
    // If you want to edit the stat values of a monster, be sure to change
    // both the "base" stat value and the corresponding "adjusted" stat
    // value.
    u16 base_max_hp;
    u16 base_max_mp;
    u16 base_attack;
    u16 base_defense;
    u16 base_agility;
    u16 base_wisdom;
    u16 current_hp; // This appears to be healed right after loading the game (at least at a centre)
    u16 adjusted_max_hp;
    u16 current_mp; // This appears to be healed right after loading the game (at least at a centre)
    u16 adjusted_max_mp;
    u16 adjusted_attack;
    u16 adjusted_defense;
    u16 adjusted_agility;
    u16 adjusted_wisdom;
    
    u32 exp; // TODO: confirm the size
    // Note: Exp to next level is not stored, it is re-calculated based on the monster's level
    u8 tactic;
    u8 unknown_17[0x6];
    u8 unknown_18[0x4];
    u8 equipment;

    // Skill sets // TODO: change to arrays of 3 elements
    u8 first_skill_set_id;
    u8 second_skill_set_id;
    u8 third_skill_set_id;
    u8 first_skill_set_points;
    u8 second_skill_set_points;
    u8 third_skill_set_points;
    u8 first_set_num_unlocked_skills;
    u8 second_set_num_unlocked_skills;
    u8 third_set_num_unlocked_skills;

    u8 unknown_20;
    u16 unallocated_skill_points;
    u8 skills[0x1E]; // TODO: confirm size
    u8 traits[0x1F]; // TODO: confirm size
    u8 unknown_21[10];
    u8 level_when_hashed;
    u16 hash;
    u16 unknown_22;
    u8 scout_name[12];
    parent_monster parents[2];
    parent_monster grandparents[4]; // These have no name or scout name info
};

fn format_playtime(u32 raw) {
    u32 remaining = raw & 0b111111;
    u32 seconds = (raw >> 6) & 0b111111;
    u32 minutes = (raw >> 12) & 0b111111;
    u32 hours = raw >> 18;

    return std::format("{}:{:0>2}:{:0>2} ({})", hours, minutes, seconds, remaining);
};

struct name {
    u8 name[9];
    u8 unknown_a[3];
};

struct player_info {
    name name;
    u32 gold;
    u32 atm_gold;
    u8 items_in_hand[16];
    u8 item_in_bag_counts[256];
    u8 num_darkonium_times_5;
    u8 unknown_b[3];
    u32 playtime [[format("format_playtime")]];
    u8 num_party_monsters;
    u8 num_monsters;
    u8 unknown_c[290];
    u32 num_monsters_scouted;
    u8 unknown_d[8];
    u32 num_battles_won;
    u32 num_times_synthesized;
    u8 unknown[640];
};

u32 rng_counter @ 0x020BEC98;
u32 rng_value @ 0x020BEC9C;

player_info player_info @ 0x020BE340;
monster player_monsters[100] @ 0x20B3D8C;
monster incarnus @ 0x020B2DBC;