fix unit table in v2/v3 ItemCreator

This commit is contained in:
Martin Michelsen
2023-10-28 13:23:00 -07:00
parent 8a1c4f5f8b
commit 2c6df68af3
4 changed files with 54 additions and 23 deletions
+37 -13
View File
@@ -16,6 +16,7 @@ ItemCreator::ItemCreator(
shared_ptr<const WeaponRandomSet> weapon_random_set,
shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set,
shared_ptr<const ItemParameterTable> item_parameter_table,
GameVersion version,
Episode episode,
GameMode mode,
uint8_t difficulty,
@@ -23,6 +24,7 @@ ItemCreator::ItemCreator(
uint32_t random_seed,
shared_ptr<const BattleRules> restrictions)
: log("[ItemCreator] "),
version(version),
episode(episode),
mode(mode),
difficulty(difficulty),
@@ -35,7 +37,9 @@ ItemCreator::ItemCreator(
item_parameter_table(item_parameter_table),
pt(common_item_set->get_table(this->episode, this->mode, this->difficulty, this->section_id)),
restrictions(restrictions),
random_crypt(random_seed) {}
random_crypt(random_seed) {
this->generate_unit_weights_tables();
}
bool ItemCreator::are_rare_drops_allowed() const {
// Note: The client has an additional check here, which appears to be a subtle
@@ -420,7 +424,7 @@ void ItemCreator::set_tool_item_amount_to_1(ItemData& item) const {
}
void ItemCreator::clear_tool_item_if_invalid(ItemData& item) {
if ((item.data1[1] == 2) &&
if ((item.data1[1] == 0x02) &&
((item.data1[2] > 0x1D) || (item.data1[4] > 0x12))) {
item.clear();
}
@@ -591,7 +595,7 @@ void ItemCreator::generate_common_tool_variances(uint32_t area_norm, ItemData& i
item.clear();
uint8_t tool_class = this->get_rand_from_weighted_tables_2d_vertical(this->pt->tool_class_prob_table(), area_norm);
if (tool_class == 0x1A) {
if (this->is_v3() && (tool_class == 0x1A)) {
tool_class = 0x73;
}
@@ -699,7 +703,7 @@ uint8_t ItemCreator::choose_weapon_special(uint8_t det) {
static const uint8_t maxes[4] = {8, 10, 11, 11};
uint8_t det2 = this->rand_int(maxes[det]);
size_t index = 0;
for (size_t z = 1; z < 0x29; z++) {
for (size_t z = 1; z < this->item_parameter_table->num_specials; z++) {
if (det + 1 == this->item_parameter_table->get_special_stars(z)) {
if (index == det2) {
return z;
@@ -716,18 +720,38 @@ void ItemCreator::generate_unit_weights_tables() {
// Note: This part of the function was originally in a different function,
// since it had another callsite. Unlike the original code, we generate these
// tables only once at construction time, so we've inlined the function here.
size_t star_base_index;
switch (this->version) {
case GameVersion::DC:
case GameVersion::PC:
star_base_index = 0x1D1;
this->unit_weights_table1.resize(0x84);
break;
case GameVersion::GC:
case GameVersion::XB:
star_base_index = 0x2AF;
this->unit_weights_table1.resize(0x88);
break;
case GameVersion::BB:
star_base_index = 0x37D;
this->unit_weights_table1.resize(0x88);
break;
default:
throw logic_error("invalid game version");
}
size_t z;
for (z = 0; z < 0x10; z++) {
uint8_t v = this->item_parameter_table->get_item_stars(z + 0x37D);
this->unit_weights_table1[(z * 5) + 0] = v - 1;
this->unit_weights_table1[(z * 5) + 1] = v - 1;
this->unit_weights_table1[(z * 5) + 2] = v;
this->unit_weights_table1[(z * 5) + 3] = v + 1;
this->unit_weights_table1[(z * 5) + 4] = v + 1;
uint8_t v = this->item_parameter_table->get_item_stars(z + star_base_index);
this->unit_weights_table1.at((z * 5) + 0) = v - 1;
this->unit_weights_table1.at((z * 5) + 1) = v - 1;
this->unit_weights_table1.at((z * 5) + 2) = v;
this->unit_weights_table1.at((z * 5) + 3) = v + 1;
this->unit_weights_table1.at((z * 5) + 4) = v + 1;
}
for (; z < 0x48; z++) {
this->unit_weights_table1[z + 0x50] =
this->item_parameter_table->get_item_stars(z + 0x37D);
for (; z < (this->unit_weights_table1.size() - 0x40); z++) {
this->unit_weights_table1.at(z + 0x40) = this->item_parameter_table->get_item_stars(z + star_base_index);
}
// Note: Inlining ends here
+7 -1
View File
@@ -19,6 +19,7 @@ public:
std::shared_ptr<const WeaponRandomSet> weapon_random_set,
std::shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set,
std::shared_ptr<const ItemParameterTable> item_parameter_table,
GameVersion version,
Episode episode,
GameMode mode,
uint8_t difficulty,
@@ -45,6 +46,7 @@ public:
private:
PrefixedLogger log;
GameVersion version;
Episode episode;
GameMode mode;
uint8_t difficulty;
@@ -58,13 +60,17 @@ private:
std::shared_ptr<const CommonItemSet::Table> pt;
std::shared_ptr<const BattleRules> restrictions;
parray<uint8_t, 0x88> unit_weights_table1;
std::vector<uint8_t> unit_weights_table1;
parray<int8_t, 0x0D> unit_weights_table2;
// Note: The original implementation uses 17 different random states for some
// reason. We forego that and use only one for simplicity.
PSOV2Encryption random_crypt;
inline bool is_v3() const {
return (this->version != GameVersion::DC) && (this->version != GameVersion::PC);
}
bool are_rare_drops_allowed() const;
uint8_t normalize_area_number(uint8_t area) const;
+9 -9
View File
@@ -334,6 +334,15 @@ public:
size_t price_for_item(const ItemData& item) const;
size_t num_weapon_classes;
size_t num_tool_classes;
size_t item_stars_first_id;
size_t item_stars_last_id;
size_t special_stars_begin_index;
size_t num_specials;
size_t first_rare_mag_index;
size_t star_value_table_size;
private:
struct TableOffsetsV2 {
// TODO: Is weapon count 0x89 or 0x8A? It could be that the last entry in
@@ -412,15 +421,6 @@ private:
float get_sale_divisor_t(uint32_t weapon_table_offset, uint32_t non_weapon_table_offset, uint8_t data1_0, uint8_t data1_1) const;
template <bool IsBigEndian>
std::pair<const ItemParameterTable::EventItem*, size_t> get_event_items_t(uint32_t base_offset, uint8_t event_number) const;
size_t num_weapon_classes;
size_t num_tool_classes;
size_t item_stars_first_id;
size_t item_stars_last_id;
size_t special_stars_begin_index;
size_t num_specials;
size_t first_rare_mag_index;
size_t star_value_table_size;
};
class MagEvolutionTable {
+1
View File
@@ -67,6 +67,7 @@ void Lobby::create_item_creator() {
s->weapon_random_sets.at(this->difficulty),
s->tekker_adjustment_set,
s->item_parameter_table_for_version(this->base_version),
this->base_version,
this->episode,
(this->mode == GameMode::SOLO) ? GameMode::NORMAL : this->mode,
this->difficulty,