split disp data into stats and visual substructures

This commit is contained in:
Martin Michelsen
2023-06-26 21:25:24 -07:00
parent e1b4bd32c9
commit 8656222be3
14 changed files with 237 additions and 427 deletions
+60 -195
View File
@@ -27,7 +27,7 @@ static const string ACCOUNT_FILE_SIGNATURE =
static FileContentsCache player_files_cache(300 * 1000 * 1000);
PlayerStats::PlayerStats() noexcept
CharacterStats::CharacterStats() noexcept
: atp(0),
mst(0),
evp(0),
@@ -36,11 +36,13 @@ PlayerStats::PlayerStats() noexcept
ata(0),
lck(0) {}
PlayerDispDataDCPCV3::PlayerDispDataDCPCV3() noexcept
PlayerStats::PlayerStats() noexcept
: level(0),
experience(0),
meseta(0),
unknown_a2(0),
meseta(0) {}
PlayerVisualConfig::PlayerVisualConfig() noexcept
: unknown_a2(0),
name_color(0),
extra_model(0),
name_color_checksum(0),
@@ -62,121 +64,43 @@ PlayerDispDataDCPCV3::PlayerDispDataDCPCV3() noexcept
void PlayerDispDataDCPCV3::enforce_v2_limits() {
// V1/V2 have fewer classes, so we'll substitute some here
if (this->char_class == 11) {
this->char_class = 0; // FOmar -> HUmar
} else if (this->char_class == 10) {
this->char_class = 1; // RAmarl -> HUnewearl
} else if (this->char_class == 9) {
this->char_class = 5; // HUcaseal -> RAcaseal
if (this->visual.char_class == 11) {
this->visual.char_class = 0; // FOmar -> HUmar
} else if (this->visual.char_class == 10) {
this->visual.char_class = 1; // RAmarl -> HUnewearl
} else if (this->visual.char_class == 9) {
this->visual.char_class = 5; // HUcaseal -> RAcaseal
}
// If the player is somehow still not a valid class, make them appear as the
// "ninja" NPC
if (this->char_class > 8) {
this->extra_model = 0;
this->v2_flags |= 2;
if (this->visual.char_class > 8) {
this->visual.extra_model = 0;
this->visual.v2_flags |= 2;
}
this->version = 2;
this->visual.version = 2;
}
PlayerDispDataBB PlayerDispDataDCPCV3::to_bb() const {
PlayerDispDataBB bb;
bb.stats.atp = this->stats.atp;
bb.stats.mst = this->stats.mst;
bb.stats.evp = this->stats.evp;
bb.stats.hp = this->stats.hp;
bb.stats.dfp = this->stats.dfp;
bb.stats.ata = this->stats.ata;
bb.stats.lck = this->stats.lck;
bb.unknown_a1 = this->unknown_a1;
bb.level = this->level;
bb.experience = this->experience;
bb.meseta = this->meseta;
bb.guild_card = " 0";
bb.unknown_a2 = this->unknown_a2;
bb.name_color = this->name_color;
bb.extra_model = this->extra_model;
bb.unused = this->unused;
bb.name_color_checksum = this->name_color_checksum;
bb.section_id = this->section_id;
bb.char_class = this->char_class;
bb.v2_flags = this->v2_flags;
bb.version = this->version;
bb.v1_flags = this->v1_flags;
bb.costume = this->costume;
bb.skin = this->skin;
bb.face = this->face;
bb.head = this->head;
bb.hair = this->hair;
bb.hair_r = this->hair_r;
bb.hair_g = this->hair_g;
bb.hair_b = this->hair_b;
bb.proportion_x = this->proportion_x;
bb.proportion_y = this->proportion_y;
bb.name = add_language_marker(this->name, 'J');
bb.stats = this->stats;
bb.visual = this->visual;
bb.visual.name = " 0";
bb.name = add_language_marker(this->visual.name, 'J');
bb.config = this->config;
bb.technique_levels = this->technique_levels;
return bb;
}
PlayerDispDataBB::PlayerDispDataBB() noexcept
: level(0),
experience(0),
meseta(0),
unknown_a2(0),
name_color(0),
extra_model(0),
name_color_checksum(0),
section_id(0),
char_class(0),
v2_flags(0),
version(0),
v1_flags(0),
costume(0),
skin(0),
face(0),
head(0),
hair(0),
hair_r(0),
hair_g(0),
hair_b(0),
proportion_x(0),
proportion_y(0) {}
: play_time(0),
unknown_a3(0) {}
PlayerDispDataDCPCV3 PlayerDispDataBB::to_dcpcv3() const {
PlayerDispDataDCPCV3 ret;
ret.stats.atp = this->stats.atp;
ret.stats.mst = this->stats.mst;
ret.stats.evp = this->stats.evp;
ret.stats.hp = this->stats.hp;
ret.stats.dfp = this->stats.dfp;
ret.stats.ata = this->stats.ata;
ret.stats.lck = this->stats.lck;
ret.unknown_a1 = this->unknown_a1;
ret.level = this->level;
ret.experience = this->experience;
ret.meseta = this->meseta;
ret.unknown_a2 = this->unknown_a2;
ret.name_color = this->name_color;
ret.extra_model = this->extra_model;
ret.unused = this->unused;
ret.name_color_checksum = this->name_color_checksum;
ret.section_id = this->section_id;
ret.char_class = this->char_class;
ret.v2_flags = this->v2_flags;
ret.version = this->version;
ret.v1_flags = this->v1_flags;
ret.costume = this->costume;
ret.skin = this->skin;
ret.face = this->face;
ret.head = this->head;
ret.hair = this->hair;
ret.hair_r = this->hair_r;
ret.hair_g = this->hair_g;
ret.hair_b = this->hair_b;
ret.proportion_x = this->proportion_x;
ret.proportion_y = this->proportion_y;
ret.name = remove_language_marker(this->name);
ret.stats = this->stats;
ret.visual = this->visual;
ret.visual.name = remove_language_marker(this->name);
ret.config = this->config;
ret.technique_levels = this->technique_levels;
return ret;
@@ -184,105 +108,46 @@ PlayerDispDataDCPCV3 PlayerDispDataBB::to_dcpcv3() const {
PlayerDispDataBBPreview PlayerDispDataBB::to_preview() const {
PlayerDispDataBBPreview pre;
pre.level = this->level;
pre.experience = this->experience;
pre.guild_card = this->guild_card;
pre.unknown_a2 = this->unknown_a2;
pre.name_color = this->name_color;
pre.extra_model = this->extra_model;
pre.unused = this->unused;
pre.name_color_checksum = this->name_color_checksum;
pre.section_id = this->section_id;
pre.char_class = this->char_class;
pre.v2_flags = this->v2_flags;
pre.version = this->version;
pre.v1_flags = this->v1_flags;
pre.costume = this->costume;
pre.skin = this->skin;
pre.face = this->face;
pre.head = this->head;
pre.hair = this->hair;
pre.hair_r = this->hair_r;
pre.hair_g = this->hair_g;
pre.hair_b = this->hair_b;
pre.proportion_x = this->proportion_x;
pre.proportion_y = this->proportion_y;
pre.level = this->stats.level;
pre.experience = this->stats.experience;
pre.visual = this->visual;
pre.name = this->name;
pre.play_time = this->play_time;
return pre;
}
void PlayerDispDataBB::apply_preview(const PlayerDispDataBBPreview& pre) {
this->level = pre.level;
this->experience = pre.experience;
this->guild_card = pre.guild_card;
this->unknown_a2 = pre.unknown_a2;
this->name_color = pre.name_color;
this->extra_model = pre.extra_model;
this->unused = pre.unused;
this->name_color_checksum = pre.name_color_checksum;
this->section_id = pre.section_id;
this->char_class = pre.char_class;
this->v2_flags = pre.v2_flags;
this->version = pre.version;
this->v1_flags = pre.v1_flags;
this->costume = pre.costume;
this->skin = pre.skin;
this->face = pre.face;
this->head = pre.head;
this->hair = pre.hair;
this->hair_r = pre.hair_r;
this->hair_g = pre.hair_g;
this->hair_b = pre.hair_b;
this->proportion_x = pre.proportion_x;
this->proportion_y = pre.proportion_y;
this->stats.level = pre.level;
this->stats.experience = pre.experience;
this->visual = pre.visual;
this->name = pre.name;
}
void PlayerDispDataBB::apply_dressing_room(const PlayerDispDataBBPreview& pre) {
this->name_color = pre.name_color;
this->extra_model = pre.extra_model;
this->name_color_checksum = pre.name_color_checksum;
this->section_id = pre.section_id;
this->char_class = pre.char_class;
this->v2_flags = pre.v2_flags;
this->version = pre.version;
this->v1_flags = pre.v1_flags;
this->costume = pre.costume;
this->skin = pre.skin;
this->face = pre.face;
this->head = pre.head;
this->hair = pre.hair;
this->hair_r = pre.hair_r;
this->hair_g = pre.hair_g;
this->hair_b = pre.hair_b;
this->proportion_x = pre.proportion_x;
this->proportion_y = pre.proportion_y;
this->visual.name_color = pre.visual.name_color;
this->visual.extra_model = pre.visual.extra_model;
this->visual.name_color_checksum = pre.visual.name_color_checksum;
this->visual.section_id = pre.visual.section_id;
this->visual.char_class = pre.visual.char_class;
this->visual.v2_flags = pre.visual.v2_flags;
this->visual.version = pre.visual.version;
this->visual.v1_flags = pre.visual.v1_flags;
this->visual.costume = pre.visual.costume;
this->visual.skin = pre.visual.skin;
this->visual.face = pre.visual.face;
this->visual.head = pre.visual.head;
this->visual.hair = pre.visual.hair;
this->visual.hair_r = pre.visual.hair_r;
this->visual.hair_g = pre.visual.hair_g;
this->visual.hair_b = pre.visual.hair_b;
this->visual.proportion_x = pre.visual.proportion_x;
this->visual.proportion_y = pre.visual.proportion_y;
this->name = pre.name;
}
PlayerDispDataBBPreview::PlayerDispDataBBPreview() noexcept
: experience(0),
level(0),
unknown_a2(0),
name_color(0),
extra_model(0),
name_color_checksum(0),
section_id(0),
char_class(0),
v2_flags(0),
version(0),
v1_flags(0),
costume(0),
skin(0),
face(0),
head(0),
hair(0),
hair_r(0),
hair_g(0),
hair_b(0),
proportion_x(0),
proportion_y(0),
play_time(0) {}
GuildCardV3::GuildCardV3() noexcept
@@ -416,14 +281,14 @@ void ClientGameData::create_player(
const PlayerDispDataBBPreview& preview,
shared_ptr<const LevelTable> level_table) {
shared_ptr<SavedPlayerDataBB> data(new SavedPlayerDataBB(
load_object_file<SavedPlayerDataBB>(player_template_filename(preview.char_class))));
load_object_file<SavedPlayerDataBB>(player_template_filename(preview.visual.char_class))));
if (data->signature != PLAYER_FILE_SIGNATURE) {
throw runtime_error("player data header is incorrect");
}
try {
data->disp.apply_preview(preview);
data->disp.stats = level_table->base_stats_for_class(data->disp.char_class);
data->disp.stats.char_stats = level_table->base_stats_for_class(data->disp.visual.char_class);
} catch (const exception& e) {
throw runtime_error(string_printf("template application failed: %s", e.what()));
}
@@ -572,8 +437,8 @@ PlayerBB ClientGameData::export_player_bb() {
ret.guild_card_description = player->guild_card_description;
ret.reserved1 = 0;
ret.reserved2 = 0;
ret.section_id = player->disp.section_id;
ret.char_class = player->disp.char_class;
ret.section_id = player->disp.visual.section_id;
ret.char_class = player->disp.visual.char_class;
ret.unknown3 = 0;
ret.symbol_chats = account->symbol_chats;
ret.shortcuts = account->shortcuts;
@@ -678,9 +543,9 @@ void SavedPlayerDataBB::add_item(const PlayerInventoryItem& item) {
// Annoyingly, meseta is in the disp data, not in the inventory struct. If the
// item is meseta, we have to modify disp instead.
if (pid == MESETA_IDENTIFIER) {
this->disp.meseta += item.data.data2d;
if (this->disp.meseta > 999999) {
this->disp.meseta = 999999;
this->disp.stats.meseta += item.data.data2d;
if (this->disp.stats.meseta > 999999) {
this->disp.stats.meseta = 999999;
}
return;
}
@@ -762,10 +627,10 @@ PlayerInventoryItem SavedPlayerDataBB::remove_item(
// If we're removing meseta (signaled by an invalid item ID), then create a
// meseta item.
if (item_id == 0xFFFFFFFF) {
if (amount <= this->disp.meseta) {
this->disp.meseta -= amount;
if (amount <= this->disp.stats.meseta) {
this->disp.stats.meseta -= amount;
} else if (allow_meseta_overdraft) {
this->disp.meseta = 0;
this->disp.stats.meseta = 0;
} else {
throw out_of_range("player does not have enough meseta");
}
@@ -919,7 +784,7 @@ size_t PlayerBank::find_item(uint32_t item_id) {
}
void SavedPlayerDataBB::print_inventory(FILE* stream) const {
fprintf(stream, "[PlayerInventory] Meseta: %" PRIu32 "\n", this->disp.meseta.load());
fprintf(stream, "[PlayerInventory] Meseta: %" PRIu32 "\n", this->disp.stats.meseta.load());
fprintf(stream, "[PlayerInventory] %hhu items\n", this->inventory.num_items);
for (size_t x = 0; x < this->inventory.num_items; x++) {
const auto& item = this->inventory.items[x];