mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2025-11-05 02:07:46 -06:00
more d2s parsing, refactor
This commit is contained in:
147
src/D2Item.php
Normal file
147
src/D2Item.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
require_once 'D2BitReader.php';
|
||||
require_once 'D2ItemStructureData.php';
|
||||
|
||||
class D2Item {
|
||||
|
||||
private $bits = null;
|
||||
public $iData = null;
|
||||
|
||||
public function __construct($bits) {
|
||||
if ($bits == '')
|
||||
return false;
|
||||
$this->bits = $bits;
|
||||
return $this->parseItem();
|
||||
}
|
||||
|
||||
/* set $this->iData to array of item details
|
||||
*
|
||||
* @return array of item details
|
||||
*/
|
||||
|
||||
private function parseItem() {
|
||||
$b = new D2BitReader($this->bits);
|
||||
|
||||
$b->skip(16); // Skip JM
|
||||
$b->skip(4); // skip unknown 4 bytes
|
||||
$this->iData['identified'] = $b->read(1); // bit 20, identified
|
||||
$b->skip(6); // skip unknown 6 bytes
|
||||
$this->iData['socketed'] = $b->read(1); // bit 27, socketed
|
||||
$b->skip(1);
|
||||
// This bit is set on items which you have picked up since the last time the game was saved.
|
||||
$this->iData['pickedUpSinceLastSave'] = $b->read(1); // bit 29
|
||||
$b->skip(2);
|
||||
$this->iData['ear'] = $b->read(1); // bit 32 bool
|
||||
$this->iData['startingItem'] = $b->read(1); // bit 33 bool
|
||||
$b->skip(3);
|
||||
$this->iData['compact'] = $b->read(1); // bit 37 compact
|
||||
$this->iData['ethereal'] = $b->read(1); // bit 38 ethereal
|
||||
$b->skip(1); // unknown, seems always 1
|
||||
$this->iData['personalized'] = $b->read(1); // bit 40 Item has been personalized (by Anya in Act V)
|
||||
$b->skip(1);
|
||||
$this->iData['runeword'] = $b->read(1); // bit 42 the item has been given a Rune Word.
|
||||
$b->skip(15); // unknown; some of these bits may be set
|
||||
|
||||
|
||||
// item location
|
||||
$location = bindec($b->readr(3)); // bit 58 parent Item location.
|
||||
$body = bindec($b->readr(4)); // bit 61 If the item is equipped
|
||||
$col = bindec($b->readr(4)); // bit 65 Column number of the left corner of the item
|
||||
$row = bindec($b->readr(4)); // bit 69 Row number of the top of the item, counting from 0.
|
||||
$_stored = bindec($b->readr(3)); // bit 73
|
||||
|
||||
|
||||
// weird behavior/bug
|
||||
// if item is in a container, bodypart will be NULL
|
||||
// if item is on bodypart, container will be NULL
|
||||
switch ($location) {
|
||||
case D2ItemLocation::STORED:
|
||||
switch ($_stored) {
|
||||
case D2ItemLocationStored::NONE:
|
||||
$this->iData['container'] = ''; // item is not stored, check bit 58
|
||||
break;
|
||||
case D2ItemLocationStored::INVENTORY:
|
||||
$this->iData['container'] = 'Inventory';
|
||||
break;
|
||||
case D2ItemLocationStored::CUBE:
|
||||
$this->iData['container'] = 'Horadric Cube';
|
||||
break;
|
||||
case D2ItemLocationStored::STASH:
|
||||
$this->iData['container'] = 'Stash';
|
||||
break;
|
||||
default: $this->iData['container'] = 'Unknown';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case D2ItemLocation::EQUIPPED:
|
||||
switch ($body) {
|
||||
case D2ItemLocationBody::HELMET: $this->iData['bodypart'] = 'Helmet';
|
||||
break;
|
||||
case D2ItemLocationBody::AMULET: $this->iData['bodypart'] = 'Amulet';
|
||||
break;
|
||||
case D2ItemLocationBody::ARMOR: $this->iData['bodypart'] = 'Armor';
|
||||
break;
|
||||
case D2ItemLocationBody::WEAPONR: $this->iData['bodypart'] = 'Weapon R';
|
||||
break;
|
||||
case D2ItemLocationBody::WEAPONL: $this->iData['bodypart'] = 'Weapon L';
|
||||
break;
|
||||
case D2ItemLocationBody::RINGR: $this->iData['bodypart'] = 'Ring R';
|
||||
break;
|
||||
case D2ItemLocationBody::RINGL: $this->iData['bodypart'] = 'Ring L';
|
||||
break;
|
||||
case D2ItemLocationBody::BELT: $this->iData['bodypart'] = 'Belt';
|
||||
break;
|
||||
case D2ItemLocationBody::BOOTS: $this->iData['bodypart'] = 'Boots';
|
||||
break;
|
||||
case D2ItemLocationBody::GLOVES: $this->iData['bodypart'] = 'Gloves';
|
||||
break;
|
||||
case D2ItemLocationBody::WEAPONR2: $this->iData['bodypart'] = 'Weapon Alt R';
|
||||
break;
|
||||
case D2ItemLocationBody::WEAPONL2: $this->iData['bodypart'] = 'Weapon Alt L';
|
||||
break;
|
||||
default: $this->iData['bodypart'] = 'Unknown';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if item is ear
|
||||
if ($this->iData['ear']){
|
||||
// set item code/basename
|
||||
$this->iData['itemCode'] = 'ear';
|
||||
$this->iData['basename'] = 'Ear';
|
||||
// get ear class/level
|
||||
$eclass = bindec($b->readr(3)); // bit 76
|
||||
$elevel = bindec($b->readr(7)); // bit 79
|
||||
// get ear char's name
|
||||
}
|
||||
|
||||
// get item code
|
||||
$b->seek(76);
|
||||
$itemCode = '';
|
||||
foreach (str_split($b->read(32), 8) as $byte) {
|
||||
$itemCode .= chr(bindec(strrev($byte)));
|
||||
}
|
||||
$this->iData['itemCode'] = trim($itemCode);
|
||||
|
||||
// get namestr
|
||||
$sql = "SELECT code,namestr FROM armor WHERE code='{$this->iData['itemCode']}'";
|
||||
$res = PDO_FetchAssoc($sql);
|
||||
if (empty($res)){
|
||||
$sql = "SELECT code,namestr FROM misc WHERE code='{$this->iData['itemCode']}'";
|
||||
$res = PDO_FetchAssoc($sql);
|
||||
}
|
||||
if (empty($res)){
|
||||
$sql = "SELECT code,namestr FROM misc WHERE code='{$this->iData['itemCode']}'";
|
||||
$res = PDO_FetchAssoc($sql);
|
||||
}
|
||||
|
||||
$sql = "SELECT `String` FROM strings WHERE `Key`='{$res[$this->iData['itemCode']]}'";
|
||||
$res = PDO_FetchOne($sql);
|
||||
$this->iData['basename'] = $res;
|
||||
|
||||
return $this->iData;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user