Posted: Thu Nov 08, 2001 3:35 am Post subject: -------------------------------------------------------------------------------- Some of my own findings (old, possibly incorrect) --------------------------------------------- Incoming packets: Packet 0x9c general layout: --------------------------- Bit(0:7) Packet message (0x9c) Bit(8:15) Action bit(16:23) Item type bit(24:31) Valid data size in bytes (0x16-0xFF?) bit(32:63) Item ID: bit(64:95) Flags bit(96:105) Unknown bit(106:108) Position type bit(109:125) X-position bit(126:141) Y-position bit(142:173) Itemcode bit(174:176) Unknown bit(177:183) Magic level (?) bit(184:187) Item quality bit(188:190) Item design (For rings/amus) bit(191:199) Unknown bit(200:+) Prefix/suffix/modifiers/quantities etc... Item type: ---------- 0x00 Helm 0x01 Armor 0x05 Weapon 0x07 Shield 0x10 Most other items Item quality: ------------- 0x0 Most other items 0x1 Damaged/cracked 0x2 normal 0x3 superior 0x4 magic 0x5 set 0x6 rare 0x7 unique 0x09 Gem Action: ------- 0x00 New item ID on ground 0x01 Pick up to cursor 0x02 Drop from cursor to ground 0x03 Old item ID on ground 0x04 Place in backpack 0x0E Place in belt Flags: ------ bit(64) Sockets are full (1=yes/0=no) Bit(6 Item identified (1=yes/0=no) Bit(69) Item is ethereal (1=yes/0=no) Bit(75) Item has sockets (1=yes/0=no) Bit(77) Item just generated (1=yes/0=no) Bit(80) Item is an ear (1=yes/0=no) If yes, see structure for ear! Bit(87) Item is magic or higher (0=yes/1=no) Unknown origin: --------------------------------------------- Detailed 9C Item info WARNING: Some of this information could be wrong. In particular, there are several of the values that I have taken from other sources and not checked myself. I have tried not to include too much information that I have not yet verified. * PACKET MESSAGE ID -- byte: 00, bits: 000-007 9C for item packets, 9D for items char is wearing note that the structure below reflects 9C packets only! 9D packets have 5 extra bytes inserted at byte 10! * ORIGIN -- byte: 01, bits: 008-015 for 9C packets 00 = new item on ground 01 = pick up to cursor 02 = drop from cursor to ground 03 = old item on ground 04 = inventory (including stash) 0B = store 0C = removed from store (e.g., when you buy an item) 0E = belt * PACKET LENGTH -- byte: 02, bits: 016-023 number of bytes in the packet * ITEM CATEGORY -- byte: 03, bits: 024-031 00 = helm 01 = armor 05 = weapon (including xbows) 06 = bow (excluding xbows) 07 = shield 10 = misc * ITEM ID -- bytes: 04-07, bits: 032-063 unique ID within a game (not persisted!) these IDs are assigned sequentially within a game * FLAGS -- bytes: 08-11, bits: 064-095 not sure what all of these are... special includes quest items (e.g., Mephisto's Soulstone), but also seems to include potions in belt... isSocketed = (flags & 0x00080000) > 0 isEtheral = (flags & 0x00004000) > 0 isSpecial = (flags & 0x0000FF00) == 0x0000C000 * UNKNOWN??? -- bytes: 12-13, bits: 096-111 * X/Y ITEM POSITION -- byte: 14, bits: 112-119 this can be the position in the inventory, stash, store, etc * ITEM LOCATION -- byte: 15, bits: 124-127 (low nybble) if in store (ORIGIN = 0B) 02 = armor tab 04 = weap1 tab 06 = weap2 tab 08 = misc tab if in inventory/stash (ORIGIN = 04) 00 = belt 02 = inventory 08 = Horadric Cube 0A = stash * ITEM CODE -- bytes: 15-18, bits 120-147 (24 bits total) this code is a 3 character alpha-numeric code (stored as ASCII) this code can be found in the "code" column of following MPQ files: "Weapons.txt", "Armor.txt", and "Misc.txt" * UNKNOWN??? -- bytes: 18-19, bits: 148-159 * FLAGS2 -- bytes: 20-21, bits: 160-171 not sure what all of these are... isMagic = (flags2 & 0x000F) == 0x0001; isJwlChrm = (flags2 & 0xF000) == 0x2000; (jewels, charms) isInferior = (flags2 & 0xF000) == 0x4000; (*** see special encoding below) isNormal = (flags2 & 0xF000) == 0x8000; isSuperior = (flags2 & 0xF000) == 0xC000; (*** see special encoding below) isUnique = (flags2 & 0xF000) == 0xE001; isRare = (flags2 & 0xF001) == 0xA001; isMisc = (flags2 & 0xF001) == 0xA000; (includes items like keys, arrows, etc) !!! WARNING: From here on out, the location of bits in the packet !!! can vary (e.g., inferior will add 3 bits for the quality identifier). !!! Hence all parsing must be done relative to where we last left off. !!! This parsing starts at byte 21, bit 4 (high nybble of byte 21). * INFERIOR ITEM -- 3 bits these 3 bits are only present if the item is inferior (see isInferior FLAGS2) 00 = crude 01 = cracked 02 = damaged 03 = low quality ================================================== ================== ARMORS -------------------------------------------------------------------- I have not looked closely at armors since I have been focusing on weapons, but there is a 10 bit offset before the DURABILITY, even for normal armors. Not sure what this is right now. ================================================== ================== NORMAL ITEM -------------------------------------------------------------------- * DURABILITY MAX -- 8 bits * DURABILITY CURRENT - 8 bits * NUMBER OF SOCKETS -- 4 bits these 4 bits are only present if the item is socketed (see isSocketed FLAGS) ================================================== ================== SUPERIOR ITEM -------------------------------------------------------------------- * SUPERIOR TYPE -- 3 bits 00 = AR 01 = Max Dmg 02 = AC 03 = AR + Max Dmg 04 = Durability 05 = Durability + AR 06 = Durability + Max Dmg 07 = Durability + AC * DURABILITY MAX -- 8 bits * DURABILITY CURRENT - 8 bits * NUMBER OF SOCKETS -- 4 bits these 4 bits are only present if the item is socketed (see isSocketed FLAGS) * SUPERIOR PARAMS -- ??? bits the superior parameters are then encoded have not looked at these closely yet the values for AR (10 bits) + Max Dmg (7 bits) are not offset, but Durability (7 bits) looks like it is offset by 20d ================================================== ================== MAGIC ITEM -------------------------------------------------------------------- * MAGIC PREFIX -- 11 bits this prefix is an ID that comes from the "MagicPrefix.txt" MPQ file this id is not actually in the MPQ itself, but is the row number (which is calculated including the blank lines) * MAGIC SUFFIX -- 11 bits this prefix is an ID that comes from the "MagicSuffix.txt" MPQ file this id is not actually in the MPQ itself, but is the row number (which is calculated including the blank lines) * DURABILITY MAX -- 8 bits * DURABILITY CURRENT - 8 bits * ITEM MODS -- (varies) see next section ================================================== ================== ITEM MODS -------------------------------------------------------------------- Ok, here is where things get tricky! There are 2 different encoding schemes for the mods themselves (and the "NEw" scheme has a wrinkle in it as well). To determine which encoding scheme is used, you must look at the affix information in the MPQ file. The two things that seem to matter are the "version" column (0, 1, or 100) and the number of stats that a given mod has (e.g., "of Frost" has 3 stats: cold-min, cold-max, and cold-len). There is another MPQ table that comes into play as well, the "ItemStatCost.txt" file. This file is important because it contains the number of bits that a stat parameter takes (saveBits), and its offset (saveAdd) from 0 (since not all stats are 0-based; e.g., STATS_ITEM_UNDEADDAMAGE_PERCENT is offset by 20). The Affix tables and ItemStatCost tables can be correlated using the "Properties.txt" MPQ file. This file contains a "code" that is found in the Affix tables (mod1code, mod2code, mod3code). This code jas a corresponding "ModFuncOffset" that comes from the ItemStatCost table. WARNING: The "ModFuncOffsets" that do not start with "STATS_" must be prefixed with this string in order to find a match! * PREFIX RULES - Always use the "NEW" encoding scheme (see below). * SUFFIX RULES - If the version is 0 or 1, *and* the affix mod has more than 1 parameter use the "OLD" encoding scheme (see below). - Otherwise, use the "NEW" encoding scheme (see below). I have no idea why suffix parsing would be different, but I had to use this technique in order to properly parse suffix mods with 3 parameters (e.g., of Frost). Note that the Sharp prefix mod has 2 parameters and parses differently. Originally, I thought that these two affixes would have different versions but they did not; both had a version of 1. So perhaps my determination for how to parse the affix is ill founed. ================================================== ================== "OLD" ITEM MODS -------------------------------------------------------------------- "OLD" item mods have an stat id that can be completely ignored. They have 0-3 parameters. This number is determined by the affix (from the mod codes in the MPQ file). * STAT ID -- 9 bits this is the STAT ID from the "ItemStatCost.txt" MPQ file WARNING: there is only 1 stat id even though there can be multiple mods! Furthermore, this stat id is ignored since we already know the stats from the prefix/suffix mod codes! * PARAMETER value -- (optional and number of bits varies) the number of bits that make up the parameter value is determined by the "saveBits" column of the stat note that this value may be offset by the "saveAdd" column WARNING: that stat id corresponding to this stat must be looked up from the mod code pf the affix since only the first parameter has a stat id! Yes this is really stupid, but don't blame me! ================================================== ================== "NEW" ITEM MODS -------------------------------------------------------------------- "NEW" item mods have 0 or 1 parameter associated with each stat. * STAT ID -- 9 bits this is the STAT ID from the "ItemStatCost.txt" MPQ file * PARAMETER value -- (optional and number of bits varies) the number of bits that make up the parameter value is determined by the "saveBits" column of the stat note that this value may be offset by the "saveAdd" column * 2nd PARAMETER value -- (optional, but ignored if present) some stats have 2 parameter values! in such a case, the stat will have its "Target Stat" (from the "ItemStatCost.txt" MPQ file) be other than "-1". This value corresponds to the stat id of the second parameter. This second parameter looks like it can be ignored (at least for the purposes of determining the mods of an item). E.g., the "Jagged" maps to STATS_ITEM_MAXDAMAGE_PERCENT. This stat has a "Target Stat" of 22 (STATS_MAXDAMAGE). In this case, both the first and second parameter are identical.