fix GC rare enemy logic

This commit is contained in:
Martin Michelsen
2024-01-04 23:09:09 -08:00
parent d3d89f0168
commit 83f5487e7b
5 changed files with 31 additions and 12 deletions
-1
View File
@@ -4,7 +4,6 @@
- Implement decrypt/encrypt actions for VMS files - Implement decrypt/encrypt actions for VMS files
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.) - Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
- Add an idle connection timeout for proxy sessions - Add an idle connection timeout for proxy sessions
- Check server's rare enemy logic against GC's logic
## Episode 3 ## Episode 3
+11
View File
@@ -1094,3 +1094,14 @@ const vector<EnemyType>& enemy_types_for_rare_table_index(Episode episode, uint8
return empty_vec; return empty_vec;
} }
} }
bool enemy_type_is_rare(EnemyType type) {
return ((type == EnemyType::HILDEBLUE) ||
(type == EnemyType::AL_RAPPY) ||
(type == EnemyType::NAR_LILY) ||
(type == EnemyType::POUILLY_SLIME) ||
(type == EnemyType::MERISSA_AA) ||
(type == EnemyType::PAZUZU_ALT) ||
(type == EnemyType::DORPHON_ECLAIR) ||
(type == EnemyType::KONDRIEU));
}
+1
View File
@@ -145,3 +145,4 @@ bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type);
uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type); uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type);
uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type); uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type);
const std::vector<EnemyType>& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index); const std::vector<EnemyType>& enemy_types_for_rare_table_index(Episode episode, uint8_t rt_index);
bool enemy_type_is_rare(EnemyType type);
+17 -10
View File
@@ -665,8 +665,14 @@ Map::Enemy::Enemy(uint16_t enemy_id, size_t source_index, uint8_t floor, EnemyTy
} }
string Map::Enemy::str() const { string Map::Enemy::str() const {
return string_printf("[Map::Enemy E-%hX source %zX %s floor=%02hhX flags=%02hhX last_hit_by_client_id=%hu]", return string_printf("[Map::Enemy E-%hX source %zX %s%s floor=%02hhX flags=%02hhX last_hit_by_client_id=%hu]",
this->enemy_id, this->source_index, name_for_enum(this->type), this->floor, this->state_flags, this->last_hit_by_client_id); this->enemy_id,
this->source_index,
name_for_enum(this->type),
enemy_type_is_rare(this->type) ? " RARE" : "",
this->floor,
this->state_flags,
this->last_hit_by_client_id);
} }
string Map::Object::str() const { string Map::Object::str() const {
@@ -738,8 +744,9 @@ bool Map::check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate) {
// TODO: We only need the first value from this crypt, so it's unfortunate // TODO: We only need the first value from this crypt, so it's unfortunate
// that we have to initialize the entire thing. Find a way to make this // that we have to initialize the entire thing. Find a way to make this
// faster. // faster.
PSOV2Encryption crypt(this->random_crypt->seed()); PSOV2Encryption crypt(this->random_crypt->seed() + 0x1000 + this->enemies.size());
if ((static_cast<float>((crypt.next() >> 16) & 0xFFFF) / 65536.0f) < 0.002f) { if ((static_cast<float>((crypt.next() >> 16) & 0xFFFF) / 65536.0f) < 0.002f) {
this->rare_enemy_indexes.emplace_back(this->enemies.size());
return true; return true;
} }
} }
@@ -828,15 +835,15 @@ void Map::add_enemy(
add(EnemyType::NON_ENEMY_NPC); add(EnemyType::NON_ENEMY_NPC);
break; break;
case 0x0040: // TObjEneMoja case 0x0040: { // TObjEneMoja
add(this->check_and_log_rare_enemy(e.uparam1 != 0, rare_rates->hildeblue) bool default_is_rare = (this->version == Version::BB_V4) ? (e.uparam1 & 1) : (e.uparam1 != 0);
add(this->check_and_log_rare_enemy(default_is_rare, rare_rates->hildeblue)
? EnemyType::HILDEBLUE ? EnemyType::HILDEBLUE
: EnemyType::HILDEBEAR); : EnemyType::HILDEBEAR);
break; break;
}
case 0x0041: { // TObjEneLappy case 0x0041: { // TObjEneLappy
// On BB, the set rare condition is uparam1 & 1; on other versions it's bool default_is_rare = (this->version == Version::BB_V4) ? (e.uparam1 & 1) : (e.uparam1 != 0);
// simply uparam1 != 0.
bool default_is_rare = rare_rates ? (e.uparam1 & 1) : (e.uparam1 != 0);
bool is_rare = this->check_and_log_rare_enemy(default_is_rare, rare_rates->rappy); bool is_rare = this->check_and_log_rare_enemy(default_is_rare, rare_rates->rappy);
switch (episode) { switch (episode) {
case Episode::EP1: case Episode::EP1:
@@ -893,7 +900,7 @@ void Map::add_enemy(
if ((episode == Episode::EP2) && (e.floor == 0x11)) { if ((episode == Episode::EP2) && (e.floor == 0x11)) {
add(EnemyType::DEL_LILY); add(EnemyType::DEL_LILY);
} else { } else {
add(this->check_and_log_rare_enemy(e.uparam1 != 0, rare_rates->nar_lily) add(this->check_and_log_rare_enemy((this->version == Version::BB_V4) && (e.uparam1 & 1), rare_rates->nar_lily)
? EnemyType::NAR_LILY ? EnemyType::NAR_LILY
: EnemyType::POISON_LILY); : EnemyType::POISON_LILY);
} }
@@ -907,7 +914,7 @@ void Map::add_enemy(
break; break;
} }
case 0x0064: // TObjEneSlime case 0x0064: // TObjEneSlime
add(this->check_and_log_rare_enemy(e.uparam1 != 0, rare_rates->pouilly_slime) add(this->check_and_log_rare_enemy((this->version == Version::BB_V4) && (e.uparam1 & 1), rare_rates->pouilly_slime)
? EnemyType::POUILLY_SLIME ? EnemyType::POUILLY_SLIME
: EnemyType::POFUILLY_SLIME); : EnemyType::POFUILLY_SLIME);
default_num_children = 4; default_num_children = 4;
+2 -1
View File
@@ -4394,7 +4394,8 @@ static void on_6F(shared_ptr<Client> c, uint16_t command, uint32_t, string& data
for (size_t z = 0; z < l->variations.size(); z++) { for (size_t z = 0; z < l->variations.size(); z++) {
variations_str += string_printf("%" PRIX32, l->variations[z].load()); variations_str += string_printf("%" PRIX32, l->variations[z].load());
} }
send_text_message_printf(c, "Rare seed: %08" PRIX32 "\nVariations: %s", l->random_seed, variations_str.c_str()); send_text_message_printf(c, "Rare seed: %08" PRIX32 "\nRare enemies: %zu\nVariations: %s\n",
l->random_seed, l->map->rare_enemy_indexes.size(), variations_str.c_str());
} }
bool should_resume_game = true; bool should_resume_game = true;