D2S Editor Pretty much finished, seems to be working 100%

This commit is contained in:
Hash Borgir 2023-06-03 23:38:00 -06:00
parent dc7e046077
commit ad2e7c2c0b
6 changed files with 397 additions and 268 deletions

View File

@ -376,12 +376,25 @@ $(document).ready(function () {
}); });
}); });
$(".form-check-input").click(function () {
var $checkbox = $(this);
var currentValue = $checkbox.val();
// Toggle the value between 1 and 0
var newValue = currentValue === '1' ? '0' : '1';
// Update the value of the checkbox
$checkbox.val(newValue);
});
// Get the value of the input named "filePath" // Get the value of the input named "filePath"
function constructURL(cmd, name, value, filePath) { function constructURL(cmd, name, value, filePath) {
return "/saveCharacter.php?cmd=" + cmd + "&name=" + name + "&value=" + value + "&filePath=" + filePath; return "/saveCharacter.php?cmd=" + cmd + "&name=" + name + "&value=" + value + "&filePath=" + filePath;
} }
$(".charform input[name='Difficulty'], .charform .skill, #CharacterName, #CharacterClass, #CharacterLevel, #CharacterClass, .stats input").change(function () { $(".charform input[name='Difficulty'], .charform .skill, #CharacterName, #CharacterClass, #CharacterLevel, #CharacterClass, .stats input, .form-check-input").change(function () {
var name = $(this).attr("name"); var name = $(this).attr("name");
var newValue = $(this).val(); var newValue = $(this).val();
@ -395,22 +408,27 @@ $(document).ready(function () {
console.log(url); console.log(url);
console.log(newValue) console.log(newValue)
$.get(url, function (response) { $.get(url, function (response) {
if (cmd == 'CharacterName') { if (cmd == 'CharacterName') {
location.reload(); location.reload();
} }
console.log(response); console.log(response);
}); });
}); });
// colorize the acts
var acts = ['Act 1', 'Act 2', 'Act 3', 'Act 4', 'Act 5'];
for (var i = 0; i < acts.length; i++) {
var act = acts[i];
var className = 'act' + (i + 1);
// Find the checkbox with a label containing the act
$('input[type="checkbox"] + label:contains("' + act + '")').each(function () {
// Add a class to the parent div
$(this).parent().addClass(className);
});
}
});// end document.ready });// end document.ready

View File

@ -332,3 +332,24 @@ hr.style-four {
border: 0; border: 0;
box-shadow: inset 0 12px 12px -12px rgba(0, 0, 0, 0.5); box-shadow: inset 0 12px 12px -12px rgba(0, 0, 0, 0.5);
} }
.act1 {
border: 1px solid #ddd;
background: #d0fffe;
}
.act2 {
border: 1px solid #ddd;
background: #fffddb;
}
.act3 {
border: 1px solid #ddd;
background: #e4ffde;
}
.act4 {
border: 1px solid #ddd;
background: #ffd3fd;
}
.act5 {
border: 1px solid #ddd;
background: #ffe7d3;
}

View File

@ -51,133 +51,6 @@ $cmd = $g['cmd'];
// Get the file path from the POST data and replace backslashes / // Get the file path from the POST data and replace backslashes /
$filePath = $g['filePath']; $filePath = $g['filePath'];
//$filePath = str_replace("\\", "\\\\", $filePath); //$filePath = str_replace("\\", "\\\\", $filePath);
// Handle the WP check/uncheck
if ($cmd == "wp") {
$diff = $g['diff'];
if ($diff == "Norm") {
$offset = 643;
}
if ($diff == "NM") {
$offset = 667;
}
if ($diff == "Hell") {
$offset = 691;
}
/*
array (size=5)
'cmd' => string 'wp' (length=2)
'name' => string '1' (length=1)
'value' => string '1' (length=1)
'filePath' => string 'D:\\Diablo II\\MODS\\ironman-dev\\save\\Sorc.d2s' (length=48)
'diff' => string 'Norm' (length=4)
*/
$fileContents = file_get_contents($filePath); // Read the contents of the file
$ByteReader = new D2ByteReader($fileContents); // Create a new instance of D2ByteReader with the file data
$fileData = $ByteReader->getData(); // Get the data from the ByteReader instance
$wpBytes = $ByteReader->read($offset, 5, 1);
$wpBytesToBits = $ByteReader->toBits($wpBytes);
$BitReader = new D2BitReader($wpBytesToBits);
$BitReader->setBit($g['name'], $g['value']);
$newBits = $BitReader->getBits();
$newBitsToBytes = $ByteReader->bitsToHexString($newBits);
$ByteReader->writeBytes($offset, $newBitsToBytes);
$newFileData = $ByteReader->getData();
$fileSaved = file_put_contents($filePath, $newFileData);
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
if ($fileSaved) {
echo "Success";
} else {
echo "Fail";
}
}
/*
* array (size=5)
'cmd' => string 'q' (length=1)
'name' => string 'Sisters_Burial_Grounds' (length=29)
'value' => string '1' (length=1)
'filePath' => string 'D:\\Diablo II\\MODS\\ironman-dev\\save\\Sorc.d2s' (length=48)
'diff' => string 'Norm' (length=4)
At each quest offset, read a short, 2 bytes.
347 => 'Den_Of_Evil',
349 => 'Sisters_Burial_Grounds',
351 => 'Tools_Of_The_Trade',
353 => 'The_Search_For_Cain',
355 => 'The_Forgotten_Tower',
357 => 'Sisters_To_The_Slaughter',
Each short is 16 bytes.
*
* 0xFEFF = 11111110 11111111
* Short #0 Den of Evil Bit 4 is set when you enter the Den.
*/
if ($cmd == "q") {
$diff = $g['diff'];
if ($diff == "Norm") {
$qArray = array_flip($csData->qNorm);
$questOffset = $qArray[$g['name']];
}
if ($diff == "NM") {
$qArray = array_flip($csData->qNM);
$questOffset = $qArray[$g['name']];
}
if ($diff == "Hell") {
$qArray = array_flip($csData->qHell);
$questOffset = $qArray[$g['name']];
}
// Open the file in binary mode for both reading and writing
$fp = fopen($filePath, "rb+");
if ($g['value']) {
// Set the file pointer position to the quest offset
fseek($fp, $questOffset);
// Write the byte value 0xFE at the current position
fwrite($fp, pack('C', 0xFE));
// Move the file pointer to the next position
fseek($fp, $questOffset + 1);
// Write the byte value 0xFF at the current position
fwrite($fp, pack('C', 0xFF));
echo "Quest Just Finished, Collect Reward!";
} else {
// Set the file pointer position to the quest offset
fseek($fp, $questOffset);
// Write the byte value 0xFE at the current position
fwrite($fp, pack('C', 0x00));
// Move the file pointer to the next position
fseek($fp, $questOffset + 1);
// Write the byte value 0xFF at the current position
fwrite($fp, pack('C', 0x00));
echo "Quest Not Started Yet!";
}
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
fclose($fp);
}
$cmd = $_GET['cmd']; $cmd = $_GET['cmd'];
$name = $_GET['name']; $name = $_GET['name'];
@ -220,18 +93,21 @@ switch ($cmd) {
// handle difficulty wierdly // handle difficulty wierdly
case "Normal": case "Normal":
$char->setChar("Difficulty", $value); $char->setChar("CharacterProgression", $value);
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath"; echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break; break;
case "NM": case "Finished Normal":
$char->setChar("Difficulty", $value); $char->setChar("CharacterProgression", $value);
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath"; echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break; break;
case "Hell": case "Finished Nightmare":
$char->setChar("Difficulty", $value); $char->setChar("CharacterProgression", $value);
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break;
case "Finished Hell":
$char->setChar("CharacterProgression", $value);
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath"; echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break; break;
// skills // skills
case "skills": case "skills":
//var_dump($char->cData); //var_dump($char->cData);
@ -299,6 +175,147 @@ switch ($cmd) {
$char->setStat("maxstamina", $value); // Set the "maxstamina" stat to the provided value $char->setStat("maxstamina", $value); // Set the "maxstamina" stat to the provided value
echo "Handling maxstamina command - Value: $value, File Path: $filePath"; // Display a message indicating the handling of the maxstamina command echo "Handling maxstamina command - Value: $value, File Path: $filePath"; // Display a message indicating the handling of the maxstamina command
break; break;
case "Died":
$char->setChar("CharacterStatus", "Died", $value); // Set the "CharacterStatusDied" value to the provided value
echo "Handling Died command - Value: $value, File Path: $filePath"; // Display a message indicating the handling of the Died command
break;
case "Expansion":
$char->setChar("CharacterStatus", "Expansion", $value); // Set the "CharacterStatusExpansion" value to the provided value
echo "Handling Expansion command - Value: $value, File Path: $filePath"; // Display a message indicating the handling of the Expansion command
break;
case "Hardcore":
$char->setChar("CharacterStatus", "Hardcore", $value); // Set the "CharacterStatusHardcore" value to the provided value
echo "Handling Hardcore command - Value: $value, File Path: $filePath"; // Display a message indicating the handling of the Hardcore command
break;
// Handle the WP check/uncheck
case "wp":
$diff = $g['diff'];
if ($diff == "Norm") {
$offset = 643;
}
if ($diff == "NM") {
$offset = 667;
}
if ($diff == "Hell") {
$offset = 691;
}
/*
array (size=5)
'cmd' => string 'wp' (length=2)
'name' => string '1' (length=1)
'value' => string '1' (length=1)
'filePath' => string 'D:\\Diablo II\\MODS\\ironman-dev\\save\\Sorc.d2s' (length=48)
'diff' => string 'Norm' (length=4)
*/
$fileContents = file_get_contents($filePath); // Read the contents of the file
$ByteReader = new D2ByteReader($fileContents); // Create a new instance of D2ByteReader with the file data
$fileData = $ByteReader->getData(); // Get the data from the ByteReader instance
$wpBytes = $ByteReader->read($offset, 5, 1);
$wpBytesToBits = $ByteReader->toBits($wpBytes);
$BitReader = new D2BitReader($wpBytesToBits);
$BitReader->setBit($g['name'], $g['value']);
$newBits = $BitReader->getBits();
$newBitsToBytes = $ByteReader->bitsToHexString($newBits);
$ByteReader->writeBytes($offset, $newBitsToBytes);
$newFileData = $ByteReader->getData();
$fileSaved = file_put_contents($filePath, $newFileData);
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
if ($fileSaved) {
echo "Success";
} else {
echo "Fail";
}
break;
/*
* array (size=5)
'cmd' => string 'q' (length=1)
'name' => string 'Sisters_Burial_Grounds' (length=29)
'value' => string '1' (length=1)
'filePath' => string 'D:\\Diablo II\\MODS\\ironman-dev\\save\\Sorc.d2s' (length=48)
'diff' => string 'Norm' (length=4)
At each quest offset, read a short, 2 bytes.
347 => 'Den_Of_Evil',
349 => 'Sisters_Burial_Grounds',
351 => 'Tools_Of_The_Trade',
353 => 'The_Search_For_Cain',
355 => 'The_Forgotten_Tower',
357 => 'Sisters_To_The_Slaughter',
Each short is 16 bytes.
*
* 0xFEFF = 11111110 11111111
* Short #0 Den of Evil Bit 4 is set when you enter the Den.
*/
case "q":
$diff = $g['diff'];
if ($diff == "Norm") {
$qArray = array_flip($csData->qNorm);
$questOffset = $qArray[$g['name']];
}
if ($diff == "NM") {
$qArray = array_flip($csData->qNM);
$questOffset = $qArray[$g['name']];
}
if ($diff == "Hell") {
$qArray = array_flip($csData->qHell);
$questOffset = $qArray[$g['name']];
}
// Open the file in binary mode for both reading and writing
$fp = fopen($filePath, "rb+");
if ($g['value']) {
// Set the file pointer position to the quest offset
fseek($fp, $questOffset);
// Write the byte value 0xFE at the current position
fwrite($fp, pack('C', 0xFE));
// Move the file pointer to the next position
fseek($fp, $questOffset + 1);
// Write the byte value 0xFF at the current position
fwrite($fp, pack('C', 0xFF));
echo "Quest Just Finished, Collect Reward!";
} else {
// Set the file pointer position to the quest offset
fseek($fp, $questOffset);
// Write the byte value 0xFE at the current position
fwrite($fp, pack('C', 0x00));
// Move the file pointer to the next position
fseek($fp, $questOffset + 1);
// Write the byte value 0xFF at the current position
fwrite($fp, pack('C', 0x00));
echo "Quest Not Started Yet!";
}
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
fclose($fp);
break;
// default command // default command
default: default:

View File

@ -177,13 +177,19 @@ WHERE sk.charclass = '$class'";
if ($cData['CharacterStatus'] == 'Hardcore Expansion') { if ($cData['CharacterStatus'] == 'Hardcore Expansion') {
$cData['CharacterProgression'] = $this->sData->characterProgressionExpHC[$progression]; $cData['CharacterProgression'] = $this->sData->characterProgressionExpHC[$progression];
} }
if ($cData['CharacterStatus'] == "Expansion") { if (str_contains($cData['CharacterStatus'], "Expansion")) {
$cData['CharacterProgression'] = $this->sData->characterProgressionExp[$progression]; $cData['CharacterProgression'] = $this->sData->characterProgressionExp[$progression];
$cData['CharacterStatusExpansion'] = 1;
} }
if ($cData['CharacterStatus'] == "Hardcore") { if (str_contains($cData['CharacterStatus'], "Hardcore")) {
$cData['CharacterProgression'] = $this->sData->characterProgressionClassicHC[$progression]; $cData['CharacterProgression'] = $this->sData->characterProgressionClassicHC[$progression];
$cData['CharacterStatusHardcore'] = 1;
} }
if (str_contains($cData['CharacterStatus'], "Died")) {
$cData['CharacterProgression'] = $this->sData->characterProgressionClassicHC[$progression];
$cData['CharacterStatusDied'] = 1;
}
$cData['CharacterClass'] = $this->sData->class[unpack('C', $this->bData[40])[1]]; $cData['CharacterClass'] = $this->sData->class[unpack('C', $this->bData[40])[1]];
$cData['CharacterLevel'] = unpack('C', $this->bData[43])[1]; $cData['CharacterLevel'] = unpack('C', $this->bData[43])[1];
$cData['Lastplayed'] = gmdate("Y-m-d\TH:i:s\Z", unpack('L', $this->bData[48])[0]); $cData['Lastplayed'] = gmdate("Y-m-d\TH:i:s\Z", unpack('L', $this->bData[48])[0]);
@ -319,24 +325,53 @@ WHERE sk.charclass = '$class'";
$len = $if - $gf; $len = $if - $gf;
$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();
$bytes = $this->ByteReader->toBytes($bits); $bytes = $this->ByteReader->toBytes($bits);
// var_dump($bits);
// // Split the bits into 8-bit pieces
// var_dump(str_split($bits, 8));
/*
* CSvBits for Example, how many bits they store
Stat ID CSvBits
strength 0 10
energy 1 10
dexterity 2 10
vitality 3 10
statpts 4 10
newskills 5 8
hitpoints 6 21
maxhp 7 21
mana 8 21
maxmana 9 21
stamina 10 21
maxstamina 11 21
level 12 7
experience 13 32
gold 14 25
goldbank 15 25
*/
$stats->rewind(); $stats->rewind();
$ids = []; // Array to store the encountered stat IDs $ids = []; // Array to store the encountered stat IDs
// Iterate over the stats and collect their IDs // Iterate over the stats and collect their IDs
for ($i = 0; $i <= count($this->ISC); $i++) { for ($i = 0; $i <= count($this->ISC); $i++) {
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9))); //var_dump("Offset Before Starting: " . $stats->getOffset());
$id = hexdec($this->ByteReader->toBytesR($stats->readb(9))); // read 9 bits for stat id
// Skip the bits corresponding to the stat if needed //var_dump("$id Stat Done: ". $stats->getOffset());
// if ISC saves the stat, meaning CSVBits is set, it means it saves that my bits for this stat
// then we can skip that many number of bits, so we can get the next stat id
if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') { if ($this->ISC[$id]['CSvBits'] !== NULL && $this->ISC[$id]['CSvBits'] !== '') {
$stats->skip($this->ISC[$id]['CSvBits']); $stats->skip($this->ISC[$id]['CSvBits']);
//var_dump("Offset After Skipping Bits for $id: ". $stats->getOffset());
} }
$ids[$id] = $id; // Store the ID in the array $ids[$id] = $id; // Store the ID in the array
} }
//ddump($ids);
$stats->rewind(); $stats->rewind();
$values = []; // Array to store the parsed stat values $values = []; // Array to store the parsed stat values
@ -351,6 +386,9 @@ WHERE sk.charclass = '$class'";
$values[$stat] = hexdec($this->ByteReader->toBytesR($val)); $values[$stat] = hexdec($this->ByteReader->toBytesR($val));
} }
} }
//ddump($values);
// Perform additional calculations or conversions on specific stats // Perform additional calculations or conversions on specific stats
$values['hitpoints'] = (int) round($values['hitpoints'] >> 11); $values['hitpoints'] = (int) round($values['hitpoints'] >> 11);

View File

@ -182,33 +182,33 @@ class D2CharStructureData {
*/ */
public $qNorm = [ public $qNorm = [
//345 => 'introWarriv', //345 => 'introWarriv',
347 => 'Den_Of_Evil', 347 => 'Act 1 - Den_Of_Evil',
349 => 'Sisters_Burial_Grounds', 349 => 'Act 1 - Sisters_Burial_Grounds',
351 => 'Tools_Of_The_Trade', 351 => 'Act 1 - Tools_Of_The_Trade',
353 => 'The_Search_For_Cain', 353 => 'Act 1 - The_Search_For_Cain',
355 => 'The_Forgotten_Tower', 355 => 'Act 1 - The_Forgotten_Tower',
357 => 'Sisters_To_The_Slaughter', 357 => 'Act 1 - Sisters_To_The_Slaughter',
//359 => 'traveledToAct2', //359 => 'traveledToAct2',
//361 => 'introJerhyn', //361 => 'introJerhyn',
363 => 'Radaments_Lair', 363 => 'Act 2 - Radaments_Lair',
365 => 'TheHoradric_Staff', 365 => 'Act 2 - TheHoradric_Staff',
367 => 'Tainted_Sun', 367 => 'Act 2 - Tainted_Sun',
369 => 'Arcane_Sanctuary', 369 => 'Act 2 - Arcane_Sanctuary',
371 => 'The_Summoner', 371 => 'Act 2 - The_Summoner',
373 => 'The_Seven_Tombs', 373 => 'Act 2 - The_Seven_Tombs',
//375 => 'traveledToAct3', //375 => 'traveledToAct3',
//377 => 'introHratli', //377 => 'introHratli',
379 => 'LamEsens_Tome', 379 => 'Act 3 - LamEsens_Tome',
381 => 'Khalims_Will', 381 => 'Act 3 - Khalims_Will',
383 => 'Blade_Of_The_Old_Religion', 383 => 'Act 3 - Blade_Of_The_Old_Religion',
385 => 'The_Golden_Bird', 385 => 'Act 3 - The_Golden_Bird',
387 => 'The_Blackened_Temple', 387 => 'Act 3 - The_Blackened_Temple',
389 => 'The_Guardian', 389 => 'Act 3 - The_Guardian',
//391 => 'traveledtoAct4', //391 => 'traveledtoAct4',
//393 => 'introToAct4', //393 => 'introToAct4',
395 => 'The_Fallen_Angel', 395 => 'Act 4 - The_Fallen_Angel',
397 => 'Terrors_End', 397 => 'Act 4 - Terrors_End',
399 => 'Hell_Forge', 399 => 'Act 4 - Hell_Forge',
//401 => 'traveledToAct5', //401 => 'traveledToAct5',
//403 => 'empty31', //403 => 'empty31',
//405 => 'empty32', //405 => 'empty32',
@ -216,12 +216,12 @@ class D2CharStructureData {
//409 => 'completedTerrorsEnd', //409 => 'completedTerrorsEnd',
//411 => 'empty21', //411 => 'empty21',
//413 => 'empty22', //413 => 'empty22',
415 => 'Siege_On_Harrogath', 415 => 'Act 5 - Siege_On_Harrogath',
417 => 'Rescue_On_MountArreat', 417 => 'Act 5 - Rescue_On_MountArreat',
419 => 'Prison_Of_Ice', 419 => 'Act 5 - Prison_Of_Ice',
421 => 'Betrayal_Of_Harrogath', 421 => 'Act 5 - Betrayal_Of_Harrogath',
423 => 'Rite_Of_Passage', 423 => 'Act 5 - Rite_Of_Passage',
425 => 'Eve_Of_Destruction', 425 => 'Act 5 - Eve_Of_Destruction',
// read 425, pointer at 427, + 14 = 441 qNM offset // read 425, pointer at 427, + 14 = 441 qNM offset
]; ];
@ -230,33 +230,33 @@ class D2CharStructureData {
*/ */
public $qNM = [ public $qNM = [
//441 => 'introWarrivNM', //441 => 'introWarrivNM',
443 => 'Den_Of_Evil_NM', 443 => 'Act 1 - Den_Of_Evil_NM',
445 => 'Sisters_Burial_Grounds_NM', 445 => 'Act 1 - Sisters_Burial_Grounds_NM',
447 => 'Tools_Of_The_Trade_NM', 447 => 'Act 1 - Tools_Of_The_Trade_NM',
449 => 'The_Search_For_Cain_NM', 449 => 'Act 1 - The_Search_For_Cain_NM',
451 => 'The_Forgotten_Tower_NM', 451 => 'Act 1 - The_Forgotten_Tower_NM',
453 => 'Sisters_To_The_Slaughter_NM', 453 => 'Act 1 - Sisters_To_The_Slaughter_NM',
//455 => 'traveledToAct2', //455 => 'traveledToAct2',
//457 => 'introJerhyn', //457 => 'introJerhyn',
459 => 'Radaments_Lair_NM', 459 => 'Act 2 - Radaments_Lair_NM',
461 => 'The_Horadric_Staff_NM', 461 => 'Act 2 - The_Horadric_Staff_NM',
463 => 'Tainted_Sun_NM', 463 => 'Act 2 - Tainted_Sun_NM',
465 => 'Arcane_Sanctuary_NM', 465 => 'Act 2 - Arcane_Sanctuary_NM',
467 => 'The_Summoner_NM', 467 => 'Act 2 - The_Summoner_NM',
469 => 'The_SevenTombs_NM', 469 => 'Act 2 - The_SevenTombs_NM',
//471 => 'traveledToAct3', //471 => 'traveledToAct3',
//473 => 'introHratli', //473 => 'introHratli',
475 => 'Lam_Esens_Tome_NM', 475 => 'Act 3 - Lam_Esens_Tome_NM',
477 => 'Khalims_Will_NM', 477 => 'Act 3 - Khalims_Will_NM',
479 => 'Blade_Of_The_OldReligion_NM', 479 => 'Act 3 - Blade_Of_The_OldReligion_NM',
481 => 'The_Golden_Bird_NM', 481 => 'Act 3 - The_Golden_Bird_NM',
483 => 'The_Blackened_Temple_NM', 483 => 'Act 3 - The_Blackened_Temple_NM',
485 => 'The_Guardian_NM', 485 => 'Act 3 - The_Guardian_NM',
//487 => 'traveledtoAct4', //487 => 'traveledtoAct4',
//489 => 'introToAct4', //489 => 'introToAct4',
491 => 'The_Fallen_Angel_NM', 491 => 'Act 4 - The_Fallen_Angel_NM',
493 => 'Terrors_End_NM', 493 => 'Act 4 - Terrors_End_NM',
495 => 'Hell_Forge_NM', 495 => 'Act 4 - Hell_Forge_NM',
//497 => 'traveledToAct5', //497 => 'traveledToAct5',
//499 => 'empty31', //499 => 'empty31',
//501 => 'empty32', //501 => 'empty32',
@ -264,12 +264,12 @@ class D2CharStructureData {
//505 => 'completedTerrorsEnd', //505 => 'completedTerrorsEnd',
//507 => 'empty21', //507 => 'empty21',
//509 => 'empty22', //509 => 'empty22',
511 => 'Siege_On_Harrogath', 511 => 'Act 5 - Siege_On_Harrogath',
513 => 'Rescue_On_MountArreat', 513 => 'Act 5 - Rescue_On_MountArreat',
515 => 'Prison_Of_Ice', 515 => 'Act 5 - Prison_Of_Ice',
517 => 'Betrayal_Of_Harrogath', 517 => 'Act 5 - Betrayal_Of_Harrogath',
519 => 'Rite_Of_Passage', 519 => 'Act 5 - Rite_Of_Passage',
521 => 'Eve_Of_Destruction', 521 => 'Act 5 - Eve_Of_Destruction',
// read 521, pointer at 523, + 14 = 537 qHell offset // read 521, pointer at 523, + 14 = 537 qHell offset
]; ];
@ -278,46 +278,46 @@ class D2CharStructureData {
*/ */
public $qHell = [ public $qHell = [
//537 => 'introWarriv', //537 => 'introWarriv',
539 => 'Den_Of_Evil_Hell', 539 => 'Act 1 - Den_Of_Evil_Hell',
541 => 'Sisters_Burial_Grounds_Hell', 541 => 'Act 1 - Sisters_Burial_Grounds_Hell',
543 => 'Tools_Of_The_Trade_Hell', 543 => 'Act 1 - Act 5 - Tools_Of_The_Trade_Hell',
545 => 'The_Search_For_Cain_Hell', 545 => 'Act 1 - The_Search_For_Cain_Hell',
547 => 'The_Forgotten_Tower_Hell', 547 => 'Act 1 - The_Forgotten_Tower_Hell',
549 => 'Sisters_To_The_Slaughter_Hell', 549 => 'Act 1 - Sisters_To_The_Slaughter_Hell',
//551 => 'traveledToAct2', //551 => 'traveledToAct2',
//553 => 'introJerhyn', //553 => 'introJerhyn',
555 => 'Radaments_Lair_Hell', 555 => 'Act 2 - Radaments_Lair_Hell',
557 => 'The_Horadric_Staff_Hell', 557 => 'Act 2 - The_Horadric_Staff_Hell',
559 => 'Tainted_Sun_Hell', 559 => 'Act 2 - Tainted_Sun_Hell',
561 => 'Arcane_Sanctuary_Hell', 561 => 'Act 2 - Arcane_Sanctuary_Hell',
563 => 'The_Summoner_Hell', 563 => 'Act 2 - The_Summoner_Hell',
565 => 'The_SevenTombs_Hell', 565 => 'Act 2 - The_SevenTombs_Hell',
//567 => 'traveledToAct3', //567 => 'traveledToAct3',
//569 => 'introHratli', //569 => 'introHratli',
571 => 'Lam_Esens_Tome_Hell', 571 => 'Act 3 - Lam_Esens_Tome_Hell',
573 => 'KhalimsWill_Hell', 573 => 'Act 3 - KhalimsWill_Hell',
575 => 'Blade_Of_The_Old_Religion_Hell', 575 => 'Act 3 - Blade_Of_The_Old_Religion_Hell',
577 => 'The_Golden_Bird_Hell', 577 => 'Act 3 - The_Golden_Bird_Hell',
579 => 'The_Blackened_Temple_Hell', 579 => 'Act 3 - The_Blackened_Temple_Hell',
581 => 'The_Guardian_Hell', 581 => 'Act 3 - The_Guardian_Hell',
//583 => 'traveledtoAct4', //583 => 'traveledtoAct4',
//585 => 'introToAct4', //585 => 'introToAct4',
587 => 'The_Fallen_Angel_Hell', 587 => 'Act 4 - The_Fallen_Angel_Hell',
589 => 'Terrors_End_Hell', 589 => 'Act 4 - Terrors_End_Hell',
591 => 'Hell_Forge_Hell', 591 => 'Act 4 - Hell_Forge_Hell',
//593 => 'traveledToAct5', //593 => 'traveledToAct5',
//595 => 'empty31', //595 => 'empty31',
//597 => 'empty32', //597 => 'empty32',
//599 => 'empty33', //599 => 'empty33',
601 => 'completedTerrorsEnd', //601 => 'completedTerrorsEnd',
//603 => 'empty21', //603 => 'empty21',
//605 => 'empty22', //605 => 'empty22',
607 => 'Siege_On_Harrogath', 607 => 'Act 5 - Siege_On_Harrogath',
609 => 'Rescue_On_MountArreat', 609 => 'Act 5 - Rescue_On_MountArreat',
611 => 'Prison_Of_Ice', 611 => 'Act 5 - Prison_Of_Ice',
613 => 'Betrayal_Of_Harrogath', 613 => 'Act 5 - Betrayal_Of_Harrogath',
615 => 'Rite_Of_Passage', 615 => 'Act 5 - Rite_Of_Passage',
617 => 'Eve_Of_Destruction', 617 => 'Act 5 - Eve_Of_Destruction',
]; ];
/** /**

View File

@ -25,15 +25,15 @@ EOT;
$quests = ''; $quests = '';
foreach ($c->cData['Quests'] as $quest) { foreach ($c->cData['Quests'] as $quest) {
foreach ($quest as $difficulty => $q) { foreach ($quest as $difficulty => $q) {
$quests .= "<h2>$difficulty</h2>"; $quests .= "<h2 style='text-align: center'>$difficulty</h2>";
foreach ($q as $k => $v) { foreach ($q as $k => $v) {
$kD = str_replace("_", " ", $k); $kD = str_replace("_", " ", $k);
$kD = str_replace([" NM", " Hell"], "", $kD); $kD = str_replace([" NM", " Hell"], "", $kD);
$checked = ($v == 1) ? 'checked' : ''; $checked = ($v == 1) ? 'checked' : '';
$quests .= "<input class='qcheck' diff='$difficulty' type='checkbox' value='1' name='$k' id='$k' $checked>"; $quests .= "<div class='qcheckgroup' ><input class='qcheck' diff='$difficulty' type='checkbox' value='1' name='$k' id='$k' $checked>";
$quests .= "<label for='$k'>$kD</label><br>"; $quests .= "<label for='$k'>$kD</label><br></div>";
} }
} }
} }
@ -45,7 +45,7 @@ EOT;
//$wps .= "<label style='font-size: 1.3em; color: red;' for='wp_all_off'>Disable All Waypoints</label><hr>"; //$wps .= "<label style='font-size: 1.3em; color: red;' for='wp_all_off'>Disable All Waypoints</label><hr>";
foreach ($c->cData['Waypoints'] as $diff => $waypoints) { // diff is difficulty foreach ($c->cData['Waypoints'] as $diff => $waypoints) { // diff is difficulty
$wps .= "<h2>$diff</h2>"; $wps .= "<h2 style='text-align: center'>$diff</h2>";
array_pop($waypoints); array_pop($waypoints);
$wp_count = 0; $wp_count = 0;
foreach ($waypoints as $k => $v) { foreach ($waypoints as $k => $v) {
@ -54,8 +54,8 @@ EOT;
$kD = str_replace([" NM", " Hell"], "", $kD); $kD = str_replace([" NM", " Hell"], "", $kD);
$checked = ($v == 1 && $k != '') ? 'checked ' : ''; $checked = ($v == 1 && $k != '') ? 'checked ' : '';
$wps .= "<input diff='$diff' class='wpcheck' type='checkbox' value='1' name='$wp_count' id='$k' $checked>"; $wps .= "<div class='wcheckgroup' ><input diff='$diff' class='wpcheck' type='checkbox' value='1' name='$wp_count' id='$k' $checked>";
$wps .= "<label for='$k'>$kD</label><br>"; $wps .= "<label for='$k'>$kD</label><br></div>";
$wp_count++; $wp_count++;
} }
} }
@ -71,34 +71,35 @@ EOT;
} }
$difficulties = [ $difficulties = [
'Normal' => '1', 'Normal' => '0',
'NM' => '2', 'Finished Normal' => '1',
'Hell' => '3' 'Finished Nightmare' => '2',
'Finished Hell' => '3'
]; ];
$radio = ''; $radio = '';
foreach ($difficulties as $difficulty => $id) { foreach ($difficulties as $difficulty => $id) {
$checked = ($c->cData['Difficulty'][$difficulty] == 1) ? 'checked' : ''; $checked = ($c->cData['Difficulty'][$difficulty] == 1) ? 'checked' : '';
$radio .= "<input $checked type='radio' id='$difficulty' name='Difficulty' value='$difficulty'>"; $radio .= "<input $checked type='radio' id='$difficulty' name='Difficulty' value='$id'>";
$radio .= "<label for='$difficulty'>$difficulty</label><br>"; $radio .= "<label for='$difficulty'>$difficulty</label><br>";
} }
$skills = ''; $skills = '';
/* /*
'skills' => 'skills' =>
array (size=1) array (size=1)
'skills' => 'skills' =>
array (size=52) array (size=52)
0 => 0 =>
array (size=7) array (size=7)
'id' => int 36 'id' => int 36
'skill' => string 'Fire Bolt' (length=9) 'skill' => string 'Fire Bolt' (length=9)
'points' => int 0 'points' => int 0
'page' => int 3 'page' => int 3
'row' => int 1 'row' => int 1
'col' => int 2 'col' => int 2
'icon' => int 0 'icon' => int 0
*/ */
$skillcounter = 1; $skillcounter = 1;
foreach ($c->cData['skills']['skills'] as $k => $skill) { foreach ($c->cData['skills']['skills'] as $k => $skill) {
@ -106,6 +107,29 @@ EOT;
$skillcounter++; $skillcounter++;
} }
// ddump($c->cData['CharacterStatusDied']);
$statuses = [
'Died' => 'CharacterStatusDied',
'Expansion' => 'CharacterStatusExpansion',
'Hardcore' => 'CharacterStatusHardcore',
];
$checkboxes = '';
foreach ($statuses as $status => $dataKey) {
$checked = $c->cData[$dataKey] ? 'checked' : '';
$checkboxes .= <<<HTML
<div class="col">
<div class="form-check">
<label class="form-check-label" for="{$status}">{$status}: </label><br>
<input class="form-check-input" {$checked} type="checkbox" id="{$status}" name="CharacterStatus[{$status}]" value="{$c->cData[$dataKey]}">
</div>
</div>
HTML;
}
$tabContent .= <<<EOT $tabContent .= <<<EOT
<div style="background: white; margin-top: 10px;" class="tab-pane fade" id="{$c->cData['CharacterName']}" role="tabpanel" aria-labelledby="{$c->cData['CharacterName']}-tab"> <div style="background: white; margin-top: 10px;" class="tab-pane fade" id="{$c->cData['CharacterName']}" role="tabpanel" aria-labelledby="{$c->cData['CharacterName']}-tab">
<form id='{$c->cData['CharacterName']}' class="charform {$c->cData['CharacterName']}" method="POST" action="/saveCharacter.php"> <form id='{$c->cData['CharacterName']}' class="charform {$c->cData['CharacterName']}" method="POST" action="/saveCharacter.php">
@ -122,10 +146,23 @@ EOT;
</select><br> </select><br>
Character Level: <input style="border: 1px solid black;width: 54px;" type="number" name="CharacterLevel" id="CharacterLevel" value="{$c->cData['CharacterLevel']}"> Character Level: <input style="border: 1px solid black;width: 54px;" type="number" name="CharacterLevel" id="CharacterLevel" value="{$c->cData['CharacterLevel']}">
<hr> <hr>
<div style="background: #efe;">
Difficulty:<br>
$radio
</div>
<hr>
<!--Character Status -->
<div class="form-row">
$checkboxes
<br><br>
</div>
<hr>
<!-- STATS --> <!-- STATS -->
<div class="stats"> <div class="stats">
<div class="form-row"> <div class="form-row" style="background: #eed;">
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="strength">Strength:</label> <label for="strength">Strength:</label>
<input type="number" class="form-control" id="strength" name="strength" min="1" max="255" value="{$c->cData['stats']['strength']}" required> <input type="number" class="form-control" id="strength" name="strength" min="1" max="255" value="{$c->cData['stats']['strength']}" required>
@ -144,7 +181,7 @@ EOT;
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row" style="background: #eee;">
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="hitpoints">Hitpoints:</label> <label for="hitpoints">Hitpoints:</label>
<input type="number" class="form-control" id="hitpoints" name="hitpoints" min="1" max="255" value="{$c->cData['stats']['hitpoints']}" required> <input type="number" class="form-control" id="hitpoints" name="hitpoints" min="1" max="255" value="{$c->cData['stats']['hitpoints']}" required>
@ -163,7 +200,7 @@ EOT;
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row" style="background: #eed;">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="stamina">Stamina:</label> <label for="stamina">Stamina:</label>
<input type="number" class="form-control" id="stamina" name="stamina" min="1" max="255" value="{$c->cData['stats']['stamina']}" required> <input type="number" class="form-control" id="stamina" name="stamina" min="1" max="255" value="{$c->cData['stats']['stamina']}" required>
@ -172,22 +209,20 @@ EOT;
<label for="maxstamina">Max Stamina:</label> <label for="maxstamina">Max Stamina:</label>
<input type="number" class="form-control" id="maxstamina" name="maxstamina" min="1" max="255" value="{$c->cData['stats']['maxstamina']}" required> <input type="number" class="form-control" id="maxstamina" name="maxstamina" min="1" max="255" value="{$c->cData['stats']['maxstamina']}" required>
</div> </div>
</div> </div>
</div> </div>
<hr> <hr>
<!--Difficulty:<br> <div style="background:;">
$radio--> <h3 style="text-align: center">Skills</h3>
<div>
<h3>Skills</h3>
$skills $skills
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<h3>Quests</h3> <h3 style="text-align: center">Quests</h3>
$quests $quests
</div> </div>
<div class="col"> <div class="col">
<h3>Waypoints</h3> <h3 style="text-align: center">Waypoints</h3>
$wps $wps
</div> </div>
</div> </div>