UPDATE: Code clean up, added a few tweaks, including a cached image file! Enjoy.
Code
<?php
/***********************************************************
* READ: png files are best to use for dynamics *
* Class images are only supported with .png *
* Animated /gifs do not work with dynamics! *
* created by kaspir@jsp *
************************************************************/
/******************************************************
* BASICS *
*******************************************************/
// general settings
$char_id = '115079'; // number in character url after the i=
$img_fn = 'bg'; // only the filename of background image file, with no file extension (do not use jpeg however -- only png, gif, jpg supported)
$img_url = 'http://www.thetopfew.com/LS/renders/class/'; // set path to your class images folder
$in_guild = false; // are you in a guild?
$guild_id = '768'; // if so, what's the number in guild url after the i=
$cachetime = 5*60; // 5min default (set to 0 while testing)
// get background image file name extension without knowing it (change nothing here)
$img_info = pathinfo(get_filename($img_fn));
$img_type = $img_info['extension'];
$image = $img_fn.'.'.$img_type;
// load correct image header & disable header cache (FYI: I still disable image cache in .htaccess file)
header ('Content-type: image/'.$img_type.'');
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
header('Pragma: no-cache');
// serve from the cached image if it is younger than $cachetime
$cache_fn = 'cachefile';
$cachefile = $cache_fn.'.'.$img_type;
if (file_exists($cachefile) && (time() - $cachetime < filemtime($cachefile))) { readfile($cachefile); exit; }
// if cache file doesn't exist or is too old, script is loaded and buffer is started.
ob_start(); //OB is built in buffer to store info with php, this starts the storage
// create the image from any supported background type (FYI: only png backgrounds support char class images)
if ($img_type == 'png') { $image = imagecreatefrompng($image); }
if ($img_type == 'gif') { $image = imagecreatefromgif($image); }
if ($img_type == 'jpg') { $image = imagecreatefromjpeg($image); }
// set some colors for future use
$red = imagecolorallocate($image, 235, 64, 52);
$cool = imagecolorallocate($image, 81, 86, 96);
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
// set font(s)
$font = '/batmanforever.ttf';
/******************************************************
* LOAD DATA *
*******************************************************/
// create array for classes
$class_name = array(
-1 => 'None',
0 => 'Fighter',
1 => 'Barbarian',
2 => 'Rogue',
3 => 'Magician',
4 => 'Guardian',
5 => 'Samurai',
6 => 'Paladin',
7 => 'Monk',
8 => 'Ninja',
9 => 'Warlock',
10 => 'Headhunter',
11=> 'Alchemist');
// create array for class images (WARNING: png files only!)
$class_img = array(
-1 => $img_url.'blank.png',
0 => $img_url.'0.png',
1 => $img_url.'1.png',
2 => $img_url.'2.png',
3 => $img_url.'3.png',
4 => $img_url.'4.png',
5 => $img_url.'5.png',
6 => $img_url.'6.png',
7 => $img_url.'7.png',
8 => $img_url.'8.png',
9 => $img_url.'9.png',
10 => $img_url.'10.png',
11 => $img_url.'11.png');
// load xml data
if ($in_guild == true) $guild = simplexml_load_file('http://ladderslasher.d2jsp.org/xmlGuild.php?i='.$guild_id, 'SimpleXMLElement', LIBXML_NOCDATA);
$data = simplexml_load_file('http://ladderslasher.d2jsp.org/xmlChar.php?i='.$char_id, 'SimpleXMLElement', LIBXML_NOCDATA);
// create an array for proficiencies
$temp = explode(";", $data->cprof);
foreach ((array) $temp as $value) {
$temp2 = explode(",", $value);
$cprof[(int)$temp2[0]] = (int)$temp2[1];
}
$temp3 = explode(";", $data->wprof);
foreach ((array) $temp3 as $value) {
$temp4 = explode(",", $value);
$wprof[(int)$temp4[0]] = (int)$temp4[1];
}
$temp5 = explode(";", $data->sprof);
foreach ((array) $temp5 as $value) {
$temp6 = explode(",", $value);
$sprof[(int)$temp6[0]] = (int)$temp6[1];
}
// assign character data to variables
if ($in_guild == true) $jsp_name = $guild->member[1]->attributes()->name; else $jsp_name = 'null'; // only assign if guild member
if ($in_guild == true) $gps = $guild->member[1]->attributes()->gps; else $gps = 'null'; // only assign if guild member
$id = (int)$data->id;
$name = $data->name;
if ((int)$data->core == 0) { $core = 'SC'; } else { $core = 'HC'; }
$class_id = (int)$data->classid;
$class = $class_name[$class_id];
$class_img = $class_img[$class_id];
$level = (int)$data->level;
$exp = (int)$data->exp;
$kills = (int)$data->kills;
$deaths = (int)$data->deaths;
$lastclick = (int)$data->lastaction; // FIXME: break down first before using
$str = (int)$data->strength;
$dex = (int)$data->dexterity;
$vita = (int)$data->vitality;
$intel = (int)$data->intelligence;
$hpmax = (int)$data->hpmax;
$mpmax = (int)$data->mpmax;
$mqpasses = $data->mqpasses;
$mqattempts = $data->mqattempts;
// profs below
$sword = $wprof[0];
$club = $wprof[1];
$axe = $wprof[2];
$dagger = $wprof[3];
$staff = $wprof[4];
$longsword = $wprof[5];
$warhammer = $wprof[6];
$battleaxe = $wprof[7];
$spear = $wprof[8];
$polearm = $wprof[9];
$ice = $cprof[0];
$fire = $cprof[1];
$lightning = $cprof[2];
$wind = $cprof[3];
$earth = $cprof[4];
$wheal = $cprof[5];
$heal = $cprof[6];
$focus = $cprof[7];
$fishing = $sprof[0];
$cooking = $sprof[1];
$glyphing = $sprof[2];
$transmuting = $sprof[3];
$suffusencing = $sprof[4];
//FYI: If char's prof is 0.00% it will not display
/*************************************************************
* LEVEL PROGRESS BAR /w Background *
*************************************************************/
// set your x and y coordinates here
//# Example: $mqbar_specs = array(left indent, bar end, top indent, top ends, background color, fill color)
$lvlbar_specs = array(194, 346, 57, 53, $cool, $white); // adjust here
//drawLvlBar($image, $exp, $level, $lvlbar_specs); // turn on here
/***********************************************************
* MQ PROGRESS BAR /w Background *
***********************************************************/
// mq progress bar: adjust position, size & draw
//# Example: $mqbar_specs = array(left indent, bar end, top indent, top ends, background color, fill color)
$mqbar_specs = array(194, 346, 57, 53, $cool, $white); // adjust here
drawMqBar($image, $class_id, $level, $mqbar_specs); // turn on here
/***********************************************************
* CLASS IMAGE OVERLAY *
***********************************************************/
// class image: adjust position, size, opacity & attach image
//# Example: $img_specs = array(left indent, top indent, set width, set height, opacity 1-100)
$img_specs = array(158, 6, 60, 90, 100); // adjust here
imgAdjustLoad($image, $class_img, $img_specs); // turn on here
/******************************************************
* TEXT PART *
******************************************************/
//Example; ImageTTFText ($image, textsize, angle, right indent, down indent, color, font, "text");
// show player core
ImageTTFText ($image, 12, 40, 327, 92, $red, $font, $core);
// show experience to next lvl and a percent.
//ImageTTFText ($image, 6, 0, 290, 58, $black, $font, "Next Lvl ");
//ImageTTFText ($image, 9, 0, 290, 72, $white, $font, calcExpPercent($exp)."%");
// show mq percent
ImageTTFText ($image, 6, 0, 290, 58, $black, $font, "Till MQ ");
ImageTTFText ($image, 9, 0, 295, 72, $white, $font, get_MqPercent(getMqLevel($class_id), $level)."%");
// show d2jsp name (warning, must be in a guild for this to work!)
//ImageTTFText ($image, 9, 0, 100, 100, $white, $font, $jsp_name);
// show name
//ImageTTFText ($image, 9, 0, 122, 33, $white, $font, "Name: ");
//ImageTTFText ($image, 9, 0, 180, 33, $white, $font, $name);
// show class
//ImageTTFText ($image, 9, 0, 200, 33, $white, $font, "Class: ");
ImageTTFText ($image, 11, 0, 210, 46, $white, $font, $class);
// show lvl
//ImageTTFText ($image, 9, 0, 300, 46, $white, $font, "Lvl: ");
//ImageTTFText ($image, 9, 0, 324, 46, $white, $font, $level);
// show experience
//ImageTTFText ($image, 9, 0, 180, 45, $white, $font, "Experience: ");
//ImageTTFText ($image, 9, 0, 250, 45, $white, $font, $exp);
// show kills
ImageTTFText ($image, 10, 0, 210, 31, $white, $font, "Kills: ");
ImageTTFText ($image, 10, 0, 256, 31, $white, $font, $kills);
// show HP max
//ImageTTFText ($image, 9, 0, 122, 57, $white, $font, "HP: ");
//ImageTTFText ($image, 9, 0, 145, 57, $white, $font, $hpmax);
// show MQ passen and attempts
//ImageTTFText ($image, 9, 0, 242, 57, $white, $font, "MQ: ");
ImageTTFText ($image, 11, 0, 240, 101, $white, $font, $mqpasses."/".$mqattempts);
// whatever words you might want to display
//ImageTTFText ($image, 15, 0, 122, 82, $white, $font, "Whatever");
//ImageTTFText ($image, 15, 0, 122, 95, $white, $font, "You Want");
// show guild points (warning, must be in a guild for this to work!)
//ImageTTFText ($image, 12, 0, 260, 140, $white, $font, "Guild GPs: ");
//ImageTTFText ($image, 14, 0, 100, 100, $white, $font, $gps);
// show proficiencies
ImageTTFText ($image, 10, 0, 18, 19, $white, $font, $sword); // sword
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $club); // club
ImageTTFText ($image, 11, 0, 18, 43, $white, $font, $axe); // axe
ImageTTFText ($image, 10, 0, 18, 65, $white, $font, $dagger); // dagger
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $staff); // staff
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $longsword); // longsword
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $warhammer); // warhammer
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $battleaxe); // battleaxe
ImageTTFText ($image, 11, 0, 330, 120, $white, $font, $spear); // spear
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $polearm); // polearm
ImageTTFText ($image, 10, 0, 226, 120, $white, $font, $ice); // ice
ImageTTFText ($image, 10, 0, 255, 120, $white, $font, $fire); // fire
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $lightning); // lightning
//ImageTTFText ($image, 10, 0, 46, 139, $white, $font, $wind); // wind
//ImageTTFText ($image, 10, 0, 80, 26, $white, $font, $earth); // earth
//ImageTTFText ($image, 10, 0, 15, 79, $white, $font, $wheal); // wild heal
//ImageTTFText ($image, 10, 0, 106, 26, $white, $font, $heal); // heal
ImageTTFText ($image, 10, 0, 286, 120, $white, $font, $focus); // focus heal
//ImageTTFText ($image, 10, 0, 46, 79, $white, $font, $fishing); // fishing
//ImageTTFText ($image, 10, 0, 15, 119, $white, $font, $cooking); // cooking
//ImageTTFText ($image, 10, 0, 330, 120, $white, $font, $glyphing); // glyphing
//ImageTTFText ($image, 10, 0, 46, 119, $white, $font, $transmuting); // transmuting
//ImageTTFText ($image, 10, 0, 270, 125, $white, $font, $suffusencing); // suffusencing
/******************************************************
* FUNCTIONS (DO NOT EDIT) *
******************************************************/
/***
* Get our image extension without knowing it.
***/
function get_filename($fn) {
$exts = array('gif', 'png', 'jpg');
foreach($exts as $ext) {
if (file_exists($fn.".".$ext)) {
$filename = $fn.".".$ext;
}
}
return $filename;
}
/***
* Draw a level (exp) progress bar.
***/
function drawLvlBar($image, $exp, $level, $specs) {
$barpixelX = calcBarPixelX($specs[0], $specs[1], calcExpPercent($exp));
// Image, x-coorinate for point 1, y-coorinate for point 1, x-coorinate for point 2, y-coorinate for point 2, color
imagefilledrectangle($image, $specs[0], $specs[2], $specs[1], $specs[3], $specs[4]); // background
imagefilledrectangle($image, $specs[0], $specs[2], $barpixelX, $specs[3], $specs[5]); // current fill
}
/***
* Draw a MQ progress bar.
***/
function drawMqBar($image, $class_id, $level, $specs) {
$mq_barpixelX = calcBarPixelX($specs[0], $specs[1], get_MqPercent(getMqLevel($class_id), $level));
// Image, x-coorinate for point 1, y-coorinate for point 1, x-coorinate for point 2, y-coorinate for point 2, color
imagefilledrectangle($image, $specs[0], $specs[2], $specs[1], $specs[3], $specs[4]); // background
imagefilledrectangle($image, $specs[0], $specs[2], $mq_barpixelX, $specs[3], $specs[5]); // current fill
}
/***
* Get required MQ level based on class.
***/
function getMqLevel($class_id) {
$mq_lvlreq = 71; // default
if ($class_id == 5) { $mq_lvlreq = 73; } // Samurai
if ($class_id == 6) { $mq_lvlreq = 75; } // Paladin
if ($class_id == 7) { $mq_lvlreq = 77; } // Monk
if ($class_id == 8) { $mq_lvlreq = 79; } // Ninja
if ($class_id == 9) { $mq_lvlreq = 81; } // Warlock
if ($class_id == 10) { $mq_lvlreq = 83; } // Headhunter
if ($class_id == 11) { $mq_lvlreq = 85; } // Alchemist
return $mq_lvlreq;
}
/***
* Carry out all class image operations. Resize, preserve, clip both, merge, load & destroy.
***/
function imgAdjustLoad($image, $img, $specs) {
// get actual image dimensions
list($width_orig, $height_orig) = getimagesize($img);
// preserve image size ratio & assign new var
list($new_width, $new_height) = preserveImgRatio($specs[2], $specs[3], $width_orig, $height_orig);
// create class image & resize while preserving transparency
$img = imagecreatefrompng($img);
$img = resizePng($img, $new_width, $new_height);
// create a clipping area
$cut = imagecreatetruecolor($width_orig, $height_orig);
// clip section from background
imagecopy($cut, $image, 0, 0, $specs[0], $specs[1], $width_orig, $height_orig);
// clip section from class image
imagecopy($cut, $img, 0, 0, 0, 0, $new_width, $new_height);
// merge cut & load, then destroy
imagecopymerge($image, $cut, $specs[0], $specs[1], 0, 0, $width_orig, $height_orig, $specs[4]);
imagedestroy($img);
}
/***
* Preserve image proportion ratio.
***/
function preserveImgRatio($width, $height, $width_orig, $height_orig) {
$ratio_orig = $width_orig / $height_orig;
if ($width / $height > $ratio_orig) {
$width = $height * $ratio_orig;
} else {
$height = $width / $ratio_orig;
}
return array($width, $height);
}
/***
* Calculate the percentage of level done.
***/
function calcExpPercent($input) {
$temp1 = fmod($input, 1000000);
$temp1 = ($temp1 / 1000000);
$temp1 = $temp1 * 100;
return (int)$temp1;
}
/***
* Calculate percent till MQ.
***/
function get_MqPercent($mq_lvlreq, $level) {
if ($mq_lvlreq > 0) {
return round($level / ($mq_lvlreq / 100), 0); // 0 is # of decimals we want
} else {
return 1; // this can not be 0, cause we use this output in multiplication later on
}
}
/***
* Calculate the current fill bar width. Used for both EXP and MQ bars. (kaspir@jsp)
***/
function calcBarPixelX($first_x, $second_x, $percent) {
$bar_width = $second_x - $first_x; // actual bar width in pixels
$bar_grow = ($bar_width / 100);
$total = round($bar_grow * $percent) + $first_x;
return (int)$total;
}
/***
* Resize a png and keep transparency. Credit goes to: https://stackoverflow.com/users/1998322/michael
***/
function resizePng($im, $dst_width, $dst_height) {
$width = imagesx($im);
$height = imagesy($im);
$newImg = imagecreatetruecolor($dst_width, $dst_height);
imagealphablending($newImg, false);
imagesavealpha($newImg, true);
$transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
imagefilledrectangle($newImg, 0, 0, $width, $height, $transparent);
imagecopyresampled($newImg, $im, 0, 0, 0, 0, $dst_width, $dst_height, $width, $height);
return $newImg;
}
// output and destroy image(s)
if ($img_type == 'png') { imagepng($image); }
if ($img_type == 'gif') { imagegif($image); }
if ($img_type == 'jpg') { imagejpeg($image); }
imagedestroy($image);
// save the contents of output buffer to the cache file
$fp = fopen($cachefile, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
// send the output to the browser
ob_end_flush();
?>
FYI: Guild charter service is ready to go also! (no plans on sharing this script)