support non-BB rare enemy generation logic

This commit is contained in:
Martin Michelsen
2024-01-03 23:27:06 -08:00
parent fccc0f7346
commit e13b220be9
4 changed files with 26 additions and 6 deletions
+1
View File
@@ -5,6 +5,7 @@
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
- Add an idle connection timeout for proxy sessions
- Look into JP heart symbol bug on Linux
- Check server's rare enemy logic against GC's logic
## Episode 3
+1 -1
View File
@@ -262,7 +262,7 @@ void Lobby::create_item_creator() {
}
void Lobby::load_maps() {
this->map = make_shared<Map>(this->lobby_id, this->random_crypt);
this->map = make_shared<Map>(this->base_version, this->lobby_id, this->random_crypt);
auto rare_rates = ((this->base_version == Version::BB_V4) && this->rare_enemy_rates)
? this->rare_enemy_rates
+22 -4
View File
@@ -683,8 +683,9 @@ string Map::Object::str() const {
this->item_drop_checked ? "true" : "false");
}
Map::Map(uint32_t lobby_id, std::shared_ptr<PSOLFGEncryption> random_crypt)
Map::Map(Version version, uint32_t lobby_id, std::shared_ptr<PSOLFGEncryption> random_crypt)
: log(string_printf("[Lobby:%08" PRIX32 ":map] ", lobby_id), lobby_log.min_level),
version(version),
random_crypt(random_crypt) {}
void Map::clear() {
@@ -722,10 +723,27 @@ bool Map::check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate) {
if (default_is_rare) {
return true;
}
if ((this->rare_enemy_indexes.size() < 0x10) && (this->random_crypt->next() < rare_rate)) {
this->rare_enemy_indexes.emplace_back(this->enemies.size());
return true;
// On BB, rare enemy indexes are generated by the server and sent to the
// client, so we can use any method we want to choose rares. On other
// versions, we must match the client's logic, even though it's more
// computationally expensive.
if (this->version == Version::BB_V4) {
if ((this->rare_enemy_indexes.size() < 0x10) && (this->random_crypt->next() < rare_rate)) {
this->rare_enemy_indexes.emplace_back(this->enemies.size());
return true;
}
} else {
// 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
// faster.
PSOV2Encryption crypt(this->random_crypt->seed());
if ((static_cast<float>((crypt.next() >> 16) & 0xFFFF) / 65536.0f) < 0.002f) {
return true;
}
}
return false;
}
+2 -1
View File
@@ -256,7 +256,7 @@ struct Map {
void generate_shuffled_location_table(const Map::RandomEnemyLocationsHeader& header, StringReader r, uint16_t section);
};
Map(uint32_t lobby_id, std::shared_ptr<PSOLFGEncryption> random_crypt);
Map(Version version, uint32_t lobby_id, std::shared_ptr<PSOLFGEncryption> random_crypt);
~Map() = default;
void clear();
@@ -315,6 +315,7 @@ struct Map {
static std::string disassemble_quest_data(const void* data, size_t size);
PrefixedLogger log;
Version version;
std::shared_ptr<PSOLFGEncryption> random_crypt;
std::vector<Object> objects;
std::vector<Enemy> enemies;