Checksum code fixed. Added DocBlocks to D2Classes. TODO: Fill in docblocks, refactor, code cleanup

This commit is contained in:
Hash Borgir
2022-07-06 17:41:24 -06:00
parent f3b24de2a8
commit eb28039f88
28 changed files with 1285 additions and 340 deletions

View File

@@ -1,15 +1,31 @@
<?php
/**
*
*/
class D2BitReader {
/**
* @var string
*/
private string $bits = '';
/**
* @var int
*/
private int $offset = 0;
/**
* @param string $bits
*/
public function __construct(string $bits = '') {
$this->bits = $bits;
return true;
}
/**
* @param int $numBits
* @return int
*/
public function skip(int $numBits): int {
$this->offset += $numBits;
return $this->offset;
@@ -17,6 +33,11 @@ class D2BitReader {
/* read X number of bits, like fread */
/**
* @param int $numBits
* @param bool $str
* @return string
*/
public function read(int $numBits = 0, bool $str = true): string {
$bits = null;
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
@@ -26,10 +47,21 @@ class D2BitReader {
return $bits;
}
/**
* @param string $bits
* @param string $bitsToWrite
* @param int $offset
* @return array|string|string[]
*/
public function writeBits(string $bits, string $bitsToWrite, int $offset) {
return substr_replace($bits, $bitsToWrite, $offset, strlen($bitsToWrite));
}
/**
* @param int $numBits
* @param bool $str
* @return string
*/
public function readb(int $numBits = 0, bool $str = true): string {
$bits = null;
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
@@ -39,6 +71,10 @@ class D2BitReader {
return strrev(str_pad($bits, 16, 0, STR_PAD_RIGHT));
}
/**
* @param int $numBits
* @return string
*/
public function readr(int $numBits = 0): string {
$bits = null;
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
@@ -50,6 +86,10 @@ class D2BitReader {
/* seek to offset (like fseek) */
/**
* @param int $pos
* @return bool
*/
public function seek(int $pos): bool {
if ($pos < 0 || $pos > strlen($this->bits)) {
return false;
@@ -60,6 +100,9 @@ class D2BitReader {
/* rewind offset to 0 */
/**
* @return bool
*/
public function rewind(): bool {
$this->offset = 0;
return true;
@@ -67,6 +110,10 @@ class D2BitReader {
/* Get Bit */
/**
* @param string $bitNum
* @return int
*/
public function getBit(string $bitNum): int {
if ($bitNum < 0 || $bitNum > strlen($this->bits)) {
return false;
@@ -76,6 +123,11 @@ class D2BitReader {
/* Set Bit */
/**
* @param int $bitNum
* @param int $bitVal
* @return bool
*/
public function setBit(int $bitNum, int $bitVal): bool {
if ($bitVal < 0 || $bitVal > 1) {
return false;
@@ -84,18 +136,32 @@ class D2BitReader {
return true;
}
/**
* @return string
*/
public function getBits(): string {
return $this->bits;
}
/**
* @param string $bits
* @return void
*/
public function setBits(string $bits) {
$this->bits = $bits;
}
/**
* @return int
*/
public function getOffset(): int {
return $this->offset;
}
/**
* @param int $offset
* @return bool
*/
public function setOffset(int $offset): bool {
if ($offset < 0 || $offset > strlen($this->bits))
return false;

View File

@@ -3,17 +3,33 @@
require_once './src/D2Functions.php';
require_once './src/D2BitReader.php';
/**
*
*/
class D2ByteReader {
/**
* @var string
*/
private string $data = '';
/**
* @var int
*/
private int $offset = 0;
/**
* @param string $data
*/
public function __construct(string $data) {
if (!$data)
return false;
$this->data = $data;
}
/**
* @param int $numBytes
* @return bool
*/
public function skip(int $numBytes): bool {
if ($numBytes < 0 || $numBytes > strlen($this->data))
return false;
@@ -21,6 +37,10 @@ class D2ByteReader {
return $true;
}
/**
* @param int $pos
* @return bool
*/
public function seek(int $pos): bool {
if ($pos < 0 || $pos > strlen($this->data))
return false;
@@ -28,6 +48,12 @@ class D2ByteReader {
return true;
}
/**
* @param int $offset
* @param int $numBytes
* @param bool $str
* @return string
*/
public function readh(int $offset, int $numBytes, bool $str = true): string {
$this->seek($offset);
$bytes = null;
@@ -37,6 +63,12 @@ class D2ByteReader {
return unpack('H*', $bytes)[1];
}
/**
* @param int $offset
* @param int $numBytes
* @param bool $str
* @return array
*/
public function readc(int $offset, int $numBytes, bool $str = true): array {
$this->seek($offset);
$bytes = null;
@@ -46,15 +78,28 @@ class D2ByteReader {
return unpack('C*', $bytes);
}
/**
* @return bool
*/
public function rewind(): bool {
$this->offset = 0;
return true;
}
/**
* @param int $offset
* @param int $byte
* @return void
*/
public function writeByte(int $offset, int $byte) {
$this->data[$offset] = pack('C', $byte);
}
/**
* @param int $offset
* @param string $bytes
* @return false|void
*/
public function writeBytes(int $offset, string $bytes) {
if ($offset < 0 || $offset > strlen($this->data) || $bytes == '')
return false;
@@ -64,26 +109,46 @@ class D2ByteReader {
$this->data[$pos] = pack('H*', $byte);
}
}
/**
* @param int $offset
* @param string $bytes
* @return false|void
*/
public function insertBytes(int $offset, string $bytes) {
if ($offset < 0 || $offset > strlen($this->data) || $bytes == '')
return false;
$data = bin2hex($this->data); // convert to hex bytes string
$newData = substr_replace($data, $bytes, $offset, 0);
$this->data = hex2bin($newData);
}
}
/**
* @return false|string
*/
public function getData() {
return $this->data ? $this->data : false;
}
/**
* @param $data
* @return void
*/
public function setData($data){
$this->data = $data;
}
/**
* @return int
*/
public function getOffset(): int {
return $this->offset;
}
/**
* @param string $str
* @return bool
*/
public function isHexString(string $str): bool {
if (strlen($str) % 2 == 0 && (ctype_xdigit($str))) {
return true;
@@ -91,6 +156,10 @@ class D2ByteReader {
return false;
}
/**
* @param $input
* @return string
*/
public function toBits($input): string {
$output = '';
if ($this->isHexString($input)) {
@@ -113,13 +182,21 @@ class D2ByteReader {
}
}
/**
* @param string $bits
* @return string
*/
public function toBytesR(string $bits) : string {
foreach (str_split($bits, 8) as $byteString) {
$bytes .= strtoupper(str_pad(dechex(bindec(($byteString))), 2, 0, STR_PAD_LEFT));
}
return $bytes;
}
/**
* @param string $bits
* @return string
*/
public function toBytes(string $bits) : string {
foreach (str_split($bits, 8) as $byteString) {
$bytes .= strtoupper(str_pad(dechex(bindec(strrev($byteString))), 2, 0, STR_PAD_LEFT));
@@ -127,6 +204,10 @@ class D2ByteReader {
return $bytes;
}
/**
* @param string $bits
* @return string
*/
public function bitsToHexString(string $bits): string {
$bytes = '';
foreach (str_split($bits, 8) as $byte) {
@@ -135,6 +216,10 @@ class D2ByteReader {
return $bytes;
}
/**
* @param string $bits
* @return array
*/
public function bitsToHexArray(string $bits): array {
$bytes = [];
foreach (str_split($bits, 8) as $byte) {
@@ -143,6 +228,10 @@ class D2ByteReader {
return $bytes;
}
/**
* @param string $bits
* @return array
*/
public function bitsToIntArray(string $bits): array {
$bytes = [];
foreach (str_split($bits, 8) as $byte) {
@@ -151,18 +240,21 @@ class D2ByteReader {
return $bytes;
}
/*
@return Byte with Nth bit set to X
/**
* @param int $byte
* @param int $pos
* @param bool $bit
* @return int
*/
public function setBit(int $byte, int $pos, bool $bit) {
return ($bit ? ($byte | (1 << $pos)) : ($byte & ~(1 << $pos)) );
}
/*
@return Bit at Nth position in Byte
/**
* @param int $byte
* @param int $pos
* @return int
*/
public function getBit(int $byte, int $pos): int {
return intval(($byte & (1 << $pos)) != 0);
}

View File

@@ -8,24 +8,70 @@ require_once 'D2Item.php';
require_once 'D2ByteReader.php';
require_once 'D2Functions.php';
/**
*
*/
class D2Char {
/**
* @var null
*/
public $cData = null; // char data output
/**
* @var null
*/
public $items = null; // char item data
/**
* @var D2ByteReader|null
*/
public $ByteReader = null; // put $data into bytereader
/**
* @var string|null
*/
public $filePath = null; // .d2s file path
/**
* @var D2CharStructureData
*/
private $sData = null; // char file structure data
/**
* @var null
*/
private $bData = null; // char binary data from d2s
/**
* @var false|resource
*/
private $fp = null; // file pointer
/**
* @var false|string
*/
private $data = null; // full d2s file loaded in $data
/**
* @var null
*/
private $ISC = null;
/**
* @var null
*/
private $skillData = null;
/**
* @return void
*/
public function save() {
file_put_contents($this->filePath, $this->data);
checksumFix($this->filePath);
$this->ByteReader->setData($this->data); // update bytereader data
$this->ByteReader->writeBytes(12, "00000000"); // clear old checksum
$this->data = $this->ByteReader->getData(); // update this data to what we get from bytereader after clearing checksum
$checksum = checksum(unpack('C*', $this->data)); // get new checksum
$this->ByteReader->setData($this->data); // update bytereader data
$this->ByteReader->writeBytes(12, $checksum); // write new checksum
$this->data = $this->ByteReader->getData(); // update this data
file_put_contents($this->filePath, $this->data); // write file
}
/**
* @param $file
*/
public function __construct($file) {
$this->sData = new D2CharStructureData();
$this->filePath = $_SESSION['savepath'] . $file;
@@ -52,7 +98,7 @@ class D2Char {
$classes = array_flip(['ama' => 0, 'sor' => 1, 'nec' => 2, 'pal' => 3, 'bar' => 4, 'dru' => 5, 'ass' => 6]);
$class = $classes[hexdec($this->ByteReader->readh(40, 1))];
$sql = "SELECT sk.id,sk.Skill,sk.skilldesc,`str name`,strings.`String`,skilldesc.SkillPage,skilldesc.SkillRow,skilldesc.SkillColumn,skilldesc.ListRow,skilldesc.ListPool,skilldesc.IconCel
FROM skills as sk
FROM skills as sk
LEFT JOIN skilldesc ON sk.skilldesc = skilldesc.skilldesc
LEFT JOIN strings on skilldesc.`str name` = strings.Key
WHERE sk.charclass = '$class'";
@@ -64,6 +110,9 @@ WHERE sk.charclass = '$class'";
return $this->parseChar(); // end of parseChar() calls parseItems(), parseStats, etc.
}
/**
* @return void
*/
public function parseItems() {
$i_TotalOffset = strpos($this->data, "JM");
fseek($this->fp, $i_TotalOffset + 2);
@@ -83,6 +132,9 @@ WHERE sk.charclass = '$class'";
}
}
/**
* @return array|null
*/
public function parseChar() {
$cData = null;
$cData['Identifier'] = bin2hex($this->bData[0]);
@@ -90,30 +142,46 @@ WHERE sk.charclass = '$class'";
$cData['VersionID'] = ($this->sData->version[unpack('l', $this->bData[4])[1]]);
// 1.41 KB (1,447 bytes) - checks out
$cData['Filesize'] = round(unpack('l', $this->bData[8])[1] / 1024, 2) . " KB";
//$cData['Filesize'] = round(unpack('l', $this->bData[8])[1] / 1024, 2) . " KB";
$cData['Filesize'] = unpack('L', $this->bData[8])[1];
$cData['Checksum'] = bin2hex($this->bData[12]);
$cData['Activeweapon'] = unpack('l', $this->bData[16]);
$cData['Activeweapon'] = unpack('L', $this->bData[16]);
$cData['CharacterName'] = str_replace("\0", "", $this->bData[20]);
$cData['CharacterStatus'] = array_filter(str_split(strtobits($this->bData[36])));
foreach ($cData['CharacterStatus'] as $k => $v) {
$str .= ($characterStatus[$k]) . " ";
$characterStatus = array_filter(str_split(strrev(strtobits($this->bData[36]))));
foreach ($characterStatus as $k => $v) {
$str .= $this->sData->characterStatus[$k] . " ";
}
$cData['CharacterStatus'] = $str;
$cData['Characterprogression'] = bindec($this->bData[37]);
$cData['CharacterStatus'] = trim($str);
$progression = hexdec(bin2hex($this->bData[37]));
$cData['CharacterProgression'] = $this->sData->characterProgressionClassic[$progression];
if ($cData['CharacterStatus'] == 'Hardcore Expansion') {
$cData['CharacterProgression'] = $this->sData->characterProgressionExpHC[$progression];
}
if ($cData['CharacterStatus'] == "Expansion") {
$cData['CharacterProgression'] = $this->sData->characterProgressionExp[$progression];
}
if ($cData['CharacterStatus'] == "Hardcore") {
$cData['CharacterProgression'] = $this->sData->characterProgressionClassicHC[$progression];
}
$cData['CharacterClass'] = $this->sData->class[unpack('C', $this->bData[40])[1]];
$cData['CharacterLevel'] = unpack('C', $this->bData[43])[1];
$cData['Lastplayed'] = gmdate("Y-m-d\TH:i:s\Z", unpack('I', $this->bData[48])[0]);
$cData['Lastplayed'] = gmdate("Y-m-d\TH:i:s\Z", unpack('L', $this->bData[48])[0]);
$skills = (unpack('l16', $this->bData[56]));
// Hotkey assigned skills
foreach ($skills as $skill) {
$cData['Assignedskills'][] = ($this->sData->skills[$skill]);
$cData['Assignedskills'] = array_filter($cData['Assignedskills']);
}
$cData['LeftmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[120])[1]];
$cData['RightmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[124])[1]];
$cData['LeftswapmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[128])[1]];
$cData['RightswapmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[132])[1]];
$cData['LeftmousebuttonskillID'] = $this->sData->skills[unpack('L', $this->bData[120])[1]];
$cData['RightmousebuttonskillID'] = $this->sData->skills[unpack('L', $this->bData[124])[1]];
$cData['LeftswapmousebuttonskillID'] = $this->sData->skills[unpack('L', $this->bData[128])[1]];
$cData['RightswapmousebuttonskillID'] = $this->sData->skills[unpack('L', $this->bData[132])[1]];
// Char menu appearance not needed
// $cData['Charactermenuappearance'] = unpack('i', $this->bData[136]);
@@ -128,7 +196,7 @@ WHERE sk.charclass = '$class'";
// found in the character.map file, according to the difficulty being played. Not needed
//$cData['MapID'] = $this->bData[171];
$cData['MercenaryDead'] = unpack('i', $this->bData[177])[1];
$cData['MercenaryDead'] = unpack('i-', $this->bData[177])[1];
// This looks like a random ID for your mercenary.
// $cData['MercenaryID'] = unpack('H*', $this->bData[179]);
$cData['MercenaryNameID'] = unpack('S', $this->bData[183])[1];
@@ -149,13 +217,16 @@ WHERE sk.charclass = '$class'";
$this->cData['skills'] = $this->parseSkills();
unset($this->items);
unset($this->bData);
//unset($this->bData);
unset($this->sData);
unset($this->fp);
return $this->cData;
}
/**
* @return array
*/
public function parseSkills() {
$if = strposX($this->data, 'if', 1) + 2; // find if and skip it
$jm = strposX($this->data, 'JM', 1);
@@ -177,6 +248,10 @@ WHERE sk.charclass = '$class'";
return $cData;
}
/**
* @param int $points
* @return void
*/
public function setAllSkills(int $points) {
$if = strposX($this->data, 'if', 1) + 2; // find if and skip it
$jm = strposX($this->data, 'JM', 1);
@@ -188,6 +263,11 @@ WHERE sk.charclass = '$class'";
$this->save();
}
/**
* @param int $skill
* @param int $points
* @return void
*/
public function setSkill(int $skill, int $points) {
$skill -= 1;
$if = strposX($this->data, 'if', 1) + 2; // find if and skip it
@@ -198,6 +278,9 @@ WHERE sk.charclass = '$class'";
$this->save();
}
/**
* @return void
*/
public function parseStats() {
$gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it
$if = strposX($this->data, 'if', 1);
@@ -205,13 +288,13 @@ WHERE sk.charclass = '$class'";
$stats = new D2BitReader($this->ByteReader->toBits($this->ByteReader->readh($gf, $len)));
$bits = $stats->getBits();
$bytes = $this->ByteReader->toBytes($bits);
$bytes = $this->ByteReader->toBytes($bits);
$stats->rewind();
for ($i = 0; $i <= strlen($bits); $i++) {
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9)));
if ($this->ISC[$id]['CSvBits'] !== NULL) {
if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') {
$stats->skip($this->ISC[$id]['CSvBits']);
}
$ids[$id] = $id;
@@ -219,11 +302,11 @@ WHERE sk.charclass = '$class'";
$stats->rewind();
foreach ($ids as $id) {
$stats->skip(9);
if ($this->ISC[$id]['CSvBits'] !== NULL) {
if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') {
$val = $stats->readb($this->ISC[$id]['CSvBits']);
$stat = $this->ISC[$id]['Stat'];
$values[$stat] = hexdec($this->ByteReader->toBytesR($val));
}
$stat = $this->ISC[$id]['Stat'];
$values[$stat] = hexdec($this->ByteReader->toBytesR($val));
}
$values['hitpoints'] = (int) round($values['hitpoints'] >> 11);
$values['maxhp'] = (int) round($values['maxhp'] >> 11);
@@ -231,12 +314,19 @@ WHERE sk.charclass = '$class'";
$values['maxmana'] = (int) round($values['maxmana'] >> 11);
$values['stamina'] = (int) round($values['stamina'] >> 11);
$values['maxstamina'] = (int) round($values['maxstamina'] >> 11);
$values['killcounter'] = (int) round($values['killcounter'] >> 1);
$values['soulcounter'] = (int) round($values['soulcounter'] / 2);
$values['killcounter'] = (int) round($values['killcounter'] / 2);
$this->cData['stats'] = $values;
}
public function setChar(string $stat, mixed $val) {
/**
* @param string $stat
* @param mixed $val
* @param mixed|null $val2
* @return false|void
*/
public function setChar(string $stat, mixed $val, mixed $val2 = null) {
switch ($stat) {
case 'CharacterName':
if (strlen($val) < 1 || strlen($val) > 15) {
@@ -244,15 +334,20 @@ WHERE sk.charclass = '$class'";
}
$pack = $this->ByteReader->bitsToHexString($this->ByteReader->toBits(pack('Z16', $val)));
$this->ByteReader->writeBytes(20, $pack);
$this->data = $this->ByteReader->getData();
$this->save();
rename($this->filePath, $_SESSION['savepath'] . "$val.d2s");
break;
case "CharacterClass":
$this->ByteReader->writeByte(40, $val);
$this->data = $this->ByteReader->getData();
$this->save();
$classes = [
'Amazon' => 0,
'Sorceress' => 1,
'Necromancer' => 2,
'Paladin' => 3,
'Barbarian' => 4,
'Druid' => 5,
'Assassin' => 6
];
$this->ByteReader->writeByte(40, $classes[$val]);
break;
case "CharacterLevel":
if ($val > 99) {
@@ -271,26 +366,111 @@ WHERE sk.charclass = '$class'";
$res = PDO_FetchOne($sql);
$this->setStat('experience', $res);
break;
case 'CharacterStatus':
switch ($val) {
case 'Died':
$status = (strtobits($this->data[36]));
$status[3] = $val2;
$byte = $this->ByteReader->bitsToHexString($status);
$this->ByteReader->writeByte(36, hexdec($byte));
break;
case 'Hardcore':
$status = (strtobits($this->data[36]));
$status[2] = $val2;
$byte = $this->ByteReader->bitsToHexString($status);
$this->ByteReader->writeByte(36, hexdec($byte));
break;
case 'Expansion':
$status = strrev(strtobits($this->data[36]));
$status[5] = $val2;
$byte = $this->ByteReader->bitsToHexString($status);
$this->ByteReader->writeByte(36, hexdec($byte));
break;
}
break;
case 'CharacterProgression': // 0 in normal, 1 finished normal, 2 finished nm, 3 finished hell
switch ($val) {
case 0: // in normal
$this->data[37] = pack('C', 3);
break;
case 1: // finished normal
$this->data[37] = pack('C', 8);
break;
case 2: // finished nm
$this->data[37] = pack('C', 13);
break;
case 3: // finished hell
$this->data[37] = pack('C', 15);
break;
$this->save();
}
break;
case 'LeftmousebuttonskillID':
$this->ByteReader->writeBytes(120, dechex($val));
break;
case 'RightmousebuttonskillID':
$this->ByteReader->writeBytes(124, dechex($val));
break;
case 'LeftswapmousebuttonskillID':
$this->ByteReader->writeBytes(128, dechex($val));
break;
case 'RightswapmousebuttonskillID':
$this->ByteReader->writeBytes(132, dechex($val));
break;
}
// finally save char data to d2s file
$this->data = $this->ByteReader->getData();
$this->save();
}
/**
* @return void
*/
public function resetFileSize() {
$filesize = strlen($this->data);
$this->fp = fopen($this->filePath, "r+b");
fseek($this->fp, 8);
fwrite($this->fp, pack('L', $filesize));
fclose($this->fp);
$this->fp = fopen($this->filePath, "r+b");
checksumFix($this->filePath);
fseek($this->fp, 8);
//ddump(unpack('L', fread($this->fp, 4))[1]);
}
/**
* @return false|string
*/
public function generateAllStats() {
// 003C08E081000F067860C001071C0008020800F040020064A000000A2C00C0030C000D000000006E05000000FE3F
$stats = '';
foreach ($this->ISC as $i) {
$id = strrev(str_pad((decbin($i['ID'])), 9, 0, STR_PAD_LEFT));
$val = strrev(str_pad((decbin(20)), (int) $i['CSvBits'], 0, STR_PAD_LEFT));
for ($i = 0; $i < 16; $i++) {
$id = strrev(str_pad((decbin((int) $this->ISC[$i]['ID'])), 9, 0, STR_PAD_LEFT));
$val = strrev(str_pad((decbin(20)), (int) $this->ISC[$i]['CSvBits'], 0, STR_PAD_LEFT));
// dump($id);
// dump($val);
$stat = $id . $val;
$stats .= $stat;
}
$stats .= "000011111111100";
dump($stats);
$gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it
$if = strposX($this->data, 'if', 1);
$len = $if - $gf;
$statall = $stats . "11111111100";
$bytes = $this->ByteReader->toBytes($statall);
$bytes = $this->ByteReader->toBytes($stats);
// refresh this data
$data = $this->ByteReader->getData();
// delete everything between GF---and---IF
@@ -303,19 +483,27 @@ WHERE sk.charclass = '$class'";
$this->data = $data;
$this->save();
$this->resetFileSize();
$filedata = file_get_contents($this->filePath);
$this->ByteReader = new D2ByteReader($filedata);
$this->data = $this->ByteReader->getData();
return $this->data;
}
/**
* @param string $stat
* @param mixed $val
* @return void
*/
public function setStat(string $stat, mixed $val) {
$gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it
$if = strposX($this->data, 'if', 1);
$len = $if - $gf;
$stats = new D2BitReader($this->ByteReader->toBits($this->ByteReader->readh($gf, $len)));
$bits = $stats->getBits();
$bits = $stats->getBits();
$cleanbits = substr($bits, 0, -11);
$stats->setBits($cleanbits);
$bits = $stats->getBits();
@@ -324,7 +512,9 @@ WHERE sk.charclass = '$class'";
for ($i = 0; $i <= strlen($bits); $i++) {
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9)));
$_offsets[$id] = $stats->getOffset();
$stats->skip($this->ISC[$id]['CSvBits']);
if ($this->ISC[$id]['CSvBits'] !== null && $this->ISC[$id]['CSvBits'] !== '') {
$stats->skip($this->ISC[$id]['CSvBits']);
}
}
$_offsets[0] = 9;
$offsets = null;
@@ -332,7 +522,9 @@ WHERE sk.charclass = '$class'";
$_stat = $this->ISC[$k]['Stat'];
$_stats[$_stat] = $this->ISC[$k]['Stat'];
$csvbits[$_stat] = $this->ISC[$k]['CSvBits'];
$maxValues[$_stat] = pow(2, $this->ISC[$k]['CSvBits']) - 1;
if ($this->ISC[$k]['CSvBits'] !== null && $this->ISC[$k]['CSvBits'] !== '') {
$maxValues[$_stat] = pow(2, $this->ISC[$k]['CSvBits']) - 1;
}
$offsets[$_stat] = $v;
}
if ($stat == 'hitpoints' || $stat == 'maxhp' || $stat == 'mana' || $stat == 'maxmana' || $stat == 'stamina' || $stat == 'maxstamina') {
@@ -344,14 +536,22 @@ WHERE sk.charclass = '$class'";
}
$bitsToWrite = strrev(str_pad(decbin(intval($val)), $csvbits[$_stats[$stat]], 0, STR_PAD_LEFT));
$statOffset = $offsets[$_stats[$stat]];
$newBits = $stats->writeBits($bits, $bitsToWrite, $statOffset) . "11111111100"; // 0x1FF padding
$stats->setBits($newBits);
$bytes = $this->ByteReader->toBytes($newBits);
$this->ByteReader->writeBytes($gf, $bytes);
$this->data = $this->ByteReader->getData();
$this->save();
if (!array_key_exists($stat, $_stats)) {
$this->ByteReader->toBits($this->generateAllStats());
} else {
$newBits = $stats->writeBits($bits, $bitsToWrite, $statOffset) . "11111111100"; // 0x1FF padding
$stats->setBits($newBits);
$bytes = $this->ByteReader->toBytes($newBits);
$this->ByteReader->writeBytes($gf, $bytes);
$this->data = $this->ByteReader->getData();
$this->save();
}
}
/**
* @param $file
* @return array
*/
public function getQuestData($file) {
$questsNorm = null;
$questsNM = null;
@@ -390,6 +590,10 @@ WHERE sk.charclass = '$class'";
return $quests;
}
/**
* @param $file
* @return array
*/
public function getWaypointsData($file) {
$wp = null;
fseek($this->fp, $this->sData->wpOffsetsNorm);

View File

@@ -2,84 +2,306 @@
require_once 'D2BitReader.php';
/**
*
*/
class D2CharItem {
/**
* @var string
*/
private string $bits;
/**
* @var string
*/
public $basename = ''; //name of the base item
/**
* @var string
*/
public $item_name = ''; //name string
/**
* @var string
*/
public $item_rank = ''; //normal/exceptional/elite
/**
* @var string
*/
public $item_type = ''; //basic type: armor/weapon/misc
//flags
/**
* @var int
*/
public $identified = 0;
/**
* @var int
*/
public $sockets = 0;
/**
* @var int
*/
public $ear = 0;
/**
* @var int
*/
public $starter = 0;
/**
* @var int
*/
public $compact = 0;
/**
* @var
*/
public $ethereal;
/**
* @var
*/
public $personalized;
/**
* @var
*/
public $runeword;
/**
* @var
*/
public $version;
/**
* @var string
*/
public $runeword_name = '';
/**
* @var string
*/
public $runes_title = '';
//placement
/**
* @var int
*/
public $location = 0;
/**
* @var int
*/
public $body = 0;
/**
* @var int
*/
public $col = 0;
/**
* @var int
*/
public $row = 0;
/**
* @var int
*/
public $container = 0;
/**
* @var
*/
public $parent;
/**
* @var
*/
public $storage;
/**
* @var
*/
public $bodypart;
/**
* @var int
*/
public $invH = 0;
/**
* @var int
*/
public $invW = 0;
/**
* @var int
*/
public $beltrows = 1;
//features
/**
* @var string
*/
public $item_code = ''; //3 letter code from txt
/**
* @var int
*/
public $SocketsFilled = 0;
/**
* @var int
*/
public $SocketsNum = 0;
/**
* @var bool
*/
public $socketable = false; //gem, rune, jewel
/**
* @var string
*/
public $fingerprint = '';
/**
* @var int
*/
public $itemlvl = 0; //item level
/**
* @var int
*/
public $quality = 0;
/**
* @var bool
*/
public $isCharm = false;
/**
* @var bool
*/
public $isJewel = false;
/**
* @var string
*/
public $magic_rank = 'Normal'; //normal/magic/rare/crafted/set/unique
/**
* @var int
*/
public $set_id = 0; //set item id from txt
/**
* @var string
*/
public $set_item = '';
/**
* @var int
*/
public $set_name = 0; //set name, if it is set item,
/**
* @var string
*/
public $personname = '';
/**
* @var int
*/
public $questdif = -1;
/**
* @var
*/
public $gold;
/**
* @var string
*/
public $GUID = '';
/**
* @var int
*/
public $defense = 0;
/**
* @var int
*/
public $mindam = 0;
/**
* @var int
*/
public $maxdam = 0;
/**
* @var int
*/
public $mindam2 = 0;
/**
* @var int
*/
public $maxdam2 = 0;
/**
* @var int
*/
public $mindammi = 0;
/**
* @var int
*/
public $maxdammi = 0;
/**
* @var int
*/
public $MaxDur = 0;
/**
* @var int
*/
public $CurDur = 0;
/**
* @var int
*/
public $reqlvl = 0;
/**
* @var int
*/
public $reqstr = 0;
/**
* @var int
*/
public $reqdex = 0;
/**
* @var int
*/
public $speed = 0;
/**
* @var int
*/
public $throwing = 0;
/**
* @var int
*/
public $stackable = 0;
/**
* @var string
*/
public $charName = ''; //ear's name
/**
* @var
*/
public $gfx; //graphic file name
/**
* @var int
*/
public $baseTrans = -1; //transform indexes for colour remap base item
/**
* @var int
*/
public $magicTrans = -1; //transform indexes for colour remap magic item
/**
* @var
*/
public $type; //type column from txt
/**
* @var string
*/
public $spelldesc = ''; //desc for potions
/**
* @var
*/
public $ditem; //link to item properties from txt
//mods
/**
* @var int
*/
public $dammult = 100; //damage multiply
/**
* @var int
*/
public $damminadd = 0; //damage add
/**
* @var int
*/
public $dammaxadd = 0; //damage add
/**
* @var int
*/
public $defmult = 100; //defense multiply
/**
* @var int
*/
public $defadd = 0; //defense multiply
/**
* @var int[]
*/
public $resist = array(0, 0, 0, 0, 0, 0); //phy, mag, fire, light, cold, poison
/**
* @var int[]
*/
public $attributes = array(0, 0, 0, 0); //str, dex, vit, ene
//arrays
@@ -87,18 +309,33 @@ class D2CharItem {
//socketed items, collected in above function,
//because item has only data for itselt, and
//gems/runes/jewels are standalone
public $SocketItems = array();
/**
* @var array
*/
public $SocketItems = array();
/**
* @var array
*/
public $properties = array(); //item variable properties
/**
* @var array
*/
public $propids = array(); //properties ids list
/**
* @param string $bits
*/
public function __construct(string $bits){
if ($bits == '') return false;
$this->bits = $bits;
return $this->parseItem();
}
/**
* @return void
*/
public function parseItem(){
}

View File

@@ -7,12 +7,24 @@ ini_set('max_execution_time', '0');
session_start();
ob_start();
/**
*
*/
define('DB_FILE', $_SESSION['modname'] . ".db");
PDO_Connect("sqlite:" . DB_FILE);
/**
*
*/
class D2CharStructureData {
/**
* @var
*/
public $skills;
/**
* @var string[]
*/
public $class = [
0 => 'Amazon',
1 => 'Sorceress',
@@ -22,6 +34,9 @@ class D2CharStructureData {
5 => 'Druid',
6 => 'Assassin'
];
/**
* @var string[]
*/
public $characterStatus = [
0 => '',
1 => '',
@@ -32,6 +47,93 @@ class D2CharStructureData {
6 => 'Ladder',
7 => ''
];
/**
* @var string[]
*/
public $characterProgressionClassicHC = [
0 => '',
1 => '',
2 => '',
3 => '',
4 => 'Count / Countess',
5 => 'Count / Countess',
6 => 'Count / Countess',
7 => 'Count / Countess',
8 => 'Duke / Duchess',
9 => 'Duke / Duchess',
10 => 'Duke / Duchess',
11 => 'Duke / Duchess',
12 => 'Duke / Duchess',
13 => '',
14 => '',
15 => '',
];
/**
* @var string[]
*/
public $characterProgressionClassic = [
0 => '',
1 => '',
2 => '',
3 => '',
4 => 'Sir / Dame',
5 => 'Sir / Dame',
6 => 'Sir / Dame',
7 => 'Sir / Dame',
8 => 'Lord / Lady',
9 => 'Lord / Lady',
10 => 'Lord / Lady',
11 => 'Lord / Lady',
12 => 'Baron / Baroness',
13 => '',
14 => '',
15 => '',
];
/**
* @var string[]
*/
public $characterProgressionExp = [
0 => '',
1 => '',
2 => '',
3 => '',
4 => '',
5 => 'Slayer',
6 => 'Slayer',
7 => 'Slayer',
8 => 'Slayer',
9 => '',
10 => 'Champion',
11 => 'Champion',
12 => 'Champion',
13 => 'Champion',
14 => 'Patriarch / Matriarch ',
15 => 'Patriarch / Matriarch ',
];
/**
* @var string[]
*/
public $characterProgressionExpHC = [
0 => '',
1 => '',
2 => '',
3 => '',
4 => '',
5 => 'Destroyer',
6 => 'Destroyer',
7 => 'Destroyer',
8 => 'Destroyer',
9 => '',
10 => 'Conqueror',
11 => 'Conqueror',
12 => 'Conqueror',
13 => 'Conqueror',
14 => 'Guardian',
15 => 'Guardian',
];
/**
* @var int[]
*/
public $offsets = [
0 => 4, // Identifier
4 => 4, // Version ID
@@ -67,6 +169,9 @@ class D2CharStructureData {
633 => 81, // Waypoints
714 => 51, // NPC Introductions
];
/**
* @var string[]
*/
public $qNorm = [
345 => 'introWarriv',
347 => 'Den_Of_Evil',
@@ -95,14 +200,14 @@ class D2CharStructureData {
393 => 'introToAct4',
395 => 'The_Fallen_Angel',
397 => 'Terrors_End',
399 => 'Hell_Forge',
399 => 'Hell_Forge',
401 => 'traveledToAct5',
//403 => 'empty31',
//405 => 'empty32',
//407 => 'empty33',
409 => 'completedTerrorsEnd',
//411 => 'empty21',
//413 => 'empty22',
//413 => 'empty22',
415 => 'Siege_On_Harrogath',
417 => 'Rescue_On_MountArreat',
419 => 'Prison_Of_Ice',
@@ -110,8 +215,10 @@ class D2CharStructureData {
423 => 'Rite_Of_Passage',
425 => 'Eve_Of_Destruction',
// read 425, pointer at 427, + 14 = 441 qNM offset
];
/**
* @var string[]
*/
public $qNM = [
441 => 'introWarrivNM',
443 => 'Den_Of_Evil_NM',
@@ -147,7 +254,7 @@ class D2CharStructureData {
//503 => 'empty33',
505 => 'completedTerrorsEnd',
//507 => 'empty21',
//509 => 'empty22',
//509 => 'empty22',
511 => 'Siege_On_Harrogath',
513 => 'Rescue_On_MountArreat',
515 => 'Prison_Of_Ice',
@@ -155,9 +262,10 @@ class D2CharStructureData {
519 => 'Rite_Of_Passage',
521 => 'Eve_Of_Destruction',
// read 521, pointer at 523, + 14 = 537 qHell offset
];
/**
* @var string[]
*/
public $qHell = [
537 => 'introWarriv',
539 => 'Den_Of_Evil_Hell',
@@ -193,15 +301,17 @@ class D2CharStructureData {
//599 => 'empty33',
601 => 'completedTerrorsEnd',
//603 => 'empty21',
//605 => 'empty22',
//605 => 'empty22',
607 => 'Siege_On_Harrogath',
609 => 'Rescue_On_MountArreat',
611 => 'Prison_Of_Ice',
613 => 'Betrayal_Of_Harrogath',
615=> 'Rite_Of_Passage',
615 => 'Rite_Of_Passage',
617 => 'Eve_Of_Destruction',
];
/**
* @var string[]
*/
public $version = [
71 => "1.00 through v1.06",
87 => "1.07 or Expansion Set v1.08",
@@ -209,12 +319,21 @@ class D2CharStructureData {
92 => "v1.09 (both the standard game and the Expansion Set.)",
96 => "v1.10+"
];
/**
* @var int
*/
public $wpOffsetsNorm = 643;
/**
* @var int
*/
public $wpOffsetsNM = 667;
/**
* @var int
*/
public $wpOffsetsHell = 691;
/**
* @var string[]
*/
public $wpNames = [
0 => 'Act 1 - Rogue_Encampment',
1 => 'Act 1 - Cold_Plains',
@@ -255,18 +374,23 @@ class D2CharStructureData {
36 => 'Act 5 - Frozen_Tundra',
37 => "Act 5 - The_Ancients_Way",
38 => 'Act 5 - Worldstone_Keep_level_2'
];
];
/**
* @var int[]|string[]
*/
public $_qNorm;
/**
* @var int[]|string[]
*/
public $_qNM;
/**
* @var int[]|string[]
*/
public $_qHell;
/*
Initialize Skills From Skills.txt
*/
/**
*
*/
public function __construct() {
$sql = "
SELECT
@@ -285,11 +409,11 @@ class D2CharStructureData {
foreach ($res as $r) {
$this->skills[$r['Id']] = $r['String'];
}
$this->_qNorm = array_flip($this->qNorm);
$this->_qNM = array_flip($this->qNM);
$this->_qHell = array_flip($this->qHell);
$this->_qHell = array_flip($this->qHell);
}
}

View File

@@ -42,13 +42,24 @@
*/
/**
*
*/
class D2Database {
public function __construct() {
/**
*
*/
public function __construct() {
PDO_Connect("sqlite:" . DB_FILE);
}
public function createTables($file, $data) {
/**
* @param $file
* @param $data
* @return void
*/
public function createTables($file, $data) {
$tableName = basename($file);
$tableName = strtolower(substr($tableName, 0, -4));
$sql = '';
@@ -68,7 +79,12 @@ class D2Database {
}
}
public function fillsTables($file, $data) {
/**
* @param $file
* @param $data
* @return void
*/
public function fillsTables($file, $data) {
$tableName = basename($file);
$tableName = strtolower(substr($tableName, 0, -4));
@@ -106,7 +122,11 @@ class D2Database {
}
}
public function writeTbl($data) {
/**
* @param $data
* @return void
*/
public function writeTbl($data) {
$sql = 'CREATE TABLE IF NOT EXISTS `strings` (`Key` VARCHAR(255), `String` VARCHAR(255));';
$res = PDO_Execute($sql);
@@ -120,7 +140,11 @@ class D2Database {
$res = PDO_Execute($sql);
}
public function getString($key) {
/**
* @param $key
* @return mixed
*/
public function getString($key) {
$sql = "SELECT String FROM `strings` WHERE `Key`='$key'";
$res = PDO_FetchRow($sql);

View File

@@ -42,8 +42,14 @@
*/
/**
*
*/
class D2DocGenerator {
/**
*
*/
public function __construct() {
require_once './config.php';
require_once './_pdo.php';
@@ -61,6 +67,9 @@ class D2DocGenerator {
$idata = new D2ItemData();
}
/**
* @return array
*/
public function getIscProps() {
$sql = "
SELECT p.`code` as prop,
@@ -103,6 +112,9 @@ class D2DocGenerator {
return $isc;
}
/**
* @return array
*/
public function getStrings() {
// load strings
$sql = 'SELECT * FROM strings';
@@ -110,6 +122,9 @@ class D2DocGenerator {
return $strings;
}
/**
* @return array
*/
public function getItemTypesTbl() {
// load itemtypes table in memory
$sql = "SELECT ItemType,Code FROM itemtypes";
@@ -118,6 +133,9 @@ class D2DocGenerator {
return $itemtypesTbl;
}
/**
* @return array
*/
public function getNameStr() {
// load namestr from 3 files
$sql = "SELECT code,namestr FROM armor
@@ -130,6 +148,10 @@ class D2DocGenerator {
return $namestr;
}
/**
* @param $code
* @return string
*/
public function getImage($code) {
$sql = "SELECT invfile FROM armor WHERE `code`=\"$code\" OR `type`=\"$code\" OR `type2`=\"$code\"";
$img = PDO_FetchOne($sql);
@@ -144,6 +166,10 @@ class D2DocGenerator {
return $img = (!empty($img)) ? "$img.png" : "1.png";
}
/**
* @param $code
* @return false
*/
public function getItemName($code) {
$sql = "SELECT name FROM armor WHERE `code`=\"$code\" OR `type`=\"$code\" OR `type2`=\"$code\"";
$name = PDO_FetchOne($sql);
@@ -158,6 +184,9 @@ class D2DocGenerator {
return $name;
}
/**
* @return void
*/
public function generateDocs() {
}

View File

@@ -42,11 +42,23 @@
*/
/**
*
*/
class D2Files {
/**
* @var array
*/
public $files = [];
/**
* @var
*/
public $charFiles;
/**
*
*/
public function __construct() {
$filesToIgnore = [
"aiparms.txt",
@@ -64,6 +76,9 @@ class D2Files {
return $this->files;
}
/**
* @return mixed
*/
public function getSaveFiles() {
$glob = glob($_SESSION['savepath'] . '*.d2s');

View File

@@ -42,6 +42,10 @@
*/
/**
* @param $var
* @return void
*/
function ddump($var) {
//echo "<pre>";
var_dump($var);
@@ -51,6 +55,10 @@ function ddump($var) {
die();
}
/**
* @param $var
* @return void
*/
function dump($var) {
//echo "<pre>";
var_dump($var);
@@ -59,6 +67,10 @@ function dump($var) {
//echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT);
}
/**
* @param string $str
* @return string
*/
function strtobits(string $str): string {
$ret = "";
for ($i = 0; $i < strlen($str); ++$i) {
@@ -74,14 +86,29 @@ function strtobits(string $str): string {
return $ret;
}
/**
* @param string $hex
* @return string
*/
function swapEndianness(string $hex) {
return implode('', array_reverse(str_split($hex, 2)));
}
/**
* @param int $n
* @param int $p
* @param bool $b
* @return int
*/
function setBit(int $n, int $p, bool $b) {
return ($b ? ($n | (1 << $p)) : ($n & ~(1 << $p)) );
}
/**
* @param int $b
* @param int $p
* @return int
*/
function getBit(int $b, int $p) {
return intval(($b & (1 << $p)) !== 0);
}
@@ -91,30 +118,22 @@ function getBit(int $b, int $p) {
* @param $data
* @return string
*/
//function checksum($data) {
// $nSignature = 0;
// $checksum = 0;
// foreach ($data as $k => $byte) {
//// if ($k == 12 || $k == 13 || $k == 14 || $k == 15) {
//// $byte = 0;
//// }
// $nSignature = ((($nSignature << 1) | ($nSignature >> 31)) + $byte) & 0xFFFFFFFF;
// $checksum = (($checksum << 1) & 0xffffffff) + $byte + (($checksum & 0x80000000) != 0 ? 1 : 0);
// }
// dump(swapEndianness(dechex($nSignature)));
// dump(swapEndianness(dechex($checksum)));
// //return swapEndianness(dechex($nSignature));
// //return swapEndianness(dechex($checksum)); // all of a sudden started returning wrong value, no longer works
//}
//
//function checksumFix(object $ByteReader, string $filePath) {
// $ByteReader->writeBytes(12, 00000000); // zero old checksum
// $newChecksum = checksum(unpack('C*', $ByteReader->getData())); // get new checksum
// $ByteReader->writeBytes(12, $newChecksum); // write new checksum
// file_put_contents($filePath, $ByteReader->getData()); // write bytestream to file
//}
function checksum($fileData) {
$nSignature = 0;
foreach ($fileData as $k => $byte) {
if ($k == 12 || $k == 13 || $k == 14 || $k == 15) {
$byte = 0;
}
$nSignature = ((($nSignature << 1) | ($nSignature >> 31)) + $byte & 0xFFFFFFFF);
}
return swapEndianness(str_pad(dechex($nSignature), 8, 0, STR_PAD_LEFT));
}
function checksumFix(string $filePath) {
/**
* @param string $filePath
* @return string
*/
function checksumFix(string $filePath) {
return trim(shell_exec("bin\d2scs.exe \"$filePath\""));
}
@@ -135,10 +154,18 @@ function strposX($haystack, $needle, $number) {
}
}
/**
* @param string $bit
* @return int
*/
function isBit(string $bit): int {
return ((int) $bit ? 1 : 0 );
}
/**
* @param $input
* @return string
*/
function toBits($input): string {
$output = '';
if (is_string($input)) {
@@ -156,6 +183,9 @@ function toBits($input): string {
}
}
/**
* @return void
*/
function print_mem() {
/* Currently used memory */
$mem_usage = memory_get_usage();
@@ -167,6 +197,11 @@ function print_mem() {
echo 'Peak usage: <strong>' . round($mem_peak / 1024 / 1024) . 'MB</strong> RAM.<br><br>';
}
/**
* @param $src
* @param $dst
* @return void
*/
function rcopy($src, $dst) {
// open the source directory
$dir = opendir($src);
@@ -185,6 +220,10 @@ function rcopy($src, $dst) {
closedir($dir);
}
/**
* @param $src
* @return void
*/
function rrmdir($src) {
$dir = opendir($src);
while (false !== ( $file = readdir($dir))) {

View File

@@ -3,11 +3,23 @@
require_once 'D2BitReader.php';
require_once 'D2ItemStructureData.php';
/**
*
*/
class D2Item {
/**
* @var null
*/
private $bits = null;
/**
* @var null
*/
public $iData = null;
/**
* @param $bits
*/
public function __construct($bits) {
if ($bits == '')
return false;
@@ -20,6 +32,9 @@ class D2Item {
* @return array of item details
*/
/**
* @return null
*/
private function parseItem() {
$b = new D2BitReader($this->bits);

View File

@@ -1,10 +1,22 @@
<?php
/**
*
*/
class D2ItemData {
/**
* @var
*/
public $strings;
/**
* @var
*/
public $images;
/**
* @return void
*/
public function getImages() {
$sql = "SELECT code,uniqueinvfile,invfile,type,type2 FROM armor
UNION ALL
@@ -24,6 +36,11 @@ class D2ItemData {
unset($isc2);
}
/**
* @param $index
* @param $doc
* @return false|string
*/
public function uniqueItems($index, $doc = FALSE) {
if (empty($this->images)) {
$this->getImages();
@@ -897,6 +914,10 @@ class D2ItemData {
}
}
/**
* @param $iscStat
* @return mixed
*/
public function getIscStrings($iscStat) {
if (empty($this->strings)) {
$this->getStrings();
@@ -904,6 +925,9 @@ class D2ItemData {
return ($this->strings[$iscStat]);
}
/**
* @return void
*/
public function getStrings() {
$sql = "
SELECT p.`code` as prop,

View File

@@ -42,6 +42,9 @@
*/
/**
*
*/
class D2ItemDesc {
/*
@@ -135,14 +138,26 @@ class D2ItemDesc {
*/
public $str = '';
/**
* @var string
*/
public $str = '';
// takes value, param.
// value == Value to show on this stat
//descfunc 14
public $skilltabsDesc;
public $skilltabsDescClean;
public $skilltabs = [
/**
* @var
*/
public $skilltabsDesc;
/**
* @var
*/
public $skilltabsDescClean;
/**
* @var string[]
*/
public $skilltabs = [
//ama
'0' => 'StrSklTabItem3',
'1' => 'StrSklTabItem2',
@@ -172,7 +187,10 @@ class D2ItemDesc {
'19' => 'StrSklTabItem20',
'20' => 'StrSklTabItem21'
];
public $charClass = [
/**
* @var string[]
*/
public $charClass = [
"ama" => "Amazon",
"sor" => "Sorceress",
"nec" => "Necromancer",
@@ -245,7 +263,13 @@ class D2ItemDesc {
*
*/
public function prep($par, $min, $max) {
/**
* @param $par
* @param $min
* @param $max
* @return void
*/
public function prep($par, $min, $max) {
}
@@ -268,16 +292,19 @@ class D2ItemDesc {
*/
public function __construct() {
/**
*
*/
public function __construct() {
}
public function getDesc($params = []) {
/**
* @param $params
* @return false|string
*/
public function getDesc($params = []) {
if (empty($params))
return false;

View File

@@ -1,40 +1,112 @@
<?php
/**
*
*/
class D2ItemLocation {
//location
/**
*
*/
const STORED = 0;
/**
*
*/
const EQUIPPED = 1;
/**
*
*/
const BELTI = 2;
/**
*
*/
const CURSOR = 4;
/**
*
*/
const ITEM = 6;
}
/**
*
*/
class D2ItemLocationStored {
//storage
/**
*
*/
const NONE = 0;
/**
*
*/
const INVENTORY = 1;
/**
*
*/
const CUBE = 4;
/**
*
*/
const STASH = 5;
}
/**
*
*/
class D2ItemLocationBody {
//body parts
/**
*
*/
const HELMET = 1;
/**
*
*/
const AMULET = 2;
/**
*
*/
const ARMOR = 3;
/**
*
*/
const WEAPONR = 4;
/**
*
*/
const WEAPONL = 5;
/**
*
*/
const RINGR = 6;
/**
*
*/
const RINGL = 7;
/**
*
*/
const BELT = 8;
/**
*
*/
const BOOTS = 9;
/**
*
*/
const GLOVES = 10;
/**
*
*/
const WEAPONR2 = 11;
/**
*
*/
const WEAPONL2 = 12;
}

View File

@@ -42,11 +42,22 @@
*/
/**
*
*/
class D2SaveTXT {
public $path;
public function save($file, $data) {
/**
* @var mixed
*/
public $path;
/**
* @param $file
* @param $data
* @return void
*/
public function save($file, $data) {
$fp = fopen($this->path.DIRECTORY_SEPARATOR.$file, 'a+');
$this->saveBackup($file);
@@ -54,7 +65,11 @@ class D2SaveTXT {
}
public function saveBackup($file){
/**
* @param $file
* @return void
*/
public function saveBackup($file){
// if dir doesn't exist, create it
if (!is_dir($this->path.DIRECTORY_SEPARATOR."backup")) mkdir($this->path."backup", 0700);
@@ -71,8 +86,12 @@ class D2SaveTXT {
echo "Failed to create backup of $file...\n";
}
}
public function saveTblEnries($filename) {
/**
* @param $filename
* @return void
*/
public function saveTblEnries($filename) {
$post = $_POST;
if (!is_dir($this->path."tblEntries")) mkdir($this->path."tblEntries", 0700);
@@ -81,9 +100,12 @@ class D2SaveTXT {
$str = '"'.$post['index'].'"'."\t".'"'.$post['index'].'"'.PHP_EOL;
$file = $this->path."\\tblEntries\\$filename";
file_put_contents($file, $str, FILE_APPEND);
}
public function __construct() {
}
/**
*
*/
public function __construct() {
$this->path = TXT_PATH;
}

View File

@@ -1,8 +1,17 @@
<?php
/**
*
*/
class D2Strings {
/**
* @var array
*/
public array $strings;
/**
*
*/
public function __construct(){
$sql = "SELECT * FROM strings";
$this->strings = PDO_FetchAssoc($sql);

View File

@@ -41,20 +41,41 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
*
*/
class D2TxtParser {
public $path = TXT_PATH;
/**
* @var mixed
*/
public $path = TXT_PATH;
public $db;
public function __construct() {
/**
* @var
*/
public $db;
/**
*
*/
public function __construct() {
}
public function parseFile($file) {
/**
* @param $file
* @return array
*/
public function parseFile($file) {
return $this->parseData($file);
}
function filterProps($file) {
/**
* @param $file
* @return array
*/
function filterProps($file) {
$data = $this->parseData($file);
$propsToFilter = file(FILTER_PROPERTIES_FILE, FILE_IGNORE_NEW_LINES);
foreach ($data as $d) {
@@ -65,7 +86,11 @@ class D2TxtParser {
return $filteredProps;
}
public function parseData($file) {
/**
* @param $file
* @return array
*/
public function parseData($file) {
$file = $this->path . $file;
$rows = array_map(function ($v) {
return str_getcsv($v, "\t");

View File

@@ -47,7 +47,7 @@
<div>
<div class="center item_desc" style="">
<div style="height: 116px;background: url(/img/items/bg.png) center top no-repeat;">
<div style="height: 116px;background: url(/img/bg.png) center top no-repeat;">
<a href="" target="_blank" class="item_debug_link">
<img style="" class="item img-fluid" src="">
</a>