From f2deefdfe0f1c24e1bd6b72208dbf75d5e7cee90 Mon Sep 17 00:00:00 2001 From: Hash Borgir Date: Tue, 6 Jun 2023 02:05:50 -0600 Subject: [PATCH] more item parsing --- src/D2Item.php | 89 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/src/D2Item.php b/src/D2Item.php index db1a0ed..05e3651 100644 --- a/src/D2Item.php +++ b/src/D2Item.php @@ -68,6 +68,7 @@ class D2Item { $b->seek(108); $this->iData['gems_in'] = bindec($b->readr(3)); + // bit 111, 32bits, Unique identifier. Diablo II randomly generates a value for this field in order to discourage cheaters from "duping" items. //This appears to be the item's level; i.e., the level with which the item was created (or 'dropped'). The item level is based on the level of the monster who dropped it, the level of the area you're in if found in a chest, or, in rare cases, your characters level. The item level determines what modifiers are allowed on the item. $b->seek(143); $this->iData['ilvl'] = bindec($b->readr(7)); @@ -107,16 +108,19 @@ class D2Item { // ring/amu/jew/char or not. 1 or 0. if 1, next 3 are set // If this bit is set, the item has one of multiple pictures associated with it; the next field determines which picture a particular item uses. If this bit is 0, the next field is absent. The picture field is used for rings, amulets, jewels, and charms. - - $b->seek(151); - if (bindec($b->read(1))) { + // After the above data, if the item is a ring, amulet, jewel, or charm, then it has a 1 bit followed by three more bits. All other items (that I've seen) have just a single 0 bit. + $b->seek(151); // ring bit + $ring = bindec($b->read(1)); + if ($ring) { // we read 1 bit at 151, end up at 152 $b->seek(152); - $jarc_picture = bindec($b->readr(3)); + $ringPic = bindec($b->readr(3)); // for jew, amu, rin, char + } + // if ring bit is 0, go to 152 and read 1 bit + else { + // This bit apparently is set for certain class-specific Expansion Set items. It indicates the presence of the next 11-bit field. If this bit is 0, the next field is absent. + $b->seek(152); + $_class_specific = bindec($b->read(1)); } - - // This bit apparently is set for certain class-specific Expansion Set items. It indicates the presence of the next 11-bit field. If this bit is 0, the next field is absent. - $b->seek(152); - /* Credit for the discovery of this field's meaning goes entirely to Guillaume Courtin of France. Thanks! :-> This field indicates magic properties which are inherent in certain class-specific items. A given class-specific item will (almost) always start with the same set of properties, even if its quality is "normal". Other quality ratings may add more properties to the standard set. It appears that items which will have this field are: Amazon-only bows, spears, and javelins @@ -124,13 +128,78 @@ class D2Item { Paladin-only shields Orbs (Sorceress-Only wands) */ - if (bindec($b->read(1))) { + // if class specific bit (152) is 1, then go to 153 and read 11 bits + if ($_class_specific) { $b->seek(153); $class_specific = bindec($b->readr(11)); } + // + { + // if 151 is 1, but 152 is 0, then we have read 152/153/154 already, so we should be at 155 + if ($ring && !$_class_specific) { + $b->seek(155); + // if 151 is 1 then we're at 155. if 152 is 1, then we read from 155 to 165, arrive at bit 166 + } else if ($ring && $_class_specific) { + $b->seek(166); + // if 151 is 0, we alreay just read it, then we're at 152. if 152 is 1, then we read from 153 to 163, arrive at 164 + } else if ($_class_specific && !$ring) { + $b->seek(164); + } + switch ($quality) { + case D2ItemQuality::LOW_QUALITY: + $low_quality_item_data = bindec($b->readr(3)); + switch ($low_quality_item_data) { + case 0: + $this->iData['low_quality_item_data'] = "Crude"; + break; + case 1: + $this->iData['low_quality_item_data'] = "Cracked"; + break; + case 2: + $this->iData['low_quality_item_data'] = "Damaged"; + break; + case 3: + $this->iData['low_quality_item_data'] = "Low Quality"; + break; + default: + $this->iData['low_quality_item_data'] = "Unknown quality"; + break; + } + break; + // Normal items have no extra quality data. + case D2ItemQuality::NORMAL: + break; + case D2ItemQuality::HIGH_QUALITY: + $high_quality_item_data = bindec($b->readr(3)); + break; + case D2ItemQuality::MAGIC: + // read 11 bits, prefix. + // if no prefix, then next 11 bits will be suffix + $this->iData['$magic_prefix'] = bindec($b->readr(11)); + $this->iData['magic_suffix'] = bindec($b->readr(11)); + break; + case D2ItemQuality::SET: + // Set items have a 12-bit field containing the ID of the set. (Not the set member, but the whole set.) The set member is identified by cross-referencing the item type with the set ID. Also note that set items have an extra field following the item-specific data. + // Set identifier; i.e., all items which are part of the set will have the same value in this field. + $set_item = bindec($b->readr(12)); + break; + case D2ItemQuality::RARE: + $this->iData['iquality'] = "Rare"; + break; + case D2ItemQuality::UNIQUE: + $this->iData['iquality'] = "Unique"; + break; + case D2ItemQuality::CRAFTED: + $this->iData['iquality'] = "Crafted"; + break; + default: + $this->iData['iquality'] = "Unknown"; + break; + } + } // weird behavior/bug // if item is in a container, bodypart will be NULL @@ -235,7 +304,7 @@ class D2Item { $sql = "SELECT * from weapons WHERE code = '{$this->iData['code']}'"; $res = PDO_FetchRow($sql); } - $this->iData['txt']=($res); + //$this->iData['txt'] = ($res); $sql = " SELECT code, namestr