From 4770297cd0bc7b73eadabc598a122784a4f3ce4e Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 27 Mar 2025 23:38:37 -0700 Subject: [PATCH] document some things in ItemPMT --- src/CommandFormats.hh | 4 +++- src/ItemNameIndex.cc | 4 ++-- src/ItemParameterTable.cc | 2 +- src/ItemParameterTable.hh | 19 ++++++++++++++----- src/ReceiveSubcommands.cc | 6 +++++- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 019a129c..eeda3899 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -3930,7 +3930,9 @@ struct G_Unknown_6x04 { // subclass of 6x60. struct G_WriteSwitchFlag_6x05 { - // Note: header.object_id is 0xFFFF for room clear when all enemies defeated + // header.entity_id may be 0xFFFF if no object is responsible for the switch + // flag state change - this can happen when a wave event script sets a switch + // flag, for example. G_EntityIDHeader header; // TODO: Some of these might be big-endian on GC; it only byteswaps // switch_flag_num. Are the others actually uint16, or are they uint8[2]? diff --git a/src/ItemNameIndex.cc b/src/ItemNameIndex.cc index 52f09318..4b68d763 100644 --- a/src/ItemNameIndex.cc +++ b/src/ItemNameIndex.cc @@ -662,7 +662,7 @@ ItemData ItemNameIndex::parse_item_description_phase(const std::string& descript void ItemNameIndex::print_table(FILE* stream) const { auto pmt = this->item_parameter_table; - fprintf(stream, "WEAPON => ---ID--- TYPE SKIN POINTS FLAG ATPLO ATPHI ATPRQ MSTRQ ATARQ -MST- GND PH SP ATA SB PJ 1X 1Y 2X 2Y CL A1 A2 A3 A4 A5 TB CT V1 ST* USL ---DIVISOR--- NAME\n"); + fprintf(stream, "WEAPON => ---ID--- TYPE SKIN POINTS FLAG ATPLO ATPHI ATPRQ MSTRQ ATARQ -MST- GND PH SP ATA SB PJ 1X 1Y 2X 2Y CL A1 A2 A3 A4 A5 TB BF V1 ST* USL ---DIVISOR--- NAME\n"); for (size_t data1_1 = 0; data1_1 < pmt->num_weapon_classes; data1_1++) { uint8_t v1_replacement = pmt->get_weapon_v1_replacement(data1_1); float sale_divisor = pmt->get_sale_divisor(0x00, data1_1); @@ -712,7 +712,7 @@ void ItemNameIndex::print_table(FILE* stream) const { w.unknown_a4, w.unknown_a5, w.tech_boost, - w.combo_type, + w.behavior_flags, v1_replacement, stars, is_unsealable ? "YES" : " no", diff --git a/src/ItemParameterTable.cc b/src/ItemParameterTable.cc index 9e4a1499..22d59ac9 100644 --- a/src/ItemParameterTable.cc +++ b/src/ItemParameterTable.cc @@ -238,7 +238,7 @@ ItemParameterTable::WeaponV4 ItemParameterTable::WeaponV3T::to_v4() const { ret.unknown_a4 = this->unknown_a4; ret.unknown_a5 = this->unknown_a5; ret.tech_boost = this->tech_boost; - ret.combo_type = this->combo_type; + ret.behavior_flags = this->behavior_flags; return ret; } diff --git a/src/ItemParameterTable.hh b/src/ItemParameterTable.hh index 3d411d33..b08848f4 100644 --- a/src/ItemParameterTable.hh +++ b/src/ItemParameterTable.hh @@ -133,7 +133,12 @@ public: /* 24 */ uint8_t unknown_a4 = 0; /* 25 */ uint8_t unknown_a5 = 0; /* 26 */ uint8_t tech_boost = 0; - /* 27 */ uint8_t combo_type = 0; + // Flags in this field: + // 01 = disable combos (weapon can only be used once in a row) + // 02 = TODO (sets TItemWeapon flag 40000; used in TItemWeapon_v1E) + // 04 = TODO (sets TItemWeapon flag 80000; used in TItemWeapon_v1E) + // 08 = weapon cannot have attributes (they are ignored if present) + /* 27 */ uint8_t behavior_flags = 0; /* 28 */ WeaponV4 to_v4() const; @@ -170,7 +175,7 @@ public: /* 28 */ uint8_t unknown_a4 = 0; /* 29 */ uint8_t unknown_a5 = 0; /* 2A */ uint8_t tech_boost = 0; - /* 2B */ uint8_t combo_type = 0; + /* 2B */ uint8_t behavior_flags = 0; /* 2C */ } __packed_ws__(WeaponV4, 0x2C); @@ -198,9 +203,13 @@ public: struct ArmorOrShieldFinalT : ArmorOrShieldT { /* 14 */ uint8_t stat_boost = 0; /* 15 */ uint8_t tech_boost = 0; - // TODO: Figure out what this does. Only two values appear to do anything: - // 01 sets item->flags |= 4 - // 03 sets item->flags |= 8 + // TODO: Figure out what this does. Only a few values appear to do anything: + // Shields: + // 01 sets item->flags |= 4 (used in TItemProShield_v10) + // 03 sets item->flags |= 8 (used in TItemProShield_v1A) + // Armors: + // 01 sets item->flags |= 1 (used in TItemProArmor_v10) + // 02 constructs TItemProArmorParticle instead of TItemProArmor /* 16 */ uint8_t flags_type = 0; /* 17 */ uint8_t unknown_a4 = 0; /* 18 */ diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index 0aa7f50c..a468337a 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -1756,7 +1756,11 @@ static void on_switch_state_changed(shared_ptr c, uint8_t command, uint8 send_text_message_printf(c, "$C5K-%03zX A %s", obj_st->k_id, obj_st->type_name(c->version())); } - if (l->switch_flags) { + // Apparently sometimes 6x05 is sent with an invalid switch flag number. The + // client seems to just ignore the command in that case, so we go ahead and + // forward it (in case the client's object update function is meaningful + // somehow) and just don't update our view of the switch flags. + if (l->switch_flags && (cmd.switch_flag_num < 0x100)) { if (cmd.flags & 1) { l->switch_flags->set(cmd.switch_flag_floor, cmd.switch_flag_num); if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {