mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2024-11-30 04:26:03 +00:00
latest, d2s stuff
This commit is contained in:
parent
e51e40175e
commit
f3b24de2a8
101
CharEditor.php
101
CharEditor.php
@ -14,6 +14,7 @@ require_once './src/D2Functions.php';
|
|||||||
require_once './src/D2ByteReader.php';
|
require_once './src/D2ByteReader.php';
|
||||||
require_once './src/D2BitReader.php';
|
require_once './src/D2BitReader.php';
|
||||||
require_once './src/D2Item.php';
|
require_once './src/D2Item.php';
|
||||||
|
require_once './src/D2Char.php';
|
||||||
|
|
||||||
define('DB_FILE', $_SESSION['modname'] . ".db");
|
define('DB_FILE', $_SESSION['modname'] . ".db");
|
||||||
PDO_Connect("sqlite:" . DB_FILE);
|
PDO_Connect("sqlite:" . DB_FILE);
|
||||||
@ -31,99 +32,33 @@ $namestr = PDO_FetchAssoc($sql);
|
|||||||
|
|
||||||
$sql = "SELECT ID,Stat,CSvBits FROM itemstatcost WHERE Saved=1";
|
$sql = "SELECT ID,Stat,CSvBits FROM itemstatcost WHERE Saved=1";
|
||||||
$ISCData = PDO_FetchAll($sql);
|
$ISCData = PDO_FetchAll($sql);
|
||||||
|
|
||||||
foreach ($ISCData as $k => $v) {
|
foreach ($ISCData as $k => $v) {
|
||||||
$ISC[$v['ID']] = $v;
|
$ISC[$v['ID']] = $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
//$filePath = "D:\Diablo II\MODS\ironman-dev\save\Aldur.d2s";
|
//$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\Lok.d2s";
|
||||||
//$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Pal.d2s";
|
//$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Pal.d2s";
|
||||||
//$filePath = "D:\Diablo II\MODS\MedianXL2012\save\Test.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
|
$filePath = "Test.d2s";
|
||||||
$if = strposX($data, 'if', 1);
|
$char = new D2Char($filePath);
|
||||||
$len = $if - $gf;
|
//$char->setAllSkills(56);
|
||||||
|
//$char->setSkill(1, 99);
|
||||||
$stats = new D2BitReader($ByteReader->toBits($ByteReader->readh($gf, $len)));
|
//$char->setChar("CharacterClass", 1); // 127
|
||||||
|
$char->setChar("CharacterLevel", 0);
|
||||||
$bits = $stats->getBits();
|
$char->setStat("strength", 30);
|
||||||
$cleanbits = substr($bits, 0, -11);
|
$char->setStat("energy", 30);
|
||||||
$stats->setBits($cleanbits);
|
$char->setStat("dexterity", 30);
|
||||||
|
$char->setStat("vitality", 30);
|
||||||
//$stats->rewind();
|
$char->setStat("mana", 120);
|
||||||
//foreach ($ISC as $i) {
|
$char->setStat("maxmana", 200);
|
||||||
// $stat = $i['Stat'];
|
$char->setStat("stamina", 80);
|
||||||
// $CSvBits = (int) $i['CSvBits'];
|
$char->setStat("maxstamina", 120);
|
||||||
//
|
|
||||||
// $id = hexdec($ByteReader->toBytesR($stats->readb(9)));
|
|
||||||
// $stats->skip($CSvBits);
|
|
||||||
// $ids[$id] = ($ISC[$id]);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
unset($char); // destroy $char so we can read it again after writing to it to get updated stats
|
||||||
|
|
||||||
$stats->rewind();
|
$char = new D2Char($filePath);
|
||||||
for($i=0; $i <= strlen($bits); $i++) {
|
var_dump($char->cData['stats']);
|
||||||
$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);
|
|
@ -62,8 +62,8 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE
|
|||||||
$_SESSION['modname'] = $lastUsedMod['modname'];
|
$_SESSION['modname'] = $lastUsedMod['modname'];
|
||||||
$_SESSION['path'] = $lastUsedMod['path'];
|
$_SESSION['path'] = $lastUsedMod['path'];
|
||||||
|
|
||||||
$sql = "SELECT theme FROM `D2Modder` WHERE `modname`='{$_SESSION['modname']}'";
|
$sql = "SELECT theme FROM `D2Modder` WHERE modname= :modname";
|
||||||
$res = PDO_FetchAll($sql);
|
$res = PDO_FetchAll($sql, ['modname' => $_SESSION['modname']]);
|
||||||
|
|
||||||
if ($res[0]['theme'] == 1) {
|
if ($res[0]['theme'] == 1) {
|
||||||
$css = 'dark.css';
|
$css = 'dark.css';
|
||||||
@ -88,6 +88,7 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE
|
|||||||
|
|
||||||
foreach ($charFiles as $charFile) {
|
foreach ($charFiles as $charFile) {
|
||||||
$charData[] = new D2Char($charFile); // $charData goes into chars.php tab
|
$charData[] = new D2Char($charFile); // $charData goes into chars.php tab
|
||||||
|
//$charData[] = $_charData->cData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -162,6 +163,8 @@ if (!isset($_SESSION['modname']) || (!file_exists(APP_DB)) || (!file_exists($_SE
|
|||||||
*
|
*
|
||||||
* Unique Items Form was posted here
|
* Unique Items Form was posted here
|
||||||
*
|
*
|
||||||
|
* TODO: Move this somewhre else, for fucks sake, why post here? That's just fucking stupid.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ($_POST['formtype'] == "uniqueitems") {
|
if ($_POST['formtype'] == "uniqueitems") {
|
||||||
|
Binary file not shown.
16
res/app.js
16
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,
|
// every time we change a prop dropdown,
|
||||||
//
|
//
|
||||||
|
@ -17,7 +17,7 @@ class D2BitReader {
|
|||||||
|
|
||||||
/* read X number of bits, like fread */
|
/* 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;
|
$bits = null;
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
||||||
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
||||||
@ -26,7 +26,11 @@ class D2BitReader {
|
|||||||
return $bits;
|
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;
|
$bits = null;
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
||||||
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
$str ? $bits .= $this->bits[$i] : $bits[] = $this->bits[$i];
|
||||||
@ -35,7 +39,7 @@ class D2BitReader {
|
|||||||
return strrev(str_pad($bits, 16, 0, STR_PAD_RIGHT));
|
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;
|
$bits = null;
|
||||||
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
for ($i = $this->offset; $i < $this->offset + $numBits; $i++) {
|
||||||
$bits .= $this->bits[$i];
|
$bits .= $this->bits[$i];
|
||||||
@ -83,6 +87,7 @@ class D2BitReader {
|
|||||||
public function getBits(): string {
|
public function getBits(): string {
|
||||||
return $this->bits;
|
return $this->bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBits(string $bits) {
|
public function setBits(string $bits) {
|
||||||
$this->bits = $bits;
|
$this->bits = $bits;
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,22 @@ class D2ByteReader {
|
|||||||
$this->data[$pos] = pack('H*', $byte);
|
$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() {
|
public function getData() {
|
||||||
return $this->data ? $this->data : false;
|
return $this->data ? $this->data : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setData($data){
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
public function getOffset(): int {
|
public function getOffset(): int {
|
||||||
return $this->offset;
|
return $this->offset;
|
||||||
}
|
}
|
||||||
|
212
src/D2Char.php
212
src/D2Char.php
@ -6,31 +6,40 @@ require_once 'D2BitReader.php';
|
|||||||
require_once 'D2Strings.php';
|
require_once 'D2Strings.php';
|
||||||
require_once 'D2Item.php';
|
require_once 'D2Item.php';
|
||||||
require_once 'D2ByteReader.php';
|
require_once 'D2ByteReader.php';
|
||||||
|
require_once 'D2Functions.php';
|
||||||
|
|
||||||
class D2Char {
|
class D2Char {
|
||||||
|
|
||||||
public $cData = null; // char data output
|
public $cData = null; // char data output
|
||||||
public $items = null; // char item data
|
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 $sData = null; // char file structure data
|
||||||
private $bData = null; // char binary data from d2s
|
private $bData = null; // char binary data from d2s
|
||||||
private $filePath = null; // .d2s file path
|
|
||||||
private $fp = null; // file pointer
|
private $fp = null; // file pointer
|
||||||
private $data = null; // full d2s file loaded in $data
|
private $data = null; // full d2s file loaded in $data
|
||||||
private $ByteReader = null; // put $data into bytereader
|
|
||||||
private $ISC = null;
|
private $ISC = null;
|
||||||
|
private $skillData = null;
|
||||||
|
|
||||||
|
public function save() {
|
||||||
|
file_put_contents($this->filePath, $this->data);
|
||||||
|
checksumFix($this->filePath);
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct($file) {
|
public function __construct($file) {
|
||||||
$this->sData = new D2CharStructureData();
|
$this->sData = new D2CharStructureData();
|
||||||
$this->filePath = $_SESSION['savepath'] . $file;
|
$this->filePath = $_SESSION['savepath'] . $file;
|
||||||
$this->fp = fopen($this->filePath, "r+b");
|
$this->fp = fopen($this->filePath, "r+b");
|
||||||
$this->data = file_get_contents($this->filePath);
|
$data = file_get_contents($this->filePath);
|
||||||
$this->ByteReader = new D2ByteReader($this->data);
|
$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);
|
$ISCData = PDO_FetchAll($sql);
|
||||||
|
|
||||||
foreach ($ISCData as $k => $v) {
|
foreach ($ISCData as $k => $v) {
|
||||||
$this->ISC[$v['ID']] = $v;
|
$this->ISC[$v['ID']] = $v;
|
||||||
|
$this->_ISC[$v['Stat']] = $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read offsets here from sData and put into $this->bData
|
// read offsets here from sData and put into $this->bData
|
||||||
@ -40,6 +49,18 @@ class D2Char {
|
|||||||
$this->bData[$k] = fread($this->fp, $v);
|
$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.
|
return $this->parseChar(); // end of parseChar() calls parseItems(), parseStats, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +106,8 @@ class D2Char {
|
|||||||
|
|
||||||
$skills = (unpack('l16', $this->bData[56]));
|
$skills = (unpack('l16', $this->bData[56]));
|
||||||
foreach ($skills as $skill) {
|
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]];
|
$cData['LeftmousebuttonskillID'] = $this->sData->skills[unpack('i', $this->bData[120])[1]];
|
||||||
@ -101,7 +123,7 @@ class D2Char {
|
|||||||
$onDifficulty['Normal'] = $x[0][0];
|
$onDifficulty['Normal'] = $x[0][0];
|
||||||
$onDifficulty['NM'] = $x[1][0];
|
$onDifficulty['NM'] = $x[1][0];
|
||||||
$onDifficulty['Hell'] = $x[2][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
|
// 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
|
// found in the character.map file, according to the difficulty being played. Not needed
|
||||||
//$cData['MapID'] = $this->bData[171];
|
//$cData['MapID'] = $this->bData[171];
|
||||||
@ -124,19 +146,58 @@ class D2Char {
|
|||||||
$this->cData = $cData;
|
$this->cData = $cData;
|
||||||
// parse stats
|
// parse stats
|
||||||
$this->parseStats();
|
$this->parseStats();
|
||||||
|
$this->cData['skills'] = $this->parseSkills();
|
||||||
|
|
||||||
unset($this->items);
|
unset($this->items);
|
||||||
unset($this->bData);
|
unset($this->bData);
|
||||||
unset($this->sData);
|
unset($this->sData);
|
||||||
unset($this->ByteReader);
|
|
||||||
unset($this->data);
|
|
||||||
unset($this->fp);
|
unset($this->fp);
|
||||||
unset($this->ISC);
|
|
||||||
|
|
||||||
return $this->cData;
|
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() {
|
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);
|
$if = strposX($this->data, 'if', 1);
|
||||||
@ -144,22 +205,21 @@ class D2Char {
|
|||||||
$stats = new D2BitReader($this->ByteReader->toBits($this->ByteReader->readh($gf, $len)));
|
$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);
|
$bytes = $this->ByteReader->toBytes($bits);
|
||||||
$bits = $stats->getBits();
|
|
||||||
|
|
||||||
$stats->rewind();
|
$stats->rewind();
|
||||||
for($i=0; $i <= strlen($bits); $i++) {
|
for ($i = 0; $i <= strlen($bits); $i++) {
|
||||||
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9)));
|
$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']);
|
$stats->skip($this->ISC[$id]['CSvBits']);
|
||||||
}
|
}
|
||||||
$ids[$id] = $id;
|
$ids[$id] = $id;
|
||||||
}
|
}
|
||||||
$stats->rewind();
|
$stats->rewind();
|
||||||
foreach($ids as $id){
|
foreach ($ids as $id) {
|
||||||
$stats->skip(9);
|
$stats->skip(9);
|
||||||
if($this->ISC[$id]['CSvBits'] !== NULL){
|
if ($this->ISC[$id]['CSvBits'] !== NULL) {
|
||||||
$val = $stats->readb($this->ISC[$id]['CSvBits']);
|
$val = $stats->readb($this->ISC[$id]['CSvBits']);
|
||||||
}
|
}
|
||||||
$stat = $this->ISC[$id]['Stat'];
|
$stat = $this->ISC[$id]['Stat'];
|
||||||
@ -176,6 +236,122 @@ class D2Char {
|
|||||||
$this->cData['stats'] = $values;
|
$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) {
|
public function getQuestData($file) {
|
||||||
$questsNorm = null;
|
$questsNorm = null;
|
||||||
$questsNM = null;
|
$questsNM = null;
|
||||||
|
@ -1,65 +1,64 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (C) 2021 Hash Borgir
|
Copyright (C) 2021 Hash Borgir
|
||||||
|
|
||||||
This file is part of D2Modder
|
This file is part of D2Modder
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with
|
Redistribution and use in source and binary forms, with
|
||||||
or without modification, are permitted provided that the
|
or without modification, are permitted provided that the
|
||||||
following conditions are met:
|
following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
* Redistributions of source code must retain the above
|
||||||
copyright notice, this list of conditions and the
|
copyright notice, this list of conditions and the
|
||||||
following disclaimer.
|
following disclaimer.
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
* Redistributions in binary form must reproduce the above
|
||||||
copyright notice, this list of conditions and the
|
copyright notice, this list of conditions and the
|
||||||
following disclaimer in the documentation and/or other
|
following disclaimer in the documentation and/or other
|
||||||
materials provided with the distribution.
|
materials provided with the distribution.
|
||||||
|
|
||||||
* This software must not be used for commercial purposes
|
* This software must not be used for commercial purposes
|
||||||
* without my consent. Any sales or commercial use are prohibited
|
* without my consent. Any sales or commercial use are prohibited
|
||||||
* without my express knowledge and consent.
|
* without my express knowledge and consent.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY!
|
but WITHOUT ANY WARRANTY!
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
function ddump($var) {
|
|
||||||
//echo "<pre>";
|
|
||||||
var_dump($var);
|
|
||||||
//echo "</pre>";
|
|
||||||
|
|
||||||
|
function ddump($var) {
|
||||||
|
//echo "<pre>";
|
||||||
|
var_dump($var);
|
||||||
|
//echo "</pre>";
|
||||||
// 'Content-Type: application/json');
|
// 'Content-Type: application/json');
|
||||||
// echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT);
|
// echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT);
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
function dump($var) {
|
function dump($var) {
|
||||||
//echo "<pre>";
|
//echo "<pre>";
|
||||||
var_dump($var);
|
var_dump($var);
|
||||||
//echo "</pre>";
|
//echo "</pre>";
|
||||||
|
//'Content-Type: application/json');
|
||||||
//'Content-Type: application/json');
|
//echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT);
|
||||||
//echo json_encode($var, JSON_INVALID_UTF8_IGNORE | JSON_PRETTY_PRINT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function strtobits(string $str): string {
|
function strtobits(string $str): string {
|
||||||
$ret = "";
|
$ret = "";
|
||||||
for ($i = 0; $i < strlen($str); ++$i) {
|
for ($i = 0; $i < strlen($str); ++$i) {
|
||||||
@ -79,25 +78,44 @@ function swapEndianness(string $hex) {
|
|||||||
return implode('', array_reverse(str_split($hex, 2)));
|
return implode('', array_reverse(str_split($hex, 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setBit(int $n, int $p, bool $b) {
|
||||||
function setBit(int $n, int $p, bool $b){
|
|
||||||
return ($b ? ($n | (1 << $p)) : ($n & ~(1 << $p)) );
|
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);
|
return intval(($b & (1 << $p)) !== 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate D2S Checksum
|
* Calculate D2S Checksum
|
||||||
* @param $data
|
* @param $data
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function checksum($data) : string {
|
//function checksum($data) {
|
||||||
$nSignature = 0;
|
// $nSignature = 0;
|
||||||
foreach($data as $byte){
|
// $checksum = 0;
|
||||||
$nSignature = ((($nSignature << 1) | ($nSignature >> 31)) + $byte) & 0xFFFFFFFF;
|
// foreach ($data as $k => $byte) {
|
||||||
}
|
//// if ($k == 12 || $k == 13 || $k == 14 || $k == 15) {
|
||||||
return swapEndianness(dechex($nSignature));
|
//// $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,55 +135,49 @@ function strposX($haystack, $needle, $number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function isBit(string $bit): int {
|
function isBit(string $bit): int {
|
||||||
return ((int) $bit ? 1 : 0 );
|
return ((int) $bit ? 1 : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
function toBits($input): string {
|
function toBits($input): string {
|
||||||
$output = '';
|
$output = '';
|
||||||
if (is_string($input)){
|
if (is_string($input)) {
|
||||||
foreach(str_split($input) as $i){
|
foreach (str_split($input) as $i) {
|
||||||
$output .= str_pad(decbin(ord($i)), 8, 0, STR_PAD_LEFT);
|
$output .= str_pad(decbin(ord($i)), 8, 0, STR_PAD_LEFT);
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
} else if (is_int($input)){
|
} else if (is_int($input)) {
|
||||||
return str_pad(decbin($input), 8, 0, STR_PAD_LEFT);
|
return str_pad(decbin($input), 8, 0, STR_PAD_LEFT);
|
||||||
} else if (is_array($input)){
|
} else if (is_array($input)) {
|
||||||
foreach ($input as $i) {
|
foreach ($input as $i) {
|
||||||
$output .= tobits($i);
|
$output .= tobits($i);
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_mem()
|
function print_mem() {
|
||||||
{
|
/* Currently used memory */
|
||||||
/* Currently used memory */
|
$mem_usage = memory_get_usage();
|
||||||
$mem_usage = memory_get_usage();
|
|
||||||
|
|
||||||
/* Peak memory usage */
|
/* Peak memory usage */
|
||||||
$mem_peak = memory_get_peak_usage();
|
$mem_peak = memory_get_peak_usage();
|
||||||
|
|
||||||
echo 'The script is now using: <strong>' . round($mem_usage / 1024) . 'KB</strong> of memory.<br>';
|
echo 'D2Modder is now using: <strong>' . round($mem_usage / 1024 / 1024) . 'MB</strong> RAM.<br>';
|
||||||
echo 'Peak usage: <strong>' . round($mem_peak / 1024) . 'KB</strong> of memory.<br><br>';
|
echo 'Peak usage: <strong>' . round($mem_peak / 1024 / 1024) . 'MB</strong> RAM.<br><br>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function rcopy($src, $dst) {
|
function rcopy($src, $dst) {
|
||||||
// open the source directory
|
// open the source directory
|
||||||
$dir = opendir($src);
|
$dir = opendir($src);
|
||||||
// Make the destination directory if not exist
|
// Make the destination directory if not exist
|
||||||
@mkdir($dst);
|
@mkdir($dst);
|
||||||
// Loop through the files in source directory
|
// Loop through the files in source directory
|
||||||
while( $file = readdir($dir) ) {
|
while ($file = readdir($dir)) {
|
||||||
if (( $file != '.' ) && ( $file != '..' )) {
|
if (( $file != '.' ) && ( $file != '..' )) {
|
||||||
if ( is_dir($src . '/' . $file) )
|
if (is_dir($src . '/' . $file)) {
|
||||||
{
|
|
||||||
rcopy($src . '/' . $file, $dst . '/' . $file);
|
rcopy($src . '/' . $file, $dst . '/' . $file);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
copy($src . '/' . $file, $dst . '/' . $file);
|
copy($src . '/' . $file, $dst . '/' . $file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,16 +185,14 @@ function rcopy($src, $dst) {
|
|||||||
closedir($dir);
|
closedir($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function rrmdir($src) {
|
function rrmdir($src) {
|
||||||
$dir = opendir($src);
|
$dir = opendir($src);
|
||||||
while(false !== ( $file = readdir($dir)) ) {
|
while (false !== ( $file = readdir($dir))) {
|
||||||
if (( $file != '.' ) && ( $file != '..' )) {
|
if (( $file != '.' ) && ( $file != '..' )) {
|
||||||
$full = $src . '/' . $file;
|
$full = $src . '/' . $file;
|
||||||
if ( is_dir($full) ) {
|
if (is_dir($full)) {
|
||||||
rrmdir($full);
|
rrmdir($full);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
unlink($full);
|
unlink($full);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,5 @@
|
|||||||
<!-- <h1 id="credits-">Credits:</h1>
|
<!-- <h1 id="credits-">Credits:</h1>
|
||||||
<p><a target="_blank" href="https://d2mods.info">Thanks Phrozen Keep! My favorite mod community since 2002!</a></p>-->
|
<p><a target="_blank" href="https://d2mods.info">Thanks Phrozen Keep! My favorite mod community since 2002!</a></p>-->
|
||||||
<p style="text-align: center">Copyright HashCasper 2021 - All Rights Reserved</p>
|
<p style="text-align: center">Copyright HashCasper 2021 - All Rights Reserved</p>
|
||||||
|
<p style="text-align: center"><?php print_mem(); ?></p>
|
||||||
</footer>
|
</footer>
|
@ -194,11 +194,10 @@ EOT;
|
|||||||
if ($c->cData['Quests'][0]['Norm']["ToolsOfTheTrade"]) $a1q5 = "checked";
|
if ($c->cData['Quests'][0]['Norm']["ToolsOfTheTrade"]) $a1q5 = "checked";
|
||||||
if ($c->cData['Quests'][0]['Norm']["SistersToTheSlaughter"]) $a1q6 = "checked";
|
if ($c->cData['Quests'][0]['Norm']["SistersToTheSlaughter"]) $a1q6 = "checked";
|
||||||
|
|
||||||
|
$skills = '';
|
||||||
|
foreach($c->cData['skills']['skills'] as $k => $skill){
|
||||||
|
$skills .= "<input style='width: 64px;' class='skill-$k skill' name='$k' type='number' min='1' max='99' value='{$skill['points']}'>: {$skill['skill']}<hr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// dump($c['Waypoints']);
|
// dump($c['Waypoints']);
|
||||||
$tabContent .= <<<EOT
|
$tabContent .= <<<EOT
|
||||||
@ -217,6 +216,9 @@ EOT;
|
|||||||
</select>
|
</select>
|
||||||
Level: <input style="border: 1px solid black;width: 54px;" type="number" id="CharacterLevel" value="{$c->cData['CharacterLevel']}"><br>
|
Level: <input style="border: 1px solid black;width: 54px;" type="number" id="CharacterLevel" value="{$c->cData['CharacterLevel']}"><br>
|
||||||
$radio
|
$radio
|
||||||
|
$skills
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col"><h2>Quests</h2>
|
<div class="col"><h2>Quests</h2>
|
||||||
$quests
|
$quests
|
||||||
|
47
test.php
47
test.php
@ -156,21 +156,40 @@ class D2ByteReader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$file = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s";
|
$filename = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s";
|
||||||
$data = file_get_contents($file);
|
$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
|
//$file = "D:\Diablo II\MODS\ironman-dev\save\Barb.d2s";
|
||||||
$newChecksum = checksum(unpack('C*', $c->getData())); // get new checksum
|
//$data = file_get_contents($file);
|
||||||
$c->writeBytes(12, $newChecksum); // write new checksum
|
//
|
||||||
file_put_contents($file, $c->getData()); // write bytestream to 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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user