<?php
if(isset($_GET['char']))
$Load=$_GET['char'];
$Paperdoll=new Paperdoll($Load);
class Paperdoll
{
var $Debug=FALSE;
var $Logs;
var $Load;
var $Char;
var $PdollBG=0;
var $NameTitle;
var $Index;
var $Female;
var $Hue;
var $Gump;
var $Hues_Mul = FALSE;
var $TileData_Mul = FALSE;
var $Gump_Mul = FALSE;
var $Gump_Idx = FALSE;
var $Image_Temp;
var $Name;
var $Title;
var $Width;
var $Height;
function Paperdoll($Load)
{
$this->Load=$Load;
$this->Initialize();
}
function Initialize()
{
$this->InitializeDB();
$this->InitChar();
if(!isset($this->Char))
die('Character not found!');
$this->InitPdollBg();
$this->InitMulFiles();
$this->RemoveGuildStrings();
$this->SetBodyIndex();
$this->SetBodyHue();
$this->SetDimensions(); //Optional ($Height,$Width)
$this->InitItems();
$this->BuildGump();
$this->FormatText();
$this->AddText();
if($this->Debug)
{
for($i=0; $i<sizeof($this->Logs); $i++)
{
echo $this->Logs[$i]."<br/>";
}
}
else
{
$this->CreateGump();
}
$this->KillFiles();
}
function InitializeDB()
{
if($this->Debug)
$this->Logs[]="Initializing Database...";
include_once("../mysql/config.php");
include_once("../mysql/database.php");
$this->Database=$database;
if(isset($this->Database))
{
if($this->Debug)
$this->Logs[]="Done!";
}
else
{
if($this->Debug)
$this->Logs[]="Failed!";
}
}
function InitChar()
{
if($this->Debug)
$this->Logs[]="Initializing Character...";
$Q="SELECT * FROM ".TBL_CHARS." WHERE id='".$this->Load."'";
if($this->Debug)
$this->Logs[]="Query Database: ".$Q;
$this->Char=$this->Database->fquery($Q);
if($this->Char)
{
if($this->Debug)
$this->Logs[]="Done!";
}
else
{
if($this->Debug)
$this->Logs[]="Failed!";
}
}
function InitPdollBg()
{
if($this->Debug)
$this->Logs[]="Initializing Paperdoll Background...";
$Q="SELECT paperdoll_bg FROM ".TBL_ACCOUNTS_PROFILES." WHERE name='".$this->Char['accname']."'";
if($this->Debug)
$this->Logs[]="Query Database: ".$Q;
if($Result=$this->Database->fquery($Q))
{
$this->PdollBG = (int)$Result['paperdoll_bg'];
if(isset($_GET['bg']))
{
$this->PdollBG = (int)$_GET['bg'];
}
if($this->Debug)
$this->Logs[]="Background ID: ".$this->PdollBG;
}
else
{
if($this->Debug)
$this->Logs[]="Failed!";
}
if($this->Debug)
$this->Logs[]="Done!";
}
function RemoveGuildStrings()
{
if($this->Debug)
$this->Logs[]="Removing Guild Strings...";
$Remove=Array("(Order)","(Chaos)");
$this->NameTitle = str_replace($Remove,"",$this->Char['noto_title']);
if($this->Debug)
$this->Logs[]="Done!";
}
function SetBodyIndex()
{
if($this->Debug)
$this->Logs[]="Setting Body Index...";
if($this->Char['female']==1)
{
$this->Index = "13";
$this->Female = "1";
}
else
{
$this->Index = "12";
$this->Female = "0";
}
if($this->Debug)
$this->Logs[]="Index: ".$this->Index." * Female: ".$this->Female;
if($this->Debug)
$this->Logs[]="Done!";
}
function SetBodyHue()
{
if($this->Debug)
$this->Logs[]="Setting BodyHue...";
$this->Hue=(string)$this->Char['bodyhue'];
$this->Gump="1";
if($this->Debug)
$this->Logs[]="BodyHue: ".$this->Hue." * Gump: ".$this->Gump;
if($this->Debug)
$this->Logs[]="Done!";
}
function InitItems()
{
if($this->Debug)
$this->Logs[]="Initializing Items...";
$Q="SELECT * FROM ".TBL_CHARS_LAYERS." WHERE id='".$this->Char['id']."' ORDER BY layer_id";
if($this->Debug)
$this->Logs[]="Query Database: ".$Q;
$Result=$this->Database->query($Q);
$Items = Array( Array( ) );
$DoSort = false;
$Num=0;
for ( $foo=0; $Item = mysql_fetch_array($Result); $foo++)
{
if($this->Debug)
$this->Logs[]="Found Item - Parsing...";
if($this->Debug)
$this->Logs[]="Item ID: ".$Item['item_id']." * Layer: ".$Item['layer_id']." * Hue: ".$Item['item_hue'];
$Items['ids'][$Num] = $Item['item_id'];
$Items['hues'][$Num] = $Item['item_hue'];
if ($Item['layer_id'] == 13)
{
$Items['layers'][$Num++] = 3.5; // Fix for tunic
$DoSort = true;
}
else
{
$Items['layers'][$Num++] = $Item['layer_id'];
}
}
if ($DoSort)
{
if($this->Debug)
$this->Logs[]="Do Sort Items...";
array_multisort($Items['layers'], SORT_ASC, SORT_NUMERIC, $Items['ids'], SORT_ASC, SORT_NUMERIC, $Items['hues'], SORT_ASC, SORT_NUMERIC);
}
if($this->Debug)
$this->Logs[]="Insert Items into Variables...";
for ($i = 0; $i < $Num; $i++)
{
// Insert items into variables
$this->Index.= ",".$Items['ids'][$i];
$this->Hue.= ",".$Items['hues'][$i];
if ($this->Char['female']==1)
{
$this->Female.= ",1";
}
else
{
$this->Female.= ",0";
}
$this->Gump.= ",0";
}
if($this->Debug)
{
$this->Logs[]="Index-> ".$this->Index."";
$this->Logs[]="Female-> ".$this->Female."";
$this->Logs[]="Gump-> ".$this->Gump."";
$this->Logs[]="Hue-> ".$this->Hue."";
}
if($this->Debug)
$this->Logs[]="Done!";
}
function SetDimensions($W=266,$H=285)
{
if($this->Debug)
$this->Logs[]="Set Dimesions: W:".$W." H:".$H;
$this->Width=$W;
$this->Height=$H;
}
function InitMulFiles()
{
if($this->Debug)
$this->Logs[]="Initializing Mul files...";
$this->Hues_Mul = fopen("../../MulFiles/hues.mul", "rb");
if ($this->Hues_Mul == FALSE)
{
if($this->Debug)
$this->Logs[]="Failed! (Hues.mul)";
die("Unable to open hues.mul - ERROR\nDATAEND!");
exit;
}
$this->TileData_Mul = fopen("../../MulFiles/tiledata.mul", "rb");
if ($this->TileData_Mul == FALSE)
{
if($this->Debug)
$this->Logs[]="Failed! (TileData.mul)";
fclose($this->Hues_Mul);
die("Unable to open tiledata.mul - ERROR\nDATAEND!");
exit;
}
$this->Gump_Mul = fopen("../../MulFiles/gumpart.mul", "rb");
if ($this->Gump_Mul == FALSE)
{
if($this->Debug)
$this->Logs[]="Failed! (GumpArt.mul)";
fclose($this->Hues_Mul);
fclose($this->TileData_Mul);
die("Unable to open gumpart.mul - ERROR\nDATAEND!");
exit;
}
$this->Gump_Idx = fopen("../../MulFiles/gumpidx.mul", "rb");
if ($this->Gump_Idx == FALSE)
{
if($this->Debug)
$this->Logs[]="Failed! (GumpIdx.mul)";
fclose($this->Hues_Mul);
fclose($this->TileData_Mul);
fclose($this->Gump_Mul);
die("Unable to open gumpidx.mul - ERROR\nDATAEND!");
exit;
}
if($this->Debug)
$this->Logs[]="Done!";
}
function BuildGump()
{
if($this->Debug)
{
$this->Logs[]="Building The Gump...";
$this->Logs[]="Verifying Mul Files:";
$this->Logs[]="TileData: ".$this->TileData_Mul;
$this->Logs[]="Hues: ".$this->Hues_Mul;
$this->Logs[]="Gump: ".$this->Gump_Mul;
$this->Logs[]="Gump Index: ".$this->Gump_Idx;
$this->Logs[]="Done!";
}
$this->InitializeGump($this->Width,$this->Height);
if($this->Debug)
$this->Logs[]="Parsing Values...";
if (strpos($this->Index, ","))
{
$RawIndex = explode(",", $this->Index);
$RawFemale = explode(",", $this->Female);
$RawHue = explode(",", $this->Hue);
$RawGump = explode(",", $this->Gump);
if($this->Debug)
$this->Logs[]="Done!";
}
else
{
$RawIndex = array($this->Index);
$RawFemale = array($this->Female);
$RawHue = array($this->Hue);
$RawGump = array($this->Gump);
if($this->Debug)
$this->Logs[]="Done!";
}
if($this->Debug)
$this->Logs[]="Parsing Each Item...";
for ($i = 0; $i < sizeof($RawIndex); $i++)
{
$Index = (int)$RawIndex[$i];
$Female = (int)$RawFemale[$i];
$Hue = (int)$RawHue[$i];
$IsGump = (int)$RawGump[$i];
if ($Female >= 1)
$Female = 1;
else
$Female = 0;
if ($Hue < 1 || $Hue > 65535)
$Hue = 0;
if($IsGump > 0 || $Index == 12 || $Index == 13)
$IsGump = 1;
else
$IsGump = 0;
if($this->Debug)
$this->Logs[]="Index: ".$Index." * Female: ".$Female." * Hue: ".$Hue." * Gump: ".$IsGump;
if ($Index > 0x3FFF || $Index <= 0 || $Hue > 65535 || $Hue < 0)
continue;
if ($IsGump == 1) // Male/Female Gumps or Gump Param
{
$GumpID = $Index;
}
else
{
$Group = (int)($Index / 32);
$GroupIdx = $Index % 32;
fseek($this->TileData_Mul, 512 * 836 + 1188 * $Group + 4 + $GroupIdx * 37, SEEK_SET);
if (feof($this->TileData_Mul))
continue;
// Read the flags
$Flags = $this->GetValueFromFile($this->TileData_Mul, 4);
if ($Flags == -1)
{
if($this->Debug)
$this->Logs[]="Flags Say VOID, move to next Item...";
continue;
}
if ($Flags & 0x404002)
{
fseek($this->TileData_Mul, 6, SEEK_CUR);
$GumpID = $this->GetValueFromFile($this->TileData_Mul, 2);
$GumpID = ($GumpID & 0xFFFF);
if ($GumpID > 65535 || $GumpID <= 0)
{
if($this->Debug)
$this->Logs[]="Gump ID is Invalid, move to next Item...";
continue;
}
if ($GumpID < 10000)
{
if ($Female == 1)
$GumpID += 60000;
else
$GumpID += 50000;
}
}
else
{
if($this->Debug)
$this->Logs[]="Flags Say NOT WEARABLE, move to next Item...";
continue;
}
}
if($this->Debug)
$this->Logs[]="Load The Raw Gump...";
$this->LoadRawGump((int)$GumpID, (int)$Hue);
}
}
function LoadRawGump($GumpID, $Hue)
{
$SendData = '';
$Color32 = Array();
fseek($this->Gump_Idx, $GumpID * 12, SEEK_SET);
if (feof($this->Gump_Idx))
return; // Invalid gumpid, reached end of gumpindex.
$LookUp = $this->GetValueFromFile($this->Gump_Idx, 4);
if ($LookUp == -1)
{
if ($Index >= 60000)
$Index -= 10000;
fseek($this->Gump_Idx, $GumpID * 12, SEEK_SET);
if (feof($this->Gump_Idx)) // Invalid gumpid, reached end of gumpindex.
return;
$LookUp = $this->GetValueFromFile($this->Gump_Idx, 4);
if ($LookUp == -1)
return; // Gumpindex returned invalid lookup.
}
$GumpSize = $this->GetValueFromFile($this->Gump_Idx, 4);
$GumpExtra = $this->GetValueFromFile($this->Gump_Idx, 4);
fseek($this->Gump_Idx, $GumpID * 12, SEEK_SET);
$GumpWidth = (($GumpExtra >> 16) & 0xFFFF);
$GumpHeight = ($GumpExtra & 0xFFFF);
$SendData.= sprintf("Lookup: ".$LookUp."\n");
$SendData.= sprintf("Size: ".$GumpSize."\n");
$SendData.= sprintf("Height: ".$GumpHeight."\n");
$SendData.= sprintf("Width: ".$GumpWidth."\n");
if ($GumpHeight <= 0 || $GumpWidth <= 0)
return; // Gump width or height was less than 0.
fseek($this->Gump_Mul, $LookUp, SEEK_SET);
$HeightTable = $this->GetValueFromFile($this->Gump_Mul, ($GumpHeight * 4));
if (feof($this->Gump_Mul))
return; // Invalid gumpid, reached end of gumpfile.
$SendData.= sprintf("DATASTART:\n");
if ($Hue <= 0)
{
if($this->Debug)
{
$this->Logs[]="No Hue Recolor Needed...";
}
for ($Y = 1; $Y < $GumpHeight; $Y++)
{
fseek($this->Gump_Mul, $HeightTable[$Y] * 4 + $LookUp, SEEK_SET);
// Start of row
$X = 0;
while ($X < $GumpWidth)
{
$RLE = $this->GetValueFromFile($this->Gump_Mul, 4); // Read the RLE data
$Length = ($RLE >> 16) & 0xFFFF; // First two bytes - how many pixels does this color cover
$Color = $RLE & 0xFFFF; // Second two bytes - what color do we apply
// Begin RGB value decoding
$R = (($Color >> 10)*8);
$G = (($Color >> 5) & 0x1F)*8;
$B = ($Color & 0x1F)*8;
if ($R > 0 || $G > 0 || $B > 0)
$SendData.= sprintf($X.":".$Y.":".$R.":".$G.":".$B.":".$Length."***");
$X = $X + $Length;
}
}
}
else
{
if($this->Debug)
{
$this->Logs[]="Use the Hues File to Get Hue...";
}
$Hue = $Hue - 1;
$OriginalHue = $Hue;
if ($Hue > 0x8000)
$Hue = $Hue - 0x8000;
if ($Hue > 3001) // Bad hue will cause a crash
$Hue = 1;
$Colors = (int)($Hue / 8) * 4;
$Colors = 4 + $Hue * 88 + $Colors;
if($this->Debug)
{
$this->Logs[]="COLOR: ".$Colors;
}
fseek($this->Hues_Mul, $Colors, SEEK_SET);
for ($i = 0; $i < 32; $i++)
{
$Color32[$i] = $this->GetValueFromFile($this->Hues_Mul, 2);
$Color32[$i] |= 0x8000;
}
for ($Y = 1; $Y < $GumpHeight; $Y++)
{
fseek($this->Gump_Mul, $HeightTable[$Y] * 4 + $LookUp, SEEK_SET);
// Start of row
$X = 0;
while ($X < $GumpWidth)
{
$RLE = $this->GetValueFromFile($this->Gump_Mul, 4); // Read the RLE data
$Length = ($RLE >> 16) & 0xFFFF; // First two bytes - how many pixels does this color cover
$Color = $RLE & 0xFFFF; // Second two bytes - what color do we apply
// Begin RGB value decoding
$R = (($Color >> 10));
$G = (($Color >> 5) & 0x1F);
$B = ($Color & 0x1F);
// Check if we're applying a special hue (skin hues), if so, apply only to grays
if (($OriginalHue > 0x8000) && ($R == $G && $R == $B))
{
$NewR = (($Color32[$R] >> 10))*8;
$NewG = (($Color32[$R] >> 5) & 0x1F)*8;
$NewB = ($Color32[$R] & 0x1F)*8;
}
else if ($OriginalHue > 0x8000)
{
$NewR = $R * 8;
$NewG = $G * 8;
$NewB = $B * 8;
}
else
{
$NewR = (($Color32[$R] >> 10))*8;
$NewG = (($Color32[$R] >> 5) & 0x1F)*8;
$NewB = ($Color32[$R] & 0x1F)*8;
}
if((($R * 8) > 0) || (($G * 8) > 0) || (($B * 8) > 0))
$SendData.= sprintf($X.":".$Y.":".$NewR.":".$NewG.":".$NewB.":".$Length."***");
$X += $Length;
}
}
}
$SendData.= sprintf("DATAEND!");
$this->AddGump($SendData);
}
function InitializeGump($width,$height)
{
$this->Image_Temp = imagecreatefrompng("../../images/paperdolls/rpk_pdoll_".$this->PdollBG.".png") or die("couldnt create image");
$TransColor = imagecolorallocate($this->Image_Temp, 255, 64, 255);
imageColorTransparent($this->Image_Temp, $TransColor);
imagealphablending($this->Image_Temp, TRUE);
}
function FormatText()
{
// Separate name and skill title
$this->NameTitle = $this->striphtmlchars($this->NameTitle);
if (($i = strpos($this->NameTitle, ",")) !== FALSE)
{
$this->Name = substr($this->NameTitle, 0, $i);
$this->Title = substr($this->NameTitle, $i + 2);
}
else
{
$ToRemove = array("(Order)","(Chaos)");
$TextResult = str_replace($ToRemove,"",$this->NameTitle);
$this->Name = $this->Char['name'];
$this->Title = "";
}
}
function KillFiles()
{
fclose($this->Hues_Mul);
fclose($this->TileData_Mul);
fclose($this->Gump_Mul);
fclose($this->Gump_Idx);
exit;
}
function GetValueFromFile($File, $Length)
{
if (($Value = fread($File, $Length)) == FALSE)
{
if($this->Debug)
$this->Logs[]="Get Value From File returned VOID...";
return -1;
}
switch($Length)
{
case 4: $Value = unpack('l', $Value); break;
case 2: $Value = unpack('s', $Value); break;
case 1: $Value = unpack('c', $Value); break;
default: $Value = unpack('l*', $Value); return $Value;
}
if($this->Debug)
$this->Logs[]="Get Value From ".($File==$this->TileData_Mul ? "TileData:" : ($File==$this->Hues_Mul ? "Hues:" : ($File==$this->Gump_Mul ? "Gump:" : ($File==$this->Gump_Idx ? "GumpIndex:" : "File"))))." returned ".($Value[1])."...";
return ($Value[1]);
}
function AddGump($SendData)
{
if (strpos($SendData, "ERROR"))
{
if($this->Debug)
{
$Logs[]="Add Gump: Returned ERROR in DataStream";
}
return;
}
$Data = explode("DATASTART:\n", $SendData);
$Data = $Data[1];
$NewData = explode("***", $Data);
while (list($Key, $Val) = @each($NewData))
{
if($this->Debug)
{
$Logs[]="Add Gump: Key:".$Key." + Val: ".$Val;
}
if ($Val == "DATAEND!")
break;
$Val = explode(":", $Val);
$X = (int)($Val[0]);
$Y = (int)($Val[1]);
$R = (int)($Val[2]);
$G = (int)($Val[3]);
$B = (int)($Val[4]);
$Length = (int)($Val[5]); // pixel color repeat length
if ($R || $G || $B)
{
$ColorAllocate = imagecolorallocate($this->Image_Temp, $R, $G, $B);
for ($i = 0; $i < $Length; $i++)
imagesetpixel($this->Image_Temp, $X+$i, $Y, $ColorAllocate);
}
}
}
function AddText()
{
$TextColor = imagecolorallocate($this->Image_Temp, 255, 255, 0);
$Pos = (int) (135 - (strlen($this->Name) * 3.5));
if ($Pos < 0)
$Pos = 0;
imagestring($this->Image_Temp, 4, $Pos, 240, $this->Name, $TextColor);
$Pos = (int) (140 - (strlen($this->Title) * 3.5));
if ($Pos < 0)
$Pos = 0;
imagestring($this->Image_Temp, 3, $Pos, 255, $this->Title, $TextColor);
$TextColor = imagecolorallocate($this->Image_Temp, 255, 255, 0);
imagestring($this->Image_Temp, 2, 171, 100, 'Race: '.substr($this->Char['race'], 0, 10), $TextColor);
imagestring($this->Image_Temp, 2, 171, 129, 'Guild: '.($this->Char['guild_abbr']=="NULL" ? "None" : substr($this->Char['guild_abbr'], 0, 10) ), $TextColor);
imagestring($this->Image_Temp, 2, 171, 157, 'Level: 100', $TextColor);
imagestring($this->Image_Temp, 2, 171, 185, 'Rank: 1,437', $TextColor);
imagestring($this->Image_Temp, 2, 171, 212, number_format($this->Char['gametime']).'H', $TextColor);
}
function CreateGump()
{
Header("Content-type: image/png");
imagepng($this->Image_Temp);
imagedestroy($this->Image_Temp);
}
function striphtmlchars($Text)
{
$Text = str_replace("&", "&", $Text);
$Text = str_replace("'", "'", $Text);
return $Text;
}
}
?>