use JSON rare table for BB
This commit is contained in:
+2
-2
@@ -1173,7 +1173,7 @@ static void server_command_item(
|
|||||||
check_cheats_enabled(s, l);
|
check_cheats_enabled(s, l);
|
||||||
|
|
||||||
PlayerInventoryItem item;
|
PlayerInventoryItem item;
|
||||||
item.data = item_for_string(encode_sjis(args));
|
item.data = ItemData(encode_sjis(args));
|
||||||
item.data.id = l->generate_item_id(c->lobby_client_id);
|
item.data.id = l->generate_item_id(c->lobby_client_id);
|
||||||
|
|
||||||
l->add_item(item, c->area, c->x, c->z);
|
l->add_item(item, c->area, c->x, c->z);
|
||||||
@@ -1205,7 +1205,7 @@ static void proxy_command_item(
|
|||||||
bool set_drop = (!args.empty() && (args[0] == u'!'));
|
bool set_drop = (!args.empty() && (args[0] == u'!'));
|
||||||
|
|
||||||
PlayerInventoryItem item;
|
PlayerInventoryItem item;
|
||||||
item.data = item_for_string(encode_sjis(set_drop ? args.substr(1) : args));
|
item.data = ItemData(encode_sjis(set_drop ? args.substr(1) : args));
|
||||||
item.data.id = random_object<uint32_t>();
|
item.data.id = random_object<uint32_t>();
|
||||||
|
|
||||||
if (set_drop) {
|
if (set_drop) {
|
||||||
|
|||||||
+162
-5
@@ -397,6 +397,163 @@ EnemyType enum_for_name<EnemyType>(const char* name) {
|
|||||||
return names.at(name);
|
return names.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool enemy_type_valid_for_episode(Episode episode, EnemyType enemy_type) {
|
||||||
|
switch (episode) {
|
||||||
|
case Episode::EP1:
|
||||||
|
switch (enemy_type) {
|
||||||
|
case EnemyType::MOTHMANT:
|
||||||
|
case EnemyType::MONEST:
|
||||||
|
case EnemyType::SAVAGE_WOLF:
|
||||||
|
case EnemyType::BARBAROUS_WOLF:
|
||||||
|
case EnemyType::POISON_LILY:
|
||||||
|
case EnemyType::NAR_LILY:
|
||||||
|
case EnemyType::SINOW_BEAT:
|
||||||
|
case EnemyType::CANADINE:
|
||||||
|
case EnemyType::CANADINE_GROUP:
|
||||||
|
case EnemyType::CANANE:
|
||||||
|
case EnemyType::CHAOS_SORCERER:
|
||||||
|
case EnemyType::CHAOS_BRINGER:
|
||||||
|
case EnemyType::DARK_BELRA:
|
||||||
|
case EnemyType::DE_ROL_LE:
|
||||||
|
case EnemyType::DRAGON:
|
||||||
|
case EnemyType::SINOW_GOLD:
|
||||||
|
case EnemyType::RAG_RAPPY:
|
||||||
|
case EnemyType::AL_RAPPY:
|
||||||
|
case EnemyType::NANO_DRAGON:
|
||||||
|
case EnemyType::DUBCHIC:
|
||||||
|
case EnemyType::GILLCHIC:
|
||||||
|
case EnemyType::GARANZ:
|
||||||
|
case EnemyType::DARK_GUNNER:
|
||||||
|
case EnemyType::BULCLAW:
|
||||||
|
case EnemyType::CLAW:
|
||||||
|
case EnemyType::VOL_OPT_2:
|
||||||
|
case EnemyType::POUILLY_SLIME:
|
||||||
|
case EnemyType::POFUILLY_SLIME:
|
||||||
|
case EnemyType::PAN_ARMS:
|
||||||
|
case EnemyType::HIDOOM:
|
||||||
|
case EnemyType::MIGIUM:
|
||||||
|
case EnemyType::DARVANT:
|
||||||
|
case EnemyType::DARVANT_ULTIMATE:
|
||||||
|
case EnemyType::DARK_FALZ_1:
|
||||||
|
case EnemyType::DARK_FALZ_2:
|
||||||
|
case EnemyType::DARK_FALZ_3:
|
||||||
|
case EnemyType::HILDEBEAR:
|
||||||
|
case EnemyType::HILDEBLUE:
|
||||||
|
case EnemyType::BOOMA:
|
||||||
|
case EnemyType::GOBOOMA:
|
||||||
|
case EnemyType::GIGOBOOMA:
|
||||||
|
case EnemyType::GRASS_ASSASSIN:
|
||||||
|
case EnemyType::EVIL_SHARK:
|
||||||
|
case EnemyType::PAL_SHARK:
|
||||||
|
case EnemyType::GUIL_SHARK:
|
||||||
|
case EnemyType::DELSABER:
|
||||||
|
case EnemyType::DIMENIAN:
|
||||||
|
case EnemyType::LA_DIMENIAN:
|
||||||
|
case EnemyType::SO_DIMENIAN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Episode::EP2:
|
||||||
|
switch (enemy_type) {
|
||||||
|
case EnemyType::MOTHMANT:
|
||||||
|
case EnemyType::MONEST:
|
||||||
|
case EnemyType::SAVAGE_WOLF:
|
||||||
|
case EnemyType::BARBAROUS_WOLF:
|
||||||
|
case EnemyType::POISON_LILY:
|
||||||
|
case EnemyType::NAR_LILY:
|
||||||
|
case EnemyType::SINOW_BERILL:
|
||||||
|
case EnemyType::GEE:
|
||||||
|
case EnemyType::CHAOS_SORCERER:
|
||||||
|
case EnemyType::DELBITER:
|
||||||
|
case EnemyType::DARK_BELRA:
|
||||||
|
case EnemyType::BARBA_RAY:
|
||||||
|
case EnemyType::GOL_DRAGON:
|
||||||
|
case EnemyType::SINOW_SPIGELL:
|
||||||
|
case EnemyType::RAG_RAPPY:
|
||||||
|
case EnemyType::LOVE_RAPPY:
|
||||||
|
case EnemyType::SAINT_RAPPY:
|
||||||
|
case EnemyType::EGG_RAPPY:
|
||||||
|
case EnemyType::HALLO_RAPPY:
|
||||||
|
case EnemyType::GI_GUE:
|
||||||
|
case EnemyType::DUBCHIC:
|
||||||
|
case EnemyType::GILLCHIC:
|
||||||
|
case EnemyType::GARANZ:
|
||||||
|
case EnemyType::GAL_GRYPHON:
|
||||||
|
case EnemyType::EPSILON:
|
||||||
|
case EnemyType::DEL_LILY:
|
||||||
|
case EnemyType::ILL_GILL:
|
||||||
|
case EnemyType::OLGA_FLOW_1:
|
||||||
|
case EnemyType::OLGA_FLOW_2:
|
||||||
|
case EnemyType::GAEL:
|
||||||
|
case EnemyType::DELDEPTH:
|
||||||
|
case EnemyType::PAN_ARMS:
|
||||||
|
case EnemyType::HIDOOM:
|
||||||
|
case EnemyType::MIGIUM:
|
||||||
|
case EnemyType::MERICAROL:
|
||||||
|
case EnemyType::UL_GIBBON:
|
||||||
|
case EnemyType::ZOL_GIBBON:
|
||||||
|
case EnemyType::GIBBLES:
|
||||||
|
case EnemyType::MORFOS:
|
||||||
|
case EnemyType::RECOBOX:
|
||||||
|
case EnemyType::RECON:
|
||||||
|
case EnemyType::SINOW_ZOA:
|
||||||
|
case EnemyType::SINOW_ZELE:
|
||||||
|
case EnemyType::MERIKLE:
|
||||||
|
case EnemyType::MERICUS:
|
||||||
|
case EnemyType::HILDEBEAR:
|
||||||
|
case EnemyType::HILDEBLUE:
|
||||||
|
case EnemyType::MERILLIA:
|
||||||
|
case EnemyType::MERILTAS:
|
||||||
|
case EnemyType::GRASS_ASSASSIN:
|
||||||
|
case EnemyType::DOLMOLM:
|
||||||
|
case EnemyType::DOLMDARL:
|
||||||
|
case EnemyType::DELSABER:
|
||||||
|
case EnemyType::DIMENIAN:
|
||||||
|
case EnemyType::LA_DIMENIAN:
|
||||||
|
case EnemyType::SO_DIMENIAN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case Episode::EP4:
|
||||||
|
switch (enemy_type) {
|
||||||
|
case EnemyType::BOOTA:
|
||||||
|
case EnemyType::ZE_BOOTA:
|
||||||
|
case EnemyType::BA_BOOTA:
|
||||||
|
case EnemyType::SAND_RAPPY:
|
||||||
|
case EnemyType::DEL_RAPPY:
|
||||||
|
case EnemyType::ZU:
|
||||||
|
case EnemyType::PAZUZU:
|
||||||
|
case EnemyType::ASTARK:
|
||||||
|
case EnemyType::SATELLITE_LIZARD:
|
||||||
|
case EnemyType::YOWIE:
|
||||||
|
case EnemyType::DORPHON:
|
||||||
|
case EnemyType::DORPHON_ECLAIR:
|
||||||
|
case EnemyType::GORAN:
|
||||||
|
case EnemyType::PYRO_GORAN:
|
||||||
|
case EnemyType::GORAN_DETONATOR:
|
||||||
|
case EnemyType::SAND_RAPPY_ALT:
|
||||||
|
case EnemyType::DEL_RAPPY_ALT:
|
||||||
|
case EnemyType::MERISSA_A:
|
||||||
|
case EnemyType::MERISSA_AA:
|
||||||
|
case EnemyType::ZU_ALT:
|
||||||
|
case EnemyType::PAZUZU_ALT:
|
||||||
|
case EnemyType::SATELLITE_LIZARD_ALT:
|
||||||
|
case EnemyType::YOWIE_ALT:
|
||||||
|
case EnemyType::GIRTABLULU:
|
||||||
|
case EnemyType::SAINT_MILLION:
|
||||||
|
case EnemyType::SHAMBERTIN:
|
||||||
|
case EnemyType::KONDRIEU:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
switch (episode) {
|
switch (episode) {
|
||||||
case Episode::EP1:
|
case Episode::EP1:
|
||||||
@@ -725,7 +882,7 @@ uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) {
|
|||||||
return 0x53;
|
return 0x53;
|
||||||
case EnemyType::DEL_RAPPY:
|
case EnemyType::DEL_RAPPY:
|
||||||
case EnemyType::DEL_RAPPY_ALT:
|
case EnemyType::DEL_RAPPY_ALT:
|
||||||
return 0x18;
|
return 0x12;
|
||||||
case EnemyType::DELBITER:
|
case EnemyType::DELBITER:
|
||||||
return 0x48;
|
return 0x48;
|
||||||
case EnemyType::DELDEPTH:
|
case EnemyType::DELDEPTH:
|
||||||
@@ -842,16 +999,16 @@ uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) {
|
|||||||
case EnemyType::RAG_RAPPY:
|
case EnemyType::RAG_RAPPY:
|
||||||
return 0x05;
|
return 0x05;
|
||||||
case EnemyType::RECOBOX:
|
case EnemyType::RECOBOX:
|
||||||
return 0x63;
|
return 0x43;
|
||||||
case EnemyType::RECON:
|
case EnemyType::RECON:
|
||||||
return 0x64;
|
return 0x44;
|
||||||
case EnemyType::SAINT_RAPPY:
|
case EnemyType::SAINT_RAPPY:
|
||||||
return 0x4F;
|
return 0x4F;
|
||||||
case EnemyType::SAINT_MILLION:
|
case EnemyType::SAINT_MILLION:
|
||||||
return 0x13;
|
return 0x13;
|
||||||
case EnemyType::SAND_RAPPY:
|
case EnemyType::SAND_RAPPY:
|
||||||
case EnemyType::SAND_RAPPY_ALT:
|
case EnemyType::SAND_RAPPY_ALT:
|
||||||
return 0x17;
|
return 0x11;
|
||||||
case EnemyType::SATELLITE_LIZARD:
|
case EnemyType::SATELLITE_LIZARD:
|
||||||
case EnemyType::SATELLITE_LIZARD_ALT:
|
case EnemyType::SATELLITE_LIZARD_ALT:
|
||||||
return 0x03;
|
return 0x03;
|
||||||
@@ -886,7 +1043,7 @@ uint8_t rare_table_index_for_enemy_type(EnemyType enemy_type) {
|
|||||||
return 0x3C;
|
return 0x3C;
|
||||||
case EnemyType::ZU:
|
case EnemyType::ZU:
|
||||||
case EnemyType::ZU_ALT:
|
case EnemyType::ZU_ALT:
|
||||||
return 0x08;
|
return 0x07;
|
||||||
default:
|
default:
|
||||||
throw runtime_error(string_printf("%s does not have a rare table entry", name_for_enum(enemy_type)));
|
throw runtime_error(string_printf("%s does not have a rare table entry", name_for_enum(enemy_type)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,5 +140,6 @@ const char* name_for_enum<EnemyType>(EnemyType type);
|
|||||||
template <>
|
template <>
|
||||||
EnemyType enum_for_name<EnemyType>(const char* name);
|
EnemyType enum_for_name<EnemyType>(const char* name);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|||||||
+34
-33
@@ -16,6 +16,38 @@ ItemData::ItemData(const ItemData& other) {
|
|||||||
this->data2d = other.data2d;
|
this->data2d = other.data2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemData::ItemData(const string& desc) {
|
||||||
|
try {
|
||||||
|
this->parse(desc, false);
|
||||||
|
return;
|
||||||
|
} catch (const exception&) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this->parse(desc, true);
|
||||||
|
return;
|
||||||
|
} catch (const exception&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
string data = parse_data_string(desc);
|
||||||
|
if (data.size() < 2) {
|
||||||
|
throw runtime_error("item code too short");
|
||||||
|
}
|
||||||
|
if (data[0] > 4) {
|
||||||
|
throw runtime_error("invalid item class");
|
||||||
|
}
|
||||||
|
if (data.size() > 16) {
|
||||||
|
throw runtime_error("item code too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemData ret;
|
||||||
|
if (data.size() <= 12) {
|
||||||
|
memcpy(this->data1.data(), data.data(), data.size());
|
||||||
|
} else {
|
||||||
|
memcpy(this->data1.data(), data.data(), 12);
|
||||||
|
memcpy(this->data2.data(), data.data() + 12, data.size() - 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ItemData& ItemData::operator=(const ItemData& other) {
|
ItemData& ItemData::operator=(const ItemData& other) {
|
||||||
this->data1d = other.data1d;
|
this->data1d = other.data1d;
|
||||||
this->id = other.id;
|
this->id = other.id;
|
||||||
@@ -1417,7 +1449,7 @@ const unordered_map<uint32_t, ItemNameInfo> name_info_for_primary_identifier({
|
|||||||
{0x031903, "Team Points 10000"},
|
{0x031903, "Team Points 10000"},
|
||||||
});
|
});
|
||||||
|
|
||||||
ItemData::ItemData(const string& orig_description, bool skip_special) {
|
void ItemData::parse(const string& orig_description, bool skip_special) {
|
||||||
this->data1d.clear(0);
|
this->data1d.clear(0);
|
||||||
this->id = 0xFFFFFFFF;
|
this->id = 0xFFFFFFFF;
|
||||||
this->data2d = 0;
|
this->data2d = 0;
|
||||||
@@ -1490,7 +1522,7 @@ ItemData::ItemData(const string& orig_description, bool skip_special) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lookback >= 4) {
|
if (lookback >= 4) {
|
||||||
throw runtime_error("item not found");
|
throw runtime_error("item not found: " + desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = desc.substr(name_it->first.size());
|
desc = desc.substr(name_it->first.size());
|
||||||
@@ -1899,34 +1931,3 @@ string ItemData::name(bool include_color_codes) const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemData item_for_string(const string& desc) {
|
|
||||||
try {
|
|
||||||
return ItemData(desc);
|
|
||||||
} catch (const exception&) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return ItemData(desc, true);
|
|
||||||
} catch (const exception&) {
|
|
||||||
}
|
|
||||||
|
|
||||||
string data = parse_data_string(desc);
|
|
||||||
if (data.size() < 2) {
|
|
||||||
throw runtime_error("item code too short");
|
|
||||||
}
|
|
||||||
if (data[0] > 4) {
|
|
||||||
throw runtime_error("invalid item class");
|
|
||||||
}
|
|
||||||
if (data.size() > 16) {
|
|
||||||
throw runtime_error("item code too long");
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemData ret;
|
|
||||||
if (data.size() <= 12) {
|
|
||||||
memcpy(ret.data1.data(), data.data(), data.size());
|
|
||||||
} else {
|
|
||||||
memcpy(ret.data1.data(), data.data(), 12);
|
|
||||||
memcpy(ret.data2.data(), data.data() + 12, data.size() - 12);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-3
@@ -96,10 +96,12 @@ struct ItemData { // 0x14 bytes
|
|||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
ItemData();
|
ItemData();
|
||||||
explicit ItemData(const std::string& orig_description, bool skip_special = false);
|
explicit ItemData(const std::string& orig_description);
|
||||||
ItemData(const ItemData& other);
|
ItemData(const ItemData& other);
|
||||||
ItemData& operator=(const ItemData& other);
|
ItemData& operator=(const ItemData& other);
|
||||||
|
|
||||||
|
void parse(const std::string& desc, bool skip_specials);
|
||||||
|
|
||||||
bool operator==(const ItemData& other) const;
|
bool operator==(const ItemData& other) const;
|
||||||
bool operator!=(const ItemData& other) const;
|
bool operator!=(const ItemData& other) const;
|
||||||
|
|
||||||
@@ -147,5 +149,3 @@ struct ItemData { // 0x14 bytes
|
|||||||
|
|
||||||
static bool compare_for_sort(const ItemData& a, const ItemData& b);
|
static bool compare_for_sort(const ItemData& a, const ItemData& b);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
ItemData item_for_string(const std::string& desc);
|
|
||||||
|
|||||||
+60
-34
@@ -1149,9 +1149,24 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
fprintf(stdout, " Monster rares:\n");
|
fprintf(stdout, " Monster rares:\n");
|
||||||
for (size_t z = 0; z < 0x65; z++) {
|
for (size_t z = 0; z < 0x65; z++) {
|
||||||
|
string enemy_types;
|
||||||
|
for (size_t w = 0; w < static_cast<size_t>(EnemyType::MAX_ENEMY_TYPE); w++) {
|
||||||
|
auto enemy_type = static_cast<EnemyType>(w);
|
||||||
|
try {
|
||||||
|
if (rare_table_index_for_enemy_type(enemy_type) == z &&
|
||||||
|
enemy_type_valid_for_episode(episode, enemy_type)) {
|
||||||
|
enemy_types += name_for_enum(enemy_type);
|
||||||
|
enemy_types += ",";
|
||||||
|
}
|
||||||
|
} catch (const exception&) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!enemy_types.empty()) {
|
||||||
|
enemy_types.resize(enemy_types.size() - 1);
|
||||||
|
}
|
||||||
for (const auto& spec : rs->get_enemy_specs(mode, episode, difficulty, section_id, z)) {
|
for (const auto& spec : rs->get_enemy_specs(mode, episode, difficulty, section_id, z)) {
|
||||||
string s = format_drop(spec);
|
string s = format_drop(spec);
|
||||||
fprintf(stdout, " %02zX: %s\n", z, s.c_str());
|
fprintf(stdout, " %02zX: %s (%s)\n", z, s.c_str(), enemy_types.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,23 +1199,34 @@ int main(int argc, char** argv) {
|
|||||||
shared_ptr<string> data(new string(read_input_data()));
|
shared_ptr<string> data(new string(read_input_data()));
|
||||||
RELRareItemSet rs(data);
|
RELRareItemSet rs(data);
|
||||||
|
|
||||||
// Compute the mapping of {rt_index: EnemyType}
|
// Compute the mapping of {rt_index: EnemyType} for each episode
|
||||||
vector<vector<EnemyType>> rt_index_to_enemy_type;
|
const auto& generate_table = +[](Episode episode) -> vector<vector<EnemyType>> {
|
||||||
for (size_t z = 0; z < static_cast<size_t>(EnemyType::MAX_ENEMY_TYPE); z++) {
|
vector<vector<EnemyType>> ret;
|
||||||
EnemyType t = static_cast<EnemyType>(z);
|
for (size_t z = 0; z < static_cast<size_t>(EnemyType::MAX_ENEMY_TYPE); z++) {
|
||||||
try {
|
EnemyType t = static_cast<EnemyType>(z);
|
||||||
uint8_t rt_index = rare_table_index_for_enemy_type(t);
|
try {
|
||||||
if (rt_index >= rt_index_to_enemy_type.size()) {
|
uint8_t rt_index = rare_table_index_for_enemy_type(t);
|
||||||
rt_index_to_enemy_type.resize(rt_index + 1);
|
if (enemy_type_valid_for_episode(episode, t)) {
|
||||||
|
if (rt_index >= ret.size()) {
|
||||||
|
ret.resize(rt_index + 1);
|
||||||
|
}
|
||||||
|
ret[rt_index].emplace_back(t);
|
||||||
|
}
|
||||||
|
} catch (const exception&) {
|
||||||
}
|
}
|
||||||
rt_index_to_enemy_type[rt_index].emplace_back(t);
|
|
||||||
} catch (const exception&) {
|
|
||||||
}
|
}
|
||||||
}
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
JSONObject::dict_type episodes_dict;
|
JSONObject::dict_type episodes_dict;
|
||||||
static const array<Episode, 3> episodes = {Episode::EP1, Episode::EP2, Episode::EP4};
|
static const array<pair<Episode, vector<vector<EnemyType>>>, 3> episodes = {
|
||||||
for (Episode episode : episodes) {
|
make_pair(Episode::EP1, generate_table(Episode::EP1)),
|
||||||
|
make_pair(Episode::EP2, generate_table(Episode::EP2)),
|
||||||
|
make_pair(Episode::EP4, generate_table(Episode::EP4)),
|
||||||
|
};
|
||||||
|
for (const auto& episode_it : episodes) {
|
||||||
|
Episode episode = episode_it.first;
|
||||||
|
const auto& rt_index_to_enemy_type = episode_it.second;
|
||||||
JSONObject::dict_type difficulty_dict;
|
JSONObject::dict_type difficulty_dict;
|
||||||
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
|
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
|
||||||
JSONObject::dict_type section_id_dict;
|
JSONObject::dict_type section_id_dict;
|
||||||
@@ -1214,22 +1240,24 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& spec : rs.get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) {
|
for (const auto& spec : rs.get_enemy_specs(GameMode::NORMAL, episode, difficulty, section_id, rt_index)) {
|
||||||
|
uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2];
|
||||||
|
if (primary_identifier == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject::list_type spec_list;
|
JSONObject::list_type spec_list;
|
||||||
|
|
||||||
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
|
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
|
||||||
spec_list.emplace_back(make_json_str(string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)));
|
spec_list.emplace_back(make_json_str(string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)));
|
||||||
|
spec_list.emplace_back(make_json_int(primary_identifier));
|
||||||
ItemData item;
|
|
||||||
item.data1[0] = spec.item_code[0];
|
|
||||||
item.data1[1] = spec.item_code[1];
|
|
||||||
item.data1[2] = spec.item_code[2];
|
|
||||||
spec_list.emplace_back(make_json_str(item.name(false)));
|
|
||||||
|
|
||||||
JSONObject::list_type specs_list;
|
JSONObject::list_type specs_list;
|
||||||
specs_list.emplace_back(make_json_list(std::move(spec_list)));
|
specs_list.emplace_back(make_json_list(std::move(spec_list)));
|
||||||
auto specs_json = make_json_list(std::move(specs_list));
|
auto specs_json = make_json_list(std::move(specs_list));
|
||||||
for (const auto& enemy_type : enemy_types) {
|
for (const auto& enemy_type : enemy_types) {
|
||||||
collection_dict.emplace(name_for_enum(enemy_type), specs_json);
|
if (enemy_type_valid_for_episode(episode, enemy_type)) {
|
||||||
|
collection_dict.emplace(name_for_enum(enemy_type), specs_json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1238,16 +1266,16 @@ int main(int argc, char** argv) {
|
|||||||
JSONObject::list_type area_list;
|
JSONObject::list_type area_list;
|
||||||
|
|
||||||
for (const auto& spec : rs.get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) {
|
for (const auto& spec : rs.get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) {
|
||||||
|
uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2];
|
||||||
|
if (primary_identifier == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject::list_type spec_list;
|
JSONObject::list_type spec_list;
|
||||||
|
|
||||||
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
|
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
|
||||||
spec_list.emplace_back(make_json_str(string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)));
|
spec_list.emplace_back(make_json_str(string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second)));
|
||||||
|
spec_list.emplace_back(make_json_int(primary_identifier));
|
||||||
ItemData item;
|
|
||||||
item.data1[0] = spec.item_code[0];
|
|
||||||
item.data1[1] = spec.item_code[1];
|
|
||||||
item.data1[2] = spec.item_code[2];
|
|
||||||
spec_list.emplace_back(make_json_str(item.name(false)));
|
|
||||||
|
|
||||||
area_list.emplace_back(make_json_list(std::move(spec_list)));
|
area_list.emplace_back(make_json_list(std::move(spec_list)));
|
||||||
}
|
}
|
||||||
@@ -1259,11 +1287,13 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
section_id_dict.emplace(name_for_section_id(section_id), make_json_dict(std::move(collection_dict)));
|
if (!collection_dict.empty()) {
|
||||||
|
section_id_dict.emplace(name_for_section_id(section_id), make_json_dict(std::move(collection_dict)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
difficulty_dict.emplace(name_for_difficulty(difficulty), make_json_dict(std::move(section_id_dict)));
|
difficulty_dict.emplace(token_name_for_difficulty(difficulty), make_json_dict(std::move(section_id_dict)));
|
||||||
}
|
}
|
||||||
episodes_dict.emplace(name_for_episode(episode), make_json_dict(std::move(difficulty_dict)));
|
episodes_dict.emplace(token_name_for_episode(episode), make_json_dict(std::move(difficulty_dict)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject::dict_type root_dict;
|
JSONObject::dict_type root_dict;
|
||||||
@@ -1275,10 +1305,6 @@ int main(int argc, char** argv) {
|
|||||||
JSONObject::SerializeOption::SORT_DICT_KEYS);
|
JSONObject::SerializeOption::SORT_DICT_KEYS);
|
||||||
write_output_data(json_data.data(), json_data.size());
|
write_output_data(json_data.data(), json_data.size());
|
||||||
|
|
||||||
// {"Normal": {"Episode1": {"Ultimate": {"Viridia": {"GRASS_ASSASSIN": [...], "Box-Ruins2": [...]}}}}}
|
|
||||||
// ["1/32", "Slicer of Assassin"]
|
|
||||||
// [0xE0000000, 0x031000]
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-17
@@ -29,12 +29,12 @@ RareItemSet::ExpandedDrop::ExpandedDrop(const PackedDrop& d)
|
|||||||
this->item_code[2] = d.item_code[2];
|
this->item_code[2] = d.item_code[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::Table::get_enemy_specs(uint8_t enemy_type) const {
|
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::Table::get_enemy_specs(uint8_t rt_index) const {
|
||||||
vector<ExpandedDrop> ret;
|
vector<ExpandedDrop> ret;
|
||||||
if (this->monster_rares[enemy_type].item_code[0] != 0 ||
|
if (this->monster_rares[rt_index].item_code[0] != 0 ||
|
||||||
this->monster_rares[enemy_type].item_code[1] != 0 ||
|
this->monster_rares[rt_index].item_code[1] != 0 ||
|
||||||
this->monster_rares[enemy_type].item_code[2] != 0) {
|
this->monster_rares[rt_index].item_code[2] != 0) {
|
||||||
ret.emplace_back(this->monster_rares[enemy_type]);
|
ret.emplace_back(this->monster_rares[rt_index]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -115,8 +115,8 @@ GSLRareItemSet::GSLRareItemSet(shared_ptr<const string> data, bool is_big_endian
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_enemy_specs(
|
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_enemy_specs(
|
||||||
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const {
|
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const {
|
||||||
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_enemy_specs(enemy_type);
|
return this->tables.at(this->key_for_params(mode, episode, difficulty, secid))->get_enemy_specs(rt_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_box_specs(
|
std::vector<RareItemSet::ExpandedDrop> GSLRareItemSet::get_box_specs(
|
||||||
@@ -131,8 +131,8 @@ RELRareItemSet::RELRareItemSet(shared_ptr<const string> data) : data(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> RELRareItemSet::get_enemy_specs(
|
std::vector<RareItemSet::ExpandedDrop> RELRareItemSet::get_enemy_specs(
|
||||||
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const {
|
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const {
|
||||||
return this->get_table(mode, episode, difficulty, secid).get_enemy_specs(enemy_type);
|
return this->get_table(mode, episode, difficulty, secid).get_enemy_specs(rt_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> RELRareItemSet::get_box_specs(
|
std::vector<RareItemSet::ExpandedDrop> RELRareItemSet::get_box_specs(
|
||||||
@@ -193,24 +193,24 @@ JSONRareItemSet::JSONRareItemSet(std::shared_ptr<const JSONObject> json) {
|
|||||||
for (const auto& item_it : section_id_it.second->as_dict()) {
|
for (const auto& item_it : section_id_it.second->as_dict()) {
|
||||||
vector<ExpandedDrop>* target;
|
vector<ExpandedDrop>* target;
|
||||||
if (starts_with(item_it.first, "Box-")) {
|
if (starts_with(item_it.first, "Box-")) {
|
||||||
uint8_t area = drop_area_for_name(item_it.first.substr(4));
|
uint8_t area = area_for_name(item_it.first.substr(4));
|
||||||
if (collection.box_area_to_specs.size() <= area) {
|
if (collection.box_area_to_specs.size() <= area) {
|
||||||
collection.box_area_to_specs.resize(area + 1);
|
collection.box_area_to_specs.resize(area + 1);
|
||||||
}
|
}
|
||||||
target = &collection.box_area_to_specs[area];
|
target = &collection.box_area_to_specs[area];
|
||||||
} else {
|
} else {
|
||||||
size_t index = static_cast<size_t>(enum_for_name<EnemyType>(item_it.first.c_str()));
|
size_t index = rare_table_index_for_enemy_type(enum_for_name<EnemyType>(item_it.first.c_str()));
|
||||||
if (collection.enemy_type_to_specs.size() <= index) {
|
if (collection.rt_index_to_specs.size() <= index) {
|
||||||
collection.enemy_type_to_specs.resize(index + 1);
|
collection.rt_index_to_specs.resize(index + 1);
|
||||||
}
|
}
|
||||||
target = &collection.enemy_type_to_specs[index];
|
target = &collection.rt_index_to_specs[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& spec_json : item_it.second->as_list()) {
|
for (const auto& spec_json : item_it.second->as_list()) {
|
||||||
auto& spec_list = spec_json->as_list();
|
auto& spec_list = spec_json->as_list();
|
||||||
auto& d = target->emplace_back();
|
auto& d = target->emplace_back();
|
||||||
|
|
||||||
auto prob_desc = spec_list.at(1);
|
auto prob_desc = spec_list.at(0);
|
||||||
if (prob_desc->is_int()) {
|
if (prob_desc->is_int()) {
|
||||||
d.probability = spec_list.at(0)->as_int();
|
d.probability = spec_list.at(0)->as_int();
|
||||||
} else if (prob_desc->is_string()) {
|
} else if (prob_desc->is_string()) {
|
||||||
@@ -250,9 +250,9 @@ JSONRareItemSet::JSONRareItemSet(std::shared_ptr<const JSONObject> json) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RareItemSet::ExpandedDrop> JSONRareItemSet::get_enemy_specs(
|
std::vector<RareItemSet::ExpandedDrop> JSONRareItemSet::get_enemy_specs(
|
||||||
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const {
|
GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const {
|
||||||
try {
|
try {
|
||||||
return this->collections.at(this->key_for_params(mode, episode, difficulty, secid)).enemy_type_to_specs.at(enemy_type);
|
return this->collections.at(this->key_for_params(mode, episode, difficulty, secid)).rt_index_to_specs.at(rt_index);
|
||||||
} catch (const out_of_range&) {
|
} catch (const out_of_range&) {
|
||||||
static const std::vector<ExpandedDrop> empty_vector;
|
static const std::vector<ExpandedDrop> empty_vector;
|
||||||
return empty_vector;
|
return empty_vector;
|
||||||
|
|||||||
+6
-6
@@ -49,13 +49,13 @@ public:
|
|||||||
/* 0274 */ parray<be_uint32_t, 3> unknown_a5;
|
/* 0274 */ parray<be_uint32_t, 3> unknown_a5;
|
||||||
/* 0280 */
|
/* 0280 */
|
||||||
|
|
||||||
std::vector<ExpandedDrop> get_enemy_specs(uint8_t enemy_type) const;
|
std::vector<ExpandedDrop> get_enemy_specs(uint8_t rt_index) const;
|
||||||
std::vector<ExpandedDrop> get_box_specs(uint8_t area) const;
|
std::vector<ExpandedDrop> get_box_specs(uint8_t area) const;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
virtual ~RareItemSet() = default;
|
virtual ~RareItemSet() = default;
|
||||||
|
|
||||||
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const = 0;
|
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const = 0;
|
||||||
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const = 0;
|
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -68,7 +68,7 @@ class GSLRareItemSet : public RareItemSet {
|
|||||||
public:
|
public:
|
||||||
GSLRareItemSet(std::shared_ptr<const std::string> data, bool is_big_endian);
|
GSLRareItemSet(std::shared_ptr<const std::string> data, bool is_big_endian);
|
||||||
virtual ~GSLRareItemSet() = default;
|
virtual ~GSLRareItemSet() = default;
|
||||||
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const;
|
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const;
|
||||||
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -81,7 +81,7 @@ class RELRareItemSet : public RareItemSet {
|
|||||||
public:
|
public:
|
||||||
RELRareItemSet(std::shared_ptr<const std::string> data);
|
RELRareItemSet(std::shared_ptr<const std::string> data);
|
||||||
virtual ~RELRareItemSet() = default;
|
virtual ~RELRareItemSet() = default;
|
||||||
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const;
|
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const;
|
||||||
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -95,12 +95,12 @@ public:
|
|||||||
JSONRareItemSet(std::shared_ptr<const JSONObject> json);
|
JSONRareItemSet(std::shared_ptr<const JSONObject> json);
|
||||||
virtual ~JSONRareItemSet() = default;
|
virtual ~JSONRareItemSet() = default;
|
||||||
|
|
||||||
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t enemy_type) const;
|
virtual std::vector<ExpandedDrop> get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const;
|
||||||
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
virtual std::vector<ExpandedDrop> get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SpecCollection {
|
struct SpecCollection {
|
||||||
std::vector<std::vector<ExpandedDrop>> enemy_type_to_specs;
|
std::vector<std::vector<ExpandedDrop>> rt_index_to_specs;
|
||||||
std::vector<std::vector<ExpandedDrop>> box_area_to_specs;
|
std::vector<std::vector<ExpandedDrop>> box_area_to_specs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -762,7 +762,7 @@ Proxy session commands:\n\
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerInventoryItem item;
|
PlayerInventoryItem item;
|
||||||
item.data = item_for_string(command_args);
|
item.data = ItemData(command_args);
|
||||||
item.data.id = random_object<uint32_t>();
|
item.data.id = random_object<uint32_t>();
|
||||||
|
|
||||||
if (command_name == "set-next-item") {
|
if (command_name == "set-next-item") {
|
||||||
|
|||||||
+113
-61
@@ -25,6 +25,21 @@ const char* name_for_episode(Episode ep) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* token_name_for_episode(Episode ep) {
|
||||||
|
switch (ep) {
|
||||||
|
case Episode::EP1:
|
||||||
|
return "Episode1";
|
||||||
|
case Episode::EP2:
|
||||||
|
return "Episode2";
|
||||||
|
case Episode::EP3:
|
||||||
|
return "Episode3";
|
||||||
|
case Episode::EP4:
|
||||||
|
return "Episode4";
|
||||||
|
default:
|
||||||
|
throw logic_error("invalid episode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* abbreviation_for_episode(Episode ep) {
|
const char* abbreviation_for_episode(Episode ep) {
|
||||||
switch (ep) {
|
switch (ep) {
|
||||||
case Episode::NONE:
|
case Episode::NONE:
|
||||||
@@ -420,11 +435,17 @@ bool char_class_is_force(uint8_t cls) {
|
|||||||
|
|
||||||
const char* name_for_difficulty(uint8_t difficulty) {
|
const char* name_for_difficulty(uint8_t difficulty) {
|
||||||
static const array<const char*, 4> names = {
|
static const array<const char*, 4> names = {
|
||||||
"Normal",
|
"Normal", "Hard", "Very Hard", "Ultimate"};
|
||||||
"Hard",
|
try {
|
||||||
"Very Hard",
|
return names.at(difficulty);
|
||||||
"Ultimate",
|
} catch (const out_of_range&) {
|
||||||
};
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* token_name_for_difficulty(uint8_t difficulty) {
|
||||||
|
static const array<const char*, 4> names = {
|
||||||
|
"Normal", "Hard", "VeryHard", "Ultimate"};
|
||||||
try {
|
try {
|
||||||
return names.at(difficulty);
|
return names.at(difficulty);
|
||||||
} catch (const out_of_range&) {
|
} catch (const out_of_range&) {
|
||||||
@@ -578,61 +599,91 @@ const unordered_map<string, uint8_t> mag_color_for_name({
|
|||||||
{"costume-color", 0x12},
|
{"costume-color", 0x12},
|
||||||
});
|
});
|
||||||
|
|
||||||
uint8_t drop_area_for_name(const std::string& name) {
|
uint8_t area_for_name(const std::string& name) {
|
||||||
static const unordered_map<string, uint8_t> areas({
|
static const unordered_map<string, uint8_t> areas({
|
||||||
{"forest1", 0},
|
{"pioneer2", 0x00},
|
||||||
{"forest2", 1},
|
{"p2", 0x00},
|
||||||
{"dragon", 2},
|
{"forest1", 0x01},
|
||||||
{"caves1", 2},
|
{"f1", 0x01},
|
||||||
{"cave1", 2},
|
{"forest2", 0x02},
|
||||||
{"caves2", 3},
|
{"f2", 0x02},
|
||||||
{"cave2", 3},
|
{"caves1", 0x03},
|
||||||
{"caves3", 4},
|
{"cave1", 0x03},
|
||||||
{"cave3", 4},
|
{"c1", 0x03},
|
||||||
{"derolle", 5},
|
{"caves2", 0x04},
|
||||||
{"mines1", 5},
|
{"cave2", 0x04},
|
||||||
{"mine1", 5},
|
{"c2", 0x04},
|
||||||
{"mines2", 6},
|
{"caves3", 0x05},
|
||||||
{"mine2", 6},
|
{"cave3", 0x05},
|
||||||
{"volopt", 7},
|
{"c3", 0x05},
|
||||||
{"ruins1", 7},
|
{"mines1", 0x06},
|
||||||
{"ruin1", 7},
|
{"mine1", 0x06},
|
||||||
{"ruins2", 8},
|
{"m1", 0x06},
|
||||||
{"ruin2", 8},
|
{"mines2", 0x07},
|
||||||
{"ruins3", 9},
|
{"mine2", 0x07},
|
||||||
{"ruin3", 9},
|
{"m2", 0x07},
|
||||||
{"darkfalz", 9},
|
{"ruins1", 0x08},
|
||||||
|
{"ruin1", 0x08},
|
||||||
|
{"r1", 0x08},
|
||||||
|
{"ruins2", 0x09},
|
||||||
|
{"ruin2", 0x09},
|
||||||
|
{"r2", 0x09},
|
||||||
|
{"ruins3", 0x0A},
|
||||||
|
{"ruin3", 0x0A},
|
||||||
|
{"r3", 0x0A},
|
||||||
|
{"dragon", 0x0B},
|
||||||
|
{"derolle", 0x0C},
|
||||||
|
{"volopt", 0x0D},
|
||||||
|
{"darkfalz", 0x0E},
|
||||||
|
{"lobby", 0x0F},
|
||||||
|
{"battle1", 0x10},
|
||||||
|
{"battle2", 0x11},
|
||||||
|
|
||||||
{"vrtemplealpha", 0},
|
{"pioneer2", 0x00},
|
||||||
{"vrtemplebeta", 1},
|
{"p2", 0x00},
|
||||||
{"barbaray", 2},
|
{"vrtemplealpha", 0x01},
|
||||||
{"vrspaceshipalpha", 2},
|
{"templealpha", 0x01},
|
||||||
{"vrspaceshipbeta", 3},
|
{"vrtemplebeta", 0x02},
|
||||||
{"goldragon", 5},
|
{"templebeta", 0x02},
|
||||||
{"centralcontrolarea", 4},
|
{"vrspaceshipalpha", 0x03},
|
||||||
{"cca", 4},
|
{"spaceshipalpha", 0x03},
|
||||||
{"jungleareanorth", 5},
|
{"vrspaceshipbeta", 0x04},
|
||||||
{"junglenorth", 5},
|
{"spaceshipbeta", 0x04},
|
||||||
{"jungleareaeast", 5},
|
{"centralcontrolarea", 0x05},
|
||||||
{"jungleeast", 5},
|
{"cca", 0x05},
|
||||||
{"mountain", 6},
|
{"junglenorth", 0x06},
|
||||||
{"seaside", 7},
|
{"jungleeast", 0x07},
|
||||||
{"galgryphon", 8},
|
{"mountain", 0x08},
|
||||||
{"seabedupper", 8},
|
{"seaside", 0x09},
|
||||||
{"seabedlower", 9},
|
{"seabedupper", 0x0A},
|
||||||
{"olgaflow", 9},
|
{"seabedlower", 0x0B},
|
||||||
{"seasidenight", 7},
|
{"galgryphon", 0x0C},
|
||||||
{"tower", 9},
|
{"olgaflow", 0x0D},
|
||||||
|
{"barbaray", 0x0E},
|
||||||
|
{"goldragon", 0x0F},
|
||||||
|
{"seasidenight", 0x10},
|
||||||
|
{"tower", 0x11},
|
||||||
|
|
||||||
{"cratereast", 2},
|
{"pioneer2", 0x00},
|
||||||
{"craterwest", 3},
|
{"p2", 0x00},
|
||||||
{"cratersouth", 4},
|
{"cratereast", 0x01},
|
||||||
{"craternorth", 5},
|
{"ce", 0x01},
|
||||||
{"craterinterior", 6},
|
{"craterwest", 0x02},
|
||||||
{"subdesert1", 7},
|
{"cw", 0x02},
|
||||||
{"subdesert2", 8},
|
{"cratersouth", 0x03},
|
||||||
{"subdesert3", 9},
|
{"cs", 0x03},
|
||||||
{"saintmillion", 9},
|
{"craternorth", 0x04},
|
||||||
|
{"cn", 0x04},
|
||||||
|
{"craterinterior", 0x05},
|
||||||
|
{"ci", 0x05},
|
||||||
|
{"desert1", 0x06},
|
||||||
|
{"d1", 0x06},
|
||||||
|
{"desert2", 0x07},
|
||||||
|
{"d2", 0x07},
|
||||||
|
{"desert3", 0x08},
|
||||||
|
{"d3", 0x08},
|
||||||
|
{"saintmillion", 0x09},
|
||||||
|
{"purgatory", 0x0A},
|
||||||
});
|
});
|
||||||
return areas.at(tolower(name));
|
return areas.at(tolower(name));
|
||||||
}
|
}
|
||||||
@@ -660,12 +711,13 @@ static const array<const char*, 0x12> ep1_area_names = {
|
|||||||
|
|
||||||
static const array<const char*, 0x12> ep2_area_names = {
|
static const array<const char*, 0x12> ep2_area_names = {
|
||||||
"Pioneer2",
|
"Pioneer2",
|
||||||
"TempleAlpha",
|
"VRTempleAlpha",
|
||||||
"TempleBeta",
|
"VRTempleBeta",
|
||||||
"SpaceshipAlpha",
|
"VRSpaceshipAlpha",
|
||||||
|
"VRSpaceshipBeta",
|
||||||
"CentralControlArea",
|
"CentralControlArea",
|
||||||
"JungleNorth",
|
"JungleNorth",
|
||||||
"JungleSouth",
|
"JungleEast",
|
||||||
"Mountain",
|
"Mountain",
|
||||||
"Seaside",
|
"Seaside",
|
||||||
"SeabedUpper",
|
"SeabedUpper",
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ enum class Episode {
|
|||||||
EP4 = 4,
|
EP4 = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t area_limit_for_episode(Episode ep);
|
|
||||||
bool episode_has_arpg_semantics(Episode ep);
|
bool episode_has_arpg_semantics(Episode ep);
|
||||||
const char* name_for_episode(Episode ep);
|
const char* name_for_episode(Episode ep);
|
||||||
|
const char* token_name_for_episode(Episode ep);
|
||||||
const char* abbreviation_for_episode(Episode ep);
|
const char* abbreviation_for_episode(Episode ep);
|
||||||
|
|
||||||
enum class GameMode {
|
enum class GameMode {
|
||||||
@@ -71,6 +71,7 @@ bool char_class_is_ranger(uint8_t cls);
|
|||||||
bool char_class_is_force(uint8_t cls);
|
bool char_class_is_force(uint8_t cls);
|
||||||
|
|
||||||
const char* name_for_difficulty(uint8_t difficulty);
|
const char* name_for_difficulty(uint8_t difficulty);
|
||||||
|
const char* token_name_for_difficulty(uint8_t difficulty);
|
||||||
char abbreviation_for_difficulty(uint8_t difficulty);
|
char abbreviation_for_difficulty(uint8_t difficulty);
|
||||||
|
|
||||||
char char_for_language_code(uint8_t language);
|
char char_for_language_code(uint8_t language);
|
||||||
@@ -78,7 +79,6 @@ char char_for_language_code(uint8_t language);
|
|||||||
extern const std::vector<const char*> name_for_mag_color;
|
extern const std::vector<const char*> name_for_mag_color;
|
||||||
extern const std::unordered_map<std::string, uint8_t> mag_color_for_name;
|
extern const std::unordered_map<std::string, uint8_t> mag_color_for_name;
|
||||||
|
|
||||||
uint8_t drop_area_for_name(const std::string& name);
|
|
||||||
|
|
||||||
size_t area_limit_for_episode(Episode ep);
|
size_t area_limit_for_episode(Episode ep);
|
||||||
const char* name_for_area(Episode episode, uint8_t drop_area);
|
uint8_t area_for_name(const std::string& name);
|
||||||
|
const char* name_for_area(Episode episode, uint8_t area);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user