mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2024-11-30 12:36:03 +00:00
114 lines
5.2 KiB
PHP
114 lines
5.2 KiB
PHP
<?php
|
|
|
|
require_once './src/D2Functions.php';
|
|
require_once './src/D2ByteReader.php';
|
|
require_once './src/D2BitReader.php';
|
|
$str = <<<EOT
|
|
__ __
|
|
`."._ _,",'
|
|
`. "-----, .-----" ,'
|
|
`. / \ ,'
|
|
\------. _ | |__ ,-.__L | _ _ ,---.
|
|
\ .--. \ \'-, | ,',.'. \ ._ \ | \'-'/ / .-. \
|
|
| | | | | | | J /__\ L | |_)( | | | f / \ l
|
|
| | | | | | | | | ] ] | .-. \ | | | , t \ / j
|
|
/ '--' / ,'_'. |.'_'. F F / |__)/ | / '--'/ \ '-' /
|
|
/_,----' " " | " " /,' "-----' | "-----' '---'
|
|
(' | |'" | |
|
|
_,-" "-._ _,-" "-._ (C) HCB https://im.stoned.io
|
|
<_____________> <_____________> https://d2mods.org
|
|
EOT;
|
|
$cbits = [
|
|
0 => 10, 1 => 10, 2 => 10, 3 => 10, 4 => 10, 5 => 8, 6 => 21, 7 => 21, 8 => 21, 9 => 21, 10 => 21,
|
|
11 => 21, 12 => 7, 13 => 32, 14 => 25, 15 => 25, 37 => 31, 39 => 31, 41 => 31, 43 => 31, 45 => 31,
|
|
183 => 31, 184 => 31, 185 => 31]; // CSvBits to skip
|
|
|
|
$exp = [
|
|
0, 500, 1500, 3750, 7875, 14175, 22680, 32886, 44396, 57715, 72144, 90180, 112725, 140906, 176132, 220165, 275207, 344008,
|
|
430010, 537513, 671891, 839864, 1049830, 1312287, 1640359, 2050449, 2563061, 3203826, 3902260, 4663553, 5493363, 6397855,
|
|
7383752, 8458379, 9629723, 10906488, 12298162, 13815086, 15468534, 17270791, 19235252, 21376515, 23710491, 26254525, 29027522,
|
|
32050088, 35344686, 38935798, 42850109, 47116709, 51767302, 56836449, 62361819, 68384473, 74949165, 82104680, 89904191, 98405658,
|
|
107672256, 117772849, 128782495, 140783010, 153863570, 168121381, 183662396, 200602101, 219066380, 239192444, 261129853, 285041630,
|
|
311105466, 339515048, 370481492, 404234916, 441026148, 481128591, 524840254, 572485967, 624419793, 681027665, 742730244, 809986056,
|
|
883294891, 963201521, 1050299747, 1145236814, 1248718217, 1361512946, 1484459201, 1618470619, 1764543065, 1923762030, 2097310703,
|
|
2286478756, 2492671933, 2717422497, 2962400612, 3229426756, 3520485254, 3837739017];
|
|
|
|
//$file = "D:\Diablo II\MODS\ironman-dev\save\Necro.d2s";
|
|
$file = $argv[1];
|
|
if (!file_exists($file))
|
|
die("$file does not exist!");
|
|
|
|
// create ByteReader object from file binary data
|
|
$BR = new D2ByteReader(file_get_contents($file));
|
|
$data = $BR->getData();
|
|
|
|
// offset 36
|
|
// 7 6 5 4 3 2 1 0
|
|
// unknown Expansion Character unknown Died Hardcore unknown
|
|
$statusByte = unpack('C', $data[36])[1];
|
|
$dBit = getBit($statusByte, 3);
|
|
|
|
// if Character is dead, then make it alive, reduce 5 levels as penalty
|
|
|
|
if ($dBit) {
|
|
// using {} for better readability
|
|
{
|
|
$gf = strposX($data, 'gf', 1) + 2; // find gf and skip it
|
|
$if = strposX($data, 'if', 1);
|
|
$len = $if - $gf;
|
|
// create bitstream
|
|
$stats = new D2BitReader($BR->toBits($BR->readh($gf, $len)));
|
|
// remove 0x1FF from end
|
|
$bits = $stats->getBits();
|
|
$cleanbits = substr($bits, 0, -11);
|
|
$stats->setBits($cleanbits);
|
|
$bits = $stats->getBits();
|
|
// rewind bitstream
|
|
$stats->rewind();
|
|
// get bit offsets for each stat
|
|
$offsets = [];
|
|
for ($i = 0; $i < count($cbits); $i++) {
|
|
$id = hexdec($BR->toBytesR($stats->readb(9)));
|
|
$offsets[$id] = $stats->getOffset();
|
|
$stats->skip($cbits[$id]);
|
|
}
|
|
$offsets[0] = 9;
|
|
// get current character level
|
|
$level = unpack('C', $data[43])[1];
|
|
$stats->seek($offsets[12]);
|
|
$_level = hexdec($BR->toBytesR($stats->readb(7)));
|
|
// reduce current character level by 5, no penalty if < 6
|
|
if ($_level >= 80) {
|
|
$level -= 10;
|
|
} else if ($_level >= 5 || $level <= 80) {
|
|
$level -= 5;
|
|
} else if ($_level <= 5) {
|
|
$level = 1;
|
|
}
|
|
}
|
|
$data[43] = pack('C', $level);
|
|
$statusByteNew = setBit($statusByte, 3, 0); // make character alive
|
|
$data[36] = pack('C', $statusByteNew); // make character alive
|
|
|
|
$bitsToWriteLevel = strrev(str_pad(decbin(intval($level)), $cbits[12], 0, STR_PAD_LEFT));
|
|
$bitsToWriteExp = strrev(str_pad(decbin(intval($exp[$level])), $cbits[13], 0, STR_PAD_LEFT));
|
|
|
|
$_newBitsTemp = $stats->writeBits($bits, $bitsToWriteLevel, $offsets[12]);
|
|
$newBits = $stats->writeBits($_newBitsTemp, $bitsToWriteExp, $offsets[13]) . "11111111100";
|
|
$bytes = $BR->toBytes($newBits);
|
|
|
|
$BR->setData($data);
|
|
$BR->writeBytes($gf, $bytes);
|
|
$BR->writeBytes(12, "00000000");
|
|
$checksum = checksum(unpack('C*', $BR->getData()));
|
|
$BR->writeBytes(12, $checksum);
|
|
$data = $BR->getData();
|
|
file_put_contents($file, $data);
|
|
|
|
echo "<pre>$str\n\n\nCharacter is now alive. Go take some mushrooms!\n";
|
|
echo "Previous Level: $_level\n";
|
|
echo "Revive Penalty: " . $_level - $level . "\n";
|
|
echo "New Level: $level\n";
|
|
} else {
|
|
echo "<pre>$str\n\n\nCharacter is not dead. Have you been taking mushrooms lately?";
|
|
} |