fix mericarol type logic; closes #607
This commit is contained in:
@@ -158,6 +158,8 @@ const char* phosg::name_for_enum<EnemyType>(EnemyType type) {
|
|||||||
return "LOVE_RAPPY";
|
return "LOVE_RAPPY";
|
||||||
case EnemyType::MERICAROL:
|
case EnemyType::MERICAROL:
|
||||||
return "MERICAROL";
|
return "MERICAROL";
|
||||||
|
case EnemyType::MERICARAND:
|
||||||
|
return "MERICARAND";
|
||||||
case EnemyType::MERICUS:
|
case EnemyType::MERICUS:
|
||||||
return "MERICUS";
|
return "MERICUS";
|
||||||
case EnemyType::MERIKLE:
|
case EnemyType::MERIKLE:
|
||||||
@@ -348,6 +350,7 @@ EnemyType phosg::enum_for_name<EnemyType>(const char* name) {
|
|||||||
{"KONDRIEU", EnemyType::KONDRIEU},
|
{"KONDRIEU", EnemyType::KONDRIEU},
|
||||||
{"LA_DIMENIAN", EnemyType::LA_DIMENIAN},
|
{"LA_DIMENIAN", EnemyType::LA_DIMENIAN},
|
||||||
{"LOVE_RAPPY", EnemyType::LOVE_RAPPY},
|
{"LOVE_RAPPY", EnemyType::LOVE_RAPPY},
|
||||||
|
{"MERICARAND", EnemyType::MERICARAND},
|
||||||
{"MERICAROL", EnemyType::MERICAROL},
|
{"MERICAROL", EnemyType::MERICAROL},
|
||||||
{"MERICUS", EnemyType::MERICUS},
|
{"MERICUS", EnemyType::MERICUS},
|
||||||
{"MERIKLE", EnemyType::MERIKLE},
|
{"MERIKLE", EnemyType::MERIKLE},
|
||||||
@@ -500,6 +503,7 @@ bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type) {
|
|||||||
case EnemyType::LA_DIMENIAN:
|
case EnemyType::LA_DIMENIAN:
|
||||||
case EnemyType::LOVE_RAPPY:
|
case EnemyType::LOVE_RAPPY:
|
||||||
case EnemyType::MERICAROL:
|
case EnemyType::MERICAROL:
|
||||||
|
case EnemyType::MERICARAND:
|
||||||
case EnemyType::MERICUS:
|
case EnemyType::MERICUS:
|
||||||
case EnemyType::MERIKLE:
|
case EnemyType::MERIKLE:
|
||||||
case EnemyType::MERILLIA:
|
case EnemyType::MERILLIA:
|
||||||
@@ -744,6 +748,7 @@ uint8_t battle_param_index_for_enemy_type(Episode episode, EnemyType enemy_type)
|
|||||||
case EnemyType::MIGIUM:
|
case EnemyType::MIGIUM:
|
||||||
return 0x33;
|
return 0x33;
|
||||||
case EnemyType::MERICAROL:
|
case EnemyType::MERICAROL:
|
||||||
|
case EnemyType::MERICARAND:
|
||||||
return 0x3A;
|
return 0x3A;
|
||||||
case EnemyType::UL_GIBBON:
|
case EnemyType::UL_GIBBON:
|
||||||
return 0x3B;
|
return 0x3B;
|
||||||
@@ -979,6 +984,7 @@ uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) {
|
|||||||
case EnemyType::LOVE_RAPPY:
|
case EnemyType::LOVE_RAPPY:
|
||||||
return 0x33;
|
return 0x33;
|
||||||
case EnemyType::MERICAROL:
|
case EnemyType::MERICAROL:
|
||||||
|
case EnemyType::MERICARAND:
|
||||||
return 0x38;
|
return 0x38;
|
||||||
case EnemyType::MERICUS:
|
case EnemyType::MERICUS:
|
||||||
return 0x3A;
|
return 0x3A;
|
||||||
@@ -1116,6 +1122,8 @@ bool enemy_type_is_rare(EnemyType type) {
|
|||||||
(type == EnemyType::AL_RAPPY) ||
|
(type == EnemyType::AL_RAPPY) ||
|
||||||
(type == EnemyType::NAR_LILY) ||
|
(type == EnemyType::NAR_LILY) ||
|
||||||
(type == EnemyType::POUILLY_SLIME) ||
|
(type == EnemyType::POUILLY_SLIME) ||
|
||||||
|
(type == EnemyType::MERICUS) ||
|
||||||
|
(type == EnemyType::MERIKLE) ||
|
||||||
(type == EnemyType::MERISSA_AA) ||
|
(type == EnemyType::MERISSA_AA) ||
|
||||||
(type == EnemyType::PAZUZU_ALT) ||
|
(type == EnemyType::PAZUZU_ALT) ||
|
||||||
(type == EnemyType::DORPHON_ECLAIR) ||
|
(type == EnemyType::DORPHON_ECLAIR) ||
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ enum class EnemyType {
|
|||||||
KONDRIEU,
|
KONDRIEU,
|
||||||
LA_DIMENIAN,
|
LA_DIMENIAN,
|
||||||
LOVE_RAPPY,
|
LOVE_RAPPY,
|
||||||
|
MERICARAND,
|
||||||
MERICAROL,
|
MERICAROL,
|
||||||
MERICUS,
|
MERICUS,
|
||||||
MERIKLE,
|
MERIKLE,
|
||||||
|
|||||||
+63
-28
@@ -2066,12 +2066,9 @@ shared_ptr<SuperMap::Enemy> SuperMap::add_enemy_and_children(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0064: { // TObjEneSlime
|
case 0x0064: { // TObjEneSlime
|
||||||
// TODO: It appears BB doesn't have a way to force slimes to be rare via
|
// Unlike all other versions, BB doesn't have a way to force slimes to be
|
||||||
// constructor args. Is this true?
|
// rare via constructor args
|
||||||
bool is_rare_v123 = (set_entry->uparam2 & 1);
|
bool is_rare_v123 = (set_entry->uparam2 & 1);
|
||||||
if ((set_entry->num_children != 0) && (set_entry->num_children != 4)) {
|
|
||||||
this->log.warning("POFUILLY_SLIME has an unusual num_children (0x%hX)", set_entry->num_children.load());
|
|
||||||
}
|
|
||||||
default_num_children = -1; // Skip adding children later (because we do it here)
|
default_num_children = -1; // Skip adding children later (because we do it here)
|
||||||
size_t num_children = set_entry->num_children ? set_entry->num_children.load() : 4;
|
size_t num_children = set_entry->num_children ? set_entry->num_children.load() : 4;
|
||||||
for (size_t z = 0; z < num_children + 1; z++) {
|
for (size_t z = 0; z < num_children + 1; z++) {
|
||||||
@@ -2224,15 +2221,24 @@ shared_ptr<SuperMap::Enemy> SuperMap::add_enemy_and_children(
|
|||||||
default_num_children = 4;
|
default_num_children = 4;
|
||||||
break;
|
break;
|
||||||
case 0x00D5: // TObjEneMerillLia
|
case 0x00D5: // TObjEneMerillLia
|
||||||
add((set_entry->uparam1 & 0x01) ? EnemyType::MERILTAS : EnemyType::MERILLIA);
|
add((set_entry->uparam1 & 1) ? EnemyType::MERILTAS : EnemyType::MERILLIA);
|
||||||
break;
|
break;
|
||||||
case 0x00D6: // TObjEneBm9Mericarol
|
case 0x00D6: { // TObjEneBm9Mericarol
|
||||||
if (set_entry->uparam1 == 0) {
|
switch (set_entry->uparam1) {
|
||||||
add(EnemyType::MERICAROL);
|
case 0:
|
||||||
} else {
|
add(EnemyType::MERICAROL);
|
||||||
add(((set_entry->uparam1 % 3) == 2) ? EnemyType::MERICUS : EnemyType::MERIKLE);
|
break;
|
||||||
|
case 1:
|
||||||
|
add(EnemyType::MERIKLE);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
add(EnemyType::MERICUS);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
add(EnemyType::MERICARAND);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0x00D7: // TObjEneBm5GibonU
|
case 0x00D7: // TObjEneBm5GibonU
|
||||||
add((set_entry->uparam1 & 0x01) ? EnemyType::ZOL_GIBBON : EnemyType::UL_GIBBON);
|
add((set_entry->uparam1 & 0x01) ? EnemyType::ZOL_GIBBON : EnemyType::UL_GIBBON);
|
||||||
break;
|
break;
|
||||||
@@ -3218,29 +3224,31 @@ void SuperMap::print(FILE* stream) const {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Map state
|
// Map state
|
||||||
|
|
||||||
MapState::RareEnemyRates::RareEnemyRates(uint32_t enemy_rate, uint32_t boss_rate)
|
MapState::RareEnemyRates::RareEnemyRates(uint32_t enemy_rate, uint32_t mericarand_rate, uint32_t boss_rate)
|
||||||
: hildeblue(enemy_rate),
|
: hildeblue(enemy_rate),
|
||||||
rappy(enemy_rate),
|
rappy(enemy_rate),
|
||||||
nar_lily(enemy_rate),
|
nar_lily(enemy_rate),
|
||||||
pouilly_slime(enemy_rate),
|
pouilly_slime(enemy_rate),
|
||||||
|
mericarand(mericarand_rate),
|
||||||
merissa_aa(enemy_rate),
|
merissa_aa(enemy_rate),
|
||||||
pazuzu(enemy_rate),
|
pazuzu(enemy_rate),
|
||||||
dorphon_eclair(enemy_rate),
|
dorphon_eclair(enemy_rate),
|
||||||
kondrieu(boss_rate) {}
|
kondrieu(boss_rate) {}
|
||||||
|
|
||||||
MapState::RareEnemyRates::RareEnemyRates(const phosg::JSON& json)
|
MapState::RareEnemyRates::RareEnemyRates(const phosg::JSON& json)
|
||||||
: hildeblue(json.get_int("Hildeblue")),
|
: hildeblue(json.get_int("Hildeblue", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
rappy(json.get_int("Rappy")),
|
rappy(json.get_int("Rappy", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
nar_lily(json.get_int("NarLily")),
|
nar_lily(json.get_int("NarLily", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
pouilly_slime(json.get_int("PouillySlime")),
|
pouilly_slime(json.get_int("PouillySlime", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
merissa_aa(json.get_int("MerissaAA")),
|
mericarand(json.get_int("Mericarand", DEFAULT_MERICARAND_RATE_V3)),
|
||||||
pazuzu(json.get_int("Pazuzu")),
|
merissa_aa(json.get_int("MerissaAA", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
dorphon_eclair(json.get_int("DorphonEclair")),
|
pazuzu(json.get_int("Pazuzu", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
kondrieu(json.get_int("Kondrieu")) {}
|
dorphon_eclair(json.get_int("DorphonEclair", DEFAULT_RARE_ENEMY_RATE_V3)),
|
||||||
|
kondrieu(json.get_int("Kondrieu", DEFAULT_RARE_BOSS_RATE_V4)) {}
|
||||||
|
|
||||||
string MapState::RareEnemyRates::str() const {
|
string MapState::RareEnemyRates::str() const {
|
||||||
return phosg::string_printf("RareEnemyRates(hildeblue=%08" PRIX32 ", rappy=%08" PRIX32 ", nar_lily=%08" PRIX32 ", pouilly_slime=%08" PRIX32 ", merissa_aa=%08" PRIX32 ", pazuzu=%08" PRIX32 ", dorphon_eclair=%08" PRIX32 ", kondrieu=%08" PRIX32 ")",
|
return phosg::string_printf("RareEnemyRates(hildeblue=%08" PRIX32 ", rappy=%08" PRIX32 ", nar_lily=%08" PRIX32 ", pouilly_slime=%08" PRIX32 ", mericarand=%08" PRIX32 ", merissa_aa=%08" PRIX32 ", pazuzu=%08" PRIX32 ", dorphon_eclair=%08" PRIX32 ", kondrieu=%08" PRIX32 ")",
|
||||||
this->hildeblue, this->rappy, this->nar_lily, this->pouilly_slime,
|
this->hildeblue, this->rappy, this->nar_lily, this->pouilly_slime, this->mericarand,
|
||||||
this->merissa_aa, this->pazuzu, this->dorphon_eclair, this->kondrieu);
|
this->merissa_aa, this->pazuzu, this->dorphon_eclair, this->kondrieu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3250,6 +3258,7 @@ phosg::JSON MapState::RareEnemyRates::json() const {
|
|||||||
{"Rappy", this->rappy},
|
{"Rappy", this->rappy},
|
||||||
{"NarLily", this->nar_lily},
|
{"NarLily", this->nar_lily},
|
||||||
{"PouillySlime", this->pouilly_slime},
|
{"PouillySlime", this->pouilly_slime},
|
||||||
|
{"Mericarand", this->mericarand},
|
||||||
{"MerissaAA", this->merissa_aa},
|
{"MerissaAA", this->merissa_aa},
|
||||||
{"Pazuzu", this->pazuzu},
|
{"Pazuzu", this->pazuzu},
|
||||||
{"DorphonEclair", this->dorphon_eclair},
|
{"DorphonEclair", this->dorphon_eclair},
|
||||||
@@ -3269,6 +3278,8 @@ uint32_t MapState::RareEnemyRates::for_enemy_type(EnemyType type) const {
|
|||||||
return this->nar_lily;
|
return this->nar_lily;
|
||||||
case EnemyType::POFUILLY_SLIME:
|
case EnemyType::POFUILLY_SLIME:
|
||||||
return this->pouilly_slime;
|
return this->pouilly_slime;
|
||||||
|
case EnemyType::MERICARAND:
|
||||||
|
return this->mericarand;
|
||||||
case EnemyType::MERISSA_A:
|
case EnemyType::MERISSA_A:
|
||||||
return this->merissa_aa;
|
return this->merissa_aa;
|
||||||
case EnemyType::ZU:
|
case EnemyType::ZU:
|
||||||
@@ -3284,8 +3295,12 @@ uint32_t MapState::RareEnemyRates::for_enemy_type(EnemyType type) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shared_ptr<const MapState::RareEnemyRates> MapState::NO_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(0, 0);
|
const shared_ptr<const MapState::RareEnemyRates> MapState::NO_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(
|
||||||
const shared_ptr<const MapState::RareEnemyRates> MapState::DEFAULT_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(0x0083126E, 0x1999999A);
|
0, 0, 0);
|
||||||
|
const shared_ptr<const MapState::RareEnemyRates> MapState::DEFAULT_RARE_ENEMIES = make_shared<MapState::RareEnemyRates>(
|
||||||
|
MapState::RareEnemyRates::DEFAULT_RARE_ENEMY_RATE_V3,
|
||||||
|
MapState::RareEnemyRates::DEFAULT_MERICARAND_RATE_V3,
|
||||||
|
MapState::RareEnemyRates::DEFAULT_RARE_BOSS_RATE_V4);
|
||||||
|
|
||||||
uint32_t MapState::EnemyState::convert_game_flags(uint32_t game_flags, bool to_v3) {
|
uint32_t MapState::EnemyState::convert_game_flags(uint32_t game_flags, bool to_v3) {
|
||||||
// The format of game_flags was changed significantly between v2 and v3, and
|
// The format of game_flags was changed significantly between v2 and v3, and
|
||||||
@@ -3522,7 +3537,7 @@ void MapState::index_super_map(const FloorConfig& fc, shared_ptr<PSOLFGEncryptio
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto rare_type = rare_type_for_enemy_type(type, fc.super_map->get_episode(), this->event, ene->floor);
|
auto rare_type = rare_type_for_enemy_type(type, fc.super_map->get_episode(), this->event, ene->floor);
|
||||||
if (rare_type != type) {
|
if ((type == EnemyType::MERICARAND) || (rare_type != type)) {
|
||||||
unordered_map<uint32_t, float> det_cache;
|
unordered_map<uint32_t, float> det_cache;
|
||||||
uint32_t bb_rare_rate = this->bb_rare_rates->for_enemy_type(type);
|
uint32_t bb_rare_rate = this->bb_rare_rates->for_enemy_type(type);
|
||||||
for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) {
|
for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) {
|
||||||
@@ -3556,15 +3571,35 @@ void MapState::index_super_map(const FloorConfig& fc, shared_ptr<PSOLFGEncryptio
|
|||||||
det_cache.emplace(seed, det);
|
det_cache.emplace(seed, det);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On v1 and v2 (and GC NTE), the rare rate is 0.1% instead of 0.2%.
|
if (type == EnemyType::MERICARAND) {
|
||||||
if (det < (is_v1_or_v2(v) ? 0.001f : 0.002f)) {
|
// On v3, Mericarols that have uparam1 > 2 are randomized to be
|
||||||
ene_st->set_rare(v);
|
// Mericus, Merikle, or Mericarol, but the former two are not
|
||||||
|
// considered rare. (We use rare_flags anyway to distinguish them
|
||||||
|
// from Mericarol.)
|
||||||
|
if (det > 0.9) { // Merikle
|
||||||
|
ene_st->set_rare(v);
|
||||||
|
ene_st->set_mericarand_variant_flag(v);
|
||||||
|
} else if (det > 0.8) { // Mericus
|
||||||
|
ene_st->set_rare(v);
|
||||||
|
} else {
|
||||||
|
// Mericarol (no flags to set)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// On v1 and v2 (and GC NTE), the rare rate is 0.1% instead of 0.2%.
|
||||||
|
if (det < (is_v1_or_v2(v) ? 0.001f : 0.002f)) {
|
||||||
|
ene_st->set_rare(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((bb_rare_rate > 0) &&
|
} else if ((bb_rare_rate > 0) &&
|
||||||
(this->bb_rare_enemy_indexes.size() < 0x10) &&
|
(this->bb_rare_enemy_indexes.size() < 0x10) &&
|
||||||
(random_from_optional_crypt(opt_rand_crypt) < bb_rare_rate)) {
|
(random_from_optional_crypt(opt_rand_crypt) < bb_rare_rate)) {
|
||||||
this->bb_rare_enemy_indexes.emplace_back(enemy_index);
|
this->bb_rare_enemy_indexes.emplace_back(enemy_index);
|
||||||
ene_st->set_rare(v);
|
ene_st->set_rare(v);
|
||||||
|
if ((type == EnemyType::MERICARAND) && (enemy_index & 1)) {
|
||||||
|
ene_st->set_mericarand_variant_flag(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-6
@@ -628,16 +628,22 @@ protected:
|
|||||||
class MapState {
|
class MapState {
|
||||||
public:
|
public:
|
||||||
struct RareEnemyRates {
|
struct RareEnemyRates {
|
||||||
|
static constexpr uint32_t DEFAULT_RARE_ENEMY_RATE_V1_V2 = 0x00418937; // 1/1000
|
||||||
|
static constexpr uint32_t DEFAULT_RARE_ENEMY_RATE_V3 = 0x0083126E; // 1/500
|
||||||
|
static constexpr uint32_t DEFAULT_MERICARAND_RATE_V3 = 0x33333333; // 1/5
|
||||||
|
static constexpr uint32_t DEFAULT_RARE_BOSS_RATE_V4 = 0x1999999A; // 1/10
|
||||||
|
|
||||||
uint32_t hildeblue; // HILDEBEAR -> HILDEBLUE
|
uint32_t hildeblue; // HILDEBEAR -> HILDEBLUE
|
||||||
uint32_t rappy; // RAG_RAPPY -> {AL_RAPPY or seasonal rappies}; SAND_RAPPY -> DEL_RAPPY
|
uint32_t rappy; // RAG_RAPPY -> {AL_RAPPY or seasonal rappies}; SAND_RAPPY -> DEL_RAPPY
|
||||||
uint32_t nar_lily; // POISON_LILY -> NAR_LILY
|
uint32_t nar_lily; // POISON_LILY -> NAR_LILY
|
||||||
uint32_t pouilly_slime; // POFUILLY_SLIME -> POUILLY_SLIME
|
uint32_t pouilly_slime; // POFUILLY_SLIME -> POUILLY_SLIME
|
||||||
|
uint32_t mericarand; // MERICARAND -> MERIKLE or MERICUS (only for those with subtype > 2)
|
||||||
uint32_t merissa_aa; // MERISSA_A -> MERISSA_AA
|
uint32_t merissa_aa; // MERISSA_A -> MERISSA_AA
|
||||||
uint32_t pazuzu; // ZU -> PAZUZU (and _ALT variants)
|
uint32_t pazuzu; // ZU -> PAZUZU (and _ALT variants)
|
||||||
uint32_t dorphon_eclair; // DORPHON -> DORPHON_ECLAIR
|
uint32_t dorphon_eclair; // DORPHON -> DORPHON_ECLAIR
|
||||||
uint32_t kondrieu; // {SAINT_MILLION, SHAMBERTIN} -> KONDRIEU
|
uint32_t kondrieu; // {SAINT_MILLION, SHAMBERTIN} -> KONDRIEU
|
||||||
|
|
||||||
RareEnemyRates(uint32_t enemy_rate, uint32_t boss_rate);
|
RareEnemyRates(uint32_t enemy_rate, uint32_t mericarand_rate, uint32_t boss_rate);
|
||||||
explicit RareEnemyRates(const phosg::JSON& json);
|
explicit RareEnemyRates(const phosg::JSON& json);
|
||||||
|
|
||||||
uint32_t for_enemy_type(EnemyType type) const;
|
uint32_t for_enemy_type(EnemyType type) const;
|
||||||
@@ -687,9 +693,10 @@ public:
|
|||||||
};
|
};
|
||||||
size_t e_id = 0;
|
size_t e_id = 0;
|
||||||
size_t set_id = 0;
|
size_t set_id = 0;
|
||||||
|
uint32_t game_flags = 0; // From 6x0A
|
||||||
uint16_t total_damage = 0;
|
uint16_t total_damage = 0;
|
||||||
uint16_t rare_flags = 0;
|
uint16_t rare_flags = 0;
|
||||||
uint32_t game_flags = 0; // From 6x0A
|
uint16_t mericarand_variant_flags = 0;
|
||||||
uint16_t set_flags = 0; // Only used if super_ene->child_index == 0
|
uint16_t set_flags = 0; // Only used if super_ene->child_index == 0
|
||||||
uint16_t server_flags = 0;
|
uint16_t server_flags = 0;
|
||||||
|
|
||||||
@@ -721,16 +728,29 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_rare(Version version) const {
|
inline bool is_rare(Version version) const {
|
||||||
return (((rare_flags >> static_cast<size_t>(version)) & 1) ||
|
return (((this->rare_flags >> static_cast<size_t>(version)) & 1) ||
|
||||||
((version == Version::BB_V4) ? this->super_ene->is_default_rare_bb : this->super_ene->is_default_rare_v123));
|
((version == Version::BB_V4) ? this->super_ene->is_default_rare_bb : this->super_ene->is_default_rare_v123));
|
||||||
}
|
}
|
||||||
inline void set_rare(Version version) {
|
inline void set_rare(Version version) {
|
||||||
this->rare_flags |= (1 << static_cast<size_t>(version));
|
this->rare_flags |= (1 << static_cast<size_t>(version));
|
||||||
}
|
}
|
||||||
|
inline void set_mericarand_variant_flag(Version version) {
|
||||||
|
this->mericarand_variant_flags |= (1 << static_cast<size_t>(version));
|
||||||
|
}
|
||||||
inline EnemyType type(Version version, Episode episode, uint8_t event) const {
|
inline EnemyType type(Version version, Episode episode, uint8_t event) const {
|
||||||
return this->is_rare(version)
|
if (this->super_ene->type == EnemyType::MERICARAND) {
|
||||||
? rare_type_for_enemy_type(this->super_ene->type, episode, event, this->super_ene->floor)
|
if (this->is_rare(version)) {
|
||||||
: this->super_ene->type;
|
return ((this->mericarand_variant_flags >> static_cast<size_t>(version)) & 1)
|
||||||
|
? EnemyType::MERIKLE
|
||||||
|
: EnemyType::MERICUS;
|
||||||
|
} else {
|
||||||
|
return EnemyType::MERICAROL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this->is_rare(version)
|
||||||
|
? rare_type_for_enemy_type(this->super_ene->type, episode, event, this->super_ene->floor)
|
||||||
|
: this->super_ene->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inline bool ever_hit_by_client_id(uint8_t client_id) const {
|
inline bool ever_hit_by_client_id(uint8_t client_id) const {
|
||||||
return this->server_flags & (Flag::ALL_HITS_MASK_FIRST << client_id);
|
return this->server_flags & (Flag::ALL_HITS_MASK_FIRST << client_id);
|
||||||
|
|||||||
@@ -1205,18 +1205,24 @@
|
|||||||
// all difficulties use the same rates.) If the Challenge set is not
|
// all difficulties use the same rates.) If the Challenge set is not
|
||||||
// specified, the default rates are used for Challenge mode, which is 1/500
|
// specified, the default rates are used for Challenge mode, which is 1/500
|
||||||
// for all enemies.
|
// for all enemies.
|
||||||
|
// The Mericarand rate applies to Mericarol enemies whose arguments specify
|
||||||
|
// that they may be replaced with Mericus or Merikle. (Specifically, if
|
||||||
|
// uparam1 > 2, this is the case.) When a Mericarol is replaced, the enemy
|
||||||
|
// index is used to determine whether it will be a Mericus (even enemy index)
|
||||||
|
// or Merikle (odd enemy index).
|
||||||
"RareEnemyRates-Normal": {
|
"RareEnemyRates-Normal": {
|
||||||
// These are probabilities out of 0xFFFFFFFF - so 0 means that rare enemy
|
// These are probabilities out of 0xFFFFFFFF - so 0 means that rare enemy
|
||||||
// will never appear, and 0xFFFFFFFF means it will always appear (until 16
|
// will never appear, and 0xFFFFFFFF means it will always appear (until 16
|
||||||
// rare enemies have been assigned).
|
// rare enemies have been assigned).
|
||||||
"Hildeblue": 0x0083126E,
|
"Hildeblue": 0x0083126E, // 1/500
|
||||||
"Rappy": 0x0083126E,
|
"Rappy": 0x0083126E, // 1/500
|
||||||
"NarLily": 0x0083126E,
|
"NarLily": 0x0083126E, // 1/500
|
||||||
"PouillySlime": 0x0083126E,
|
"PouillySlime": 0x0083126E, // 1/500
|
||||||
"MerissaAA": 0x0083126E,
|
"Mericarand": 0x33333333, // 1/5
|
||||||
"Pazuzu": 0x0083126E,
|
"MerissaAA": 0x0083126E, // 1/500
|
||||||
"DorphonEclair": 0x0083126E,
|
"Pazuzu": 0x0083126E, // 1/500
|
||||||
"Kondrieu": 0x1999999A,
|
"DorphonEclair": 0x0083126E, // 1/500
|
||||||
|
"Kondrieu": 0x1999999A, // 1/10
|
||||||
},
|
},
|
||||||
// "RareEnemyRates-Hard": {...},
|
// "RareEnemyRates-Hard": {...},
|
||||||
// "RareEnemyRates-VeryHard": {...},
|
// "RareEnemyRates-VeryHard": {...},
|
||||||
|
|||||||
Reference in New Issue
Block a user