From 913b4297cf2afd5c0511f0d6e214aa69c2648e80 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 19 Oct 2017 17:11:49 +0200 Subject: [PATCH] * added new tooltip to view characters equipment item name * this requires loaded items - go to admin panel and select Items menu, then reload * added items.xml loader class and weapons.xml loader class * load also runes into spells table * (internal) changed spells.vocations database field to store json data instead of comma separated * (internal) renamed existing Items class to Items_Images --- admin/template/template.php | 1 + common.php | 2 +- install/includes/schema.sql | 26 +- system/functions.php | 11 +- system/item.php | 14 +- system/libs/items.php | 361 ++++++---------- system/libs/items_images.php | 266 ++++++++++++ system/libs/pot/OTS_Spell.php | 43 +- system/libs/spells.php | 85 ++-- system/libs/weapons.php | 82 ++++ system/migrations/12.php | 49 +++ system/pages/admin/items.php | 31 ++ system/pages/spells.php | 18 +- system/templates/admin.items.html.twig | 4 + system/templates/characters.html.twig | 23 + tools/tipped.css | 568 +++++++++++++++++++++++++ tools/tipped.js | 11 + 17 files changed, 1297 insertions(+), 298 deletions(-) create mode 100644 system/libs/items_images.php create mode 100644 system/libs/weapons.php create mode 100644 system/migrations/12.php create mode 100644 system/pages/admin/items.php create mode 100644 system/templates/admin.items.html.twig create mode 100755 tools/tipped.css create mode 100755 tools/tipped.js diff --git a/admin/template/template.php b/admin/template/template.php index 2ef48f79..811d97c5 100644 --- a/admin/template/template.php +++ b/admin/template/template.php @@ -43,6 +43,7 @@ 'Statistics' => 'statistics', 'Visitors' => 'visitors', 'Players' => 'players', + 'Items' => 'items', 'Tools' => array( 'phpinfo' => 'phpinfo' ), diff --git a/common.php b/common.php index b70b1909..39a4abfe 100644 --- a/common.php +++ b/common.php @@ -28,7 +28,7 @@ session_start(); define('MYAAC', true); define('MYAAC_VERSION', '0.6.1'); -define('DATABASE_VERSION', 11); +define('DATABASE_VERSION', 12); define('TABLE_PREFIX', 'myaac_'); define('START_TIME', microtime(true)); define('MYAAC_OS', (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'WINDOWS' : (strtoupper(PHP_OS) == 'DARWIN' ? 'MAC' : 'LINUX')); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index 4a07cde5..46d56dd9 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -128,6 +128,16 @@ CREATE TABLE `myaac_hooks` PRIMARY KEY (`id`) ) ENGINE = MyISAM; +CREATE TABLE `myaac_items` +( + `id` INT(11) NOT NULL, + `article` VARCHAR(5) NOT NULL DEFAULT '', + `name` VARCHAR(50) NOT NULL DEFAULT '', + `plural` VARCHAR(50) NOT NULL DEFAULT '', + `attributes` VARCHAR(500) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE = MyISAM; + CREATE TABLE `myaac_monsters` ( `id` int(11) NOT NULL AUTO_INCREMENT, `hide_creature` tinyint(1) NOT NULL default '0', @@ -235,17 +245,18 @@ CREATE TABLE `myaac_spells` `name` VARCHAR(255) NOT NULL, `words` VARCHAR(255) NOT NULL, `category` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - attack, 2 - healing, 3 - summon, 4 - supply, 5 - support', - `type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - rune', + `type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune', `level` INT(11) NOT NULL DEFAULT 0, `maglevel` INT(11) NOT NULL DEFAULT 0, `mana` INT(11) NOT NULL DEFAULT 0, `soul` TINYINT(3) NOT NULL DEFAULT 0, `conjure_count` TINYINT(3) NOT NULL DEFAULT 0, + `item_id` INT(11) NOT NULL DEFAULT 0, `premium` TINYINT(1) NOT NULL DEFAULT 0, - `vocations` VARCHAR(32) NOT NULL, + `vocations` VARCHAR(100) NOT NULL DEFAULT '', `hidden` TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (`id`), - UNIQUE (`spell`) + UNIQUE (`name`) ) ENGINE = MyISAM; CREATE TABLE `myaac_visitors` @@ -255,3 +266,12 @@ CREATE TABLE `myaac_visitors` `page` VARCHAR(100) NOT NULL, UNIQUE (`ip`) ) ENGINE = MyISAM; + +CREATE TABLE `myaac_weapons` +( + `id` INT(11) NOT NULL, + `level` INT(11) NOT NULL DEFAULT 0, + `maglevel` INT(11) NOT NULL DEFAULT 0, + `vocations` VARCHAR(100) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE = MyISAM; diff --git a/system/functions.php b/system/functions.php index ac6e318a..5660289e 100644 --- a/system/functions.php +++ b/system/functions.php @@ -119,12 +119,21 @@ function getGuildLink($name, $generate = true) function getItemImage($id, $count = 1) { + global $db; + + $tooltip = ''; + $query = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'items` WHERE `id` = ' . $db->quote($id) . ' LIMIT 1;'); + if($query->rowCount() == 1) { + $item = $query->fetch(); + $tooltip = ' class="tooltip" title="' . $item['name'] . '"'; + } + $file_name = $id; if($count > 1) $file_name .= '-' . $count; global $config; - return ' ' .$id . ''; + return ' ' .$id . ''; } function getFlagImage($country) diff --git a/system/item.php b/system/item.php index fcca1059..168e69aa 100644 --- a/system/item.php +++ b/system/item.php @@ -9,17 +9,17 @@ * @link http://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -require_once(SYSTEM . 'libs/items.php'); +require_once(SYSTEM . 'libs/items_images.php'); -Items::$files = array( +Items_Images::$files = array( 'otb' => SYSTEM . 'data/items.otb', 'spr' => SYSTEM . 'data/Tibia.spr', 'dat' => SYSTEM . 'data/Tibia.dat' ); -Items::$outputDir = BASE . 'images/items/'; +Items_Images::$outputDir = BASE . 'images/items/'; function generateItem($id = 100, $count = 1) { - Items::generate($id, $count); + Items_Images::generate($id, $count); } function itemImageExists($id, $count = 1) @@ -31,7 +31,7 @@ function itemImageExists($id, $count = 1) if($count > 1) $file_name .= '-' . $count; - $file_name = Items::$outputDir . $file_name . '.gif'; + $file_name = Items_Images::$outputDir . $file_name . '.gif'; return file_exists($file_name); } @@ -43,7 +43,7 @@ function outputItem($id = 100, $count = 1) if(!itemImageExists($id, $count)) { //echo 'plik istnieje'; - Items::generate($id, $count); + Items_Images::generate($id, $count); } $expires = 60 * 60 * 24 * 30; // 30 days @@ -56,7 +56,7 @@ function outputItem($id = 100, $count = 1) if($count > 1) $file_name .= '-' . $count; - $file_name = Items::$outputDir . $file_name . '.gif'; + $file_name = Items_Images::$outputDir . $file_name . '.gif'; readfile($file_name); } ?> diff --git a/system/libs/items.php b/system/libs/items.php index 77f38247..1804d655 100644 --- a/system/libs/items.php +++ b/system/libs/items.php @@ -3,6 +3,7 @@ * Items class * * @package MyAAC + * @author Gesior * @author Slawkens * @copyright 2017 MyAAC * @version 0.6.1 @@ -10,257 +11,135 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -if ( !function_exists( 'stackId' ) ) -{ - function stackId( $count ) +class Items { + private static $error = ''; + + public static function loadFromXML($show = false) { - if ( $count >= 50 ) - $stack = 8; - elseif ( $count >= 25 ) - $stack = 7; - elseif ( $count >= 10 ) - $stack = 6; - elseif ( $count >= 5 ) - $stack = 5; - elseif ( $count >= 4 ) - $stack = 4; - elseif ( $count >= 3 ) - $stack = 3; - elseif ( $count >= 2 ) - $stack = 2; - else - $stack = 1; - - return $stack; - } -} - -class Items -{ - public static $outputDir = ''; - public static $files = array(); - - private static $otb, $dat, $spr; - private static $lastItem; - private static $loaded = false; - - public function __destruct() - { - if(self::$otb) - fclose(self::$otb); - if(self::$dat) - fclose(self::$dat); - if(self::$spr) - fclose(self::$spr); - } - - public static function generate($id = 100, $count = 1) - { - if(!self::$loaded) - self::load(); - - $originalId = $id; - if($id < 100) - return false; - //die('ID cannot be lower than 100.'); - - rewind(self::$otb); - rewind(self::$dat); - rewind(self::$spr); - - $nostand = false; - $init = false; - $originalId = $id; - - // parse info from otb - while( false !== ( $char = fgetc( self::$otb ) ) ) - { - $byte = HEX_PREFIX.bin2hex( $char ); - - if ( $byte == 0xFE ) - $init = true; - elseif ( $byte == 0x10 and $init ) { - extract( unpack( 'x2/Ssid', fread( self::$otb, 4 ) ) ); - - if ( $id == $sid ) { - if ( HEX_PREFIX.bin2hex( fread( self::$otb, 1 ) ) == 0x11 ) { - extract( unpack( 'x2/Sid', fread( self::$otb, 4 ) ) ); - break; - } - } - $init = false; - } + global $config, $db; + + try { + $db->query("DELETE FROM `myaac_items`;"); + } catch (PDOException $error) { } - - self::$lastItem = array_sum( unpack( 'x4/S*', fread( self::$dat, 12 ))); - if($id > self::$lastItem) + + $file_path = $config['data_path'] . 'items/items.xml'; + if (!file_exists($file_path)) { + self::$error = 'Cannot load file ' . $file_path; return false; - - //ini_set('max_execution_time', 300); - // parse info from dat - for( $i = 100; $i <= $id; $i++ ) { - while( ( $byte = HEX_PREFIX.bin2hex( fgetc( self::$dat ) ) ) != 0xFF ) { - $offset = 0; - switch( $byte ) { - case 0x00: - case 0x09: - case 0x0A: - case 0x1A: - case 0x1D: - case 0x1E: - $offset = 2; - break; - - case 0x16: - case 0x19: - $offset = 4; - break; - - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x17: - case 0x18: - case 0x1B: - case 0x1C: - case 0x1F: - case 0x20: - break; - - default: - return false; #trigger_error( sprintf( 'Unknown .DAT byte %s (previous byte: %s; address %x)', $byte, $prev, ftell( $dat ), E_USER_ERROR ) ); - break; - } - - $prev = $byte; - fseek( self::$dat, $offset, SEEK_CUR ); - } - extract( unpack( 'Cwidth/Cheight', fread( self::$dat, 2 ) ) ); - - if ( $width > 1 or $height > 1 ) { - fseek( self::$dat, 1, SEEK_CUR ); - $nostand = true; - } - - $sprites_c = array_product( unpack( 'C*', fread( self::$dat, 5 ) ) ) * $width * $height; - $sprites = unpack( 'S*', fread( self::$dat, 2 * $sprites_c ) ); } - - if ( array_key_exists( stackId( $count ), $sprites ) ) { - $sprites = (array) $sprites[stackId( $count )]; + + $xml = new DOMDocument; + $xml->load($file_path); + + foreach ($xml->getElementsByTagName('item') as $item) { + if ($item->getAttribute('fromid')) { + for ($id = $item->getAttribute('fromid'); $id <= $item->getAttribute('toid'); $id++) { + self::parseNode($id, $item, $show); + } + } else + self::parseNode($item->getAttribute('id'), $item, $show); + + } + + return true; + } + + public static function parseNode($id, $node, $show = false) { + global $db; + + $name = $node->getAttribute('name'); + $article = $node->getAttribute('article'); + $plural = $node->getAttribute('plural'); + + $attributes = array(); + foreach($node->getElementsByTagName('attribute') as $attr) { + $attributes[strtolower($attr->getAttribute('key'))] = $attr->getAttribute('value'); + } + + $exist = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'items` WHERE `id` = ' . $id); + if($exist->rowCount() > 0) { + if($show) { + warning('Duplicated item with id: ' . $id); + } } else { - $sprites = (array) $sprites[array_rand( $sprites ) ]; + $db->insert(TABLE_PREFIX . 'items', array('id' => $id, 'article' => $article, 'name' => $name, 'plural' => $plural, 'attributes' => json_encode($attributes))); } - - fseek( self::$spr, 6 ); - - $sprite = imagecreatetruecolor( 32 * $width, 32 * $height ); - imagecolortransparent( $sprite, imagecolorallocate( $sprite, 0, 0, 0 ) ); - - foreach( $sprites as $key => $value ) { - fseek( self::$spr, 6 + ( $value - 1 ) * 4 ); - extract( unpack( 'Laddress', fread( self::$spr, 4 ) ) ); - - fseek( self::$spr, $address + 3 ); - extract( unpack( 'Ssize', fread( self::$spr, 2 ) ) ); - - list( $num, $bit ) = array( 0, 0 ); - - while( $bit < $size ) { - $pixels = unpack( 'Strans/Scolored', fread( self::$spr, 4 ) ); - $num += $pixels['trans']; - for( $i = 0; $i < $pixels['colored']; $i++ ) - { - extract( unpack( 'Cred/Cgreen/Cblue', fread( self::$spr, 3 ) ) ); - - $red = ( $red == 0 ? ( $green == 0 ? ( $blue == 0 ? 1 : $red ) : $red ) : $red ); - - imagesetpixel( $sprite, - $num % 32 + ( $key % 2 == 1 ? 32 : 0 ), - $num / 32 + ( $key % 4 != 1 and $key % 4 != 0 ? 32 : 0 ), - imagecolorallocate( $sprite, $red, $green, $blue ) ); - - $num++; - } - - $bit += 4 + 3 * $pixels['colored']; - } - } - - if ( $count >= 2 ) { - if ( $count > 100 ) - $count = 100; - - $font = 3; - $length = imagefontwidth( $font ) * strlen( $count ); - - $pos = array( - 'x' => ( 32 * $width ) - ( $length + 1 ), - 'y' => ( 32 * $height ) - 13 - ); - imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - imagestring( $sprite, $font, $pos['x'], $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - - imagestring( $sprite, $font, $pos['x'], $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); - - imagestring( $sprite, $font, $pos['x'], $pos['y'], $count, imagecolorallocate( $sprite, 219, 219, 219 ) ); - } - - $imagePath = self::$outputDir . ($count > 1 ? $originalId . '-' . $count : $originalId ) . '.gif'; - - // save image - imagegif($sprite, $imagePath); } - - public static function load() - { - if(!defined( 'HEX_PREFIX')) - define('HEX_PREFIX', '0x'); - - self::$otb = fopen(self::$files['otb'], 'rb'); - self::$dat = fopen(self::$files['dat'], 'rb'); - self::$spr = fopen(self::$files['spr'], 'rb'); - - if(!self::$otb || !self::$dat || !self::$spr) - die('ERROR: Cannot load data files.'); - /* - if ( $nostand ) - { - for( $i = 0; $i < sizeof( $sprites ) / 4; $i++ ) - { - $sprites = array_merge( (array) $sprites, array_reverse( array_slice( $sprites, $i * 4, 4 ) ) ); + + public static function getError() { + return self::$error; + } + + public static function getItem($id) { + global $db; + + $item = $db->select(TABLE_PREFIX . 'items', array('id' => $id)); + $item['attributes'] = json_decode($item['attributes']); + + return $item; + } + + public static function getDescription($id, $count = 1) { + global $config, $db; + + $item = self::getItem($id); + + $attr = $item['attributes']; + $s = ''; + if(!empty($item['name'])) { + if($count > 1) { + if($attr['showcount']) { + $s .= $count . ' '; + } + + if(!empty($item['plural'])) { + $s .= $item['plural']; + } + else if((int)$attr['showcount'] == 0) { + $s .= $item['name']; + } + else { + $s .= $item['name'] . 's'; + } + } + else { + if(!empty($item['aticle'])) { + $s .= $item['article'] . ' '; + } + + $s .= $item['name']; } } else - { - $sprites = (array) $sprites[array_rand( $sprites ) ]; + $s .= 'an item of type ' . $item['id']; + + if(strtolower($attr['type']) == 'rune') { + $query = $db->query('SELECT `level`, `maglevel`, `vocations` FROM `' . TABLE_PREFIX . 'spells` WHERE `item_id` = ' . $id); + if($query->rowCount() == 1) { + $query = $query->fetch(); + + if($query['level'] > 0 && $query['maglevel'] > 0) { + $s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by '; + } + + if(!empty(trim($query['vocations']))) { + $vocations = json_decode($query['vocations']); + if(count($vocations) > 0) { + foreach($vocations as $voc => $show) { + $vocations[$config['vocations'][$voc]] = $show; + } + } + } + else { + $s .= 'players'; + } + + $s .= ' with'; + + } } - */ - - self::$loaded = true; + return $s; } - - public static function loaded() { - return self::$loaded; - } -} +} \ No newline at end of file diff --git a/system/libs/items_images.php b/system/libs/items_images.php new file mode 100644 index 00000000..d4f51034 --- /dev/null +++ b/system/libs/items_images.php @@ -0,0 +1,266 @@ + + * @copyright 2017 MyAAC + * @version 0.6.1 + * @link http://my-aac.org + */ +defined('MYAAC') or die('Direct access not allowed!'); + +if ( !function_exists( 'stackId' ) ) +{ + function stackId( $count ) + { + if ( $count >= 50 ) + $stack = 8; + elseif ( $count >= 25 ) + $stack = 7; + elseif ( $count >= 10 ) + $stack = 6; + elseif ( $count >= 5 ) + $stack = 5; + elseif ( $count >= 4 ) + $stack = 4; + elseif ( $count >= 3 ) + $stack = 3; + elseif ( $count >= 2 ) + $stack = 2; + else + $stack = 1; + + return $stack; + } +} + +class Items_Images +{ + public static $outputDir = ''; + public static $files = array(); + + private static $otb, $dat, $spr; + private static $lastItem; + private static $loaded = false; + + public function __destruct() + { + if(self::$otb) + fclose(self::$otb); + if(self::$dat) + fclose(self::$dat); + if(self::$spr) + fclose(self::$spr); + } + + public static function generate($id = 100, $count = 1) + { + if(!self::$loaded) + self::load(); + + $originalId = $id; + if($id < 100) + return false; + //die('ID cannot be lower than 100.'); + + rewind(self::$otb); + rewind(self::$dat); + rewind(self::$spr); + + $nostand = false; + $init = false; + $originalId = $id; + + // parse info from otb + while( false !== ( $char = fgetc( self::$otb ) ) ) + { + $byte = HEX_PREFIX.bin2hex( $char ); + + if ( $byte == 0xFE ) + $init = true; + elseif ( $byte == 0x10 and $init ) { + extract( unpack( 'x2/Ssid', fread( self::$otb, 4 ) ) ); + + if ( $id == $sid ) { + if ( HEX_PREFIX.bin2hex( fread( self::$otb, 1 ) ) == 0x11 ) { + extract( unpack( 'x2/Sid', fread( self::$otb, 4 ) ) ); + break; + } + } + $init = false; + } + } + + self::$lastItem = array_sum( unpack( 'x4/S*', fread( self::$dat, 12 ))); + if($id > self::$lastItem) + return false; + + //ini_set('max_execution_time', 300); + // parse info from dat + for( $i = 100; $i <= $id; $i++ ) { + while( ( $byte = HEX_PREFIX.bin2hex( fgetc( self::$dat ) ) ) != 0xFF ) { + $offset = 0; + switch( $byte ) { + case 0x00: + case 0x09: + case 0x0A: + case 0x1A: + case 0x1D: + case 0x1E: + $offset = 2; + break; + + case 0x16: + case 0x19: + $offset = 4; + break; + + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x17: + case 0x18: + case 0x1B: + case 0x1C: + case 0x1F: + case 0x20: + break; + + default: + return false; #trigger_error( sprintf( 'Unknown .DAT byte %s (previous byte: %s; address %x)', $byte, $prev, ftell( $dat ), E_USER_ERROR ) ); + break; + } + + $prev = $byte; + fseek( self::$dat, $offset, SEEK_CUR ); + } + extract( unpack( 'Cwidth/Cheight', fread( self::$dat, 2 ) ) ); + + if ( $width > 1 or $height > 1 ) { + fseek( self::$dat, 1, SEEK_CUR ); + $nostand = true; + } + + $sprites_c = array_product( unpack( 'C*', fread( self::$dat, 5 ) ) ) * $width * $height; + $sprites = unpack( 'S*', fread( self::$dat, 2 * $sprites_c ) ); + } + + if ( array_key_exists( stackId( $count ), $sprites ) ) { + $sprites = (array) $sprites[stackId( $count )]; + } + else { + $sprites = (array) $sprites[array_rand( $sprites ) ]; + } + + fseek( self::$spr, 6 ); + + $sprite = imagecreatetruecolor( 32 * $width, 32 * $height ); + imagecolortransparent( $sprite, imagecolorallocate( $sprite, 0, 0, 0 ) ); + + foreach( $sprites as $key => $value ) { + fseek( self::$spr, 6 + ( $value - 1 ) * 4 ); + extract( unpack( 'Laddress', fread( self::$spr, 4 ) ) ); + + fseek( self::$spr, $address + 3 ); + extract( unpack( 'Ssize', fread( self::$spr, 2 ) ) ); + + list( $num, $bit ) = array( 0, 0 ); + + while( $bit < $size ) { + $pixels = unpack( 'Strans/Scolored', fread( self::$spr, 4 ) ); + $num += $pixels['trans']; + for( $i = 0; $i < $pixels['colored']; $i++ ) + { + extract( unpack( 'Cred/Cgreen/Cblue', fread( self::$spr, 3 ) ) ); + + $red = ( $red == 0 ? ( $green == 0 ? ( $blue == 0 ? 1 : $red ) : $red ) : $red ); + + imagesetpixel( $sprite, + $num % 32 + ( $key % 2 == 1 ? 32 : 0 ), + $num / 32 + ( $key % 4 != 1 and $key % 4 != 0 ? 32 : 0 ), + imagecolorallocate( $sprite, $red, $green, $blue ) ); + + $num++; + } + + $bit += 4 + 3 * $pixels['colored']; + } + } + + if ( $count >= 2 ) { + if ( $count > 100 ) + $count = 100; + + $font = 3; + $length = imagefontwidth( $font ) * strlen( $count ); + + $pos = array( + 'x' => ( 32 * $width ) - ( $length + 1 ), + 'y' => ( 32 * $height ) - 13 + ); + imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + imagestring( $sprite, $font, $pos['x'], $pos['y'] - 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + imagestring( $sprite, $font, $pos['x'] - 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + + imagestring( $sprite, $font, $pos['x'], $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'], $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + imagestring( $sprite, $font, $pos['x'] + 1, $pos['y'] + 1, $count, imagecolorallocate( $sprite, 1, 1, 1 ) ); + + imagestring( $sprite, $font, $pos['x'], $pos['y'], $count, imagecolorallocate( $sprite, 219, 219, 219 ) ); + } + + $imagePath = self::$outputDir . ($count > 1 ? $originalId . '-' . $count : $originalId ) . '.gif'; + + // save image + imagegif($sprite, $imagePath); + } + + public static function load() + { + if(!defined( 'HEX_PREFIX')) + define('HEX_PREFIX', '0x'); + + self::$otb = fopen(self::$files['otb'], 'rb'); + self::$dat = fopen(self::$files['dat'], 'rb'); + self::$spr = fopen(self::$files['spr'], 'rb'); + + if(!self::$otb || !self::$dat || !self::$spr) + die('ERROR: Cannot load data files.'); + /* + if ( $nostand ) + { + for( $i = 0; $i < sizeof( $sprites ) / 4; $i++ ) + { + $sprites = array_merge( (array) $sprites, array_reverse( array_slice( $sprites, $i * 4, 4 ) ) ); + } + } + else + { + $sprites = (array) $sprites[array_rand( $sprites ) ]; + } + */ + + self::$loaded = true; + } + + public static function loaded() { + return self::$loaded; + } +} diff --git a/system/libs/pot/OTS_Spell.php b/system/libs/pot/OTS_Spell.php index 8ff6ba9d..0ec51bdf 100644 --- a/system/libs/pot/OTS_Spell.php +++ b/system/libs/pot/OTS_Spell.php @@ -315,19 +315,50 @@ class OTS_Spell */ public function getVocations() { - $vocations = array(); + global $config; + if(!isset($config['vocation_ids'])) + $config['vocations_ids'] = array_flip($config['vocations']); + + $vocations = array(); foreach( $this->element->getElementsByTagName('vocation') as $vocation) { - if($vocation->getAttribute('id') != NULL) - $vocations[] = $vocation->getAttribute('id'); - else - $vocations[] = $vocation->getAttribute('name'); + if($vocation->getAttribute('id') != NULL) { + $voc_id = $vocation->getAttribute('id'); + } + else { + $voc_id = $config['vocations_ids'][$vocation->getAttribute('name')]; + } + + $vocations[] = $voc_id; } return $vocations; } - + + public function getVocationsFull() + { + global $config; + if(!isset($config['vocation_ids'])) + $config['vocations_ids'] = array_flip($config['vocations']); + + $vocations = array(); + + foreach( $this->element->getElementsByTagName('vocation') as $vocation) + { + $show = $vocation->getAttribute('showInDescription'); + if($vocation->getAttribute('id') != NULL) { + $voc_id = $vocation->getAttribute('id'); + } + else { + $voc_id = $config['vocations_ids'][$vocation->getAttribute('name')]; + } + + $vocations[$voc_id] = strlen($show) == 0 || $show != '0'; + } + + return $vocations; + } /** * Creates conjure item. * diff --git a/system/libs/spells.php b/system/libs/spells.php index 557fd184..4d1d3e2b 100644 --- a/system/libs/spells.php +++ b/system/libs/spells.php @@ -50,22 +50,8 @@ class Spells { $name = $spell->getName(); $soul = $spell->getSoul(); $spell_txt = $spell->getWords(); + $vocations = $spell->getVocations(); - $nr_of_vocations = count($vocations); - $vocations_to_db = ""; - $voc_nr = 0; - foreach($vocations as $vocation_to_add) { - if(Validator::number($vocation_to_add)) { - $vocations_to_db .= $vocation_to_add; - } - else - $vocations_to_db .= $vocations_ids[$vocation_to_add]; - $voc_nr++; - - if($voc_nr != $nr_of_vocations) { - $vocations_to_db .= ','; - } - } $enabled = $spell->isEnabled(); if($enabled) { @@ -84,7 +70,7 @@ class Spells { $type = 2; $count = $spell->getConjureCount(); try { - $db->query('INSERT INTO myaac_spells (spell, name, words, type, mana, level, maglevel, soul, premium, vocations, conjure_count, hidden) VALUES (' . $db->quote($spell_txt) . ', ' . $db->quote($name) . ', ' . $db->quote($spell_txt) . ', ' . $db->quote($type) . ', ' . $db->quote($mana) . ', ' . $db->quote($lvl) . ', ' . $db->quote($mlvl) . ', ' . $db->quote($soul) . ', ' . $db->quote($pacc) . ', ' . $db->quote($vocations_to_db) . ', ' . $db->quote($count) . ', ' . $db->quote($hide_spell) . ')'); + $db->query('INSERT INTO myaac_spells (spell, name, words, type, mana, level, maglevel, soul, premium, vocations, conjure_count, hidden) VALUES (' . $db->quote($spell_txt) . ', ' . $db->quote($name) . ', ' . $db->quote($spell_txt) . ', ' . $db->quote($type) . ', ' . $db->quote($mana) . ', ' . $db->quote($lvl) . ', ' . $db->quote($mlvl) . ', ' . $db->quote($soul) . ', ' . $db->quote($pacc) . ', ' . $db->quote(json_encode($vocations)) . ', ' . $db->quote($count) . ', ' . $db->quote($hide_spell) . ')'); if($show) { success("Added: " . $name . "
"); } @@ -114,21 +100,7 @@ class Spells { continue; $vocations = $spell->getVocations(); - $nr_of_vocations = count($vocations); - $vocations_to_db = ""; - $voc_nr = 0; - foreach($vocations as $vocation_to_add) { - if(Validator::number($vocation_to_add)) { - $vocations_to_db .= $vocation_to_add; - } - else - $vocations_to_db .= $vocations_ids[$vocation_to_add]; - $voc_nr++; - - if($voc_nr != $nr_of_vocations) { - $vocations_to_db .= ','; - } - } + $enabled = $spell->isEnabled(); if($enabled) { $hide_spell = 0; @@ -145,8 +117,10 @@ class Spells { } $type = 1; $count = 0; + + try { - $db->query("INSERT INTO myaac_spells (spell, name, words, type, mana, level, maglevel, soul, premium, vocations, conjure_count, hidden) VALUES (".$db->quote($spell_txt).", ".$db->quote($name).", ".$db->quote($spell_txt).", '".$type."', '".$mana."', '".$lvl."', '".$mlvl."', '".$soul."', '".$pacc."', '".$vocations_to_db."', '".$count."', '".$hide_spell."')"); + $db->query("INSERT INTO myaac_spells (spell, name, words, type, mana, level, maglevel, soul, premium, vocations, conjure_count, hidden) VALUES (".$db->quote($spell_txt).", ".$db->quote($name).", ".$db->quote($spell_txt).", '".$type."', '".$mana."', '".$lvl."', '".$mlvl."', '".$soul."', '".$pacc."', ".$db->quote(json_encode($vocations)).", '".$count."', '".$hide_spell."')"); if($show) { success("Added: ".$name."
"); } @@ -158,6 +132,53 @@ class Spells { } } + //add runes + $runeslist = self::$spellsList->getRunesList(); + if($show) { + echo "

Runes:

"; + } + // runes + foreach($runeslist as $spellname) { + $spell = self::$spellsList->getRune($spellname); + $lvl = $spell->getLevel(); + $mlvl = $spell->getMagicLevel(); + $mana = $spell->getMana(); + $name = $spell->getName() . ' (rune)'; + $soul = $spell->getSoul(); + $spell_txt = $spell->getWords(); + $vocations = $spell->getVocations(); + + $id = $spell->getID(); + + $enabled = $spell->isEnabled(); + if($enabled) { + $hide_spell = 0; + } + else { + $hide_spell = 1; + } + $pacc = $spell->isPremium(); + if($pacc) { + $pacc = '1'; + } + else { + $pacc = '0'; + } + $type = 3; + $count = $spell->getConjureCount(); + try { + $db->query('INSERT INTO myaac_spells (spell, name, words, type, mana, level, maglevel, soul, premium, vocations, conjure_count, item_id, hidden) VALUES (' . $db->quote($spell_txt) . ', ' . $db->quote($name) . ', ' . $db->quote($spell_txt) . ', ' . $db->quote($type) . ', ' . $db->quote($mana) . ', ' . $db->quote($lvl) . ', ' . $db->quote($mlvl) . ', ' . $db->quote($soul) . ', ' . $db->quote($pacc) . ', ' . $db->quote(json_encode($vocations)) . ', ' . $db->quote($count) . ', ' . $db->quote($id) . ', ' . $db->quote($hide_spell) . ')'); + if($show) { + success("Added: " . $name . "
"); + } + } + catch(PDOException $error) { + if($show) { + warning('Error while adding spell (' . $name . '): ' . $error->getMessage()); + } + } + } + return true; } diff --git a/system/libs/weapons.php b/system/libs/weapons.php new file mode 100644 index 00000000..f4e01a80 --- /dev/null +++ b/system/libs/weapons.php @@ -0,0 +1,82 @@ + + * @author Slawkens + * @copyright 2017 MyAAC + * @version 0.6.1 + * @link http://my-aac.org + */ +defined('MYAAC') or die('Direct access not allowed!'); + +class Weapons { + private static $error = ''; + + public static function loadFromXML($show = false) + { + global $config, $db; + + try { + $db->query("DELETE FROM `myaac_weapons`;"); + } catch (PDOException $error) { + } + + $file_path = $config['data_path'] . 'weapons/weapons.xml'; + if (!file_exists($file_path)) { + self::$error = 'Cannot load file ' . $file_path; + return false; + } + + $xml = new DOMDocument; + $xml->load($file_path); + + foreach ($xml->getElementsByTagName('wand') as $weapon) { + self::parseNode($weapon, $show); + } + foreach ($xml->getElementsByTagName('melee') as $weapon) { + self::parseNode($weapon, $show); + } + foreach ($xml->getElementsByTagName('distance') as $weapon) { + self::parseNode($weapon, $show); + } + + return true; + } + + public static function parseNode($node, $show = false) { + global $config, $db; + + $id = (int)$node->getAttribute('id'); + $vocations_ids = array_flip($config['vocations']); + $level = (int)$node->getAttribute('level'); + $maglevel = (int)$node->getAttribute('maglevel'); + + $vocations = array(); + foreach($node->getElementsByTagName('vocation') as $vocation) { + $show = $vocation->getAttribute('showInDescription'); + if(!empty($vocation->getAttribute('id'))) + $voc_id = $vocation->getAttribute('id'); + else { + $voc_id = $vocations_ids[$vocation->getAttribute('name')]; + } + + $vocations[$voc_id] = strlen($show) == 0 || $show != '0'; + } + + $exist = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'weapons` WHERE `id` = ' . $id); + if($exist->rowCount() > 0) { + if($show) { + warning('Duplicated weapon with id: ' . $id); + } + } + else { + $db->insert(TABLE_PREFIX . 'weapons', array('id' => $id, 'level' => $level, 'maglevel' => $maglevel, 'vocations' => json_encode($vocations))); + } + } + + public static function getError() { + return self::$error; + } +} \ No newline at end of file diff --git a/system/migrations/12.php b/system/migrations/12.php new file mode 100644 index 00000000..f45008ae --- /dev/null +++ b/system/migrations/12.php @@ -0,0 +1,49 @@ +query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD `item_id` INT(11) NOT NULL DEFAULT 0 AFTER `conjure_count`;"); + +// change unique index from spell to name +$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `spell`;"); +$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD UNIQUE INDEX (`name`);"); + +// change comment of spells.type +$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune';"); + +// new items table +if(!tableExist(TABLE_PREFIX . 'items')) +$db->query(" +CREATE TABLE `" . TABLE_PREFIX . "items` +( + `id` INT(11) NOT NULL, + `article` VARCHAR(5) NOT NULL DEFAULT '', + `name` VARCHAR(50) NOT NULL DEFAULT '', + `plural` VARCHAR(50) NOT NULL DEFAULT '', + `attributes` VARCHAR(500) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE = MyISAM;"); + +// new weapons table +if(!tableExist(TABLE_PREFIX . 'weapons')) +$db->query(" +CREATE TABLE `" . TABLE_PREFIX . "weapons` +( + `id` INT(11) NOT NULL, + `level` INT(11) NOT NULL DEFAULT 0, + `maglevel` INT(11) NOT NULL DEFAULT 0, + `vocations` VARCHAR(100) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE = MyISAM;"); + +// modify vocations to support json data +$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `vocations` VARCHAR(100) NOT NULL DEFAULT '';"); +$query = $db->query('SELECT `id`, `vocations` FROM `' . TABLE_PREFIX . 'spells`'); +foreach($query->fetchAll() as $spell) { + $tmp = explode(',', $spell['vocations']); + foreach($tmp as &$v) { + $v = (int)$v; + } + $db->update(TABLE_PREFIX . 'spells', array('vocations' => json_encode($tmp)), array('id' => $spell['id'])); +} +?> \ No newline at end of file diff --git a/system/pages/admin/items.php b/system/pages/admin/items.php new file mode 100644 index 00000000..2fe98533 --- /dev/null +++ b/system/pages/admin/items.php @@ -0,0 +1,31 @@ + + * @copyright 2017 MyAAC + * @version 0.6.1 + * @link http://my-aac.org + */ +defined('MYAAC') or die('Direct access not allowed!'); +$title = 'Load items.xml'; + +require(LIBS . 'items.php'); +require(LIBS . 'weapons.php'); + +echo $twig->render('admin.items.html.twig'); + +$reload = isset($_REQUEST['reload']) && (int)$_REQUEST['reload'] == 1; +if($reload) { + if(Items::loadFromXML(true)) + success('Successfully loaded items.'); + else + error(Items::getError()); + + if(Weapons::loadFromXML(true)) + success('Successfully loaded weapons.'); + else + error(Weapons::getError()); + +} \ No newline at end of file diff --git a/system/pages/spells.php b/system/pages/spells.php index 7623cf3f..bf5675a0 100644 --- a/system/pages/spells.php +++ b/system/pages/spells.php @@ -111,19 +111,21 @@ if(!in_array($order, array('spell', 'words', 'type', 'mana', 'level', 'maglevel' query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'spells') . ' WHERE ' . $db->fieldName('hidden') . ' != 1 ORDER BY ' . $order . ', level'); +$spells = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'spells` WHERE `hidden` != 1 AND `type` < 3 ORDER BY ' . $order . ', level'); if(isset($vocation_id) && $vocation_id != 'All' && $vocation_id != '') { foreach($spells as $spell) { - $spell_vocations = explode(",", $spell['vocations']); - if(in_array($vocation_id, $spell_vocations) || empty($spell['vocations'])) + $spell_vocations = json_decode($spell['vocations'], true); + if(in_array($vocation_id, $spell_vocations) || count($spell_vocations) == 0) { echo '' . $spell['name'] . '' . $spell['words'] . ''; - if($spell['type'] == 2) + if($spell['type'] == 1) + echo 'Instant'; + else if($spell['type'] == 2) echo 'Conjure ('.$spell['conjure_count'].')'; else - echo 'Instant'; + echo 'Rune'; echo '' . $spell['mana'] . '' . $spell['level'] . '' . $spell['maglevel'] . '' . $spell['soul'] . '' . ($spell ['premium'] == 1 ? 'yes' : 'no') . '' . $config['vocations'][$vocation_id] . ''; } @@ -133,13 +135,15 @@ else { foreach($spells as $spell) { - $spell_vocations = explode(",", $spell['vocations']); + $spell_vocations = json_decode($spell['vocations'], true); echo '' .$spell['name'] . '' . $spell['words'] . ''; if($spell['type'] == 1) echo 'Instant'; - else + else if($spell['type'] == 2) echo 'Conjure ('.$spell['conjure_count'].')'; + else + echo 'Rune'; echo '' . $spell['mana'] . '' . $spell['level'] . '' . $spell['maglevel'] . '' . $spell['soul'] . ''. ($spell ['premium'] == 1 ? 'yes' : 'no') .''; diff --git a/system/templates/admin.items.html.twig b/system/templates/admin.items.html.twig new file mode 100644 index 00000000..f891b86b --- /dev/null +++ b/system/templates/admin.items.html.twig @@ -0,0 +1,4 @@ +
+ + +
diff --git a/system/templates/characters.html.twig b/system/templates/characters.html.twig index 051c114f..4db64d73 100644 --- a/system/templates/characters.html.twig +++ b/system/templates/characters.html.twig @@ -1,3 +1,10 @@ + + + {% set rows = 0 %} @@ -145,6 +152,7 @@
{% if config.characters.skills %} + + {% endif %} {% if quests_enabled %} + + {% endif %} {% if config.characters.equipment %} + + {% endif %}
@@ -160,9 +168,11 @@ {% endfor %}
@@ -178,9 +188,11 @@ {% endfor %}
@@ -212,11 +224,13 @@
{% if deaths|length > 0 %} +
@@ -231,8 +245,10 @@ {% set i = i + 1 %} {% endfor %} + {% endif %} {% if frags|length > 0 %} +
@@ -246,11 +262,13 @@ {% endfor %}
+ {% endif %} {{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }} {% if config.signature_enabled %} +