d2tools/saveCharacter.php

319 lines
10 KiB
PHP
Raw Permalink Normal View History

<?php
2023-06-02 05:42:12 +00:00
// Set error reporting to only show errors and parse errors
error_reporting(E_ERROR | E_PARSE);
2023-06-02 05:42:12 +00:00
// Set the time limit for script execution to unlimited
set_time_limit(-1);
2023-06-02 05:42:12 +00:00
// Set the maximum input time to unlimited
ini_set('max_input_time', '-1');
2023-06-02 05:42:12 +00:00
// Set the maximum execution time to unlimited
ini_set('max_execution_time', '0');
2023-06-02 05:42:12 +00:00
// Start the session
session_start();
2023-06-02 05:42:12 +00:00
// Start output buffering
ob_start();
2023-06-02 05:42:12 +00:00
// Define the constant 'DB_FILE' with the value of 'modname' session variable followed by ".db"
define('DB_FILE', $_SESSION['modname'] . ".db");
2023-06-02 05:42:12 +00:00
// Include the configuration file
require_once './config.php';
2023-06-02 05:42:12 +00:00
// Include the PDO wrapper file
require_once './_pdo.php';
2023-06-02 05:42:12 +00:00
// Include the required class files
require_once "./src/D2Functions.php";
require_once "./src/D2Database.php";
require_once './src/D2Files.php';
require_once './src/D2TxtParser.php';
require_once './src/D2ItemDesc.php';
2023-06-02 05:42:12 +00:00
require_once './src/D2Char.php';
2022-06-21 02:21:28 +00:00
require_once './src/D2CharStructureData.php';
2023-06-02 05:42:12 +00:00
require_once './src/D2ByteReader.php';
2023-06-03 02:43:18 +00:00
require_once './src/D2BitReader.php';
require_once './src/D2Item.php';
require_once './src/D2Char.php';
PDO_Connect("sqlite:" . DB_FILE);
2023-06-02 05:42:12 +00:00
// Create an instance of D2CharStructureData class
$csData = new D2CharStructureData();
$g = $_GET;
$cmd = $g['cmd'];
// Get the file path from the POST data and replace backslashes /
$filePath = $g['filePath'];
2023-06-03 02:43:18 +00:00
//$filePath = str_replace("\\", "\\\\", $filePath);
$cmd = $_GET['cmd'];
$name = $_GET['name'];
$value = $_GET['value'];
$char = new D2Char(basename($filePath));
switch ($cmd) {
case "CharacterName":
// Handle CharacterName command
// Validate the character name length
if (strlen($value) < 2 || strlen($value) > 15) {
echo "Character name must be between 2 and 15 characters long.";
// You can handle the error case accordingly (e.g., return an error response)
// Additional validation checks can be added here as needed
} else {
// Validate the character name format
$pattern = '/^[A-Za-z0-9_-]+$/'; // Regular expression pattern for allowed characters
if (!preg_match($pattern, $value)) {
echo "\nCharacter name contains invalid characters. Only alphabets, numbers, underscore, and dash are allowed.";
// Handle the error case accordingly
} else {
// The character name is valid, proceed with further processing
$char->setChar($cmd, $value);
echo "\nCharacter Name and filename Changed";
}
}
echo "\nHandling CharacterName command - Name: $value, File Path: $filePath";
break;
case "CharacterClass":
// Handle CharacterClass command
$char->setChar($cmd, $value);
echo "Handling CharacterClass command - Class: $value, File Path: $filePath";
break;
case "CharacterLevel":
// Handle CharacterLevel command
$char->setChar($cmd, $value);
echo "Handling CharacterLevel command - Level: $value, File Path: $filePath";
break;
// handle difficulty wierdly
case "Normal":
$char->setChar("CharacterProgression", $value);
2023-06-03 02:43:18 +00:00
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break;
case "Finished Normal":
$char->setChar("CharacterProgression", $value);
2023-06-03 02:43:18 +00:00
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break;
case "Finished Nightmare":
$char->setChar("CharacterProgression", $value);
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break;
case "Finished Hell":
$char->setChar("CharacterProgression", $value);
2023-06-03 02:43:18 +00:00
echo "Handling Difficulty command - Difficulty: $value, File Path: $filePath";
break;
// skills
case "skills":
//var_dump($char->cData);
$char->setSkill($name, $value);
echo "Handling skills command - Skill: $name, Value: $value, File Path: $filePath";
break;
2023-06-03 21:26:07 +00:00
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;
2023-06-03 21:26:07 +00:00
2023-06-12 07:07:57 +00:00
// stats commands
2023-06-12 00:03:39 +00:00
case "stats":
echo "Handling $name command. New value: $value";
$char->setStat($name, $value);
break;
2023-06-12 07:07:57 +00:00
// setallskills
case "setallskills":
echo "Handling $name command. New value: $value";
$char->setAllSkills($value);
break;
// q_all
case "q_all":
echo "Handling $name command. New value: $value";
$fp = fopen($filePath, "rb+");
$offsets = array_merge(array_keys($csData->qNorm), array_keys($csData->qNM), array_keys($csData->qHell));
$packValue1 = ($value == 1) ? 0xFE : 0x00;
$packValue2 = ($value == 1) ? 0xFF : 0x00;
foreach ($offsets as $k => $v) {
fseek($fp, $v);
fwrite($fp, pack('C', $packValue1));
fseek($fp, $v + 1);
fwrite($fp, pack('C', $packValue2));
}
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
break;
// wp_all
case "wp_all":
echo "Handling $name command. New value: $value";
$fp = fopen($filePath, "rb+");
// Determine the pack value based on the $value variable
$packValue = ($value == 1) ? 0xFF : 0x00;
// Define the WP offsets
$wp_offsets = [
643, 644, 645, 646, 647, // Norm
667, 668, 669, 670, 671, // NM
691, 692, 693, 694, 695 // Hell
];
// Iterate over the WP offsets
foreach ($wp_offsets as $offset) {
fseek($fp, $offset);
fwrite($fp, pack('C', $packValue));
}
$checksum = (shell_exec("bin\d2scs.exe \"$filePath\""));
break;
2023-06-03 21:26:07 +00:00
// default command
2023-06-03 02:43:18 +00:00
default:
// Handle unknown command
echo "Unknown command: $cmd";
break;
}