diff --git a/CharEditor.php b/CharEditor.php index 058d0d8..dd9dd62 100644 --- a/CharEditor.php +++ b/CharEditor.php @@ -14,6 +14,7 @@ require_once './src/D2Functions.php'; require_once './src/D2ByteReader.php'; require_once './src/D2BitReader.php'; require_once './src/D2Item.php'; +require_once './src/D2Char.php'; define('DB_FILE', $_SESSION['modname'] . ".db"); PDO_Connect("sqlite:" . DB_FILE); @@ -31,99 +32,33 @@ $namestr = PDO_FetchAssoc($sql); $sql = "SELECT ID,Stat,CSvBits FROM itemstatcost WHERE Saved=1"; $ISCData = PDO_FetchAll($sql); - foreach ($ISCData as $k => $v) { $ISC[$v['ID']] = $v; } //$filePath = "D:\Diablo II\MODS\ironman-dev\save\Aldur.d2s"; -$filePath = "D:\Diablo II\MODS\ironman-dev\save\Sorc.d2s"; //$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Lok.d2s"; //$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Pal.d2s"; //$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Test.d2s"; -$data = file_get_contents($filePath); -$ByteReader = new D2ByteReader($data); -$gf = strposX($data, 'gf', 1) + 2; // find gf and skip it -$if = strposX($data, 'if', 1); -$len = $if - $gf; - -$stats = new D2BitReader($ByteReader->toBits($ByteReader->readh($gf, $len))); - -$bits = $stats->getBits(); -$cleanbits = substr($bits, 0, -11); -$stats->setBits($cleanbits); - -//$stats->rewind(); -//foreach ($ISC as $i) { -// $stat = $i['Stat']; -// $CSvBits = (int) $i['CSvBits']; -// -// $id = hexdec($ByteReader->toBytesR($stats->readb(9))); -// $stats->skip($CSvBits); -// $ids[$id] = ($ISC[$id]); -//} +$filePath = "Test.d2s"; +$char = new D2Char($filePath); +//$char->setAllSkills(56); +//$char->setSkill(1, 99); +//$char->setChar("CharacterClass", 1); // 127 +$char->setChar("CharacterLevel", 0); +$char->setStat("strength", 30); +$char->setStat("energy", 30); +$char->setStat("dexterity", 30); +$char->setStat("vitality", 30); +$char->setStat("mana", 120); +$char->setStat("maxmana", 200); +$char->setStat("stamina", 80); +$char->setStat("maxstamina", 120); +unset($char); // destroy $char so we can read it again after writing to it to get updated stats -$stats->rewind(); -for($i=0; $i <= strlen($bits); $i++) { - $id = hexdec($ByteReader->toBytesR($stats->readb(9))); - $stats->skip($ISC[$id]['CSvBits']); - $ids[$id] = $id; -} -$stats->rewind(); -foreach($ids as $id){ - $stats->skip(9); - $val = $stats->readb($ISC[$id]['CSvBits']); - $stat = $ISC[$id]['Stat']; - $values[$stat] = hexdec($ByteReader->toBytesR($val)); -} -$values['hitpoints'] = (int) round($values['hitpoints'] >> 11); -$values['maxhp'] = (int) round($values['maxhp'] >> 11); -$values['mana'] = (int) round($values['mana'] >> 11); -$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); -var_dump($values); - -//$stats->rewind(); -//for($i=0; $i <= strlen($bits); $i++) { -// $id = hexdec($ByteReader->toBytesR($stats->readb(9))); -// if (!empty($ISC[$id])){ -// $val = $stats->readb($ISC[$id]['CSvBits']); -// $stat = $ISC[$id]['Stat']; -// $values[$stat] = hexdec($ByteReader->toBytesR($val)); -// } -//} -//$values['hitpoints'] = (int) round($values['hitpoints'] / 2048); -//$values['maxhp'] = (int) round($values['maxhp'] / 2048); -//$values['mana'] = (int) round($values['mana'] / 2048); -//$values['maxmana'] = (int) round($values['maxmana'] / 2048); -//$values['stamina'] = (int) round($values['stamina'] / 2048); -//$values['maxstamina'] = (int) round($values['maxstamina'] / 2048); -//$values['killcounter'] = (int) round($values['killcounter'] / 2); -// -//var_dump($values); - - -//array_pop($ids); -// -//$stats->rewind(); -//foreach($ids as $k => $v){ -// $stat = $v['Stat']; -// $CSvBits = (int) $v['CSvBits']; -// $ValShift = (int) $i['ValShift']; -// $stats->skip(9); -// $values[$stat] = hexdec($ByteReader->toBytesR($stats->readb($CSvBits))); -//} -//$values['hitpoints'] = (int) round($values['hitpoints'] / 2048); -//$values['maxhp'] = (int) round($values['maxhp'] / 2048); -//$values['mana'] = (int) round($values['mana'] / 2048); -//$values['maxmana'] = (int) round($values['maxmana'] / 2048); -//$values['stamina'] = (int) round($values['stamina'] / 2048); -//$values['maxstamina'] = (int) round($values['maxstamina'] / 2048); -// -//dump($values); +$char = new D2Char($filePath); +var_dump($char->cData['stats']); \ No newline at end of file diff --git a/index.php b/index.php index ab6b292..5129f3c 100755 --- a/index.php +++ b/index.php @@ -62,8 +62,8 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE $_SESSION['modname'] = $lastUsedMod['modname']; $_SESSION['path'] = $lastUsedMod['path']; - $sql = "SELECT theme FROM `D2Modder` WHERE `modname`='{$_SESSION['modname']}'"; - $res = PDO_FetchAll($sql); + $sql = "SELECT theme FROM `D2Modder` WHERE modname= :modname"; + $res = PDO_FetchAll($sql, ['modname' => $_SESSION['modname']]); if ($res[0]['theme'] == 1) { $css = 'dark.css'; @@ -82,12 +82,13 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE require_once './src/D2ItemDesc.php'; require_once './src/D2Char.php'; require_once './src/D2CharStructureData.php'; - + $D2Files = new D2Files(); $charFiles = $D2Files->getSaveFiles(); foreach ($charFiles as $charFile) { $charData[] = new D2Char($charFile); // $charData goes into chars.php tab + //$charData[] = $_charData->cData; } @@ -161,6 +162,8 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE * * * Unique Items Form was posted here + * + * TODO: Move this somewhre else, for fucks sake, why post here? That's just fucking stupid. * */ diff --git a/ironman-dev.db-journal b/ironman-dev.db-journal deleted file mode 100644 index eb5f80a..0000000 Binary files a/ironman-dev.db-journal and /dev/null differ diff --git a/res/app.js b/res/app.js index f103f57..7aa191b 100755 --- a/res/app.js +++ b/res/app.js @@ -171,19 +171,11 @@ $(document).ready(function () { }); + $('input[name="invfile"]').keyup(function(){ + invImg = docpath + '/img/items/' + this.value + ".png"; + $(".item").attr("src", invImg); + }); - /* - * - * - * - * - * - * - * - * - * - - **/ // every time we change a prop dropdown, // diff --git a/src/D2BitReader.php b/src/D2BitReader.php index a746f0a..68d8c93 100644 --- a/src/D2BitReader.php +++ b/src/D2BitReader.php @@ -17,7 +17,7 @@ class D2BitReader { /* read X number of bits, like fread */ - public function read(int $numBits = 0, bool $str = true) : string { + public function read(int $numBits = 0, bool $str = true): string { $bits = null; for ($i = $this->offset; $i < $this->offset + $numBits; $i++) { $str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i]; @@ -26,16 +26,20 @@ class D2BitReader { return $bits; } - public function readb(int $numBits = 0, bool $str = true) : string { + public function writeBits(string $bits, string $bitsToWrite, int $offset) { + return substr_replace($bits, $bitsToWrite, $offset, strlen($bitsToWrite)); + } + + public function readb(int $numBits = 0, bool $str = true): string { $bits = null; for ($i = $this->offset; $i < $this->offset + $numBits; $i++) { $str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i]; } $this->offset += $numBits; return strrev(str_pad($bits, 16, 0, STR_PAD_RIGHT)); - } + } - public function readr(int $numBits = 0) : string { + public function readr(int $numBits = 0): string { $bits = null; for ($i = $this->offset; $i < $this->offset + $numBits; $i++) { $bits .= $this->bits[$i]; @@ -83,9 +87,10 @@ class D2BitReader { public function getBits(): string { return $this->bits; } + public function setBits(string $bits) { $this->bits = $bits; - } + } public function getOffset(): int { return $this->offset; diff --git a/src/D2ByteReader.php b/src/D2ByteReader.php index b1e13ce..94b66d4 100644 --- a/src/D2ByteReader.php +++ b/src/D2ByteReader.php @@ -64,10 +64,21 @@ class D2ByteReader { $this->data[$pos] = pack('H*', $byte); } } + 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); + } public function getData() { return $this->data ? $this->data : false; } + + public function setData($data){ + $this->data = $data; + } public function getOffset(): int { return $this->offset; diff --git a/src/D2Char.php b/src/D2Char.php index 6cbbe06..6332c69 100644 --- a/src/D2Char.php +++ b/src/D2Char.php @@ -6,31 +6,40 @@ require_once 'D2BitReader.php'; require_once 'D2Strings.php'; require_once 'D2Item.php'; require_once 'D2ByteReader.php'; +require_once 'D2Functions.php'; class D2Char { public $cData = null; // char data output public $items = null; // char item data + public $ByteReader = null; // put $data into bytereader + public $filePath = null; // .d2s file path private $sData = null; // char file structure data private $bData = null; // char binary data from d2s - private $filePath = null; // .d2s file path private $fp = null; // file pointer private $data = null; // full d2s file loaded in $data - private $ByteReader = null; // put $data into bytereader private $ISC = null; + private $skillData = null; + + public function save() { + file_put_contents($this->filePath, $this->data); + checksumFix($this->filePath); + } public function __construct($file) { $this->sData = new D2CharStructureData(); $this->filePath = $_SESSION['savepath'] . $file; $this->fp = fopen($this->filePath, "r+b"); - $this->data = file_get_contents($this->filePath); - $this->ByteReader = new D2ByteReader($this->data); + $data = file_get_contents($this->filePath); + $this->ByteReader = new D2ByteReader($data); + $this->data = $this->ByteReader->getData(); - $sql = "SELECT ID,Stat,CSvBits FROM itemstatcost WHERE Saved=1"; + $sql = "SELECT ID,Stat,CSvBits,ValShift FROM itemstatcost WHERE Saved=1"; $ISCData = PDO_FetchAll($sql); foreach ($ISCData as $k => $v) { $this->ISC[$v['ID']] = $v; + $this->_ISC[$v['Stat']] = $v; } // read offsets here from sData and put into $this->bData @@ -40,6 +49,18 @@ class D2Char { $this->bData[$k] = fread($this->fp, $v); } + $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 +LEFT JOIN skilldesc ON sk.skilldesc = skilldesc.skilldesc +LEFT JOIN strings on skilldesc.`str name` = strings.Key +WHERE sk.charclass = '$class'"; + $sd = PDO_FetchAll($sql); + foreach ($sd as $k => $v) { + $this->skillData[$k + 1] = $v; + } + return $this->parseChar(); // end of parseChar() calls parseItems(), parseStats, etc. } @@ -85,7 +106,8 @@ class D2Char { $skills = (unpack('l16', $this->bData[56])); foreach ($skills as $skill) { - $cData['Assignedskills'][] = $this->sData->skills[$skill]; + $cData['Assignedskills'][] = ($this->sData->skills[$skill]); + $cData['Assignedskills'] = array_filter($cData['Assignedskills']); } $cData['LeftmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[120])[1]]; @@ -101,7 +123,7 @@ class D2Char { $onDifficulty['Normal'] = $x[0][0]; $onDifficulty['NM'] = $x[1][0]; $onDifficulty['Hell'] = $x[2][0]; - $cData['Difficulty'] = ($onDifficulty); // $diff; + $cData['Difficulty'] = array_filter($onDifficulty); // $diff; // Map ID. This value looks like a random number, but it corresponds with one of the longwords // found in the character.map file, according to the difficulty being played. Not needed //$cData['MapID'] = $this->bData[171]; @@ -123,45 +145,83 @@ class D2Char { $cData['items'] = $this->items; // cData[items] will be $this->items $this->cData = $cData; // parse stats - $this->parseStats(); - + $this->parseStats(); + $this->cData['skills'] = $this->parseSkills(); + + unset($this->items); + unset($this->bData); + unset($this->sData); + unset($this->fp); - unset($this->items); - unset($this->bData); - unset($this->sData); - unset($this->ByteReader); - unset($this->data); - unset($this->fp); - unset($this->ISC); - return $this->cData; } + public function parseSkills() { + $if = strposX($this->data, 'if', 1) + 2; // find if and skip it + $jm = strposX($this->data, 'JM', 1); + $skills = ($this->ByteReader->readc($if, ($jm - $if))); + + foreach ($skills as $k => $v) { + if ($this->skillData[$k]['String']) { + $cData['skills'][$k] = [ + 'skill' => $this->skillData[$k]['String'], + 'points' => $v, + 'page' => $this->skillData[$k]['SkillPage'], + 'row' => $this->skillData[$k]['ListRow'], + 'col' => $this->skillData[$k]['SkillColumn'], + 'icon' => $this->skillData[$k]['IconCel'], + ]; + } + } + $cData['skills'] = array_values($cData['skills']); + return $cData; + } + + public function setAllSkills(int $points) { + $if = strposX($this->data, 'if', 1) + 2; // find if and skip it + $jm = strposX($this->data, 'JM', 1); + $len = $jm - $if; + for ($i = 0; $i < $len; $i++) { + $this->ByteReader->writeByte($if + $i, $points); + } + $this->data = $this->ByteReader->getData(); + $this->save(); + } + + public function setSkill(int $skill, int $points) { + $skill -= 1; + $if = strposX($this->data, 'if', 1) + 2; // find if and skip it + $jm = strposX($this->data, 'JM', 1); + // set $kill to $points + $this->ByteReader->writeByte($if + $skill, $points); + $this->data = $this->ByteReader->getData(); + $this->save(); + } + public function parseStats() { - $gf = strposX($this->data, 'gf', 1) + 2; // find gf and skip it + $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(); + $bytes = $this->ByteReader->toBytes($bits); $stats->rewind(); - for($i=0; $i <= strlen($bits); $i++) { + 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) { $stats->skip($this->ISC[$id]['CSvBits']); } $ids[$id] = $id; } $stats->rewind(); - foreach($ids as $id){ + foreach ($ids as $id) { $stats->skip(9); - if($this->ISC[$id]['CSvBits'] !== NULL){ + if ($this->ISC[$id]['CSvBits'] !== NULL) { $val = $stats->readb($this->ISC[$id]['CSvBits']); - } + } $stat = $this->ISC[$id]['Stat']; $values[$stat] = hexdec($this->ByteReader->toBytesR($val)); } @@ -172,10 +232,126 @@ class D2Char { $values['stamina'] = (int) round($values['stamina'] >> 11); $values['maxstamina'] = (int) round($values['maxstamina'] >> 11); $values['killcounter'] = (int) round($values['killcounter'] >> 1); - + $this->cData['stats'] = $values; } + public function setChar(string $stat, mixed $val) { + switch ($stat) { + case 'CharacterName': + if (strlen($val) < 1 || strlen($val) > 15) { + return false; + } + $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(); + break; + case "CharacterLevel": + if ($val > 99) { + $val = 99; + } + // level is edited in two places. + // byte 43 + $this->ByteReader->writeByte(43, $val); + // and in charstats + $this->setStat('level', $val); + + // now we have to set the experience stat for this level + // it's 1 level below as it starts from 0, for next level + // $val -= 1; + $sql = "SELECT {$this->cData['CharacterClass']} FROM experience WHERE level = '$val'"; + $res = PDO_FetchOne($sql); + $this->setStat('experience', $res); + break; + } + } + + 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)); + $stat = $id . $val; + $stats .= $stat; + } + + $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); + + // refresh this data + $data = $this->ByteReader->getData(); + // delete everything between GF---and---IF + $data = substr_replace($data, "", $gf, $len); + // pack hex bites into binary string + $packedbytes = (pack('H*', $bytes)); + // now insert new packed byte stat data between gf and if + $data = substr_replace($data, $packedbytes, 767, 0); + + $this->data = $data; + $this->save(); + + $filedata = file_get_contents($this->filePath); + $this->ByteReader = new D2ByteReader($filedata); + $this->data = $this->ByteReader->getData(); + } + + 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(); + + $cleanbits = substr($bits, 0, -11); + $stats->setBits($cleanbits); + $bits = $stats->getBits(); + $stats->rewind(); + $_offsets = []; + 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']); + } + $_offsets[0] = 9; + $offsets = null; + foreach ($_offsets as $k => $v) { + $_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; + $offsets[$_stat] = $v; + } + if ($stat == 'hitpoints' || $stat == 'maxhp' || $stat == 'mana' || $stat == 'maxmana' || $stat == 'stamina' || $stat == 'maxstamina') { + $val = (int) ($val << 8); + } + // << 8 multiplication, if the value is larger than what the stat can hold, set it to the max. + if ($val > $maxValues[$stat]) { + $val = $maxValues[$stat]; + } + $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(); + } + public function getQuestData($file) { $questsNorm = null; $questsNM = null; diff --git a/src/D2Functions.php b/src/D2Functions.php index 42b91c7..7bdd515 100755 --- a/src/D2Functions.php +++ b/src/D2Functions.php @@ -1,65 +1,64 @@ "; - var_dump($var); - //echo ""; - + //echo "
";
+    var_dump($var);
+    //echo "
"; // 'Content-Type: application/json'); // echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT); - die(); + die(); } function dump($var) { - //echo "
";
-	var_dump($var);
-	//echo "
"; - - //'Content-Type: application/json'); - //echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT); + //echo "
";
+    var_dump($var);
+    //echo "
"; + //'Content-Type: application/json'); + //echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT); } - function strtobits(string $str): string { $ret = ""; for ($i = 0; $i < strlen($str); ++$i) { @@ -79,25 +78,44 @@ function swapEndianness(string $hex) { return implode('', array_reverse(str_split($hex, 2))); } - -function setBit(int $n, int $p, bool $b){ - return ($b ? ($n | (1 << $p)) : ($n & ~(1 << $p)) ); +function setBit(int $n, int $p, bool $b) { + return ($b ? ($n | (1 << $p)) : ($n & ~(1 << $p)) ); } -function getBit(int $b, int $p){ +function getBit(int $b, int $p) { return intval(($b & (1 << $p)) !== 0); } + /** * Calculate D2S Checksum * @param $data * @return string */ -function checksum($data) : string { - $nSignature = 0; - foreach($data as $byte){ - $nSignature = ((($nSignature << 1) | ($nSignature >> 31)) + $byte) & 0xFFFFFFFF; - } - return swapEndianness(dechex($nSignature)); +//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 checksumFix(string $filePath) { + return trim(shell_exec("bin\d2scs.exe \"$filePath\"")); } /** @@ -117,76 +135,68 @@ function strposX($haystack, $needle, $number) { } } - function isBit(string $bit): int { return ((int) $bit ? 1 : 0 ); } function toBits($input): string { $output = ''; - if (is_string($input)){ - foreach(str_split($input) as $i){ + if (is_string($input)) { + foreach (str_split($input) as $i) { $output .= str_pad(decbin(ord($i)), 8, 0, STR_PAD_LEFT); } return $output; - } else if (is_int($input)){ + } else if (is_int($input)) { return str_pad(decbin($input), 8, 0, STR_PAD_LEFT); - } else if (is_array($input)){ + } else if (is_array($input)) { foreach ($input as $i) { $output .= tobits($i); } return $output; - } - + } } -function print_mem() -{ - /* Currently used memory */ - $mem_usage = memory_get_usage(); - - /* Peak memory usage */ - $mem_peak = memory_get_peak_usage(); +function print_mem() { + /* Currently used memory */ + $mem_usage = memory_get_usage(); - echo 'The script is now using: ' . round($mem_usage / 1024) . 'KB of memory.
'; - echo 'Peak usage: ' . round($mem_peak / 1024) . 'KB of memory.

'; + /* Peak memory usage */ + $mem_peak = memory_get_peak_usage(); + + echo 'D2Modder is now using: ' . round($mem_usage / 1024 / 1024) . 'MB RAM.
'; + echo 'Peak usage: ' . round($mem_peak / 1024 / 1024) . 'MB RAM.

'; } - -function rcopy($src, $dst) { +function rcopy($src, $dst) { // open the source directory - $dir = opendir($src); + $dir = opendir($src); // Make the destination directory if not exist - @mkdir($dst); + @mkdir($dst); // Loop through the files in source directory - while( $file = readdir($dir) ) { - if (( $file != '.' ) && ( $file != '..' )) { - if ( is_dir($src . '/' . $file) ) - { - rcopy($src . '/' . $file, $dst . '/' . $file); - } - else { - copy($src . '/' . $file, $dst . '/' . $file); - } - } - } + while ($file = readdir($dir)) { + if (( $file != '.' ) && ( $file != '..' )) { + if (is_dir($src . '/' . $file)) { + rcopy($src . '/' . $file, $dst . '/' . $file); + } else { + copy($src . '/' . $file, $dst . '/' . $file); + } + } + } closedir($dir); } - function rrmdir($src) { $dir = opendir($src); - while(false !== ( $file = readdir($dir)) ) { + while (false !== ( $file = readdir($dir))) { if (( $file != '.' ) && ( $file != '..' )) { $full = $src . '/' . $file; - if ( is_dir($full) ) { + if (is_dir($full)) { rrmdir($full); - } - else { + } else { unlink($full); } } } closedir($dir); rmdir($src); -} \ No newline at end of file +} diff --git a/src/footer.php b/src/footer.php index 3386e5b..4990113 100755 --- a/src/footer.php +++ b/src/footer.php @@ -23,4 +23,5 @@

Copyright HashCasper 2021 - All Rights Reserved

+

\ No newline at end of file diff --git a/src/tabs/Chars.php b/src/tabs/Chars.php index 503abcd..5592d15 100644 --- a/src/tabs/Chars.php +++ b/src/tabs/Chars.php @@ -194,11 +194,10 @@ EOT; if ($c->cData['Quests'][0]['Norm']["ToolsOfTheTrade"]) $a1q5 = "checked"; if ($c->cData['Quests'][0]['Norm']["SistersToTheSlaughter"]) $a1q6 = "checked"; - - - - - + $skills = ''; + foreach($c->cData['skills']['skills'] as $k => $skill){ + $skills .= ": {$skill['skill']}
"; + } // dump($c['Waypoints']); $tabContent .= << Level:
$radio + $skills + +

Quests

$quests diff --git a/test.php b/test.php index f849627..aa6878f 100644 --- a/test.php +++ b/test.php @@ -156,21 +156,40 @@ class D2ByteReader { } -$file = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s"; -$data = file_get_contents($file); +$filename = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s"; +$fileData = unpack('C*', file_get_contents($filename)); // open file and unpack +var_dump(checksum($fileData)); -$c = new D2ByteReader($data); -$bytes = $c->readh(643, 5); -$bits = $c->toBits($bytes); -$bits[4] = 1; -$bits[5] = 1; -$bits[8] = 1; -$newBytes = $c->bitsToHexString($bits); -$c->writeBytes(643, $newBytes); -$c->writeBytes(12, "00000000"); // zero old checksum -$newChecksum = checksum(unpack('C*', $c->getData())); // get new checksum -$c->writeBytes(12, $newChecksum); // write new checksum -file_put_contents($file, $c->getData()); // write bytestream to file \ No newline at end of file +//$file = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s"; +//$data = file_get_contents($file); +// +//$c = new D2ByteReader($data); +// +//$checksum = checksum(unpack('C*', $c->getData())); +// +//ddump($checksum); + +//$bytes = $c->readh(643, 5); +//$bits = $c->toBits($bytes); +// +//$bits[4] = 0; +//$bits[5] = 0; +//$bits[8] = 0; + +//$newBytes = $c->bitsToHexString($bits); +//$c->writeBytes(643, $newBytes); +// +//$c->writeBytes(12, "00000000"); // zero old checksum +// +//dump($c->readh(12, 4)); +// +//$newChecksum = checksum(unpack('C*', $c->getData())); // get new checksum +//$c->writeBytes(12, $newChecksum); // write new checksum +// +//dump($c->readh(12, 4)); +// +//file_put_contents($file, $c->getData()); // write bytestream to file +