- Joined
- Aug 12, 2009
- Messages
- 1,810
- Reaction score
- 606
Alright so, in the next few months or so I will build a new GD little by little since my old one was just scripts thrown to the public with not much instructions on how to use it or build it. Instead of doing everything privately and quick, I will take my time to not mess up on these scripts. The old ones weren't good since they didn't generate all the images and was handled badly all while I tried optimizing it at the same time. Hope to be finish with this in about .. 4 months or so? I will dedicate about 2-3 hours on the weekends(currently attending UCF and being a stem major is rough so I apologize on the lack of time I spend). For now I will add my scripts here and update them best I can. Also make them user friendly to understand.
Information:
- Testing: v169.1 GMS
- Coding: SimpleXML(output JSON)
- Database for testing GD: IntrinsicMS(Thanks to @Lynx1213 )
- Extractor: Harepacker 4.3(+maplelib.dll fix)
- v1.0(old): here
Accessory:
V.2.0
PHP:
<?php
/**
* Accessories JSON Creation
* @author iAkira
* [USER=316612]Version[/USER] 2.0
*/
ini_set('max_execution_time', 14000); // Extend execution timing.
/**
* @vslot
* Af = AccessoryFace
* Ay = AccessoryEyes
* Ae = AccessoryEars
* Pe = Pendant
* Be = Belt
* Me = Medal
* Sh = Shoulder
* Po = Pocket
* Ba = Badge
* Si = Emblem
**/
//Locate access and delivery folders.
$dir = 'XML/'; // Location of your XML files.
$output = 'RhaArias/'; // Output location for JSON files.
// Don't touch this.
$storage = [];
$skip = ['Pe','Be','Me','Sh','Po','Ba','Si']; // Not shown on character.
// Creates output folder if doesn't exist.
if (!file_exists($output)) {
mkdir($output, 0777, true);
}
// Don't touch anything beyond this point unless you know what you're doing.
foreach(array_slice(scandir($dir), 2) as $id) {
// ID of current interation iteration.
$pureID = substr($id, 0, -8);
// Jump transparent cash item.
if($pureID == '01022048'){
continue;
}
foreach (simplexml_load_file($dir.$id)->imgdir as $parent) {
if($parent['name'] == 'info'){
// Jump over items not shown on character.
foreach($parent->children()->string as $vslot){
if(in_array((string)$vslot['value'], $skip)) {
continue 3;
}
}
} else if($parent['name'] == 'default') {
$cache = $parent->children()[0];
$storage['x'] = -((int)$cache->vector['x'] + (int)$cache->imgdir->vector['x']);
$storage['y'] = -((int)$cache->vector['y'] + (int)$cache->imgdir->vector['y']);
$storage['z'] = (string)$parent->children()[0]->string[0]['value'];
// Finding the source image if it contains a source attribute.
if(isset($parent->children()[0]->string[1])){
$rawSource = $parent->children()[0]->string[1]['value'];
$pureSource = explode('/', $rawSource);
$pureSourceID = mb_strimwidth(preg_replace('/[^0-9]/','', $rawSource), 0, 8, '');
// Checks if source image is an icon.
if(in_array('iconRaw', $pureSource)) {
$location = in_array($pureID.'.img', $pureSource)? $id : $pureSourceID.'.img.xml';
$storage['d'] = (string)simplexml_load_file($dir.$location)->imgdir[0]->canvas[1]['basedata'];
// Checks if the source image is located outside the current item ID through a pattern (default/default).
} else if((count($pureSource) != count(array_count_values($pureSource)))){
$location = simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir[0]->canvas[1]['basedata'];
foreach (simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir as $parent2) {
if($parent2['name'] == 'default'){
$storage['d'] = (string)$parent2->children()[0]['basedata'];
break;
}
}
// Unique source image location requires more checks.
} else {
//Character/Accessory/01012025.img/blaze/0/default
//Checks if source image is in Accessories or not.
if($pureSource[1] == substr($dir, 0, -1)) {
foreach (simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir as $parent2) {
//Checks specific imgdir
if($parent2['name'] == $pureSource[3]){
$storage['d'] = (string)$parent2->children()[0]['basedata'];
echo (string)$parent2->children()[0]['basedata'];
break;
}
}
}
}
} else {
$storage['d'] = (string)$parent->children()[0]['basedata'];
}
break;
}
}
// Creates JSON file of current ID.
$file = fopen($output.$pureID.'.json', 'w');
fwrite($file, json_encode($storage, JSON_UNESCAPED_SLASHES));
fclose($file);
// Something some keys are left over so wiping the storage is needed.
$storage = [];
}
?>
(Interesting finding while debunking a bit was that none of the released GD have the fully vslot support for caps which is extremely important)
Cap:
Vslot information:
Script:
JSON File result:
PHP:
<?php
/**
* Accessories JSON Creation
* @author iAkira
* [USER=316612]Version[/USER] 2.0
*/
/**
* @vSlot
* CpH1H2H3H4H5H6HfHsHbHc = Replaces Hair
* CpH1H2H3H4H5H6HfHbHxHs = Replaces Hair
* CpH1H2H3H4H5H6HfHsHbHx = Replaces Hair
* CpH1H2H3H4H5H6HfHsHb = Replaces Hair
* CpH1H2H3H4H5H6HsHb = replace Hair
* CpHdH1H2H3H4H5HfHsFcAfAyAsAfAe = no overhead/ or face / or accessories
* CpH1H2H3H4H5H6HfHsHbHcAfAyAsAfAe = Replaces Hair/ no acceosries
* CpHdH1H2H3H4H5H6HsHfHbAfAyAsAe = Replaces Hair/ no acceosries but has faces
* CpH1H2H3H4H5H6HfHsHbAe = Replaces Hair and no earrings
* CpH1H2H3H4H5HfHsHbAe = No hairoverhead no ears
* CpH1H3H4H5H6HfHsHbAe = no earring no overheadhair (noshade?)
* CpH1H3H4H5H6HfHbAe = no earrings or overhead
* CpH1H2H3H5HfHsAfAyAsAeHbH4H6 = no earring and no hair(Replace hair no accessories)
* CpH1H2H3H4H5H6HfHsHbHcAe = unknown
* CpHdH1H2H3H4 = unknown (could be no overhead/no face/ no accessories MAYBE earring itemid: 01002470)
* CpH5 = allow hairoverhead
* Cp = Allow everything(even earrings) allow hairoverhead
* CpH1H4 = no overhead
* CpH1H5 = no overhead
* CpH2H5 = no overhead
* CpH1H5Hb = no overhead/ Hb may = defaultAc
* CpHdH1H2H3H5HfHsFcAfAyAsAfAe = no face/accessories/ or hair
* CpH1H2H3H4H5H6HsHfHbAfAyAsAe = No Hair no accessories
* CpH1H5FcAfAyAsAfAe = no overhead no face no accessories
* CpH1H5AyAs = no overhead/ no accessory eyes / As?
* CpH1H5AfAyAsAe = no overhead or accessories
* CpH1H2H5Hs = remove all hair and accessories(someone test itemid:01002583)
* CpH1H2H3H4H5HfHsAeAs = remove hair, eye accessories.(some one test itemid: 01002241)
* CpH5Ae = allow hairoverhead/ remove ear accessories
* '2' = allow everything(test itemid:01003104) but no overhead
*/
?>
PHP:
<?php
/**
* Cap JSON Creation
* @author iAkira
* [USER=316612]Version[/USER] 2.0
*/
// Unique items like Teddy Ribbon & Warm Bao support added as well
ini_set('max_execution_time', 14000);
$dir = 'XML/';
$output = 'RhaArias/';
$storage = [];
//default back -> hairoverhead -> default
//"z_defaultB": "accessoryEar", (01003108)
//defaultacc (id:01003657 look into it but for now can be excluded)
//a0-b3 (01004533 items Nexon never advertised, so idk how it looks in game, excluded for now)
$getInfo = ['default','defaultAc','defaultBelowBody','defaultAC','defaultTail','defaultBack','defaultB','acc','defaultback','0','hairBelowBody','defaultAcc'];
$uniqueIDs = ['01003862', '01004414'];
if (!file_exists($output)) {
mkdir($output, 0777, true);
}
foreach(array_slice(scandir($dir), 2) as $id) {
$xml = simplexml_load_file($dir.$id);
$pureID = substr($id, 0, -8);
// Just Icon, so we skip it.
if(!isset($xml->imgdir[1])) {
continue;
}
// Loop all nodes to find 'Default'(couldnt assume it was at 1 like in accessories since the info[0] sometimes is last.)
foreach ($xml->imgdir as $parent0) {
$stance = (in_array($pureID, $uniqueIDs)) ? 'walk1' : 'default';
if ($parent0['name'] == 'info') {
// 5th Anniversary Giant Cake Hat has more strings.
$storage['vslot'] = (string) $parent0->string[($id == '01003104.img.xml') ? 5 : 1]['value'];
if(count($storage) > 1) {
break;
}
} else if ($parent0['name'] == $stance) {
$imgdir =($stance =='walk1') ? $parent0->imgdir[0]->canvas : $parent0->canvas;
foreach ($imgdir as $parent1) {
if(in_array($parent1['name'], $getInfo)) {
// Blank image, skip it.
if((int)$parent1['width'] == 1) {
continue;
} else {
$storage['x_'.$parent1['name']] = -((int)$parent1->vector[0]['x'] + (int)$parent1->imgdir[0]->vector[0]['x']);
$storage['y_'.$parent1['name']] = -((int)$parent1->vector[0]['y'] + (int)$parent1->imgdir[0]->vector[0]['y']);
$storage['z_'.$parent1['name']] = (string)$parent1->string[0]['value'];
// Check if it contains source.
if(isset($parent1->string[1])) {
$rawSource = $parent1->string[1]['value'];
$pureSource = explode('/', $rawSource);
$pureSourceID = mb_strimwidth(preg_replace('/[^0-9]/','', $rawSource), 0, 8, '');
//usually default sourcing only not Ac
//check if only default/default and check if current id or not.
if((count($pureSource) != count(array_count_values($pureSource)))){
foreach (simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir as $parent2) {
if($parent2['name'] == 'default'){
$storage['d_'.$parent1['name']] = (string)$parent2->children()[0]['basedata'];
break;
}
}
} else if(in_array('icon', $pureSource) || in_array('iconRaw', $pureSource)){
$parent2 = ($pureSourceID != preg_replace('/[^0-9]/','', $id)) ? simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir : $xml->imgdir;
//removed because never called
/*if($parent2[0]['name'] != 'info') {
echo $id.'<br />';
foreach ($parent2 as $parent3) {
if($parent3->canvas['name'] == 'info'){
$info = $parent3->canvas;
echo $id.'<br />';
break;
}
}
} else {*/
$info = $parent2[0]->canvas;
$canvas = in_array('icon', $pureSource) ? $info[0] : $info[1];//icon or iconRaw
$storage['d_'.$parent1['name']] = (string)$canvas['basedata'];
} else if (in_array('defaultBelowBody', $pureSource) || in_array('defaultBack', $pureSource) || in_array('defaultAc', $pureSource) || in_array('acc', $pureSource)){
$parent2 = simplexml_load_file($dir.$pureSourceID.'.img.xml')->imgdir;
foreach ($parent2 as $parent3) {
if($parent3['name'] == $pureSource[count($pureSource)-2]) {
foreach ($parent3->canvas as $parent4) {
if($parent4['name'] == $pureSource[count($pureSource)-1]) {
$storage['d_'.$parent1['name']] = (string)$parent4['basedata'];
break;
}
}
break;
}
}
}
} else {
$storage['d_'.$parent1['name']] = (string)$parent1['basedata'];
}
}
}//else are the rejected nodes
}
// itemID that only consist of vslot(all nodes had width of 1 so doesn't need a JSON file)
if(count($storage) == 1) {
continue 2;
} else if(array_key_exists('vslot', $storage)) {
break;
}
}
}
$file = fopen($output.$pureID.'.json', 'w');
fwrite($file, json_encode($storage, JSON_UNESCAPED_SLASHES));
fclose($file);
$storage = [];
}
?>
{
"vslot": "CpH5",
"x_default": 5,
"y_default": -15,
"z_default": "capOverHair",
"d_default": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAbCAYAAABiFp9rAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJKSURBVEhLrVQLlYMwEMTCWcBCLWChFmohFrCABSxgIRZiIRb2ZvaTBo5yfXedx7xAsplJNhuGf0A6/hm9yJmQSBVl3eqrmEvoJE5WIUf0M8Ch/RqnLy3mLejENvkEjIk4XUix/oCP/4q2iyuzOttizmKoYVLXsOjXHg01FakrAgvIeDYwpoZJXcNUjqAYmb1l83Aj9pF8nkZvGbq6IwzIFQdC4snTghTiZeGHp5K7ZDrxkNQyyXOYAcEJNKJ42qTeV6XMWbbbQ+ojQzzDDNwilT7PQT2TPUdblU6kSGdUYbKMk9TxIfmWpE4wp9nq83rgm3om+xOWCpKrxI7UAILb16RcvKWZZBjQJFo3CFLPZPfQAS1hMlUpSFW5LzuTZbhBc5KSniZ81+8eMOqKpMFHHUwbWHDI65iaSWIcxEO4p7AYjjjsynsdjGchMH3YUcWOwiREF7wH8zTbOXmp7/DD6BigRlZxZUpSxrsahXgaRvALO71rsWh10oiZCLgm9c3kDHqHouJmFWT6KB6c8b1hAVZ1zDPmUdwNAm8YgavdlcKVo8pWCPeFsaLEebdsjjW9UV8MzxvdgybsZ/pY4tgZV59hxrvEVLKtM/r1T2FX4pVJwIdOwLmYQFJQ/xKJfwici6csxvs/O0ldk9/DVhMrivfOqOCXw1bPgzvVXXu+Ig5m1HK+RBM/muxSQ22eYTDAYcRQx+Su0a9ox2Z0BYx7/J/xuxHHPmBEPI16w77vY0aBg5HuFmCMhf4fKhirV6Blv/Oj6IXfMBiGb567zd/OoHxnAAAAAElFTkSuQmCC"
}
PHP:
<?php
/**
* Cape JSON Creation
* @author iAkira
* [USER=316612]Version[/USER] 2.0
*/
ini_set('max_execution_time', 14000);
$dir = 'XML/';
$output = 'RhaArias/';
$storage = [];
if (!file_exists($output)) {
mkdir($output, 0777, true);
}
foreach(array_slice(scandir($dir), 2) as $id) {
$xml = simplexml_load_file($dir.$id)->imgdir;
$pureID = substr($id, 0, -8);
$path = '';
// Only icon Jump.
if(!isset($xml[1])) { continue; }
// [New]Pathing
// uol are basically a 'redirect' of the FULL information rather then partial info.
// Source is a partial redirect to the base64 image, but uol is a redirect on x,y,z, and base64.
foreach($xml as $parent0) {
if($parent0['name'] == 'stand1') {
$path = isset($parent0->imgdir[0]->uol) ? 'default' : 'stand1';
break;
}
}
// Collection data
foreach($xml as $parent) {
if($parent['name'] == $path) {
// Empty node
if(!isset($parent->imgdir[0]) && !isset($parent->canvas[0])){
continue;
}
// Some itemID arent animated so they don't have the imgdir[0,1,2,3,4, etc] since the cape is static.
$type = isset($parent->canvas[0]) ? $parent : $parent->imgdir[0];
foreach($type->canvas as $parent1) {
// Jump canvas with width 1(blank image)
if((int) $parent1['width'] == 1) { continue; }
$storage['x_'.$parent1['name']] = -((int)$parent1->vector[0]['x'] + (int)$parent1->imgdir[0]->vector[0]['x']);
$storage['y_'.$parent1['name']] = -((int)$parent1->vector[0]['y'] + (int)$parent1->imgdir[0]->vector[0]['y']);
$storage['z_'.$parent1['name']] = (string)$parent1->string[0]['value'];
//Character/Cape/01100000.img/walk1/0/cape
//<ignore>/<ignore>/<location>/<imgdir>/<position>/<canvas>
if(isset($parent1->string[1])) {
$rawSource = $parent1->string[1]['value'];
$pureSource = explode('/', $rawSource);
// It's okay to remove the mb_strimwidth function since the ALL source are all the same template as above.
// No icon sourcing found.
// While checking source, found out the $pureSource is the same for every ID. So no if statements are needed.
$source = (preg_replace('/[^0-9]/','', $pureSource[2]) != $pureID) ? simplexml_load_file($dir.$pureSource[2].'.xml')->imgdir : $xml;
foreach($source as $parent2) {
if($parent2['name'] == $pureSource[3]) {
//find canvas name(some might have more than one canvas ex.capeArm)
foreach($parent2->imgdir[(int)$pureSource[4]]->canvas as $parent3) {
if($parent3['name'] == $pureSource[5]) {
$storage['d_'.$parent1['name']] = (string)$parent3['basedata'];
break 2;
}
}
}
}
} else {
$storage['d_'.$parent1['name']] = (string)$parent1['basedata'];
}
}
break;
}
}
if(count($storage) != 0) {
$file = fopen($output.$pureID.'.json', 'w');
fwrite($file, json_encode($storage, JSON_UNESCAPED_SLASHES));
fclose($file);
}
$storage = [];
}
?>
Version 2.0.0
Version: 2.0.1
PHP:
<?php
ini_set('max_execution_time', 14000); // Extend execution timing.
$dir = 'XML/'; // Location of your XML files.
$output = 'RhaArias/'; // Output location for JSON files.
$storage = [];
//check all the hair name values
// Creates output folder if doesn't exist.
if (!file_exists($output)) {
mkdir($output, 0777, true);
}
foreach(array_slice(scandir($dir), 2) as $id) {
$xml = simplexml_load_file($dir.$id)->imgdir;
foreach($xml as $parent) {
if($parent['name'] == 'default') {
foreach ($parent->canvas as $parent2){
if((int)$parent2['width'] == 1){ continue; }
$storage['x_'.$parent2['name']] = -((int)$parent2->vector[0]['x'] + (int)$parent2->imgdir[0]->vector[0]['x']);
$storage['y_'.$parent2['name']] = -((int)$parent2->vector[0]['y'] + (int)$parent2->imgdir[0]->vector[0]['y']);
$storage['z_'.$parent2['name']] = (string)$parent2->string[0]['value'];
//Character/Hair/00030100.img/default/hairOverHead
//Character/Hair/00030741.img/default/hair(same id backhair redirect to hair)(do a check to remove because it's the same backhair and hair with the same image?)
//itemid(00030741) ^
//Character/00002000.img/blink/0/body(blank image)
//width="1" height="1" remove these from creation and loop.
if(isset($parent2->string[1])){
echo $id;
break 2;
}
}
}
}
$storage = [];
}
//print_r($storage);
?>
PHP:
<?php
// Supports the Kanna hair which were an event by Nexon in creations.
// Supports hairOverHead, hairShade(hate Nexon..), hairBelowBody, Hair, and hairBelowHead
ini_set('max_execution_time', 14000); // Extend execution timing.
$dir = 'XML/'; // Location of your XML files.
$output = 'RhaArias/'; // Output location for JSON files.
$storage = [];
// Remove duplicated images.
$removal = [];
$removal['hairBelowBody'] = array_merge(range(32660,32667), [38920]);
$removal['hairBelowHead'] = range(33390,33397);
$removal['hairOverHead'] = array_merge(range(31200,31217), range(30740,30747));
//These are useless images that are either slighty modified or cut off a bit.(experimental images I believe).
$exception =['hairOverHeadProne','hairBelowBodyProne','hairBelowBody_prone', 'hairProne'];
if (!file_exists($output)) {
mkdir($output, 0777, true);
}
foreach(array_slice(scandir($dir), 2) as $id) {
$xml = simplexml_load_file($dir.$id)->imgdir;
$pureID = substr($id, 0, -8);
foreach($xml as $parent) {
if($parent['name'] == 'default') {
//hairshade is a god damn imgdir. really nexon..
if(isset($parent->imgdir[0]->canvas[0])){
$cache0 = $parent->imgdir[0]->canvas[0];
if((int)$cache0['width'] != 1){
$storage['x_hairShade'] = -((int)$cache0->vector[0]['x'] + (int)(isset($cache0->imgdir[0]->vector[0]['x']) ? $cache0->imgdir[0]->vector[0]['x'] : 0));
$storage['y_hairShade'] = -((int)$cache0->vector[0]['y'] + (int)(isset($cache0->imgdir[0]->vector[0]['y']) ? $cache0->imgdir[0]->vector[0]['y'] : 0));
$storage['d_hairShade'] = (string)$cache0['basedata'];
if(isset($cache0->string)) {
foreach($cache0->string as $parent1) {
if($parent1['name'] == 'source') {
$storage['d_hairShade'] = sourceImage($parent1['value'], $pureID, $xml, true);
break;
}
}
}
}
}
foreach ($parent->canvas as $parent2){
if((int)$parent2['width'] == 1 || in_array($parent2['name'], $exception)){
continue;
}
foreach($removal as $revType => $revID) {
if(in_array((int)$pureID, $revID) && $parent2['name'] == $revType) {
continue 2;
}
}
//There is a unique canvas named hairBelowHead but some z value rename this to hairBelowBody.
//So $type variable does the following:"x_hairBelowHead" to "x_hairBelowBody" if the statement exist.
$type = ($parent2['name'] == 'hairBelowHead' && (string)$parent2->string[0]['value'] == 'hairBelowBody') ? 'hairBelowBody' : $parent2['name'];
$storage['x_'.$type] = -((int)$parent2->vector[0]['x'] + (int)$parent2->imgdir[0]->vector[0]['x']);
$storage['y_'.$type] = -((int)$parent2->vector[0]['y'] + (int)$parent2->imgdir[0]->vector[0]['y']);
$storage['d_'.$type] = (isset($parent2->string[1])) ? sourceImage($parent2->string[1]['value'], $pureID, $xml, false) : (string) $parent2['basedata'];
}
break;
}
}
//It's greater than 0 over 3 because some hairID only have 3 things(default hair x,y, and d)
if(count($storage) > 0) {
$file = fopen($output.$pureID.'.json', 'w');
fwrite($file, json_encode($storage, JSON_UNESCAPED_SLASHES));
fclose($file);
}
$storage = [];
}
function sourceImage($value, $currentID, $currentIDData, $isShade) {
$data = '';
$pureSource = explode('/', $value);
$pureSourceID = preg_replace('/\D/', '', $pureSource[2]);
$path = ($pureSourceID == $currentID) ? $currentIDData : simplexml_load_file('XML/'.$pureSource[2].'.xml')->imgdir;
foreach($path as $parent3) {
if($parent3['name'] == $pureSource[3]) {
if(isset($parent3->canvas) && !$isShade) {
$path2 = [$parent3->canvas, 4];
} else if(isset($parent3->imgdir)){
$cache = $parent3->imgdir;
for ($i = 0, $o = -1; $i < count($cache); $i++){
if($cache[$i]['name'] == $pureSource[4]) {
$o = $i;
break;
}
}
$path2 = [$cache[$o]->canvas, 5];
}
foreach($path2[0] as $parent4) {
if($parent4['name'] == $pureSource[$path2[1]]) {
$data = (string) $parent4['basedata'];
break 2;
}
}
}
}
return $data;
}
?>
Kappa123.
Last edited: