switch item pickup notifs to explicit lists
This commit is contained in:
@@ -101,6 +101,14 @@ bool ItemData::empty() const {
|
||||
}
|
||||
|
||||
uint32_t ItemData::primary_identifier() const {
|
||||
// Primary identifiers are like:
|
||||
// - 00TTSS00 = weapon (T = type, S = subtype; subtype is 0 for ES weapons)
|
||||
// - 01TTSS00 = armor/shield/unit
|
||||
// - 02TT0000 = mag
|
||||
// - 0302ZZLL = tech disk (Z = tech number, L = level)
|
||||
// - 03TTSS00 = tool
|
||||
// - 04000000 = meseta
|
||||
|
||||
// The game treats any item starting with 04 as Meseta, and ignores the rest
|
||||
// of data1 (the value is in data2)
|
||||
if (this->data1[0] == 0x04) {
|
||||
|
||||
@@ -1014,14 +1014,15 @@ uint8_t ItemParameterTable::get_item_base_stars(const ItemData& item) const {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ItemParameterTable::get_item_adjusted_stars(const ItemData& item) const {
|
||||
uint8_t ItemParameterTable::get_item_adjusted_stars(const ItemData& item, bool ignore_unidentified) const {
|
||||
uint8_t ret = this->get_item_base_stars(item);
|
||||
if (item.data1[0] == 0) {
|
||||
bool is_unidentified = (!ignore_unidentified) && (item.data1[4] & 0x80);
|
||||
if (ret < 9) {
|
||||
if (!(item.data1[4] & 0x80)) {
|
||||
if (!is_unidentified) {
|
||||
ret += this->get_special_stars(item.data1[4]);
|
||||
}
|
||||
} else if (item.data1[4] & 0x80) {
|
||||
} else if (is_unidentified) {
|
||||
ret = 0;
|
||||
}
|
||||
} else if (item.data1[0] == 1) {
|
||||
|
||||
@@ -450,7 +450,7 @@ public:
|
||||
uint32_t get_item_id(const ItemData& item) const;
|
||||
uint32_t get_item_team_points(const ItemData& item) const;
|
||||
uint8_t get_item_base_stars(const ItemData& item) const;
|
||||
uint8_t get_item_adjusted_stars(const ItemData& item) const;
|
||||
uint8_t get_item_adjusted_stars(const ItemData& item, bool ignore_unidentified = false) const;
|
||||
bool is_item_rare(const ItemData& item) const;
|
||||
bool is_unsealable_item(uint8_t data1_0, uint8_t data1_1, uint8_t data1_2) const;
|
||||
bool is_unsealable_item(const ItemData& param_1) const;
|
||||
|
||||
@@ -1997,32 +1997,14 @@ static void on_pick_up_item_generic(
|
||||
}
|
||||
}
|
||||
|
||||
if ((fi->flags & 0x1000) && (fi->data.data1[0] < 0x04)) {
|
||||
auto pmt = s->item_parameter_table(c->version());
|
||||
bool should_send_game_notif = false;
|
||||
bool should_send_global_notif = false;
|
||||
switch (fi->data.data1[0]) {
|
||||
case 0x00:
|
||||
case 0x01: {
|
||||
uint8_t stars = pmt->get_item_adjusted_stars(fi->data);
|
||||
should_send_game_notif = (stars >= s->game_rare_notif_min_stars);
|
||||
should_send_global_notif = (stars >= s->global_rare_notif_min_stars);
|
||||
break;
|
||||
}
|
||||
case 0x02: {
|
||||
should_send_game_notif = s->game_rare_mag_notifs_enabled && pmt->is_item_rare(fi->data);
|
||||
break;
|
||||
}
|
||||
case 0x03: {
|
||||
should_send_game_notif = s->game_rare_tool_notifs_enabled && pmt->is_item_rare(fi->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fi->flags & 0x1000) {
|
||||
uint32_t pi = fi->data.primary_identifier();
|
||||
bool should_send_game_notif = s->notify_game_for_item_primary_identifiers.count(pi);
|
||||
bool should_send_global_notif = s->notify_server_for_item_primary_identifiers.count(pi);
|
||||
if (should_send_game_notif || should_send_global_notif) {
|
||||
string p_name = p->disp.name.decode();
|
||||
string desc = s->describe_item(c->version(), fi->data, true);
|
||||
string message = string_printf("$C6%s$C7 has found\n%s", p_name.c_str(), desc.c_str());
|
||||
string message = string_printf("$C6%s$C7 found\n%s", p_name.c_str(), desc.c_str());
|
||||
if (should_send_global_notif) {
|
||||
for (auto& it : s->channel_to_client) {
|
||||
if (it.second->license &&
|
||||
|
||||
+25
-4
@@ -733,10 +733,6 @@ void ServerState::load_config_early() {
|
||||
this->default_rare_notifs_enabled_v3_v4 = this->default_rare_notifs_enabled_v1_v2;
|
||||
this->default_rare_notifs_enabled_v1_v2 = this->config_json->get_bool("RareNotificationsEnabledByDefaultV1V2", this->default_rare_notifs_enabled_v1_v2);
|
||||
this->default_rare_notifs_enabled_v3_v4 = this->config_json->get_bool("RareNotificationsEnabledByDefaultV3V4", this->default_rare_notifs_enabled_v3_v4);
|
||||
this->game_rare_notif_min_stars = this->config_json->get_int("GameRareNotifMinStars", this->game_rare_notif_min_stars);
|
||||
this->global_rare_notif_min_stars = this->config_json->get_int("GlobalRareNotifMinStars", this->global_rare_notif_min_stars);
|
||||
this->game_rare_mag_notifs_enabled = this->config_json->get_bool("GameRareMagNotifsEnabled", this->game_rare_mag_notifs_enabled);
|
||||
this->game_rare_tool_notifs_enabled = this->config_json->get_bool("GameRareToolNotifsEnabled", this->game_rare_tool_notifs_enabled);
|
||||
this->ep3_send_function_call_enabled = this->config_json->get_bool("EnableEpisode3SendFunctionCall", false);
|
||||
this->enable_v3_v4_protected_subcommands = this->config_json->get_bool("EnableV3V4ProtectedSubcommands", false);
|
||||
this->catch_handler_exceptions = this->config_json->get_bool("CatchHandlerExceptions", true);
|
||||
@@ -1203,6 +1199,31 @@ void ServerState::load_config_late() {
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
|
||||
this->notify_game_for_item_primary_identifiers.clear();
|
||||
try {
|
||||
for (const auto& pi_json : this->config_json->get_list("NotifyGameForItemPrimaryIdentifiers")) {
|
||||
if (pi_json->is_int()) {
|
||||
this->notify_game_for_item_primary_identifiers.emplace(pi_json->as_int());
|
||||
} else {
|
||||
auto item = this->parse_item_description(Version::BB_V4, pi_json->as_string());
|
||||
this->notify_game_for_item_primary_identifiers.emplace(item.primary_identifier());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
this->notify_server_for_item_primary_identifiers.clear();
|
||||
try {
|
||||
for (const auto& pi_json : this->config_json->get_list("NotifyServerForItemPrimaryIdentifiers")) {
|
||||
if (pi_json->is_int()) {
|
||||
this->notify_server_for_item_primary_identifiers.emplace(pi_json->as_int());
|
||||
} else {
|
||||
auto item = this->parse_item_description(Version::BB_V4, pi_json->as_string());
|
||||
this->notify_server_for_item_primary_identifiers.emplace(item.primary_identifier());
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
} else {
|
||||
config_log.warning("BB item name index is missing; cannot load quest reward lists from config");
|
||||
}
|
||||
|
||||
+2
-4
@@ -128,10 +128,8 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
bool use_game_creator_section_id = false;
|
||||
bool default_rare_notifs_enabled_v1_v2 = false;
|
||||
bool default_rare_notifs_enabled_v3_v4 = false;
|
||||
uint8_t game_rare_notif_min_stars = 0xFF;
|
||||
uint8_t global_rare_notif_min_stars = 0xFF;
|
||||
bool game_rare_mag_notifs_enabled = false;
|
||||
bool game_rare_tool_notifs_enabled = false;
|
||||
std::unordered_set<uint32_t> notify_game_for_item_primary_identifiers;
|
||||
std::unordered_set<uint32_t> notify_server_for_item_primary_identifiers;
|
||||
std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>> bb_private_keys;
|
||||
std::shared_ptr<const FunctionCodeIndex> function_code_index;
|
||||
std::shared_ptr<const PatchFileIndex> pc_patch_file_index;
|
||||
|
||||
+31
-19
@@ -969,25 +969,37 @@
|
||||
"RareNotificationsEnabledByDefaultV1V2": false,
|
||||
"RareNotificationsEnabledByDefaultV3V4": false,
|
||||
|
||||
// Conditions for when to broadcast rare notifications. These only apply to
|
||||
// items dropped by boxes and enemies; items dropped by players or created
|
||||
// with the $item command do not cause notifications when picked up.
|
||||
|
||||
// If a weapon, armor, shield, or unit with at least this many stars is
|
||||
// picked up, everyone in the game is notified. To disable these
|
||||
// notifications, set this to 255.
|
||||
"GameRareNotifMinStars": 10,
|
||||
// If a weapon, armor, shield, or unit with at least this many stars is
|
||||
// picked up, everyone on the server (except Episode 3 players) is notified.
|
||||
// To disable these notifications, set this to 255.
|
||||
"GlobalRareNotifMinStars": 12,
|
||||
// If this option is on and a rare mag is picked up, everyone in the game is
|
||||
// notified. Note that there are no rare mags in any of the default drop
|
||||
// tables, so this has no effect unless you add rare mags to the drop tables.
|
||||
"GameRareMagNotifsEnabled": true,
|
||||
// If this option is on and a rare tool item (for example, a Photon Drop) is
|
||||
// picked up, everyone in the game is notified.
|
||||
"GameRareToolNotifsEnabled": true,
|
||||
// Items for which rare notifications should be broadcast to the game or
|
||||
// entire server. These notifications occur when the item is picked up. They
|
||||
// only are generated from items dropped by boxes and enemies; items dropped
|
||||
// by players or created with the $item command do not cause notifications
|
||||
// when picked up.
|
||||
// Entries in these lists are primary identifiers, which are similar to the
|
||||
// usual 3-byte item codes but are slightly more expressive. In summary,
|
||||
// primary identifiers go like this:
|
||||
// 0x00TTSS00 = weapon (T = type, S = subtype; subtype is 0 for ES weapons)
|
||||
// 0x01TTSS00 = armor/shield/unit
|
||||
// 0x02TT0000 = mag
|
||||
// 0x03TTSS00 = tool item (except tech disks)
|
||||
// 0x0302ZZLL = tech disk (Z = tech number, L = level - 1)
|
||||
// 0x04000000 = meseta
|
||||
// For example (you can check these in names-v4.json):
|
||||
// 0x00020700 = DRAGON SLAYER (any stats)
|
||||
// 0x01012A00 = DF FIELD (any stats)
|
||||
// 0x020B0000 = Tapas (any level)
|
||||
// 0x03010200 = Trifluid (any amount)
|
||||
// 0x0302061D = Disk:Zonde Lv.30
|
||||
// 0x04000000 = Meseta (any amount)
|
||||
// As with most other places where you can specify items in this file, you
|
||||
// can also put textual item descriptions in here (e.g. "DRAGON SLAYER"), but
|
||||
// only data that would appear in the primary identifier will be used - that
|
||||
// is, if you were to put something like "DRAGON SLAYER +5 5/0/0/5/0", the
|
||||
// grind and bonuses would be ignored, and all DRAGON SLAYERs would result in
|
||||
// notifications regardless of their stats. For textual descriptions, the
|
||||
// items are parsed as they would be on BB, so certain V2-only items cannot
|
||||
// be represented this way.
|
||||
"NotifyGameForItemPrimaryIdentifiers": [],
|
||||
"NotifyServerForItemPrimaryIdentifiers": [],
|
||||
|
||||
// Whether to enable patches on Episode 3 USA. This functionality depends on
|
||||
// exploiting a bug in Episode 3, and while it seems to work reliably on
|
||||
|
||||
+2
-4
@@ -32,10 +32,8 @@
|
||||
"CheatModeBehavior": "OnByDefault",
|
||||
"UnlockAllAreas": false,
|
||||
"RareNotificationsEnabledByDefault": false,
|
||||
"GameRareNotifMinStars": 10,
|
||||
"GlobalRareNotifMinStars": 12,
|
||||
"GameRareMagNotifsEnabled": true,
|
||||
"GameRareToolNotifsEnabled": true,
|
||||
"NotifyGameForItemPrimaryIdentifiers": [],
|
||||
"NotifyServerForItemPrimaryIdentifiers": [],
|
||||
|
||||
"LocalAddress": "en0",
|
||||
"ExternalAddress": "en0",
|
||||
|
||||
Reference in New Issue
Block a user