implement $savechar on Episode 3

This commit is contained in:
Martin Michelsen
2024-06-27 23:33:22 -07:00
parent 52644695a3
commit 4bd6ef12a9
38 changed files with 474 additions and 82 deletions
+56
View File
@@ -1158,6 +1158,62 @@ void PlayerConfig::encrypt(uint8_t basis) {
this->basis = basis;
}
PlayerConfigNTE::PlayerConfigNTE(const PlayerConfig& config)
: rank_text(config.rank_text),
unknown_a1(config.unknown_a1),
tech_menu_shortcut_entries(config.tech_menu_shortcut_entries),
choice_search_config(config.choice_search_config),
scenario_progress(config.scenario_progress),
unused_offline_records(config.unused_offline_records),
unknown_a4(config.unknown_a4),
is_encrypted(config.is_encrypted),
basis(config.basis),
unused(config.unused),
card_counts(config.card_counts),
card_count_checksums(config.card_count_checksums),
rare_tokens(config.rare_tokens),
decks(config.decks),
unknown_a8(config.unknown_a8),
offline_clv_exp(config.offline_clv_exp),
online_clv_exp(config.online_clv_exp),
recent_human_opponents(config.recent_human_opponents),
unknown_a10(config.unknown_a10),
init_timestamp(config.init_timestamp),
last_online_battle_start_timestamp(config.last_online_battle_start_timestamp),
unknown_t3(config.unknown_t3),
unknown_a14(config.unknown_a14) {
// TODO: Do we need to recompute card_count_checksums? (Here or in operator
// PlayerConfig?)
}
PlayerConfigNTE::operator PlayerConfig() const {
return {
.rank_text = this->rank_text,
.unknown_a1 = this->unknown_a1,
.tech_menu_shortcut_entries = this->tech_menu_shortcut_entries,
.choice_search_config = this->choice_search_config,
.scenario_progress = this->scenario_progress,
.unused_offline_records = this->unused_offline_records,
.unknown_a4 = this->unknown_a4,
.is_encrypted = this->is_encrypted,
.basis = this->basis,
.unused = this->unused,
.card_counts = this->card_counts,
.card_count_checksums = this->card_count_checksums,
.rare_tokens = this->rare_tokens,
.decks = this->decks,
.unknown_a8 = this->unknown_a8,
.offline_clv_exp = this->offline_clv_exp,
.online_clv_exp = this->online_clv_exp,
.recent_human_opponents = this->recent_human_opponents,
.unknown_a10 = this->unknown_a10,
.init_timestamp = this->init_timestamp,
.last_online_battle_start_timestamp = this->last_online_battle_start_timestamp,
.unknown_t3 = this->unknown_t3,
.unknown_a14 = this->unknown_a14,
};
}
Rules::Rules(const JSON& json) {
this->clear();
this->overall_time_limit = json.get_int("overall_time_limit", this->overall_time_limit);
+36 -3
View File
@@ -907,12 +907,12 @@ struct PlayerConfig {
// card counts array is encrypted in memory most of the time, and they went
// out of their way to ensure the game uses an area of memory that almost no
// other game uses, which is also used by the Action Replay.)
/* 05A4:0450 */ parray<be_uint64_t, 0x1C2> rare_tokens;
/* 05A4:0450 */ parray<be_uint64_t, 450> rare_tokens;
/* 13B4:1260 */ parray<uint8_t, 0x80> unknown_a7;
/* 1434:12E0 */ parray<DeckDefinition, 25> decks;
/* 2118:1FC4 */ parray<uint8_t, 0x08> unknown_a8;
/* 2120:1FCC */ be_uint32_t offline_clv_exp; // CLvOff = this / 100
/* 2124:1FD0 */ be_uint32_t online_clv_exp; // CLvOn = this / 100
/* 2120:1FCC */ be_uint32_t offline_clv_exp; // CLvOff = (this / 100) + 1
/* 2124:1FD0 */ be_uint32_t online_clv_exp; // CLvOn = (this / 100) + 1
struct PlayerReference {
/* 00 */ be_uint32_t guild_card_number;
/* 04 */ pstring<TextEncoding::MARKED, 0x18> name;
@@ -941,6 +941,39 @@ struct PlayerConfig {
void encrypt(uint8_t basis);
} __packed_ws__(PlayerConfig, 0x2350);
struct PlayerConfigNTE {
/* 0000 */ pstring<TextEncoding::MARKED, 12> rank_text;
/* 000C */ parray<uint8_t, 0x1C> unknown_a1;
/* 0028 */ parray<be_uint16_t, 20> tech_menu_shortcut_entries;
/* 0050 */ parray<be_uint32_t, 10> choice_search_config;
/* 0078 */ parray<be_uint32_t, 0x10> scenario_progress; // Final has 0x30 entries here
/* 00B8 */ PlayerRecordsBattleBE unused_offline_records;
/* 00D0 */ parray<uint8_t, 4> unknown_a4;
/* 00D4 */ uint8_t is_encrypted;
/* 00D5 */ uint8_t basis;
/* 00D6 */ parray<uint8_t, 2> unused;
/* 00D8 */ parray<uint8_t, 1000> card_counts;
/* 04C0 */ parray<be_uint16_t, 50> card_count_checksums;
/* 0524 */ parray<be_uint64_t, 300> rare_tokens;
/* 0E84 */ parray<DeckDefinition, 25> decks;
/* 1B68 */ parray<uint8_t, 0x08> unknown_a8;
/* 1B70 */ be_uint32_t offline_clv_exp;
/* 1B74 */ be_uint32_t online_clv_exp;
/* 1B78 */ parray<PlayerConfig::PlayerReference, 10> recent_human_opponents;
/* 1C90 */ parray<uint8_t, 0x28> unknown_a10;
/* 1CB8 */ be_uint32_t init_timestamp;
/* 1CBC */ be_uint32_t last_online_battle_start_timestamp;
/* 1CC0 */ be_uint32_t unknown_t3;
/* 1CC4 */ parray<uint8_t, 0x94> unknown_a14;
/* 1D58 */
PlayerConfigNTE(const PlayerConfig& config);
operator PlayerConfig() const;
void decrypt();
void encrypt(uint8_t basis);
} __packed_ws__(PlayerConfigNTE, 0x1D58);
enum class HPType : uint8_t {
DEFEAT_PLAYER = 0,
DEFEAT_TEAM = 1,