diff --git a/README.md b/README.md index 7eea945..06ad816 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,10 @@ It's based on https://github.com/edubart/otclient and it's not backward compatib - Crosshair, floor fading, extra health/mana bars and panels - Much more client options - Removed a lot of useless and outdated things -- Advanced bot (https://github.com/OTCv8/otclientv8_bot) +- Advanced bot - Linux version - Full tibia 11.00 support +- Layouts - New login server (with ingame account and character creation) - Support for proxies to lower latency and protect against DDoS (extra paid option) - Bot protection (extra paid option) @@ -57,6 +58,7 @@ Open `init.lua` and edit: -- CONFIG APP_NAME = "otclientv8" -- important, change it, it's name for config dir and files in appdata APP_VERSION = 1337 -- client version for updater and login to indentify outdated client +DEFAULT_LAYOUT = "retro" -- If you don't use updater or other service, set it to updater = "" Services = { diff --git a/api/image.png b/api/image.png deleted file mode 100644 index fa2242e..0000000 Binary files a/api/image.png and /dev/null differ diff --git a/api/login.php b/api/login.php deleted file mode 100644 index 2414ba4..0000000 --- a/api/login.php +++ /dev/null @@ -1,181 +0,0 @@ - (filename, md5 checksum in hex) -// $things = null; things can be null if you want to use default values, but then enable auto download of sprites and dat in updater - -/* //for 860 -$things = array( - "sprites" => array("$version/Tibia.spr", "3db8c0098d34ca3d9a8ec29d40ef1b7b"), - "data" => array("$version/Tibia.dat", "85785b5d67b4c111f780a74895c85c75") -); -*/ - -// for 1099 -$things = array( - "sprites" => array("$version/Tibia.spr", "63d38646597649a55a8be463d6c0fb49"), - "data" => array("$version/Tibia.dat", "ae7157cfff42f14583d6363e77044df7") -); - -$customProtocol = nil; // if not nil it will replace client version in protocolgame, may be used to detect outdated client - -// executes modules.client_options.setOption(option, value, true) -$settings = array( - -); - -// it's from src/client/const.h, executes g_game.enableFeature/g_game.disableFeature -$features = array( - 22 => true, // GameFormatCreatureName - 25 => true, // GameExtendedClientPing - 30 => true, // GameChangeMapAwareRange -// 56 => true, // GameSpritesAlphaChannel - 80 => true, - 90 => true, // GameNewWalking -// 91 => true, // GameSmootherWalking - 95 => true, // GameBot - 97 => true, // light -); - -$rsa = "1091201329673994292788609605089955415282375029027981291234687579" . - "3726629149257644633073969600111060390723088861007265581882535850" . - "3429057592827629436413108566029093628212635953836686562675849720" . - "6207862794310902180176810615217550567108238764764442605581471797" . - "07119674283982419152118103759076030616683978566631413"; - -// proxies (it's custom feature, not available for free) -$proxies = array( - array( - "localPort" => 7172, - "host" => "51.158.184.57", - "port" => 7162, - "priority" => 0 - ), - array( - "localPort" => 7172, - "host" => "54.39.190.20", - "port" => 7162, - "priority" => 0 - ), - array( - "localPort" => 7172, - "host" => "51.83.226.109", - "port" => 7162, - "priority" => 0, - ), - array( - "localPort" => 7172, - "host" => "35.247.201.100", - "port" => 443, - "priority" => 0 - ) -); - -// config end - -$data = file_get_contents("php://input"); - -$data = json_decode($data); -if(empty($data)) { - http_response_code(400); -} - -if($data->version != $otc_version) { - die(json_encode(array("error" => "Outdated client, please update!"))); -} - -$conn = new mysqli($dbserver, $username, $password, $dbname); -if ($conn->connect_error) { - die("SQL connection failed: " . $conn->connect_error); -} - -$account = $data->account; -if($encryption == "sha1") - $password = sha1($data->password); -else if($encryption == "md5") - $password = md5($data->password); -else - $password = $data->password; - -$token = $data->token; - -$account = preg_replace("/[^A-Za-z0-9 ._-]/", '', $account); -$password = preg_replace("/[^A-Za-z0-9 ._-]/", '', $password); -$token = preg_replace("/[^A-Za-z0-9 ._-]/", '', $token); -$ip = preg_replace("/[^A-Za-z0-9 ._-]/", '', $_SERVER['REMOTE_ADDR']); - -if($maxLogins != null && $maxLogins > 0) { - $result = $conn->query("select count(*) as `attempts` from `login_attmpts` where `ip` = '".$ip."' and `date` > NOW() - INTERVAL ".$blockTime." SECOND"); - $result = $result->fetch_assoc(); - if($result['attempts'] > $maxLogins) { - die(json_encode(array("error" => "Too many login attempts, please wait ".$blockTime." seconds."))); - } - $conn->query("INSERT INTO `login_attmpts` (`acc`, `ip`, `date`) VALUES ('".$conn->real_escape_string($account)."', '".$ip."', NOW())"); -} - -$result = $conn->query("select * from accounts where `name` = '".$conn->real_escape_string($account)."' and `password` = '".$conn->real_escape_string($password)."'"); -if ($result->num_rows != 1) { - die(json_encode(array("error" => "Invalid account/password"))); -} -$acc = $result->fetch_assoc(); - -$session = "".$data->account."\n".$data->password."\n$token\n".time(); - -if($serverIp != "proxy" && $serverIp != "0.0.0.0") { - $proxies = null; -} - -$response = array( - "error" => "", - "rsa" => $rsa, - "version" => $version, - "things" => $things, - "customProtocol" => $customProtocol, - "session" => $session, - "characters" => array(), - "account" => array(), - "settings" => $settings, - "features" => $features, - "proxies" => $proxies -); - -$response["account"]["status"] = 0; // 0=ok, 1=frozen, 2=supsended -$response["account"]["subStatus"] = 1; // 0=free, 1=premium -$response["account"]["premDays"] = 65535; - -$characters = $conn->query("select * from `players` where `account_id` = '".$acc['id']."'"); -if ($characters->num_rows == 0) { - die(json_encode(array("error" => "Account doesn't have any characters"))); -} - -while($character = $characters->fetch_assoc()) { - $response["characters"][] = array( - "name" => $character['name'], - "worldName" => $serverName, - "worldIp" => $serverIp, - "worldPort" => $serverPort - // if you are good enough and can code it in lua, you can add outfit, level, vocation, whatever you want here - ); -} - -echo json_encode($response); -?> \ No newline at end of file diff --git a/api/newlogin.php b/api/newlogin.php deleted file mode 100644 index 55bcea3..0000000 --- a/api/newlogin.php +++ /dev/null @@ -1,28 +0,0 @@ - $qrcode, - "code" => $code, - "status" => "waiting" -); - -echo json_encode($data); -?> \ No newline at end of file diff --git a/api/news.php b/api/news.php deleted file mode 100644 index f11c943..0000000 --- a/api/news.php +++ /dev/null @@ -1,35 +0,0 @@ - "TEST SERVERS", "text" => "OTCLIENTV8 Accs:\nacc1/acc\nacc2/acc\nacc3/acc"); - -$news[] = array("title" => "First title", - "text" => "This is example of lua g_http api. Those news are from http://otclient.ovh/news.php - \nRequest was for language '".$lang."', however, there's only english version of this, don't have time to create more versions"); -$news[] = array("title" => "Random joke", "text" => $jokes[array_rand($jokes)]); -$news[] = array("title" => "Image test", "image" => base64_encode(file_get_contents("image.png"))); - -echo json_encode($news); - -?> \ No newline at end of file diff --git a/api/phpqrcode.php b/api/phpqrcode.php deleted file mode 100644 index 80adb9d..0000000 --- a/api/phpqrcode.php +++ /dev/null @@ -1,3312 +0,0 @@ - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* - * Version: 1.1.4 - * Build: 2010100721 - */ - - - -//---- qrconst.php ----------------------------- - - - - - -/* - * PHP QR Code encoder - * - * Common constants - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - // Encoding modes - - define('QR_MODE_NUL', -1); - define('QR_MODE_NUM', 0); - define('QR_MODE_AN', 1); - define('QR_MODE_8', 2); - define('QR_MODE_KANJI', 3); - define('QR_MODE_STRUCTURE', 4); - - // Levels of error correction. - - define('QR_ECLEVEL_L', 0); - define('QR_ECLEVEL_M', 1); - define('QR_ECLEVEL_Q', 2); - define('QR_ECLEVEL_H', 3); - - // Supported output formats - - define('QR_FORMAT_TEXT', 0); - define('QR_FORMAT_PNG', 1); - - class qrstr { - public static function set(&$srctab, $x, $y, $repl, $replLen = false) { - $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); - } - } - - - -//---- merged_config.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Config file, tuned-up for merged verion - */ - - define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there - define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true - define('QR_LOG_DIR', false); // default error logs dir - - define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code - define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly - define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false - - define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images - - - - -//---- qrtools.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Toolset, handy and debug utilites. - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRtools { - - //---------------------------------------------------------------------- - public static function binarize($frame) - { - $len = count($frame); - foreach ($frame as &$frameLine) { - - for($i=0; $i<$len; $i++) { - $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; - } - } - - return $frame; - } - - //---------------------------------------------------------------------- - public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') - { - $barcode_array = array(); - - if (!is_array($mode)) - $mode = explode(',', $mode); - - $eccLevel = 'L'; - - if (count($mode) > 1) { - $eccLevel = $mode[1]; - } - - $qrTab = QRcode::text($code, false, $eccLevel); - $size = count($qrTab); - - $barcode_array['num_rows'] = $size; - $barcode_array['num_cols'] = $size; - $barcode_array['bcode'] = array(); - - foreach ($qrTab as $line) { - $arrAdd = array(); - foreach(str_split($line) as $char) - $arrAdd[] = ($char=='1')?1:0; - $barcode_array['bcode'][] = $arrAdd; - } - - return $barcode_array; - } - - //---------------------------------------------------------------------- - public static function clearCache() - { - self::$frames = array(); - } - - //---------------------------------------------------------------------- - public static function buildCache() - { - QRtools::markTime('before_build_cache'); - - $mask = new QRmask(); - for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { - $frame = QRspec::newFrame($a); - if (QR_IMAGE) { - $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; - QRimage::png(self::binarize($frame), $fileName, 1, 0); - } - - $width = count($frame); - $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); - for ($maskNo=0; $maskNo<8; $maskNo++) - $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); - } - - QRtools::markTime('after_build_cache'); - } - - //---------------------------------------------------------------------- - public static function log($outfile, $err) - { - if (QR_LOG_DIR !== false) { - if ($err != '') { - if ($outfile !== false) { - file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); - } else { - file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); - } - } - } - } - - //---------------------------------------------------------------------- - public static function dumpMask($frame) - { - $width = count($frame); - for($y=0;$y<$width;$y++) { - for($x=0;$x<$width;$x++) { - echo ord($frame[$y][$x]).','; - } - } - } - - //---------------------------------------------------------------------- - public static function markTime($markerId) - { - list($usec, $sec) = explode(" ", microtime()); - $time = ((float)$usec + (float)$sec); - - if (!isset($GLOBALS['qr_time_bench'])) - $GLOBALS['qr_time_bench'] = array(); - - $GLOBALS['qr_time_bench'][$markerId] = $time; - } - - //---------------------------------------------------------------------- - public static function timeBenchmark() - { - self::markTime('finish'); - - $lastTime = 0; - $startTime = 0; - $p = 0; - - echo ' - - '; - - foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { - if ($p > 0) { - echo ''; - } else { - $startTime = $thisTime; - } - - $p++; - $lastTime = $thisTime; - } - - echo ' - - -
BENCHMARK
till '.$markerId.': '.number_format($thisTime-$lastTime, 6).'s
TOTAL: '.number_format($lastTime-$startTime, 6).'s
'; - } - - } - - //########################################################################## - - QRtools::markTime('start'); - - - - -//---- qrspec.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * QR Code specifications - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * The following data / specifications are taken from - * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) - * or - * "Automatic identification and data capture techniques -- - * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('QRSPEC_VERSION_MAX', 40); - define('QRSPEC_WIDTH_MAX', 177); - - define('QRCAP_WIDTH', 0); - define('QRCAP_WORDS', 1); - define('QRCAP_REMINDER', 2); - define('QRCAP_EC', 3); - - class QRspec { - - public static $capacity = array( - array( 0, 0, 0, array( 0, 0, 0, 0)), - array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 - array( 25, 44, 7, array( 10, 16, 22, 28)), - array( 29, 70, 7, array( 15, 26, 36, 44)), - array( 33, 100, 7, array( 20, 36, 52, 64)), - array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 - array( 41, 172, 7, array( 36, 64, 96, 112)), - array( 45, 196, 0, array( 40, 72, 108, 130)), - array( 49, 242, 0, array( 48, 88, 132, 156)), - array( 53, 292, 0, array( 60, 110, 160, 192)), - array( 57, 346, 0, array( 72, 130, 192, 224)), //10 - array( 61, 404, 0, array( 80, 150, 224, 264)), - array( 65, 466, 0, array( 96, 176, 260, 308)), - array( 69, 532, 0, array( 104, 198, 288, 352)), - array( 73, 581, 3, array( 120, 216, 320, 384)), - array( 77, 655, 3, array( 132, 240, 360, 432)), //15 - array( 81, 733, 3, array( 144, 280, 408, 480)), - array( 85, 815, 3, array( 168, 308, 448, 532)), - array( 89, 901, 3, array( 180, 338, 504, 588)), - array( 93, 991, 3, array( 196, 364, 546, 650)), - array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 - array(101, 1156, 4, array( 224, 442, 644, 750)), - array(105, 1258, 4, array( 252, 476, 690, 816)), - array(109, 1364, 4, array( 270, 504, 750, 900)), - array(113, 1474, 4, array( 300, 560, 810, 960)), - array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 - array(121, 1706, 4, array( 336, 644, 952, 1110)), - array(125, 1828, 4, array( 360, 700, 1020, 1200)), - array(129, 1921, 3, array( 390, 728, 1050, 1260)), - array(133, 2051, 3, array( 420, 784, 1140, 1350)), - array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 - array(141, 2323, 3, array( 480, 868, 1290, 1530)), - array(145, 2465, 3, array( 510, 924, 1350, 1620)), - array(149, 2611, 3, array( 540, 980, 1440, 1710)), - array(153, 2761, 3, array( 570, 1036, 1530, 1800)), - array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 - array(161, 3034, 0, array( 600, 1120, 1680, 1980)), - array(165, 3196, 0, array( 630, 1204, 1770, 2100)), - array(169, 3362, 0, array( 660, 1260, 1860, 2220)), - array(173, 3532, 0, array( 720, 1316, 1950, 2310)), - array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 - ); - - //---------------------------------------------------------------------- - public static function getDataLength($version, $level) - { - return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; - } - - //---------------------------------------------------------------------- - public static function getECCLength($version, $level) - { - return self::$capacity[$version][QRCAP_EC][$level]; - } - - //---------------------------------------------------------------------- - public static function getWidth($version) - { - return self::$capacity[$version][QRCAP_WIDTH]; - } - - //---------------------------------------------------------------------- - public static function getRemainder($version) - { - return self::$capacity[$version][QRCAP_REMINDER]; - } - - //---------------------------------------------------------------------- - public static function getMinimumVersion($size, $level) - { - - for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { - $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; - if($words >= $size) - return $i; - } - - return -1; - } - - //###################################################################### - - public static $lengthTableBits = array( - array(10, 12, 14), - array( 9, 11, 13), - array( 8, 16, 16), - array( 8, 10, 12) - ); - - //---------------------------------------------------------------------- - public static function lengthIndicator($mode, $version) - { - if ($mode == QR_MODE_STRUCTURE) - return 0; - - if ($version <= 9) { - $l = 0; - } else if ($version <= 26) { - $l = 1; - } else { - $l = 2; - } - - return self::$lengthTableBits[$mode][$l]; - } - - //---------------------------------------------------------------------- - public static function maximumWords($mode, $version) - { - if($mode == QR_MODE_STRUCTURE) - return 3; - - if($version <= 9) { - $l = 0; - } else if($version <= 26) { - $l = 1; - } else { - $l = 2; - } - - $bits = self::$lengthTableBits[$mode][$l]; - $words = (1 << $bits) - 1; - - if($mode == QR_MODE_KANJI) { - $words *= 2; // the number of bytes is required - } - - return $words; - } - - // Error correction code ----------------------------------------------- - // Table of the error correction code (Reed-Solomon block) - // See Table 12-16 (pp.30-36), JIS X0510:2004. - - public static $eccTable = array( - array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), - array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), - array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), - array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 - array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), - array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), - array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), - array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), - array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 - array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), - array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), - array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), - array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), - array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 - array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), - array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), - array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), - array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), - array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 - array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), - array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), - array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), - array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), - array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 - array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), - array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), - array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), - array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), - array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 - array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), - array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), - array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), - array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), - array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 - array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), - array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), - array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), - array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), - array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 - ); - - //---------------------------------------------------------------------- - // CACHEABLE!!! - - public static function getEccSpec($version, $level, array &$spec) - { - if (count($spec) < 5) { - $spec = array(0,0,0,0,0); - } - - $b1 = self::$eccTable[$version][$level][0]; - $b2 = self::$eccTable[$version][$level][1]; - $data = self::getDataLength($version, $level); - $ecc = self::getECCLength($version, $level); - - if($b2 == 0) { - $spec[0] = $b1; - $spec[1] = (int)($data / $b1); - $spec[2] = (int)($ecc / $b1); - $spec[3] = 0; - $spec[4] = 0; - } else { - $spec[0] = $b1; - $spec[1] = (int)($data / ($b1 + $b2)); - $spec[2] = (int)($ecc / ($b1 + $b2)); - $spec[3] = $b2; - $spec[4] = $spec[1] + 1; - } - } - - // Alignment pattern --------------------------------------------------- - - // Positions of alignment patterns. - // This array includes only the second and the third position of the - // alignment patterns. Rest of them can be calculated from the distance - // between them. - - // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. - - public static $alignmentPattern = array( - array( 0, 0), - array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 - array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 - array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 - array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 - array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 - array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 - array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 - array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 - ); - - - /** -------------------------------------------------------------------- - * Put an alignment marker. - * @param frame - * @param width - * @param ox,oy center coordinate of the pattern - */ - public static function putAlignmentMarker(array &$frame, $ox, $oy) - { - $finder = array( - "\xa1\xa1\xa1\xa1\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa0\xa1\xa0\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa1\xa1\xa1\xa1" - ); - - $yStart = $oy-2; - $xStart = $ox-2; - - for($y=0; $y<5; $y++) { - QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); - } - } - - //---------------------------------------------------------------------- - public static function putAlignmentPattern($version, &$frame, $width) - { - if($version < 2) - return; - - $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; - if($d < 0) { - $w = 2; - } else { - $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); - } - - if($w * $w - 3 == 1) { - $x = self::$alignmentPattern[$version][0]; - $y = self::$alignmentPattern[$version][0]; - self::putAlignmentMarker($frame, $x, $y); - return; - } - - $cx = self::$alignmentPattern[$version][0]; - for($x=1; $x<$w - 1; $x++) { - self::putAlignmentMarker($frame, 6, $cx); - self::putAlignmentMarker($frame, $cx, 6); - $cx += $d; - } - - $cy = self::$alignmentPattern[$version][0]; - for($y=0; $y<$w-1; $y++) { - $cx = self::$alignmentPattern[$version][0]; - for($x=0; $x<$w-1; $x++) { - self::putAlignmentMarker($frame, $cx, $cy); - $cx += $d; - } - $cy += $d; - } - } - - // Version information pattern ----------------------------------------- - - // Version information pattern (BCH coded). - // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. - - // size: [QRSPEC_VERSION_MAX - 6] - - public static $versionPattern = array( - 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, - 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, - 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, - 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, - 0x27541, 0x28c69 - ); - - //---------------------------------------------------------------------- - public static function getVersionPattern($version) - { - if($version < 7 || $version > QRSPEC_VERSION_MAX) - return 0; - - return self::$versionPattern[$version -7]; - } - - // Format information -------------------------------------------------- - // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) - - public static $formatInfo = array( - array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), - array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), - array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), - array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) - ); - - public static function getFormatInfo($mask, $level) - { - if($mask < 0 || $mask > 7) - return 0; - - if($level < 0 || $level > 3) - return 0; - - return self::$formatInfo[$level][$mask]; - } - - // Frame --------------------------------------------------------------- - // Cache of initial frames. - - public static $frames = array(); - - /** -------------------------------------------------------------------- - * Put a finder pattern. - * @param frame - * @param width - * @param ox,oy upper-left coordinate of the pattern - */ - public static function putFinderPattern(&$frame, $ox, $oy) - { - $finder = array( - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" - ); - - for($y=0; $y<7; $y++) { - QRstr::set($frame, $ox, $oy+$y, $finder[$y]); - } - } - - //---------------------------------------------------------------------- - public static function createFrame($version) - { - $width = self::$capacity[$version][QRCAP_WIDTH]; - $frameLine = str_repeat ("\0", $width); - $frame = array_fill(0, $width, $frameLine); - - // Finder pattern - self::putFinderPattern($frame, 0, 0); - self::putFinderPattern($frame, $width - 7, 0); - self::putFinderPattern($frame, 0, $width - 7); - - // Separator - $yOffset = $width - 7; - - for($y=0; $y<7; $y++) { - $frame[$y][7] = "\xc0"; - $frame[$y][$width - 8] = "\xc0"; - $frame[$yOffset][7] = "\xc0"; - $yOffset++; - } - - $setPattern = str_repeat("\xc0", 8); - - QRstr::set($frame, 0, 7, $setPattern); - QRstr::set($frame, $width-8, 7, $setPattern); - QRstr::set($frame, 0, $width - 8, $setPattern); - - // Format info - $setPattern = str_repeat("\x84", 9); - QRstr::set($frame, 0, 8, $setPattern); - QRstr::set($frame, $width - 8, 8, $setPattern, 8); - - $yOffset = $width - 8; - - for($y=0; $y<8; $y++,$yOffset++) { - $frame[$y][8] = "\x84"; - $frame[$yOffset][8] = "\x84"; - } - - // Timing pattern - - for($i=1; $i<$width-15; $i++) { - $frame[6][7+$i] = chr(0x90 | ($i & 1)); - $frame[7+$i][6] = chr(0x90 | ($i & 1)); - } - - // Alignment pattern - self::putAlignmentPattern($version, $frame, $width); - - // Version information - if($version >= 7) { - $vinf = self::getVersionPattern($version); - - $v = $vinf; - - for($x=0; $x<6; $x++) { - for($y=0; $y<3; $y++) { - $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - - $v = $vinf; - for($y=0; $y<6; $y++) { - for($x=0; $x<3; $x++) { - $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - } - - // and a little bit... - $frame[$width - 8][8] = "\x81"; - - return $frame; - } - - //---------------------------------------------------------------------- - public static function debug($frame, $binary_mode = false) - { - if ($binary_mode) { - - foreach ($frame as &$frameLine) { - $frameLine = join('  ', explode('0', $frameLine)); - $frameLine = join('██', explode('1', $frameLine)); - } - - ?> - -


        '; - echo join("
        ", $frame); - echo '






'; - - } else { - - foreach ($frame as &$frameLine) { - $frameLine = join(' ', explode("\xc0", $frameLine)); - $frameLine = join('', explode("\xc1", $frameLine)); - $frameLine = join(' ', explode("\xa0", $frameLine)); - $frameLine = join('', explode("\xa1", $frameLine)); - $frameLine = join('', explode("\x84", $frameLine)); //format 0 - $frameLine = join('', explode("\x85", $frameLine)); //format 1 - $frameLine = join('', explode("\x81", $frameLine)); //special bit - $frameLine = join(' ', explode("\x90", $frameLine)); //clock 0 - $frameLine = join('', explode("\x91", $frameLine)); //clock 1 - $frameLine = join(' ', explode("\x88", $frameLine)); //version - $frameLine = join('', explode("\x89", $frameLine)); //version - $frameLine = join('♦', explode("\x01", $frameLine)); - $frameLine = join('⋅', explode("\0", $frameLine)); - } - - ?> - - "; - echo join("
", $frame); - echo "
"; - - } - } - - //---------------------------------------------------------------------- - public static function serial($frame) - { - return gzcompress(join("\n", $frame), 9); - } - - //---------------------------------------------------------------------- - public static function unserial($code) - { - return explode("\n", gzuncompress($code)); - } - - //---------------------------------------------------------------------- - public static function newFrame($version) - { - if($version < 1 || $version > QRSPEC_VERSION_MAX) - return null; - - if(!isset(self::$frames[$version])) { - - $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; - - if (QR_CACHEABLE) { - if (file_exists($fileName)) { - self::$frames[$version] = self::unserial(file_get_contents($fileName)); - } else { - self::$frames[$version] = self::createFrame($version); - file_put_contents($fileName, self::serial(self::$frames[$version])); - } - } else { - self::$frames[$version] = self::createFrame($version); - } - } - - if(is_null(self::$frames[$version])) - return null; - - return self::$frames[$version]; - } - - //---------------------------------------------------------------------- - public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } - public static function rsBlockNum1($spec) { return $spec[0]; } - public static function rsDataCodes1($spec) { return $spec[1]; } - public static function rsEccCodes1($spec) { return $spec[2]; } - public static function rsBlockNum2($spec) { return $spec[3]; } - public static function rsDataCodes2($spec) { return $spec[4]; } - public static function rsEccCodes2($spec) { return $spec[2]; } - public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } - public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } - - } - - - -//---- qrimage.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Image output of code using GD2 - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('QR_IMAGE', true); - - class QRimage { - - //---------------------------------------------------------------------- - public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) - { - $image = self::image($frame, $pixelPerPoint, $outerFrame); - - if ($filename === false) { - Header("Content-type: image/png"); - ImagePng($image); - } else { - if($saveandprint===TRUE){ - ImagePng($image, $filename); - header("Content-type: image/png"); - ImagePng($image); - }else{ - ImagePng($image, $filename); - } - } - - ImageDestroy($image); - } - - //---------------------------------------------------------------------- - public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) - { - $image = self::image($frame, $pixelPerPoint, $outerFrame); - - if ($filename === false) { - Header("Content-type: image/jpeg"); - ImageJpeg($image, null, $q); - } else { - ImageJpeg($image, $filename, $q); - } - - ImageDestroy($image); - } - - //---------------------------------------------------------------------- - private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) - { - $h = count($frame); - $w = strlen($frame[0]); - - $imgW = $w + 2*$outerFrame; - $imgH = $h + 2*$outerFrame; - - $base_image =ImageCreate($imgW, $imgH); - - $col[0] = ImageColorAllocate($base_image,255,255,255); - $col[1] = ImageColorAllocate($base_image,0,0,0); - - imagefill($base_image, 0, 0, $col[0]); - - for($y=0; $y<$h; $y++) { - for($x=0; $x<$w; $x++) { - if ($frame[$y][$x] == '1') { - ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); - } - } - } - - $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); - ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); - ImageDestroy($base_image); - - return $target_image; - } - } - - - -//---- qrinput.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Input encoding class - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('STRUCTURE_HEADER_BITS', 20); - define('MAX_STRUCTURED_SYMBOLS', 16); - - class QRinputItem { - - public $mode; - public $size; - public $data; - public $bstream; - - public function __construct($mode, $size, $data, $bstream = null) - { - $setData = array_slice($data, 0, $size); - - if (count($setData) < $size) { - $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); - } - - if(!QRinput::check($mode, $size, $setData)) { - throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); - return null; - } - - $this->mode = $mode; - $this->size = $size; - $this->data = $setData; - $this->bstream = $bstream; - } - - //---------------------------------------------------------------------- - public function encodeModeNum($version) - { - try { - - $words = (int)($this->size / 3); - $bs = new QRbitstream(); - - $val = 0x1; - $bs->appendNum(4, $val); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); - - for($i=0; $i<$words; $i++) { - $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; - $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; - $val += (ord($this->data[$i*3+2]) - ord('0')); - $bs->appendNum(10, $val); - } - - if($this->size - $words * 3 == 1) { - $val = ord($this->data[$words*3]) - ord('0'); - $bs->appendNum(4, $val); - } else if($this->size - $words * 3 == 2) { - $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; - $val += (ord($this->data[$words*3+1]) - ord('0')); - $bs->appendNum(7, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeAn($version) - { - try { - $words = (int)($this->size / 2); - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x02); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); - - for($i=0; $i<$words; $i++) { - $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; - $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); - - $bs->appendNum(11, $val); - } - - if($this->size & 1) { - $val = QRinput::lookAnTable(ord($this->data[$words * 2])); - $bs->appendNum(6, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeMode8($version) - { - try { - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x4); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); - - for($i=0; $i<$this->size; $i++) { - $bs->appendNum(8, ord($this->data[$i])); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeKanji($version) - { - try { - - $bs = new QRbitrtream(); - - $bs->appendNum(4, 0x8); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); - - for($i=0; $i<$this->size; $i+=2) { - $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); - if($val <= 0x9ffc) { - $val -= 0x8140; - } else { - $val -= 0xc140; - } - - $h = ($val >> 8) * 0xc0; - $val = ($val & 0xff) + $h; - - $bs->appendNum(13, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeStructure() - { - try { - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x03); - $bs->appendNum(4, ord($this->data[1]) - 1); - $bs->appendNum(4, ord($this->data[0]) - 1); - $bs->appendNum(8, ord($this->data[2])); - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function estimateBitStreamSizeOfEntry($version) - { - $bits = 0; - - if($version == 0) - $version = 1; - - switch($this->mode) { - case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; - case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; - case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; - case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; - case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; - default: - return 0; - } - - $l = QRspec::lengthIndicator($this->mode, $version); - $m = 1 << $l; - $num = (int)(($this->size + $m - 1) / $m); - - $bits += $num * (4 + $l); - - return $bits; - } - - //---------------------------------------------------------------------- - public function encodeBitStream($version) - { - try { - - unset($this->bstream); - $words = QRspec::maximumWords($this->mode, $version); - - if($this->size > $words) { - - $st1 = new QRinputItem($this->mode, $words, $this->data); - $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); - - $st1->encodeBitStream($version); - $st2->encodeBitStream($version); - - $this->bstream = new QRbitstream(); - $this->bstream->append($st1->bstream); - $this->bstream->append($st2->bstream); - - unset($st1); - unset($st2); - - } else { - - $ret = 0; - - switch($this->mode) { - case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; - case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; - case QR_MODE_8: $ret = $this->encodeMode8($version); break; - case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; - case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; - - default: - break; - } - - if($ret < 0) - return -1; - } - - return $this->bstream->size(); - - } catch (Exception $e) { - return -1; - } - } - }; - - //########################################################################## - - class QRinput { - - public $items; - - private $version; - private $level; - - //---------------------------------------------------------------------- - public function __construct($version = 0, $level = QR_ECLEVEL_L) - { - if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { - throw new Exception('Invalid version no'); - return NULL; - } - - $this->version = $version; - $this->level = $level; - } - - //---------------------------------------------------------------------- - public function getVersion() - { - return $this->version; - } - - //---------------------------------------------------------------------- - public function setVersion($version) - { - if($version < 0 || $version > QRSPEC_VERSION_MAX) { - throw new Exception('Invalid version no'); - return -1; - } - - $this->version = $version; - - return 0; - } - - //---------------------------------------------------------------------- - public function getErrorCorrectionLevel() - { - return $this->level; - } - - //---------------------------------------------------------------------- - public function setErrorCorrectionLevel($level) - { - if($level > QR_ECLEVEL_H) { - throw new Exception('Invalid ECLEVEL'); - return -1; - } - - $this->level = $level; - - return 0; - } - - //---------------------------------------------------------------------- - public function appendEntry(QRinputItem $entry) - { - $this->items[] = $entry; - } - - //---------------------------------------------------------------------- - public function append($mode, $size, $data) - { - try { - $entry = new QRinputItem($mode, $size, $data); - $this->items[] = $entry; - return 0; - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - - public function insertStructuredAppendHeader($size, $index, $parity) - { - if( $size > MAX_STRUCTURED_SYMBOLS ) { - throw new Exception('insertStructuredAppendHeader wrong size'); - } - - if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { - throw new Exception('insertStructuredAppendHeader wrong index'); - } - - $buf = array($size, $index, $parity); - - try { - $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); - array_unshift($this->items, $entry); - return 0; - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function calcParity() - { - $parity = 0; - - foreach($this->items as $item) { - if($item->mode != QR_MODE_STRUCTURE) { - for($i=$item->size-1; $i>=0; $i--) { - $parity ^= $item->data[$i]; - } - } - } - - return $parity; - } - - //---------------------------------------------------------------------- - public static function checkModeNum($size, $data) - { - for($i=0; $i<$size; $i++) { - if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ - return false; - } - } - - return true; - } - - //---------------------------------------------------------------------- - public static function estimateBitsModeNum($size) - { - $w = (int)$size / 3; - $bits = $w * 10; - - switch($size - $w * 3) { - case 1: - $bits += 4; - break; - case 2: - $bits += 7; - break; - default: - break; - } - - return $bits; - } - - //---------------------------------------------------------------------- - public static $anTable = array( - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - ); - - //---------------------------------------------------------------------- - public static function lookAnTable($c) - { - return (($c > 127)?-1:self::$anTable[$c]); - } - - //---------------------------------------------------------------------- - public static function checkModeAn($size, $data) - { - for($i=0; $i<$size; $i++) { - if (self::lookAnTable(ord($data[$i])) == -1) { - return false; - } - } - - return true; - } - - //---------------------------------------------------------------------- - public static function estimateBitsModeAn($size) - { - $w = (int)($size / 2); - $bits = $w * 11; - - if($size & 1) { - $bits += 6; - } - - return $bits; - } - - //---------------------------------------------------------------------- - public static function estimateBitsMode8($size) - { - return $size * 8; - } - - //---------------------------------------------------------------------- - public function estimateBitsModeKanji($size) - { - return (int)(($size / 2) * 13); - } - - //---------------------------------------------------------------------- - public static function checkModeKanji($size, $data) - { - if($size & 1) - return false; - - for($i=0; $i<$size; $i+=2) { - $val = (ord($data[$i]) << 8) | ord($data[$i+1]); - if( $val < 0x8140 - || ($val > 0x9ffc && $val < 0xe040) - || $val > 0xebbf) { - return false; - } - } - - return true; - } - - /*********************************************************************** - * Validation - **********************************************************************/ - - public static function check($mode, $size, $data) - { - if($size <= 0) - return false; - - switch($mode) { - case QR_MODE_NUM: return self::checkModeNum($size, $data); break; - case QR_MODE_AN: return self::checkModeAn($size, $data); break; - case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; - case QR_MODE_8: return true; break; - case QR_MODE_STRUCTURE: return true; break; - - default: - break; - } - - return false; - } - - - //---------------------------------------------------------------------- - public function estimateBitStreamSize($version) - { - $bits = 0; - - foreach($this->items as $item) { - $bits += $item->estimateBitStreamSizeOfEntry($version); - } - - return $bits; - } - - //---------------------------------------------------------------------- - public function estimateVersion() - { - $version = 0; - $prev = 0; - do { - $prev = $version; - $bits = $this->estimateBitStreamSize($prev); - $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if ($version < 0) { - return -1; - } - } while ($version > $prev); - - return $version; - } - - //---------------------------------------------------------------------- - public static function lengthOfCode($mode, $version, $bits) - { - $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); - switch($mode) { - case QR_MODE_NUM: - $chunks = (int)($payload / 10); - $remain = $payload - $chunks * 10; - $size = $chunks * 3; - if($remain >= 7) { - $size += 2; - } else if($remain >= 4) { - $size += 1; - } - break; - case QR_MODE_AN: - $chunks = (int)($payload / 11); - $remain = $payload - $chunks * 11; - $size = $chunks * 2; - if($remain >= 6) - $size++; - break; - case QR_MODE_8: - $size = (int)($payload / 8); - break; - case QR_MODE_KANJI: - $size = (int)(($payload / 13) * 2); - break; - case QR_MODE_STRUCTURE: - $size = (int)($payload / 8); - break; - default: - $size = 0; - break; - } - - $maxsize = QRspec::maximumWords($mode, $version); - if($size < 0) $size = 0; - if($size > $maxsize) $size = $maxsize; - - return $size; - } - - //---------------------------------------------------------------------- - public function createBitStream() - { - $total = 0; - - foreach($this->items as $item) { - $bits = $item->encodeBitStream($this->version); - - if($bits < 0) - return -1; - - $total += $bits; - } - - return $total; - } - - //---------------------------------------------------------------------- - public function convertData() - { - $ver = $this->estimateVersion(); - if($ver > $this->getVersion()) { - $this->setVersion($ver); - } - - for(;;) { - $bits = $this->createBitStream(); - - if($bits < 0) - return -1; - - $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if($ver < 0) { - throw new Exception('WRONG VERSION'); - return -1; - } else if($ver > $this->getVersion()) { - $this->setVersion($ver); - } else { - break; - } - } - - return 0; - } - - //---------------------------------------------------------------------- - public function appendPaddingBit(&$bstream) - { - $bits = $bstream->size(); - $maxwords = QRspec::getDataLength($this->version, $this->level); - $maxbits = $maxwords * 8; - - if ($maxbits == $bits) { - return 0; - } - - if ($maxbits - $bits < 5) { - return $bstream->appendNum($maxbits - $bits, 0); - } - - $bits += 4; - $words = (int)(($bits + 7) / 8); - - $padding = new QRbitstream(); - $ret = $padding->appendNum($words * 8 - $bits + 4, 0); - - if($ret < 0) - return $ret; - - $padlen = $maxwords - $words; - - if($padlen > 0) { - - $padbuf = array(); - for($i=0; $i<$padlen; $i++) { - $padbuf[$i] = ($i&1)?0x11:0xec; - } - - $ret = $padding->appendBytes($padlen, $padbuf); - - if($ret < 0) - return $ret; - - } - - $ret = $bstream->append($padding); - - return $ret; - } - - //---------------------------------------------------------------------- - public function mergeBitStream() - { - if($this->convertData() < 0) { - return null; - } - - $bstream = new QRbitstream(); - - foreach($this->items as $item) { - $ret = $bstream->append($item->bstream); - if($ret < 0) { - return null; - } - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function getBitStream() - { - - $bstream = $this->mergeBitStream(); - - if($bstream == null) { - return null; - } - - $ret = $this->appendPaddingBit($bstream); - if($ret < 0) { - return null; - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function getByteStream() - { - $bstream = $this->getBitStream(); - if($bstream == null) { - return null; - } - - return $bstream->toByte(); - } - } - - - - - - -//---- qrbitstream.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Bitstream class - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRbitstream { - - public $data = array(); - - //---------------------------------------------------------------------- - public function size() - { - return count($this->data); - } - - //---------------------------------------------------------------------- - public function allocate($setLength) - { - $this->data = array_fill(0, $setLength, 0); - return 0; - } - - //---------------------------------------------------------------------- - public static function newFromNum($bits, $num) - { - $bstream = new QRbitstream(); - $bstream->allocate($bits); - - $mask = 1 << ($bits - 1); - for($i=0; $i<$bits; $i++) { - if($num & $mask) { - $bstream->data[$i] = 1; - } else { - $bstream->data[$i] = 0; - } - $mask = $mask >> 1; - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public static function newFromBytes($size, $data) - { - $bstream = new QRbitstream(); - $bstream->allocate($size * 8); - $p=0; - - for($i=0; $i<$size; $i++) { - $mask = 0x80; - for($j=0; $j<8; $j++) { - if($data[$i] & $mask) { - $bstream->data[$p] = 1; - } else { - $bstream->data[$p] = 0; - } - $p++; - $mask = $mask >> 1; - } - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function append(QRbitstream $arg) - { - if (is_null($arg)) { - return -1; - } - - if($arg->size() == 0) { - return 0; - } - - if($this->size() == 0) { - $this->data = $arg->data; - return 0; - } - - $this->data = array_values(array_merge($this->data, $arg->data)); - - return 0; - } - - //---------------------------------------------------------------------- - public function appendNum($bits, $num) - { - if ($bits == 0) - return 0; - - $b = QRbitstream::newFromNum($bits, $num); - - if(is_null($b)) - return -1; - - $ret = $this->append($b); - unset($b); - - return $ret; - } - - //---------------------------------------------------------------------- - public function appendBytes($size, $data) - { - if ($size == 0) - return 0; - - $b = QRbitstream::newFromBytes($size, $data); - - if(is_null($b)) - return -1; - - $ret = $this->append($b); - unset($b); - - return $ret; - } - - //---------------------------------------------------------------------- - public function toByte() - { - - $size = $this->size(); - - if($size == 0) { - return array(); - } - - $data = array_fill(0, (int)(($size + 7) / 8), 0); - $bytes = (int)($size / 8); - - $p = 0; - - for($i=0; $i<$bytes; $i++) { - $v = 0; - for($j=0; $j<8; $j++) { - $v = $v << 1; - $v |= $this->data[$p]; - $p++; - } - $data[$i] = $v; - } - - if($size & 7) { - $v = 0; - for($j=0; $j<($size & 7); $j++) { - $v = $v << 1; - $v |= $this->data[$p]; - $p++; - } - $data[$bytes] = $v; - } - - return $data; - } - - } - - - - -//---- qrsplit.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Input splitting classes - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * The following data / specifications are taken from - * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) - * or - * "Automatic identification and data capture techniques -- - * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - class QRsplit { - - public $dataStr = ''; - public $input; - public $modeHint; - - //---------------------------------------------------------------------- - public function __construct($dataStr, $input, $modeHint) - { - $this->dataStr = $dataStr; - $this->input = $input; - $this->modeHint = $modeHint; - } - - //---------------------------------------------------------------------- - public static function isdigitat($str, $pos) - { - if ($pos >= strlen($str)) - return false; - - return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); - } - - //---------------------------------------------------------------------- - public static function isalnumat($str, $pos) - { - if ($pos >= strlen($str)) - return false; - - return (QRinput::lookAnTable(ord($str[$pos])) >= 0); - } - - //---------------------------------------------------------------------- - public function identifyMode($pos) - { - if ($pos >= strlen($this->dataStr)) - return QR_MODE_NUL; - - $c = $this->dataStr[$pos]; - - if(self::isdigitat($this->dataStr, $pos)) { - return QR_MODE_NUM; - } else if(self::isalnumat($this->dataStr, $pos)) { - return QR_MODE_AN; - } else if($this->modeHint == QR_MODE_KANJI) { - - if ($pos+1 < strlen($this->dataStr)) - { - $d = $this->dataStr[$pos+1]; - $word = (ord($c) << 8) | ord($d); - if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { - return QR_MODE_KANJI; - } - } - } - - return QR_MODE_8; - } - - //---------------------------------------------------------------------- - public function eatNum() - { - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 0; - while(self::isdigitat($this->dataStr, $p)) { - $p++; - } - - $run = $p; - $mode = $this->identifyMode($p); - - if($mode == QR_MODE_8) { - $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln - + QRinput::estimateBitsMode8(1) // + 4 + l8 - - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 - if($dif > 0) { - return $this->eat8(); - } - } - if($mode == QR_MODE_AN) { - $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln - + QRinput::estimateBitsModeAn(1) // + 4 + la - - QRinput::estimateBitsModeAn($run + 1);// - 4 - la - if($dif > 0) { - return $this->eatAn(); - } - } - - $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eatAn() - { - $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 0; - - while(self::isalnumat($this->dataStr, $p)) { - if(self::isdigitat($this->dataStr, $p)) { - $q = $p; - while(self::isdigitat($this->dataStr, $q)) { - $q++; - } - - $dif = QRinput::estimateBitsModeAn($p) // + 4 + la - + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln - - QRinput::estimateBitsModeAn($q); // - 4 - la - - if($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - - $run = $p; - - if(!self::isalnumat($this->dataStr, $p)) { - $dif = QRinput::estimateBitsModeAn($run) + 4 + $la - + QRinput::estimateBitsMode8(1) // + 4 + l8 - - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 - if($dif > 0) { - return $this->eat8(); - } - } - - $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eatKanji() - { - $p = 0; - - while($this->identifyMode($p) == QR_MODE_KANJI) { - $p += 2; - } - - $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eat8() - { - $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 1; - $dataStrLen = strlen($this->dataStr); - - while($p < $dataStrLen) { - - $mode = $this->identifyMode($p); - if($mode == QR_MODE_KANJI) { - break; - } - if($mode == QR_MODE_NUM) { - $q = $p; - while(self::isdigitat($this->dataStr, $q)) { - $q++; - } - $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 - + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln - - QRinput::estimateBitsMode8($q); // - 4 - l8 - if($dif < 0) { - break; - } else { - $p = $q; - } - } else if($mode == QR_MODE_AN) { - $q = $p; - while(self::isalnumat($this->dataStr, $q)) { - $q++; - } - $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 - + QRinput::estimateBitsModeAn($q - $p) + 4 + $la - - QRinput::estimateBitsMode8($q); // - 4 - l8 - if($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - - $run = $p; - $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); - - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function splitString() - { - while (strlen($this->dataStr) > 0) - { - if($this->dataStr == '') - return 0; - - $mode = $this->identifyMode(0); - - switch ($mode) { - case QR_MODE_NUM: $length = $this->eatNum(); break; - case QR_MODE_AN: $length = $this->eatAn(); break; - case QR_MODE_KANJI: - if ($hint == QR_MODE_KANJI) - $length = $this->eatKanji(); - else $length = $this->eat8(); - break; - default: $length = $this->eat8(); break; - - } - - if($length == 0) return 0; - if($length < 0) return -1; - - $this->dataStr = substr($this->dataStr, $length); - } - } - - //---------------------------------------------------------------------- - public function toUpper() - { - $stringLen = strlen($this->dataStr); - $p = 0; - - while ($p<$stringLen) { - $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); - if($mode == QR_MODE_KANJI) { - $p += 2; - } else { - if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { - $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); - } - $p++; - } - } - - return $this->dataStr; - } - - //---------------------------------------------------------------------- - public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) - { - if(is_null($string) || $string == '\0' || $string == '') { - throw new Exception('empty string!!!'); - } - - $split = new QRsplit($string, $input, $modeHint); - - if(!$casesensitive) - $split->toUpper(); - - return $split->splitString(); - } - } - - - -//---- qrrscode.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Reed-Solomon error correction support - * - * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q - * (libfec is released under the GNU Lesser General Public License.) - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRrsItem { - - public $mm; // Bits per symbol - public $nn; // Symbols per block (= (1<= $this->nn) { - $x -= $this->nn; - $x = ($x >> $this->mm) + ($x & $this->nn); - } - - return $x; - } - - //---------------------------------------------------------------------- - public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) - { - // Common code for intializing a Reed-Solomon control block (char or int symbols) - // Copyright 2004 Phil Karn, KA9Q - // May be used under the terms of the GNU Lesser General Public License (LGPL) - - $rs = null; - - // Check parameter ranges - if($symsize < 0 || $symsize > 8) return $rs; - if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; - if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; - if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! - if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding - - $rs = new QRrsItem(); - $rs->mm = $symsize; - $rs->nn = (1<<$symsize)-1; - $rs->pad = $pad; - - $rs->alpha_to = array_fill(0, $rs->nn+1, 0); - $rs->index_of = array_fill(0, $rs->nn+1, 0); - - // PHP style macro replacement ;) - $NN =& $rs->nn; - $A0 =& $NN; - - // Generate Galois field lookup tables - $rs->index_of[0] = $A0; // log(zero) = -inf - $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 - $sr = 1; - - for($i=0; $i<$rs->nn; $i++) { - $rs->index_of[$sr] = $i; - $rs->alpha_to[$i] = $sr; - $sr <<= 1; - if($sr & (1<<$symsize)) { - $sr ^= $gfpoly; - } - $sr &= $rs->nn; - } - - if($sr != 1){ - // field generator polynomial is not primitive! - $rs = NULL; - return $rs; - } - - /* Form RS code generator polynomial from its roots */ - $rs->genpoly = array_fill(0, $nroots+1, 0); - - $rs->fcr = $fcr; - $rs->prim = $prim; - $rs->nroots = $nroots; - $rs->gfpoly = $gfpoly; - - /* Find prim-th root of 1, used in decoding */ - for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) - ; // intentional empty-body loop! - - $rs->iprim = (int)($iprim / $prim); - $rs->genpoly[0] = 1; - - for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { - $rs->genpoly[$i+1] = 1; - - // Multiply rs->genpoly[] by @**(root + x) - for ($j = $i; $j > 0; $j--) { - if ($rs->genpoly[$j] != 0) { - $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; - } else { - $rs->genpoly[$j] = $rs->genpoly[$j-1]; - } - } - // rs->genpoly[0] can never be zero - $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; - } - - // convert rs->genpoly[] to index form for quicker encoding - for ($i = 0; $i <= $nroots; $i++) - $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; - - return $rs; - } - - //---------------------------------------------------------------------- - public function encode_rs_char($data, &$parity) - { - $MM =& $this->mm; - $NN =& $this->nn; - $ALPHA_TO =& $this->alpha_to; - $INDEX_OF =& $this->index_of; - $GENPOLY =& $this->genpoly; - $NROOTS =& $this->nroots; - $FCR =& $this->fcr; - $PRIM =& $this->prim; - $IPRIM =& $this->iprim; - $PAD =& $this->pad; - $A0 =& $NN; - - $parity = array_fill(0, $NROOTS, 0); - - for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { - - $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; - if($feedback != $A0) { - // feedback term is non-zero - - // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must - // always be for the polynomials constructed by init_rs() - $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); - - for($j=1;$j<$NROOTS;$j++) { - $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; - } - } - - // Shift - array_shift($parity); - if($feedback != $A0) { - array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); - } else { - array_push($parity, 0); - } - } - } - } - - //########################################################################## - - class QRrs { - - public static $items = array(); - - //---------------------------------------------------------------------- - public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) - { - foreach(self::$items as $rs) { - if($rs->pad != $pad) continue; - if($rs->nroots != $nroots) continue; - if($rs->mm != $symsize) continue; - if($rs->gfpoly != $gfpoly) continue; - if($rs->fcr != $fcr) continue; - if($rs->prim != $prim) continue; - - return $rs; - } - - $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); - array_unshift(self::$items, $rs); - - return $rs; - } - } - - - -//---- qrmask.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Masking - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('N1', 3); - define('N2', 3); - define('N3', 40); - define('N4', 10); - - class QRmask { - - public $runLength = array(); - - //---------------------------------------------------------------------- - public function __construct() - { - $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); - } - - //---------------------------------------------------------------------- - public function writeFormatInformation($width, &$frame, $mask, $level) - { - $blacks = 0; - $format = QRspec::getFormatInfo($mask, $level); - - for($i=0; $i<8; $i++) { - if($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - - $frame[8][$width - 1 - $i] = chr($v); - if($i < 6) { - $frame[$i][8] = chr($v); - } else { - $frame[$i + 1][8] = chr($v); - } - $format = $format >> 1; - } - - for($i=0; $i<7; $i++) { - if($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - - $frame[$width - 7 + $i][8] = chr($v); - if($i == 0) { - $frame[8][7] = chr($v); - } else { - $frame[8][6 - $i] = chr($v); - } - - $format = $format >> 1; - } - - return $blacks; - } - - //---------------------------------------------------------------------- - public function mask0($x, $y) { return ($x+$y)&1; } - public function mask1($x, $y) { return ($y&1); } - public function mask2($x, $y) { return ($x%3); } - public function mask3($x, $y) { return ($x+$y)%3; } - public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } - public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } - public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } - public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } - - //---------------------------------------------------------------------- - private function generateMaskNo($maskNo, $width, $frame) - { - $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); - - for($y=0; $y<$width; $y++) { - for($x=0; $x<$width; $x++) { - if(ord($frame[$y][$x]) & 0x80) { - $bitMask[$y][$x] = 0; - } else { - $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); - $bitMask[$y][$x] = ($maskFunc == 0)?1:0; - } - - } - } - - return $bitMask; - } - - //---------------------------------------------------------------------- - public static function serial($bitFrame) - { - $codeArr = array(); - - foreach ($bitFrame as $line) - $codeArr[] = join('', $line); - - return gzcompress(join("\n", $codeArr), 9); - } - - //---------------------------------------------------------------------- - public static function unserial($code) - { - $codeArr = array(); - - $codeLines = explode("\n", gzuncompress($code)); - foreach ($codeLines as $line) - $codeArr[] = str_split($line); - - return $codeArr; - } - - //---------------------------------------------------------------------- - public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) - { - $b = 0; - $bitMask = array(); - - $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; - - if (QR_CACHEABLE) { - if (file_exists($fileName)) { - $bitMask = self::unserial(file_get_contents($fileName)); - } else { - $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); - if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) - mkdir(QR_CACHE_DIR.'mask_'.$maskNo); - file_put_contents($fileName, self::serial($bitMask)); - } - } else { - $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); - } - - if ($maskGenOnly) - return; - - $d = $s; - - for($y=0; $y<$width; $y++) { - for($x=0; $x<$width; $x++) { - if($bitMask[$y][$x] == 1) { - $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); - } - $b += (int)(ord($d[$y][$x]) & 1); - } - } - - return $b; - } - - //---------------------------------------------------------------------- - public function makeMask($width, $frame, $maskNo, $level) - { - $masked = array_fill(0, $width, str_repeat("\0", $width)); - $this->makeMaskNo($maskNo, $width, $frame, $masked); - $this->writeFormatInformation($width, $masked, $maskNo, $level); - - return $masked; - } - - //---------------------------------------------------------------------- - public function calcN1N3($length) - { - $demerit = 0; - - for($i=0; $i<$length; $i++) { - - if($this->runLength[$i] >= 5) { - $demerit += (N1 + ($this->runLength[$i] - 5)); - } - if($i & 1) { - if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { - $fact = (int)($this->runLength[$i] / 3); - if(($this->runLength[$i-2] == $fact) && - ($this->runLength[$i-1] == $fact) && - ($this->runLength[$i+1] == $fact) && - ($this->runLength[$i+2] == $fact)) { - if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { - $demerit += N3; - } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { - $demerit += N3; - } - } - } - } - } - return $demerit; - } - - //---------------------------------------------------------------------- - public function evaluateSymbol($width, $frame) - { - $head = 0; - $demerit = 0; - - for($y=0; $y<$width; $y++) { - $head = 0; - $this->runLength[0] = 1; - - $frameY = $frame[$y]; - - if ($y>0) - $frameYM = $frame[$y-1]; - - for($x=0; $x<$width; $x++) { - if(($x > 0) && ($y > 0)) { - $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); - $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); - - if(($b22 | ($w22 ^ 1))&1) { - $demerit += N2; - } - } - if(($x == 0) && (ord($frameY[$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } else if($x > 0) { - if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - - $demerit += $this->calcN1N3($head+1); - } - - for($x=0; $x<$width; $x++) { - $head = 0; - $this->runLength[0] = 1; - - for($y=0; $y<$width; $y++) { - if($y == 0 && (ord($frame[$y][$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } else if($y > 0) { - if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - - $demerit += $this->calcN1N3($head+1); - } - - return $demerit; - } - - - //---------------------------------------------------------------------- - public function mask($width, $frame, $level) - { - $minDemerit = PHP_INT_MAX; - $bestMaskNum = 0; - $bestMask = array(); - - $checked_masks = array(0,1,2,3,4,5,6,7); - - if (QR_FIND_FROM_RANDOM !== false) { - - $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); - for ($i = 0; $i < $howManuOut; $i++) { - $remPos = rand (0, count($checked_masks)-1); - unset($checked_masks[$remPos]); - $checked_masks = array_values($checked_masks); - } - - } - - $bestMask = $frame; - - foreach($checked_masks as $i) { - $mask = array_fill(0, $width, str_repeat("\0", $width)); - - $demerit = 0; - $blacks = 0; - $blacks = $this->makeMaskNo($i, $width, $frame, $mask); - $blacks += $this->writeFormatInformation($width, $mask, $i, $level); - $blacks = (int)(100 * $blacks / ($width * $width)); - $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); - $demerit += $this->evaluateSymbol($width, $mask); - - if($demerit < $minDemerit) { - $minDemerit = $demerit; - $bestMask = $mask; - $bestMaskNum = $i; - } - } - - return $bestMask; - } - - //---------------------------------------------------------------------- - } - - - - -//---- qrencode.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Main encoder classes. - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRrsblock { - public $dataLength; - public $data = array(); - public $eccLength; - public $ecc = array(); - - public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) - { - $rs->encode_rs_char($data, $ecc); - - $this->dataLength = $dl; - $this->data = $data; - $this->eccLength = $el; - $this->ecc = $ecc; - } - }; - - //########################################################################## - - class QRrawcode { - public $version; - public $datacode = array(); - public $ecccode = array(); - public $blocks; - public $rsblocks = array(); //of RSblock - public $count; - public $dataLength; - public $eccLength; - public $b1; - - //---------------------------------------------------------------------- - public function __construct(QRinput $input) - { - $spec = array(0,0,0,0,0); - - $this->datacode = $input->getByteStream(); - if(is_null($this->datacode)) { - throw new Exception('null imput string'); - } - - QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); - - $this->version = $input->getVersion(); - $this->b1 = QRspec::rsBlockNum1($spec); - $this->dataLength = QRspec::rsDataLength($spec); - $this->eccLength = QRspec::rsEccLength($spec); - $this->ecccode = array_fill(0, $this->eccLength, 0); - $this->blocks = QRspec::rsBlockNum($spec); - - $ret = $this->init($spec); - if($ret < 0) { - throw new Exception('block alloc error'); - return null; - } - - $this->count = 0; - } - - //---------------------------------------------------------------------- - public function init(array $spec) - { - $dl = QRspec::rsDataCodes1($spec); - $el = QRspec::rsEccCodes1($spec); - $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - - - $blockNo = 0; - $dataPos = 0; - $eccPos = 0; - for($i=0; $iecccode,$eccPos); - $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); - $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); - - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - - if(QRspec::rsBlockNum2($spec) == 0) - return 0; - - $dl = QRspec::rsDataCodes2($spec); - $el = QRspec::rsEccCodes2($spec); - $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - - if($rs == NULL) return -1; - - for($i=0; $iecccode,$eccPos); - $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); - $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); - - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - - return 0; - } - - //---------------------------------------------------------------------- - public function getCode() - { - $ret; - - if($this->count < $this->dataLength) { - $row = $this->count % $this->blocks; - $col = $this->count / $this->blocks; - if($col >= $this->rsblocks[0]->dataLength) { - $row += $this->b1; - } - $ret = $this->rsblocks[$row]->data[$col]; - } else if($this->count < $this->dataLength + $this->eccLength) { - $row = ($this->count - $this->dataLength) % $this->blocks; - $col = ($this->count - $this->dataLength) / $this->blocks; - $ret = $this->rsblocks[$row]->ecc[$col]; - } else { - return 0; - } - $this->count++; - - return $ret; - } - } - - //########################################################################## - - class QRcode { - - public $version; - public $width; - public $data; - - //---------------------------------------------------------------------- - public function encodeMask(QRinput $input, $mask) - { - if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { - throw new Exception('wrong version'); - } - if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { - throw new Exception('wrong level'); - } - - $raw = new QRrawcode($input); - - QRtools::markTime('after_raw'); - - $version = $raw->version; - $width = QRspec::getWidth($version); - $frame = QRspec::newFrame($version); - - $filler = new FrameFiller($width, $frame); - if(is_null($filler)) { - return NULL; - } - - // inteleaved data and ecc codes - for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { - $code = $raw->getCode(); - $bit = 0x80; - for($j=0; $j<8; $j++) { - $addr = $filler->next(); - $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); - $bit = $bit >> 1; - } - } - - QRtools::markTime('after_filler'); - - unset($raw); - - // remainder bits - $j = QRspec::getRemainder($version); - for($i=0; $i<$j; $i++) { - $addr = $filler->next(); - $filler->setFrameAt($addr, 0x02); - } - - $frame = $filler->frame; - unset($filler); - - - // masking - $maskObj = new QRmask(); - if($mask < 0) { - - if (QR_FIND_BEST_MASK) { - $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); - } else { - $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); - } - } else { - $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); - } - - if($masked == NULL) { - return NULL; - } - - QRtools::markTime('after_mask'); - - $this->version = $version; - $this->width = $width; - $this->data = $masked; - - return $this; - } - - //---------------------------------------------------------------------- - public function encodeInput(QRinput $input) - { - return $this->encodeMask($input, -1); - } - - //---------------------------------------------------------------------- - public function encodeString8bit($string, $version, $level) - { - if(string == NULL) { - throw new Exception('empty string!'); - return NULL; - } - - $input = new QRinput($version, $level); - if($input == NULL) return NULL; - - $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); - if($ret < 0) { - unset($input); - return NULL; - } - return $this->encodeInput($input); - } - - //---------------------------------------------------------------------- - public function encodeString($string, $version, $level, $hint, $casesensitive) - { - - if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { - throw new Exception('bad hint'); - return NULL; - } - - $input = new QRinput($version, $level); - if($input == NULL) return NULL; - - $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); - if($ret < 0) { - return NULL; - } - - return $this->encodeInput($input); - } - - //---------------------------------------------------------------------- - public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encodePNG($text, $outfile, $saveandprint=false); - } - - //---------------------------------------------------------------------- - public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encode($text, $outfile); - } - - //---------------------------------------------------------------------- - public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encodeRAW($text, $outfile); - } - } - - //########################################################################## - - class FrameFiller { - - public $width; - public $frame; - public $x; - public $y; - public $dir; - public $bit; - - //---------------------------------------------------------------------- - public function __construct($width, &$frame) - { - $this->width = $width; - $this->frame = $frame; - $this->x = $width - 1; - $this->y = $width - 1; - $this->dir = -1; - $this->bit = -1; - } - - //---------------------------------------------------------------------- - public function setFrameAt($at, $val) - { - $this->frame[$at['y']][$at['x']] = chr($val); - } - - //---------------------------------------------------------------------- - public function getFrameAt($at) - { - return ord($this->frame[$at['y']][$at['x']]); - } - - //---------------------------------------------------------------------- - public function next() - { - do { - - if($this->bit == -1) { - $this->bit = 0; - return array('x'=>$this->x, 'y'=>$this->y); - } - - $x = $this->x; - $y = $this->y; - $w = $this->width; - - if($this->bit == 0) { - $x--; - $this->bit++; - } else { - $x++; - $y += $this->dir; - $this->bit--; - } - - if($this->dir < 0) { - if($y < 0) { - $y = 0; - $x -= 2; - $this->dir = 1; - if($x == 6) { - $x--; - $y = 9; - } - } - } else { - if($y == $w) { - $y = $w - 1; - $x -= 2; - $this->dir = -1; - if($x == 6) { - $x--; - $y -= 8; - } - } - } - if($x < 0 || $y < 0) return null; - - $this->x = $x; - $this->y = $y; - - } while(ord($this->frame[$y][$x]) & 0x80); - - return array('x'=>$x, 'y'=>$y); - } - - } ; - - //########################################################################## - - class QRencode { - - public $casesensitive = true; - public $eightbit = false; - - public $version = 0; - public $size = 3; - public $margin = 4; - - public $structured = 0; // not supported yet - - public $level = QR_ECLEVEL_L; - public $hint = QR_MODE_8; - - //---------------------------------------------------------------------- - public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = new QRencode(); - $enc->size = $size; - $enc->margin = $margin; - - switch ($level.'') { - case '0': - case '1': - case '2': - case '3': - $enc->level = $level; - break; - case 'l': - case 'L': - $enc->level = QR_ECLEVEL_L; - break; - case 'm': - case 'M': - $enc->level = QR_ECLEVEL_M; - break; - case 'q': - case 'Q': - $enc->level = QR_ECLEVEL_Q; - break; - case 'h': - case 'H': - $enc->level = QR_ECLEVEL_H; - break; - } - - return $enc; - } - - //---------------------------------------------------------------------- - public function encodeRAW($intext, $outfile = false) - { - $code = new QRcode(); - - if($this->eightbit) { - $code->encodeString8bit($intext, $this->version, $this->level); - } else { - $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); - } - - return $code->data; - } - - //---------------------------------------------------------------------- - public function encode($intext, $outfile = false) - { - $code = new QRcode(); - - if($this->eightbit) { - $code->encodeString8bit($intext, $this->version, $this->level); - } else { - $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); - } - - QRtools::markTime('after_encode'); - - if ($outfile!== false) { - file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); - } else { - return QRtools::binarize($code->data); - } - } - - //---------------------------------------------------------------------- - public function encodePNG($intext, $outfile = false,$saveandprint=false) - { - try { - - ob_start(); - $tab = $this->encode($intext); - $err = ob_get_contents(); - ob_end_clean(); - - if ($err != '') - QRtools::log($outfile, $err); - - $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); - - QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); - - } catch (Exception $e) { - - QRtools::log($outfile, $e->getMessage()); - - } - } - } - - diff --git a/api/status.php b/api/status.php new file mode 100644 index 0000000..2b1a20e --- /dev/null +++ b/api/status.php @@ -0,0 +1,26 @@ +([0-9]*)<\/strong>/', $site, $matches); + $online_otservlist = $matches[1]; +} catch(Exception $e) {} +$online_discord = 0; +try { + $online_discord = json_decode(file_get_contents("https://discordapp.com/api/guilds/628769144925585428/widget.json"))->presence_count; +} catch(Exception $e) {} + +$response = array( + "online" => "$online_otservlist Players online", + "discord_online" => $online_discord, + "discord_link" => "https://discord.gg/t4ntS5p" +); +echo json_encode($response); +?> \ No newline at end of file diff --git a/api/updater.php b/api/updater.php index 01a411d..0d8c8dd 100644 --- a/api/updater.php +++ b/api/updater.php @@ -22,7 +22,7 @@ $data_dir = "/var/www/otclient/files"; $things_dir = "/data/things"; // files from that dir won't be downloaded automaticly, you can set it to null to download everything automaticly (useful if you have only 1 version of data/sprites) $files_url = "http://otclient.ovh/files"; $update_checksum_interval = 60; // caling updater 100x/s would lag disc, we need to cache it -$main_files_and_dirs = array("data", "modules", "init.lua"); // used to ignore other files/dirs in data_dir +$main_files_and_dirs = array("data", "modules", "layouts", "init.lua"); // used to ignore other files/dirs in data_dir // CONFIG END diff --git a/data/images/game/actionbarslot.png b/data/images/game/actionbarslot.png new file mode 100644 index 0000000..448b71e Binary files /dev/null and b/data/images/game/actionbarslot.png differ diff --git a/data/images/game/combatmodes/pvp.png b/data/images/game/combatmodes/pvp.png new file mode 100644 index 0000000..b3087c0 Binary files /dev/null and b/data/images/game/combatmodes/pvp.png differ diff --git a/data/images/game/slots/purse.png b/data/images/game/slots/purse.png index 229e9ed..b2667a1 100644 Binary files a/data/images/game/slots/purse.png and b/data/images/game/slots/purse.png differ diff --git a/data/images/topbuttons/buttons.png b/data/images/topbuttons/buttons.png new file mode 100644 index 0000000..01cb280 Binary files /dev/null and b/data/images/topbuttons/buttons.png differ diff --git a/data/images/ui/discord.png b/data/images/ui/discord.png new file mode 100644 index 0000000..2e0d957 Binary files /dev/null and b/data/images/ui/discord.png differ diff --git a/data/minimap.otmm b/data/minimap.otmm new file mode 100644 index 0000000..a06e768 Binary files /dev/null and b/data/minimap.otmm differ diff --git a/data/styles/10-buttons.otui b/data/styles/10-buttons.otui index bf872db..4a81411 100644 --- a/data/styles/10-buttons.otui +++ b/data/styles/10-buttons.otui @@ -2,7 +2,7 @@ Button < UIButton font: verdana-11px-antialised color: #dfdfdfff size: 106 23 - text-offset: 0 0 + text-offset: 0 1 image-source: /images/ui/button image-color: #dfdfdf image-clip: 0 0 22 23 @@ -27,6 +27,7 @@ TabButton < UIButton image-color: #dfdfdf image-clip: 0 0 22 23 image-border: 3 + text-offset: 0 1 icon-color: #dfdfdf color: #dfdfdf @@ -47,6 +48,7 @@ NextButton < UIButton image-source: /images/ui/arrow_horizontal image-clip: 12 0 12 21 image-color: #ffffff + text-offset: 0 1 $hover !disabled: image-clip: 12 21 12 21 @@ -62,6 +64,7 @@ PreviousButton < UIButton image-source: /images/ui/arrow_horizontal image-clip: 0 0 12 21 image-color: #ffffff + text-offset: 0 1 $hover !disabled: image-clip: 0 21 12 21 @@ -76,6 +79,7 @@ AddButton < UIButton size: 20 20 image-source: /images/ui/icon_add image-color: #dfdfdfff + text-offset: 0 1 $hover !disabled: image-color: #dfdfdf99 diff --git a/data/styles/10-progressbars.otui b/data/styles/10-progressbars.otui index 1946016..6eac011 100644 --- a/data/styles/10-progressbars.otui +++ b/data/styles/10-progressbars.otui @@ -19,10 +19,16 @@ LifeProgressBar < UIProgressBar font: verdana-11px-rounded text-offset: 0 2 margin: 2 - + ProgressRect < UIProgressRect anchors.fill: parent phantom: true color: white background-color: #00000088 font: verdana-11px-rounded + +HealthBar < ProgressBar + background-color: #ff4444 + +ManaBar < ProgressBar + background-color: #4444ff diff --git a/data/styles/20-tabbars.otui b/data/styles/20-tabbars.otui index 06f242d..7e6b9b9 100644 --- a/data/styles/20-tabbars.otui +++ b/data/styles/20-tabbars.otui @@ -92,6 +92,9 @@ TabBarVertical < UITabBar anchors.right: scrollBar.left anchors.bottom: parent.bottom vertical-scrollbar: scrollBar + margin-right: 1 + padding-top: 10 + VerticalScrollBar id: scrollBar anchors.top: parent.top diff --git a/data/styles/20-topmenu.otui b/data/styles/20-topmenu.otui index 51456fe..60574fe 100644 --- a/data/styles/20-topmenu.otui +++ b/data/styles/20-topmenu.otui @@ -60,3 +60,56 @@ TopMenuFrameCounterLabel < Label TopMenuPingLabel < Label font: verdana-11px-rounded + +TopMenu < TopMenuPanel + id: topMenu + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + + TopMenuButtonsPanel + id: leftButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + + TopMenuButtonsPanel + id: leftGameButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: prev.right + visible: false + + TopMenuFrameCounterLabel + id: fpsLabel + text-auto-resize: true + anchors.top: parent.top + anchors.left: leftGameButtonsPanel.right + + TopMenuPingLabel + color: white + id: pingLabel + text-auto-resize: true + anchors.top: fpsLabel.bottom + anchors.left: fpsLabel.left + + Label + id: onlineLabel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + text-align: center + text-auto-resize: true + + TopMenuButtonsPanel + id: rightButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + + TopMenuButtonsPanel + id: rightGameButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: prev.left + visible: false \ No newline at end of file diff --git a/data/styles/30-miniwindow.otui b/data/styles/30-miniwindow.otui index 465c3c2..2e4a363 100644 --- a/data/styles/30-miniwindow.otui +++ b/data/styles/30-miniwindow.otui @@ -125,6 +125,4 @@ MiniWindowContents < ScrollablePanel margin-right: 1 vertical-scrollbar: miniwindowScrollBar -BorderlessGameWindow < UIWindow - focusable: false - margin: 2 +HeadlessMiniWindow < MiniWindow diff --git a/data/styles/40-background.otui b/data/styles/40-background.otui new file mode 100644 index 0000000..a87feca --- /dev/null +++ b/data/styles/40-background.otui @@ -0,0 +1,5 @@ +Background < Panel + image-source: /images/background + image-smooth: true + image-fixed-ratio: true + margin-top: 1 diff --git a/data/styles/40-console.otui b/data/styles/40-console.otui new file mode 100644 index 0000000..bc95dc8 --- /dev/null +++ b/data/styles/40-console.otui @@ -0,0 +1,185 @@ +ConsoleLabel < UITextEdit + font: verdana-11px-antialised + height: 14 + color: yellow + margin-left: 2 + text-wrap: true + text-auto-resize: true + selection-color: #111416 + selection-background-color: #999999 + change-cursor-image: false + cursor-visible: false + editable: false + draggable: true + selectable: false + focusable: false + +ConsolePhantomLabel < UILabel + font: verdana-11px-antialised + height: 14 + color: yellow + text-wrap: true + text-auto-resize: true + selection-color: #111416 + selection-background-color: #999999 + +ConsoleTabBar < MoveableTabBar + height: 28 + +ConsoleTabBarPanel < MoveableTabBarPanel + id: consoleTab + + ScrollablePanel + id: consoleBuffer + anchors.fill: parent + margin-right: 12 + vertical-scrollbar: consoleScrollBar + layout: + type: verticalBox + align-bottom: true + border-width: 1 + border-color: #202327 + background: #00000066 + inverted-scroll: true + padding: 1 + + VerticalScrollBar + id: consoleScrollBar + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + step: 14 + pixels-scroll: true + +ConsoleTabBarButton < MoveableTabBarButton + height: 28 + padding: 15 + +ConsolePanel < Panel + image-source: /images/ui/panel_bottom + image-border: 4 + + $first: + anchors.fill: parent + + $!first: + anchors.top: prev.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + + CheckBox + id: toggleChat + !tooltip: tr('Disable chat mode, allow to walk using ASDW') + anchors.left: parent.left + anchors.top: parent.top + margin-left: 13 + margin-top: 8 + @onCheckChange: toggleChat() + + TabButton + id: prevChannelButton + icon: /images/game/console/leftarrow + anchors.left: toggleChat.right + anchors.top: parent.top + margin-left: 3 + margin-top: 6 + + ConsoleTabBar + id: consoleTabBar + anchors.left: prev.right + anchors.top: parent.top + anchors.right: next.left + margin-left: 5 + margin-top: 3 + margin-right: 5 + tab-spacing: 2 + movable: true + + TabButton + id: nextChannelButton + icon: /images/game/console/rightarrow + anchors.right: next.left + anchors.top: parent.top + margin-right: 5 + margin-top: 6 + + TabButton + id: closeChannelButton + !tooltip: tr('Close this channel') .. ' (Ctrl+E)' + icon: /images/game/console/closechannel + anchors.right: next.left + anchors.top: parent.top + enabled: false + margin-right: 5 + margin-top: 6 + @onClick: removeCurrentTab() + + TabButton + id: clearChannelButton + !tooltip: tr('Clear current message window') + icon: /images/game/console/clearchannel + anchors.right: next.left + anchors.top: parent.top + margin-right: 5 + margin-top: 6 + @onClick: | + local consoleTabBar = self:getParent():getChildById('consoleTabBar') + clearChannel(consoleTabBar) + + TabButton + id: channelsButton + !tooltip: tr('Open new channel') .. ' (Ctrl+O)' + icon: /images/game/console/channels + anchors.right: next.left + anchors.top: parent.top + margin-right: 5 + margin-top: 6 + @onClick: g_game.requestChannels() + + TabButton + id: ignoreButton + !tooltip: tr('Ignore players') + icon: /images/game/console/ignore + anchors.right: parent.right + anchors.top: parent.top + margin-right: 5 + margin-top: 6 + @onClick: onClickIgnoreButton() + + Panel + id: consoleContentPanel + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: consoleTextEdit.top + margin-left: 6 + margin-right: 6 + margin-bottom: 4 + margin-top: 4 + padding: 1 + focusable: false + phantom: true + + TabButton + id: sayModeButton + icon: /images/game/console/say + !tooltip: tr('Adjust volume') + &sayMode: 2 + size: 20 20 + anchors.left: parent.left + anchors.bottom: parent.bottom + margin-left: 6 + margin-bottom: 6 + @onClick: sayModeChange() + + TextEdit + id: consoleTextEdit + anchors.left: sayModeButton.right + anchors.right: parent.right + anchors.bottom: parent.bottom + margin-right: 6 + margin-left: 6 + margin-bottom: 6 + shift-navigation: true + max-length: 255 diff --git a/modules/game_containers/container.otui b/data/styles/40-container.otui similarity index 85% rename from modules/game_containers/container.otui rename to data/styles/40-container.otui index cb505b2..b4afdf9 100644 --- a/modules/game_containers/container.otui +++ b/data/styles/40-container.otui @@ -1,67 +1,73 @@ -PageButton < Button - size: 30 18 - margin: 1 - - -ContainerWindow < MiniWindow - height: 150 - - UIItem - id: containerItemWidget - virtual: true - size: 16 16 - anchors.top: parent.top - anchors.left: parent.left - margin-top: 4 - margin-left: 4 - - UIButton - id: upButton - anchors.top: lockButton.top - anchors.right: lockButton.left - margin-right: 3 - size: 14 14 - image-source: /images/ui/miniwindow_buttons - image-clip: 42 0 14 14 - - $hover: - image-clip: 42 14 14 14 - - $pressed: - image-clip: 42 28 14 14 - - Panel - id: pagePanel - anchors.left: parent.left - anchors.right: parent.right - anchors.top: miniwindowTopBar.bottom - height: 20 - margin: 2 3 0 3 - background: #00000066 - visible: false - - Label - id: pageLabel - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - margin-top: 2 - text-auto-resize: true - - PageButton - id: prevPageButton - text: < - anchors.top: parent.top - anchors.left: parent.left - - PageButton - id: nextPageButton - text: > - anchors.top: parent.top - anchors.right: parent.right - - MiniWindowContents - padding-right: 0 - layout: - type: grid - cell-size: 34 34 - flow: true +PageButton < Button + size: 30 18 + margin: 1 + + +ContainerWindow < MiniWindow + height: 150 + + + UIItem + id: containerItemWidget + virtual: true + size: 16 16 + anchors.top: parent.top + anchors.left: parent.left + margin-top: 1 + margin-left: 3 + + UIButton + id: upButton + anchors.top: lockButton.top + anchors.right: lockButton.left + margin-right: 3 + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 42 0 14 14 + + $hover: + image-clip: 42 14 14 14 + + $pressed: + image-clip: 42 28 14 14 + + Panel + id: pagePanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: miniwindowTopBar.bottom + margin: 1 3 0 3 + background: #00000066 + height: 20 + + $on: + visible: true + + $!on: + visible: false + + Label + id: pageLabel + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + margin-top: 2 + text-auto-resize: true + + PageButton + id: prevPageButton + text: < + anchors.top: parent.top + anchors.left: parent.left + + PageButton + id: nextPageButton + text: > + anchors.top: parent.top + anchors.right: parent.right + + MiniWindowContents + padding-right: 0 + layout: + type: grid + cell-size: 34 34 + flow: true diff --git a/data/styles/40-entergame.otui b/data/styles/40-entergame.otui new file mode 100644 index 0000000..609e4bb --- /dev/null +++ b/data/styles/40-entergame.otui @@ -0,0 +1,3 @@ +EnterGameWindow < StaticMainWindow + !text: tr('Enter Game') + size: 260 354 \ No newline at end of file diff --git a/data/styles/40-gamebuttons.otui b/data/styles/40-gamebuttons.otui new file mode 100644 index 0000000..4afbeec --- /dev/null +++ b/data/styles/40-gamebuttons.otui @@ -0,0 +1,2 @@ +GameButtonsWindow < MiniWindow + height: 40 diff --git a/data/styles/40-healthinfo.otui b/data/styles/40-healthinfo.otui new file mode 100644 index 0000000..7356f3a --- /dev/null +++ b/data/styles/40-healthinfo.otui @@ -0,0 +1,146 @@ +ExperienceBar < ProgressBar + id: experienceBar + background-color: #B6E866 + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin: 1 + margin-top: 3 + +SoulLabel < GameLabel + id: soulLabel + text-align: right + color: white + font: verdana-11px-rounded + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.left: parent.horizontalCenter + margin-top: 5 + margin-right: 3 + on: true + + $!on: + visible: false + margin-top: 0 + height: 0 + +CapLabel < GameLabel + id: capLabel + color: white + font: verdana-11px-rounded + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.horizontalCenter + margin-top: 5 + margin-left: 3 + on: true + + $!on: + visible: false + margin-top: 0 + height: 0 + +ConditionWidget < UIWidget + size: 18 18 + + $!first: + margin-left: 2 + +HealthOverlay < UIWidget + id: healthOverlay + anchors.fill: parent + phantom: true + + HealthBar + id: topHealthBar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.horizontalCenter + phantom: true + + ManaBar + id: topManaBar + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.horizontalCenter + phantom: true + + UIProgressBar + id: healthCircle + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/left_empty + margin-right: 169 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: healthCircleFront + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/left_full + margin-right: 169 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: manaCircle + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/right_empty + margin-left: 130 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: manaCircleFront + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/right_full + margin-left: 130 + margin-bottom: 16 + opacity: 0.4 + image-color: #0000FFFF + phantom: true + +HealthInfoWindow < MiniWindow + icon: /images/topbuttons/healthinfo + !text: tr('Health Info') + height: 123 + + MiniWindowContents + HealthBar + id: healthBar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + margin: 2 + margin-top: 1 + + ManaBar + id: manaBar + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin: 2 + + ExperienceBar + Panel + id: conditionPanel + layout: + type: horizontalBox + height: 22 + margin-top: 4 + padding: 2 + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + border-width: 1 + border-color: #00000077 + background-color: #ffffff11 + SoulLabel + CapLabel + diff --git a/data/styles/40-inventory.otui b/data/styles/40-inventory.otui new file mode 100644 index 0000000..37e7263 --- /dev/null +++ b/data/styles/40-inventory.otui @@ -0,0 +1,299 @@ +InventoryItem < Item + $on: + image-source: /images/ui/item-blessed + +HeadSlot < InventoryItem + id: slot1 + image-source: /images/game/slots/head + &position: {x=65535, y=1, z=0} + $on: + image-source: /images/game/slots/head-blessed + +BodySlot < InventoryItem + id: slot4 + image-source: /images/game/slots/body + &position: {x=65535, y=4, z=0} + $on: + image-source: /images/game/slots/body-blessed + +LegSlot < InventoryItem + id: slot7 + image-source: /images/game/slots/legs + &position: {x=65535, y=7, z=0} + $on: + image-source: /images/game/slots/legs-blessed + +FeetSlot < InventoryItem + id: slot8 + image-source: /images/game/slots/feet + &position: {x=65535, y=8, z=0} + $on: + image-source: /images/game/slots/feet-blessed + +NeckSlot < InventoryItem + id: slot2 + image-source: /images/game/slots/neck + &position: {x=65535, y=2, z=0} + $on: + image-source: /images/game/slots/neck-blessed + +LeftSlot < InventoryItem + id: slot6 + image-source: /images/game/slots/left-hand + &position: {x=65535, y=6, z=0} + $on: + image-source: /images/game/slots/left-hand-blessed + +FingerSlot < InventoryItem + id: slot9 + image-source: /images/game/slots/finger + &position: {x=65535, y=9, z=0} + $on: + image-source: /images/game/slots/finger-blessed + +BackSlot < InventoryItem + id: slot3 + image-source: /images/game/slots/back + &position: {x=65535, y=3, z=0} + $on: + image-source: /images/game/slots/back-blessed + +RightSlot < InventoryItem + id: slot5 + image-source: /images/game/slots/right-hand + &position: {x=65535, y=5, z=0} + $on: + image-source: /images/game/slots/right-hand-blessed + +AmmoSlot < InventoryItem + id: slot10 + image-source: /images/game/slots/ammo + &position: {x=65535, y=10, z=0} + $on: + image-source: /images/game/slots/ammo-blessed + +PurseButton < UIButton + id: purseButton + size: 34 12 + !tooltip: tr('Open purse') + icon-source: /images/game/slots/purse + icon-clip: 0 0 34 12 + + $on: + icon-clip: 0 12 34 12 + + $pressed: + icon-clip: 0 12 34 12 + +CombatBox < UICheckBox + size: 20 20 + image-clip: 0 0 20 20 + margin-left: 4 + + $checked: + image-clip: 0 20 20 20 + + +InventoryButton < Button + font: verdana-11px-antialised + height: 18 + margin-top: 2 + text-align: center + +SoulCapLabel < GameLabel + text-align: center + color: #FFFFFF + font: cipsoftFont + margin-top: 4 + text-offset: 0 3 + width: 36 + height: 20 + icon-source: /images/game/slots/soulcap + +FightOffensiveBox < CombatBox + image-source: /images/game/combatmodes/fightoffensive +FightBalancedBox < CombatBox + image-source: /images/game/combatmodes/fightbalanced +FightDefensiveBox < CombatBox + image-source: /images/game/combatmodes/fightdefensive +ChaseModeBox < CombatBox + image-source: /images/game/combatmodes/chasemode +SafeFightBox < CombatBox + image-source: /images/game/combatmodes/safefight + +MountButton < CombatBox + image-source: /images/game/combatmodes/mount + +InventoryWindow < MiniWindow + icon: /images/topbuttons/inventory + height: 200 + id: inventoryWindow + @onClose: modules.game_inventory.onMiniWindowClose() + &save: true + &autoOpen: 3 + + MiniWindowContents + anchors.left: parent.left + + Panel + id: inventoryPanel + margin-right: 63 + margin-top: 2 + anchors.fill: parent + + HeadSlot + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + margin-top: 3 + + BodySlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + LegSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + FeetSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + NeckSlot + anchors.top: slot1.top + anchors.right: slot1.left + margin-top: 13 + margin-right: 5 + + LeftSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + FingerSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + BackSlot + anchors.top: slot1.top + anchors.left: slot1.right + margin-top: 13 + margin-left: 5 + + RightSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + AmmoSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + SoulCapLabel + id: soulLabel + anchors.top: slot10.bottom + anchors.horizontalCenter: slot10.horizontalCenter + + SoulCapLabel + id: capLabel + anchors.top: slot9.bottom + anchors.horizontalCenter: slot9.horizontalCenter + + PurseButton + anchors.left: slot3.left + anchors.bottom: slot3.top + margin-bottom: 3 + + Panel + id: conditionPanel + layout: + type: horizontalBox + height: 22 + padding: 2 + anchors.top: slot8.bottom + anchors.left: slot6.left + anchors.right: slot5.right + margin-top: 4 + border-width: 1 + border-color: #00000077 + background-color: #ffffff22 + + Panel + margin-top: 5 + anchors.fill: parent + anchors.left: prev.right + + FightOffensiveBox + id: fightOffensiveBox + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + ChaseModeBox + id: chaseModeBox + anchors.left: prev.right + anchors.top: parent.top + + FightBalancedBox + id: fightBalancedBox + margin-top: 22 + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + SafeFightBox + id: safeFightBox + margin-top: 22 + anchors.left: prev.right + anchors.top: parent.top + + FightDefensiveBox + id: fightDefensiveBox + margin-top: 44 + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + MountButton + id: mountButton + margin-top: 44 + anchors.left: prev.right + anchors.top: parent.top + + Panel + id: buttonsPanel + margin-top: 4 + margin-right: 5 + anchors.fill: parent + anchors.top: prev.bottom + layout: + type: verticalBox + + UIButton + id: buttonPvp + height: 20 + icon: /images/game/combatmodes/pvp + icon-clip: 0 0 42 20 + + $on: + icon-clip: 0 20 42 20 + + InventoryButton + !text: tr('Stop') + @onClick: g_game.stop(); g_game.cancelAttackAndFollow() + + InventoryButton + !text: tr('Options') + @onClick: modules.client_options.toggle() + + InventoryButton + !text: tr('Hotkeys') + @onClick: modules.game_hotkeys.toggle() + + InventoryButton + !text: tr('Logout') + @onClick: modules.game_interface.tryLogout() diff --git a/data/styles/40-minimap.otui b/data/styles/40-minimap.otui new file mode 100644 index 0000000..8a7a55e --- /dev/null +++ b/data/styles/40-minimap.otui @@ -0,0 +1,268 @@ +MinimapFlag < UIWidget + size: 11 11 + focusable: false + +MinimapCross < UIWidget + focusable: false + phantom: true + image: /images/game/minimap/cross + size: 16 16 + +MinimapFloorUpButton < Button + size: 20 20 + margin-right: 28 + margin-bottom: 28 + anchors.right: parent.right + anchors.bottom: parent.bottom + icon-source: /images/game/minimap/floor_up + icon-clip: 0 32 16 16 + $pressed: + icon-clip: 0 0 16 16 + $hover !pressed: + icon-clip: 0 16 16 16 + +MinimapFloorDownButton < Button + size: 20 20 + margin-right: 28 + margin-bottom: 4 + anchors.right: parent.right + anchors.bottom: parent.bottom + icon-source: /images/game/minimap/floor_down + icon-clip: 0 32 16 16 + $pressed: + icon-clip: 0 0 16 16 + $hover !pressed: + icon-clip: 0 16 16 16 + +MinimapZoomInButton < Button + text: + + size: 20 20 + margin-right: 4 + margin-bottom: 28 + anchors.right: parent.right + anchors.bottom: parent.bottom + //icon-source: /images/game/minimap/zoom_in + +MinimapZoomOutButton < Button + text: - + size: 20 20 + margin-right: 4 + margin-bottom: 4 + anchors.right: parent.right + anchors.bottom: parent.bottom + //icon-source: /images/game/minimap/zoom_out + +MinimapResetButton < Button + !text: tr('Center') + size: 44 20 + anchors.left: parent.left + anchors.top: parent.top + margin: 4 + +Minimap < UIMinimap + draggable: true + focusable: false + cross: true + color: black + + MinimapFloorUpButton + id: floorUpWidget + @onClick: self:getParent():floorUp(1) + + MinimapFloorDownButton + id: floorDownWidget + @onClick: self:getParent():floorDown(1) + + MinimapZoomInButton + id: zoomInWidget + @onClick: self:getParent():zoomIn() + + MinimapZoomOutButton + id: zoomOutWidget + @onClick: self:getParent():zoomOut() + + MinimapResetButton + id: resetWidget + @onClick: self:getParent():reset() + + +// Minimap Flag Create Window + + +MinimapFlagCheckBox < CheckBox + size: 15 15 + margin-left: 2 + image-source: /images/game/minimap/flagcheckbox + image-size: 15 15 + image-border: 3 + icon-source: /images/game/minimap/mapflags + icon-size: 11 11 + icon-offset: 2 4 + anchors.left: prev.right + anchors.top: prev.top + $!checked: + image-clip: 26 0 26 26 + $hover !checked: + image-clip: 78 0 26 26 + $checked: + image-clip: 0 0 26 26 + $hover checked: + image-clip: 52 0 26 26 + +MinimapFlagWindow < MainWindow + !text: tr('Create Map Mark') + size: 196 185 + + Label + !text: tr('Position') .. ':' + text-auto-resize: true + anchors.top: parent.top + anchors.left: parent.left + margin-top: 2 + + Label + id: position + text-auto-resize: true + anchors.top: parent.top + anchors.right: parent.right + margin-top: 2 + + Label + !text: tr('Description') .. ':' + anchors.left: parent.left + anchors.top: prev.bottom + margin-top: 7 + + TextEdit + id: description + margin-top: 3 + anchors.left: parent.left + anchors.top: prev.bottom + anchors.right: parent.right + + MinimapFlagCheckBox + id: flag0 + icon-source: /images/game/minimap/flag0 + anchors.left: parent.left + anchors.top: prev.bottom + margin-top: 6 + margin-left: 0 + + MinimapFlagCheckBox + id: flag1 + icon-source: /images/game/minimap/flag1 + + MinimapFlagCheckBox + id: flag2 + icon-source: /images/game/minimap/flag2 + + MinimapFlagCheckBox + id: flag3 + icon-source: /images/game/minimap/flag3 + + MinimapFlagCheckBox + id: flag4 + icon-source: /images/game/minimap/flag4 + + MinimapFlagCheckBox + id: flag5 + icon-source: /images/game/minimap/flag5 + + MinimapFlagCheckBox + id: flag6 + icon-source: /images/game/minimap/flag6 + + MinimapFlagCheckBox + id: flag7 + icon-source: /images/game/minimap/flag7 + + MinimapFlagCheckBox + id: flag8 + icon-source: /images/game/minimap/flag8 + + MinimapFlagCheckBox + id: flag9 + icon-source: /images/game/minimap/flag9 + + MinimapFlagCheckBox + id: flag10 + icon-source: /images/game/minimap/flag10 + anchors.left: parent.left + anchors.top: prev.bottom + margin-top: 6 + margin-left: 0 + + MinimapFlagCheckBox + id: flag11 + icon-source: /images/game/minimap/flag11 + + MinimapFlagCheckBox + id: flag12 + icon-source: /images/game/minimap/flag12 + + MinimapFlagCheckBox + id: flag13 + icon-source: /images/game/minimap/flag13 + + MinimapFlagCheckBox + id: flag14 + icon-source: /images/game/minimap/flag14 + + MinimapFlagCheckBox + id: flag15 + icon-source: /images/game/minimap/flag15 + + MinimapFlagCheckBox + id: flag16 + icon-source: /images/game/minimap/flag16 + + MinimapFlagCheckBox + id: flag17 + icon-source: /images/game/minimap/flag17 + + MinimapFlagCheckBox + id: flag18 + icon-source: /images/game/minimap/flag18 + + MinimapFlagCheckBox + id: flag19 + icon-source: /images/game/minimap/flag19 + + Button + id: okButton + !text: tr('Ok') + width: 64 + anchors.right: next.left + anchors.bottom: parent.bottom + margin-right: 10 + + Button + id: cancelButton + !text: tr('Cancel') + width: 64 + anchors.right: parent.right + anchors.bottom: parent.bottom + +MinimapWindow < MiniWindow + height: 150 + + Label + text: ? + text-align: center + phantom: false + !tooltip: tr('Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks\nPress Ctrl+Shift+M to view the entire game map') + anchors.top: lockButton.top + anchors.right: lockButton.left + margin-right: 3 + size: 14 14 + + MiniWindowContents + Minimap + id: minimap + anchors.fill: parent + + ResizeBorder + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + enabled: true \ No newline at end of file diff --git a/data/things/.gitignore b/data/things/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/data/things/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/init.lua b/init.lua index 0e1492e..658b487 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,7 @@ -- CONFIG APP_NAME = "otclientv8" -- important, change it, it's name for config dir and files in appdata APP_VERSION = 1337 -- client version for updater and login to identify outdated client +DEFAULT_LAYOUT = "retro" -- If you don't use updater or other service, set it to updater = "" Services = { @@ -8,18 +9,19 @@ Services = { updater = "", stats = "", crash = "http://otclient.ovh/api/crash.php", - feedback = "http://otclient.ovh/api/feedback.php" + feedback = "", + status = "http://otclient.ovh/api/status.php" } -- Servers accept http login url, websocket login url or ip:port:version Servers = { +-- OTClientV8c = "otclient.ovh:7171:1099:25:30:80:90", -- OTClientV8 = "http://otclient.ovh/api/login.php", --- OTClientV8Websocket = "wss://otclient.ovh:3000/", -- OTClientV8proxy = "http://otclient.ovh/api/login.php?proxy=1", --- OTClientV8ClassicWithFeatures = "otclient.ovh:7171:1099:25:30:80:90", --- OTClientV8Classic = "otclient.ovh:7171:1099" +-- OTClientV8Test = "http://otclient.ovh/api/login2.php", } -USE_NEW_ENERGAME = false -- uses entergamev2 based on websockets instead of entergame + +USE_NEW_ENERGAME = false -- not done yet ALLOW_CUSTOM_SERVERS = true -- if true it shows option ANOTHER on server list -- CONFIG END @@ -58,6 +60,14 @@ end -- settings g_configs.loadSettings("/config.otml") +-- set layout +local settings = g_configs.getSettings() +local layout = DEFAULT_LAYOUT +if settings:exists('layout') then + layout = settings:getValue('layout') +end +g_resources.setLayout(layout) + -- load mods g_modules.discoverModules() diff --git a/layouts/README.md b/layouts/README.md new file mode 100644 index 0000000..f675d1e --- /dev/null +++ b/layouts/README.md @@ -0,0 +1,4 @@ +## Layouts overwrite files from `/data` +Foe example, if you have file `/data/images/background.png` and `/layouts/dragonball/images/background.png`, and dragonball layout is selected, then `/layouts/dragonball/images/background.png` will be loaded instead of `/data/images/background.png`. + +## Dont make layout named `default`, this name is reserved diff --git a/layouts/retro/images/background.png b/layouts/retro/images/background.png new file mode 100644 index 0000000..daa666e Binary files /dev/null and b/layouts/retro/images/background.png differ diff --git a/layouts/retro/images/game/console/channels.png b/layouts/retro/images/game/console/channels.png new file mode 100644 index 0000000..017d2eb Binary files /dev/null and b/layouts/retro/images/game/console/channels.png differ diff --git a/layouts/retro/images/game/console/clearchannel.png b/layouts/retro/images/game/console/clearchannel.png new file mode 100644 index 0000000..201bd82 Binary files /dev/null and b/layouts/retro/images/game/console/clearchannel.png differ diff --git a/layouts/retro/images/game/console/closechannel.png b/layouts/retro/images/game/console/closechannel.png new file mode 100644 index 0000000..46ea537 Binary files /dev/null and b/layouts/retro/images/game/console/closechannel.png differ diff --git a/layouts/retro/images/game/console/ignore.png b/layouts/retro/images/game/console/ignore.png new file mode 100644 index 0000000..ab08dc1 Binary files /dev/null and b/layouts/retro/images/game/console/ignore.png differ diff --git a/layouts/retro/images/game/console/leftarrow.png b/layouts/retro/images/game/console/leftarrow.png new file mode 100644 index 0000000..7e065f5 Binary files /dev/null and b/layouts/retro/images/game/console/leftarrow.png differ diff --git a/layouts/retro/images/game/console/rightarrow.png b/layouts/retro/images/game/console/rightarrow.png new file mode 100644 index 0000000..4c51e9f Binary files /dev/null and b/layouts/retro/images/game/console/rightarrow.png differ diff --git a/layouts/retro/images/game/console/say.png b/layouts/retro/images/game/console/say.png new file mode 100644 index 0000000..7f28bae Binary files /dev/null and b/layouts/retro/images/game/console/say.png differ diff --git a/layouts/retro/images/game/console/trademsg.png b/layouts/retro/images/game/console/trademsg.png new file mode 100644 index 0000000..9d96ffb Binary files /dev/null and b/layouts/retro/images/game/console/trademsg.png differ diff --git a/layouts/retro/images/game/console/whisper.png b/layouts/retro/images/game/console/whisper.png new file mode 100644 index 0000000..a66f48f Binary files /dev/null and b/layouts/retro/images/game/console/whisper.png differ diff --git a/layouts/retro/images/game/console/yell.png b/layouts/retro/images/game/console/yell.png new file mode 100644 index 0000000..3fedf22 Binary files /dev/null and b/layouts/retro/images/game/console/yell.png differ diff --git a/layouts/retro/images/topbuttons/analyzers.png b/layouts/retro/images/topbuttons/analyzers.png new file mode 100644 index 0000000..db2fa61 Binary files /dev/null and b/layouts/retro/images/topbuttons/analyzers.png differ diff --git a/layouts/retro/images/topbuttons/audio.png b/layouts/retro/images/topbuttons/audio.png new file mode 100644 index 0000000..7bac9e9 Binary files /dev/null and b/layouts/retro/images/topbuttons/audio.png differ diff --git a/layouts/retro/images/topbuttons/audio_mute.png b/layouts/retro/images/topbuttons/audio_mute.png new file mode 100644 index 0000000..a7dda9a Binary files /dev/null and b/layouts/retro/images/topbuttons/audio_mute.png differ diff --git a/layouts/retro/images/topbuttons/battle.png b/layouts/retro/images/topbuttons/battle.png new file mode 100644 index 0000000..939baba Binary files /dev/null and b/layouts/retro/images/topbuttons/battle.png differ diff --git a/layouts/retro/images/topbuttons/bot.png b/layouts/retro/images/topbuttons/bot.png new file mode 100644 index 0000000..c9871fd Binary files /dev/null and b/layouts/retro/images/topbuttons/bot.png differ diff --git a/layouts/retro/images/topbuttons/ciclopedia.png b/layouts/retro/images/topbuttons/ciclopedia.png new file mode 100644 index 0000000..8ecd0bf Binary files /dev/null and b/layouts/retro/images/topbuttons/ciclopedia.png differ diff --git a/layouts/retro/images/topbuttons/compedium.png b/layouts/retro/images/topbuttons/compedium.png new file mode 100644 index 0000000..6fe888f Binary files /dev/null and b/layouts/retro/images/topbuttons/compedium.png differ diff --git a/layouts/retro/images/topbuttons/cooldowns.png b/layouts/retro/images/topbuttons/cooldowns.png new file mode 100644 index 0000000..fd5d845 Binary files /dev/null and b/layouts/retro/images/topbuttons/cooldowns.png differ diff --git a/layouts/retro/images/topbuttons/dailyreward.png b/layouts/retro/images/topbuttons/dailyreward.png new file mode 100644 index 0000000..1aa046a Binary files /dev/null and b/layouts/retro/images/topbuttons/dailyreward.png differ diff --git a/layouts/retro/images/topbuttons/debug.png b/layouts/retro/images/topbuttons/debug.png new file mode 100644 index 0000000..f8000f6 Binary files /dev/null and b/layouts/retro/images/topbuttons/debug.png differ diff --git a/layouts/retro/images/topbuttons/exit.png b/layouts/retro/images/topbuttons/exit.png new file mode 100644 index 0000000..15f4b71 Binary files /dev/null and b/layouts/retro/images/topbuttons/exit.png differ diff --git a/layouts/retro/images/topbuttons/healthinfo.png b/layouts/retro/images/topbuttons/healthinfo.png new file mode 100644 index 0000000..68ac924 Binary files /dev/null and b/layouts/retro/images/topbuttons/healthinfo.png differ diff --git a/layouts/retro/images/topbuttons/hotkeys.png b/layouts/retro/images/topbuttons/hotkeys.png new file mode 100644 index 0000000..bbb9901 Binary files /dev/null and b/layouts/retro/images/topbuttons/hotkeys.png differ diff --git a/layouts/retro/images/topbuttons/inventory.png b/layouts/retro/images/topbuttons/inventory.png new file mode 100644 index 0000000..f5a3479 Binary files /dev/null and b/layouts/retro/images/topbuttons/inventory.png differ diff --git a/layouts/retro/images/topbuttons/login.png b/layouts/retro/images/topbuttons/login.png new file mode 100644 index 0000000..55ec697 Binary files /dev/null and b/layouts/retro/images/topbuttons/login.png differ diff --git a/layouts/retro/images/topbuttons/logout.png b/layouts/retro/images/topbuttons/logout.png new file mode 100644 index 0000000..4813b91 Binary files /dev/null and b/layouts/retro/images/topbuttons/logout.png differ diff --git a/layouts/retro/images/topbuttons/minimap.png b/layouts/retro/images/topbuttons/minimap.png new file mode 100644 index 0000000..c397923 Binary files /dev/null and b/layouts/retro/images/topbuttons/minimap.png differ diff --git a/layouts/retro/images/topbuttons/modulemanager.png b/layouts/retro/images/topbuttons/modulemanager.png new file mode 100644 index 0000000..8089991 Binary files /dev/null and b/layouts/retro/images/topbuttons/modulemanager.png differ diff --git a/layouts/retro/images/topbuttons/motd.png b/layouts/retro/images/topbuttons/motd.png new file mode 100644 index 0000000..793fe7a Binary files /dev/null and b/layouts/retro/images/topbuttons/motd.png differ diff --git a/layouts/retro/images/topbuttons/options.png b/layouts/retro/images/topbuttons/options.png new file mode 100644 index 0000000..64a2186 Binary files /dev/null and b/layouts/retro/images/topbuttons/options.png differ diff --git a/layouts/retro/images/topbuttons/particles.png b/layouts/retro/images/topbuttons/particles.png new file mode 100644 index 0000000..a52cc24 Binary files /dev/null and b/layouts/retro/images/topbuttons/particles.png differ diff --git a/layouts/retro/images/topbuttons/prey.png b/layouts/retro/images/topbuttons/prey.png new file mode 100644 index 0000000..ddef6ee Binary files /dev/null and b/layouts/retro/images/topbuttons/prey.png differ diff --git a/layouts/retro/images/topbuttons/questlog.png b/layouts/retro/images/topbuttons/questlog.png new file mode 100644 index 0000000..105e529 Binary files /dev/null and b/layouts/retro/images/topbuttons/questlog.png differ diff --git a/layouts/retro/images/topbuttons/shop.png b/layouts/retro/images/topbuttons/shop.png new file mode 100644 index 0000000..21d5e95 Binary files /dev/null and b/layouts/retro/images/topbuttons/shop.png differ diff --git a/layouts/retro/images/topbuttons/skills.png b/layouts/retro/images/topbuttons/skills.png new file mode 100644 index 0000000..9424cea Binary files /dev/null and b/layouts/retro/images/topbuttons/skills.png differ diff --git a/layouts/retro/images/topbuttons/spelllist.png b/layouts/retro/images/topbuttons/spelllist.png new file mode 100644 index 0000000..b21d17a Binary files /dev/null and b/layouts/retro/images/topbuttons/spelllist.png differ diff --git a/layouts/retro/images/topbuttons/terminal.png b/layouts/retro/images/topbuttons/terminal.png new file mode 100644 index 0000000..f55133f Binary files /dev/null and b/layouts/retro/images/topbuttons/terminal.png differ diff --git a/layouts/retro/images/topbuttons/unjustifiedpoints.png b/layouts/retro/images/topbuttons/unjustifiedpoints.png new file mode 100644 index 0000000..81de760 Binary files /dev/null and b/layouts/retro/images/topbuttons/unjustifiedpoints.png differ diff --git a/layouts/retro/images/topbuttons/viplist.png b/layouts/retro/images/topbuttons/viplist.png new file mode 100644 index 0000000..646091d Binary files /dev/null and b/layouts/retro/images/topbuttons/viplist.png differ diff --git a/layouts/retro/images/ui/arrow_horizontal.png b/layouts/retro/images/ui/arrow_horizontal.png new file mode 100644 index 0000000..a0ec72c Binary files /dev/null and b/layouts/retro/images/ui/arrow_horizontal.png differ diff --git a/layouts/retro/images/ui/arrow_vertical.png b/layouts/retro/images/ui/arrow_vertical.png new file mode 100644 index 0000000..d48aba3 Binary files /dev/null and b/layouts/retro/images/ui/arrow_vertical.png differ diff --git a/layouts/retro/images/ui/broder_panel.png b/layouts/retro/images/ui/broder_panel.png new file mode 100644 index 0000000..da36bae Binary files /dev/null and b/layouts/retro/images/ui/broder_panel.png differ diff --git a/layouts/retro/images/ui/button.png b/layouts/retro/images/ui/button.png new file mode 100644 index 0000000..3c8f17e Binary files /dev/null and b/layouts/retro/images/ui/button.png differ diff --git a/layouts/retro/images/ui/checkbox.png b/layouts/retro/images/ui/checkbox.png new file mode 100644 index 0000000..829cc59 Binary files /dev/null and b/layouts/retro/images/ui/checkbox.png differ diff --git a/layouts/retro/images/ui/colorbox.png b/layouts/retro/images/ui/colorbox.png new file mode 100644 index 0000000..9d2ef7f Binary files /dev/null and b/layouts/retro/images/ui/colorbox.png differ diff --git a/layouts/retro/images/ui/combobox.png b/layouts/retro/images/ui/combobox.png new file mode 100644 index 0000000..18dc0ac Binary files /dev/null and b/layouts/retro/images/ui/combobox.png differ diff --git a/layouts/retro/images/ui/combobox_rounded.png b/layouts/retro/images/ui/combobox_rounded.png new file mode 100644 index 0000000..faf8607 Binary files /dev/null and b/layouts/retro/images/ui/combobox_rounded.png differ diff --git a/layouts/retro/images/ui/combobox_square.png b/layouts/retro/images/ui/combobox_square.png new file mode 100644 index 0000000..ec0ed70 Binary files /dev/null and b/layouts/retro/images/ui/combobox_square.png differ diff --git a/layouts/retro/images/ui/icon_add.png b/layouts/retro/images/ui/icon_add.png new file mode 100644 index 0000000..f820a0b Binary files /dev/null and b/layouts/retro/images/ui/icon_add.png differ diff --git a/layouts/retro/images/ui/item.png b/layouts/retro/images/ui/item.png new file mode 100644 index 0000000..6b605a3 Binary files /dev/null and b/layouts/retro/images/ui/item.png differ diff --git a/layouts/retro/images/ui/menubarleft.png b/layouts/retro/images/ui/menubarleft.png new file mode 100644 index 0000000..4ca138b Binary files /dev/null and b/layouts/retro/images/ui/menubarleft.png differ diff --git a/layouts/retro/images/ui/menubox.png b/layouts/retro/images/ui/menubox.png new file mode 100644 index 0000000..169e36d Binary files /dev/null and b/layouts/retro/images/ui/menubox.png differ diff --git a/layouts/retro/images/ui/minibroder.png b/layouts/retro/images/ui/minibroder.png new file mode 100644 index 0000000..3dfe1b7 Binary files /dev/null and b/layouts/retro/images/ui/minibroder.png differ diff --git a/layouts/retro/images/ui/miniwindow.png b/layouts/retro/images/ui/miniwindow.png new file mode 100644 index 0000000..6886d44 Binary files /dev/null and b/layouts/retro/images/ui/miniwindow.png differ diff --git a/layouts/retro/images/ui/miniwindow_buttons.png b/layouts/retro/images/ui/miniwindow_buttons.png new file mode 100644 index 0000000..3fbb870 Binary files /dev/null and b/layouts/retro/images/ui/miniwindow_buttons.png differ diff --git a/layouts/retro/images/ui/noimage.png b/layouts/retro/images/ui/noimage.png new file mode 100644 index 0000000..efd98b7 Binary files /dev/null and b/layouts/retro/images/ui/noimage.png differ diff --git a/layouts/retro/images/ui/option_button.png b/layouts/retro/images/ui/option_button.png new file mode 100644 index 0000000..5e92446 Binary files /dev/null and b/layouts/retro/images/ui/option_button.png differ diff --git a/layouts/retro/images/ui/options_broder.png b/layouts/retro/images/ui/options_broder.png new file mode 100644 index 0000000..b7d7a36 Binary files /dev/null and b/layouts/retro/images/ui/options_broder.png differ diff --git a/layouts/retro/images/ui/panel_bottom.png b/layouts/retro/images/ui/panel_bottom.png new file mode 100644 index 0000000..c87e086 Binary files /dev/null and b/layouts/retro/images/ui/panel_bottom.png differ diff --git a/layouts/retro/images/ui/panel_flat.png b/layouts/retro/images/ui/panel_flat.png new file mode 100644 index 0000000..2da41dd Binary files /dev/null and b/layouts/retro/images/ui/panel_flat.png differ diff --git a/layouts/retro/images/ui/panel_map.png b/layouts/retro/images/ui/panel_map.png new file mode 100644 index 0000000..ea2b90e Binary files /dev/null and b/layouts/retro/images/ui/panel_map.png differ diff --git a/layouts/retro/images/ui/panel_side.png b/layouts/retro/images/ui/panel_side.png new file mode 100644 index 0000000..d7df3ba Binary files /dev/null and b/layouts/retro/images/ui/panel_side.png differ diff --git a/layouts/retro/images/ui/panel_top.png b/layouts/retro/images/ui/panel_top.png new file mode 100644 index 0000000..e403577 Binary files /dev/null and b/layouts/retro/images/ui/panel_top.png differ diff --git a/layouts/retro/images/ui/progress_icons.png b/layouts/retro/images/ui/progress_icons.png new file mode 100644 index 0000000..4f34ef3 Binary files /dev/null and b/layouts/retro/images/ui/progress_icons.png differ diff --git a/layouts/retro/images/ui/progressbar.png b/layouts/retro/images/ui/progressbar.png new file mode 100644 index 0000000..503d340 Binary files /dev/null and b/layouts/retro/images/ui/progressbar.png differ diff --git a/layouts/retro/images/ui/progressbarhpmana.png b/layouts/retro/images/ui/progressbarhpmana.png new file mode 100644 index 0000000..3ce0657 Binary files /dev/null and b/layouts/retro/images/ui/progressbarhpmana.png differ diff --git a/layouts/retro/images/ui/progressbarskills.png b/layouts/retro/images/ui/progressbarskills.png new file mode 100644 index 0000000..d139932 Binary files /dev/null and b/layouts/retro/images/ui/progressbarskills.png differ diff --git a/layouts/retro/images/ui/scrollbar.png b/layouts/retro/images/ui/scrollbar.png new file mode 100644 index 0000000..4bbd1c0 Binary files /dev/null and b/layouts/retro/images/ui/scrollbar.png differ diff --git a/layouts/retro/images/ui/separator_horizontal.png b/layouts/retro/images/ui/separator_horizontal.png new file mode 100644 index 0000000..9eb47b3 Binary files /dev/null and b/layouts/retro/images/ui/separator_horizontal.png differ diff --git a/layouts/retro/images/ui/separator_vertical.png b/layouts/retro/images/ui/separator_vertical.png new file mode 100644 index 0000000..ca3b5d3 Binary files /dev/null and b/layouts/retro/images/ui/separator_vertical.png differ diff --git a/layouts/retro/images/ui/special_miniwindow.png b/layouts/retro/images/ui/special_miniwindow.png new file mode 100644 index 0000000..906d537 Binary files /dev/null and b/layouts/retro/images/ui/special_miniwindow.png differ diff --git a/layouts/retro/images/ui/spinbox.png b/layouts/retro/images/ui/spinbox.png new file mode 100644 index 0000000..cef075c Binary files /dev/null and b/layouts/retro/images/ui/spinbox.png differ diff --git a/layouts/retro/images/ui/spinbox_down.png b/layouts/retro/images/ui/spinbox_down.png new file mode 100644 index 0000000..b124103 Binary files /dev/null and b/layouts/retro/images/ui/spinbox_down.png differ diff --git a/layouts/retro/images/ui/spinbox_up.png b/layouts/retro/images/ui/spinbox_up.png new file mode 100644 index 0000000..bf1b6d6 Binary files /dev/null and b/layouts/retro/images/ui/spinbox_up.png differ diff --git a/layouts/retro/images/ui/tabbutton_rounded.png b/layouts/retro/images/ui/tabbutton_rounded.png new file mode 100644 index 0000000..3c8f17e Binary files /dev/null and b/layouts/retro/images/ui/tabbutton_rounded.png differ diff --git a/layouts/retro/images/ui/tabbutton_square.png b/layouts/retro/images/ui/tabbutton_square.png new file mode 100644 index 0000000..f669be6 Binary files /dev/null and b/layouts/retro/images/ui/tabbutton_square.png differ diff --git a/layouts/retro/images/ui/textedit.png b/layouts/retro/images/ui/textedit.png new file mode 100644 index 0000000..9b35c60 Binary files /dev/null and b/layouts/retro/images/ui/textedit.png differ diff --git a/layouts/retro/images/ui/window.png b/layouts/retro/images/ui/window.png new file mode 100644 index 0000000..167690e Binary files /dev/null and b/layouts/retro/images/ui/window.png differ diff --git a/layouts/retro/styles/10-checkboxes.otui b/layouts/retro/styles/10-checkboxes.otui new file mode 100644 index 0000000..5a51a05 --- /dev/null +++ b/layouts/retro/styles/10-checkboxes.otui @@ -0,0 +1,59 @@ +CheckBox < UICheckBox + size: 12 12 + text-align: left + text-offset: 18 -1 + color: #dfdfdf + image-color: #dfdfdfff + image-rect: 0 0 12 12 + image-source: /images/ui/checkbox + + $hover !disabled: + color: #ffffff + + $!checked: + image-clip: 0 0 12 12 + + $checked: + image-clip: 0 12 12 12 + + $disabled: + image-color: #dfdfdf88 + color: #dfdfdf88 + opacity: 0.8 + +ColorBox < UICheckBox + size: 16 16 + image-color: #dfdfdfff + image-source: /images/ui/colorbox + + $checked: + image-clip: 16 0 16 16 + + $!checked: + image-clip: 0 0 16 16 + +ButtonBox < UICheckBox + font: verdana-11px-antialised + color: white + size: 106 23 + text-offset: 0 0 + text-align: center + image-source: /images/ui/button + image-color: #dfdfdf + image-clip: 0 0 22 23 + image-border: 3 + + $hover !disabled: + image-clip: 0 23 22 23 + + $checked: + image-clip: 0 46 22 23 + color: white + text-offset: 2 2 + + $disabled: + color: #dfdfdf88 + image-color: #dfdfdf88 + +ButtonBoxRounded < ButtonBox + image-source: /images/ui/button_rounded \ No newline at end of file diff --git a/layouts/retro/styles/10-comboboxes.otui b/layouts/retro/styles/10-comboboxes.otui new file mode 100644 index 0000000..e1d4168 --- /dev/null +++ b/layouts/retro/styles/10-comboboxes.otui @@ -0,0 +1,106 @@ +ComboBoxPopupScrollMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #BFBFBF + background-color: alpha + margin: 1 + + $hover !disabled: + color: #dfdfdf + background-color: #595959 + + $disabled: + color: #dfdfdf88 + +ComboBoxPopupScrollMenu < UIPopupScrollMenu + image-source: /images/ui/combobox_square + image-clip: 0 69 91 23 + image-border: 1 + +ComboBoxPopupMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #dfdfdf + background-color: alpha + margin: 1 + + $hover !disabled: + color: #dfdfdf + background-color: #355d89 + + $disabled: + color: #dfdfdf88 + +ComboBoxPopupMenu < UIPopupMenu + image-source: /images/ui/combobox_square + image-clip: 0 69 91 23 + image-border: 1 + +ComboBox < UIComboBox + font: verdana-11px-antialised + color: #dfdfdf + size: 91 23 + text-offset: 3 0 + text-align: left + image-source: /images/ui/combobox_square + image-border: 3 + image-border-right: 19 + image-clip: 0 0 91 23 + + $hover !disabled: + image-clip: 0 23 91 23 + + $on: + image-clip: 0 46 91 23 + + $disabled: + color: #dfdfdf88 + opacity: 0.8 + +ComboBoxRoundedPopupScrollMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #dfdfdf + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #355d89 + + $disabled: + color: #dfdfdf88 + +ComboBoxRoundedPopupScrollMenu < UIPopupScrollMenu + image-source: /images/ui/combobox_rounded + image-clip: 0 69 91 23 + image-border: 3 + +ComboBoxRoundedPopupMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #dfdfdf + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #355d89 + + $disabled: + color: #dfdfdf88 + +ComboBoxRoundedPopupMenu < UIPopupMenu + image-source: /images/ui/combobox_rounded + image-clip: 0 69 91 23 + image-border: 3 + +ComboBoxRounded < ComboBox + image-source: /images/ui/combobox_rounded + image-border: 3 diff --git a/layouts/retro/styles/10-panels.otui b/layouts/retro/styles/10-panels.otui new file mode 100644 index 0000000..15fbbc3 --- /dev/null +++ b/layouts/retro/styles/10-panels.otui @@ -0,0 +1,19 @@ +Panel < UIWidget + phantom: true + auto-focus: first + +ScrollablePanel < UIScrollArea + phantom: true + auto-focus: first + +FlatPanel < Panel + image-source: /images/ui/panel_flat + image-border: 1 + +ScrollableFlatPanel < ScrollablePanel + image-source: /images/ui/panel_flat + image-border: 1 + +LightFlatPanel < Panel + image-source: /images/ui/panel_lightflat + image-border: 1 diff --git a/layouts/retro/styles/10-progressbars.otui b/layouts/retro/styles/10-progressbars.otui new file mode 100644 index 0000000..4a8af2f --- /dev/null +++ b/layouts/retro/styles/10-progressbars.otui @@ -0,0 +1,38 @@ +ProgressBar < UIProgressBar + height: 16 + background-color: red + image-source: /images/ui/progressbar + image-border: 2 + font: verdana-11px-rounded + text-offset: 0 2 + + $!on: + visible: false + margin-top: 0 + margin-bottom: 0 + height: 0 + +LifeProgressBar < UIProgressBar + height: 16 + background-color: green + border: 1 black + font: verdana-11px-rounded + text-offset: 0 2 + margin: 2 + +ProgressRect < UIProgressRect + anchors.fill: parent + phantom: true + color: white + background-color: #00000088 + font: verdana-11px-rounded + +HealthBar < ProgressBar + image-source: /images/ui/progressbarhpmana + image-border: 3 + background-color: #ff4444 + +ManaBar < ProgressBar + image-source: /images/ui/progressbarhpmana + image-border: 4 + background-color: #4444ff diff --git a/layouts/retro/styles/10-textedits.otui b/layouts/retro/styles/10-textedits.otui new file mode 100644 index 0000000..fefa3bc --- /dev/null +++ b/layouts/retro/styles/10-textedits.otui @@ -0,0 +1,20 @@ +TextEdit < UITextEdit + font: verdana-11px-antialised + color: white + size: 86 22 + text-offset: 0 4 + opacity: 1 + padding: 4 + image-source: /images/ui/textedit + image-border: 1 + selection-color: #272727 + selection-background-color: #cccccc + $disabled: + color: #27272788 + opacity: 0.5 + +PasswordTextEdit < TextEdit + text-hidden: true + +MultilineTextEdit < TextEdit + multiline: true diff --git a/layouts/retro/styles/10-windows.otui b/layouts/retro/styles/10-windows.otui new file mode 100644 index 0000000..0e47f3a --- /dev/null +++ b/layouts/retro/styles/10-windows.otui @@ -0,0 +1,32 @@ +Window < UIWindow + font: verdana-11px-antialised + size: 236 207 + opacity: 1 + color: #8F8F8F + text-offset: 0 2 + text-align: top + image-source: /images/ui/window + image-border: 4 + image-border-top: 17 + padding-top: 25 + padding-left: 16 + padding-right: 16 + padding-bottom: 16 + + $disabled: + color: #dfdfdf + +HeadlessWindow < UIWindow + image-source: /images/ui/window_headless + image-border: 5 + padding: 5 + +MainWindow < Window + anchors.centerIn: parent + +StaticWindow < Window + &static: true + +StaticMainWindow < StaticWindow + anchors.centerIn: parent + \ No newline at end of file diff --git a/layouts/retro/styles/20-popupmenus.otui b/layouts/retro/styles/20-popupmenus.otui new file mode 100644 index 0000000..ceeb532 --- /dev/null +++ b/layouts/retro/styles/20-popupmenus.otui @@ -0,0 +1,83 @@ +PopupMenuButton < UIButton + height: 18 + size: 0 21 + text-offset: 4 2 + text-align: left + font: verdana-11px-antialised + + color: white + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #ffffff44 + image-clip: 0 40 20 20 + + $disabled: + color: #555555 + +PopupMenuShortcutLabel < Label + font: verdana-11px-antialised + text-align: right + anchors.fill: parent + margin-right: 2 + margin-left: 5 + +PopupMenuSeparator < UIWidget + margin-left: 2 + margin-right: 2 + margin-bottom: 1 + image-source: /images/ui/separator_horizontal + image-border-left: 1 + image-border-right: 1 + image-clip: 0 0 32 2 + height: 2 + phantom: true + +PopupMenu < UIPopupMenu + width: 120 + image-source: /images/ui/menubox + image-border: 3 + padding: 5 + +PopupScrollMenuButton < UIButton + height: 18 + size: 0 21 + text-offset: 4 0 + text-align: left + font: verdana-11px-antialised + + color: #aaaaaa + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #ffffff44 + image-clip: 0 40 20 20 + + $disabled: + color: #555555 + +PopupScrollMenuShortcutLabel < Label + font: verdana-11px-antialised + text-align: right + anchors.fill: parent + margin-right: 2 + margin-left: 5 + +PopupScrollMenuSeparator < UIWidget + margin-left: 2 + margin-right: 2 + margin-bottom: 1 + image-source: /images/ui/menubox + image-border-left: 1 + image-border-right: 1 + image-clip: 0 0 32 2 + height: 2 + phantom: true + +PopupScrollMenu < UIPopupScrollMenu + width: 50 + image-source: /images/ui/menubox + image-border: 3 + padding: 3 diff --git a/layouts/retro/styles/20-tabbars.otui b/layouts/retro/styles/20-tabbars.otui new file mode 100644 index 0000000..a819635 --- /dev/null +++ b/layouts/retro/styles/20-tabbars.otui @@ -0,0 +1,113 @@ +MoveableTabBar < UIMoveableTabBar + size: 80 21 +MoveableTabBarPanel < Panel +MoveableTabBarButton < UIButton + size: 96 18 + image-source: /images/ui/tabbutton_square + image-clip: 0 0 96 22 + image-border: 3 + image-border-bottom: 0 + color: #7F7F7F + anchors.top: parent.top + anchors.left: parent.left + margin-top: 2 + padding: 3 + + $checked: + image-clip: 0 36 96 22 + color: #dfdfdf + + $on !checked: + color: #F75F5F + +TabBar < UITabBar + size: 80 21 + Panel + id: buttonsPanel + anchors.fill: parent +TabBarPanel < Panel +TabBarButton < UIButton + size: 17 18 + image-source: /images/ui/tabbutton_square + image-color: #dfdfdf + image-clip: 0 0 98 18 + image-border: 3 + icon-color: #dfdfdf + color: #dfdfdf + anchors.top: parent.top + padding: 5 + + $first: + anchors.left: parent.left + + $!first: + anchors.left: prev.right + margin-left: 5 + + $hover !checked: + image-clip: 0 18 98 18 + color: #dfdfdf + + $disabled: + image-color: #dfdfdf88 + icon-color: #dfdfdf + + $checked: + image-clip: 0 36 98 18 + color: #dfdfdf + + $on !checked: + color: #de6f6f + +TabBarRounded < TabBar +TabBarRoundedPanel < TabBarPanel +TabBarRoundedButton < TabBarButton + image-source: /images/ui/tabbutton_rounded + +TabBarVertical < UITabBar + width: 96 + ScrollableFlatPanel + id: buttonsPanel + anchors.top: parent.top + anchors.left: parent.left + anchors.right: scrollBar.left + anchors.bottom: parent.bottom + vertical-scrollbar: scrollBar + margin-right: 1 + padding-top: 10 + + VerticalScrollBar + id: scrollBar + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + step: 16 + pixels-scroll: true + $!on: + width: 0 + +TabBarVerticalPanel < Panel +TabBarVerticalButton < UIButton + size: 48 48 + color: #aaaaaa + anchors.left: parent.left + anchors.right: parent.right + text-align: bottom + icon-align: top + icon-offset-y: 2 + icon-color: #888888 + $first: + anchors.top: parent.top + $!first: + anchors.top: prev.bottom + margin-top: 10 + $hover !checked: + color: white + icon-color: #dfdfdf + $disabled: + icon-color: #333333 + $checked: + icon-color: #ffffff + color: #80c7f8 + $on !checked: + color: #F55E5E \ No newline at end of file diff --git a/layouts/retro/styles/20-topmenu.otui b/layouts/retro/styles/20-topmenu.otui new file mode 100644 index 0000000..0e6657a --- /dev/null +++ b/layouts/retro/styles/20-topmenu.otui @@ -0,0 +1,131 @@ +TopButton < UIButton + size: 26 26 + image-source: /images/ui/button_top + image-clip: 0 0 26 26 + image-border: 3 + image-color: #ffffffff + icon-color: #ffffffff + icon-clip: 0 0 20 20 + + $on: + image-source: /images/ui/button_top_blink + icon-clip: 0 20 20 20 + + $hover !disabled: + image-color: #ffffff99 + image-clip: 26 0 26 26 + + $pressed: + image-clip: 52 0 26 26 + icon-clip: 0 20 20 20 + + $disabled: + image-color: #ffffff44 + icon-color: #ffffff44 + +TopToggleButton < UIButton + size: 20 20 + image-source: /images/ui/button_top + image-clip: 0 0 26 26 + image-color: #ffffffff + image-border: 3 + icon-clip: 0 0 20 20 + icon-color: #ffffffff + + $on: + icon-clip: 0 20 20 20 + + $hover !disabled: + image-color: #ffffff99 + image-clip: 26 0 26 26 + + $pressed: + image-clip: 52 0 26 26 + icon-clip: 0 20 20 20 + + $disabled: + image-color: #ffffff44 + icon-color: #ffffff44 + +TopMenuButtonsPanel < Panel + layout: + type: horizontalBox + spacing: 4 + fit-children: true + padding: 6 4 + +TopMenuPanel < Panel + height: 36 + image-source: /images/ui/panel_top + image-repeated: true + image-border: 3 + image-border-top: 0 + focusable: false + +TopMenuFrameCounterLabel < Label + font: verdana-11px-rounded + color: white + margin-top: 4 + margin-left: 5 + +TopMenuPingLabel < Label + font: verdana-11px-rounded + +TopMenu < TopMenuPanel + id: topMenu + width: 800 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + &hideIngame: true + &reverseButtons: true + + UIWidget + id: discord + anchors.top: parent.top + anchors.left: parent.left + margin-top: 3 + margin-left: 5 + image-source: /images/ui/discord + + Label + id: discordLabel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: prev.right + text-align: center + margin-left: 2 + text-auto-resize: true + + TopMenuButtonsPanel + id: rightButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: prev.right + + TopMenuButtonsPanel + id: rightGameButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: prev.right + visible: false + + Label + id: onlineLabel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + text-align: center + text-auto-resize: true + + TopMenuButtonsPanel + id: leftButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + + TopMenuButtonsPanel + id: leftGameButtonsPanel + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: prev.left + visible: false diff --git a/layouts/retro/styles/30-miniwindow.otui b/layouts/retro/styles/30-miniwindow.otui new file mode 100644 index 0000000..dc30804 --- /dev/null +++ b/layouts/retro/styles/30-miniwindow.otui @@ -0,0 +1,215 @@ +MiniWindow < UIMiniWindow + font: verdana-11px-antialised + icon-rect: 4 2 13 13 + icon-clip: 0 0 20 20 + color: #8F8F8F + width: 190 + height: 200 + text-offset: 24 2 + text-align: topLeft + image-source: /images/ui/miniwindow + image-border: 4 + image-border-top: 20 + image-border-bottom: 4 + focusable: false + &minimizedHeight: 20 + + $on: + image-border-bottom: 2 + + UIWidget + id: miniwindowTopBar + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + margin-right: 3 + margin-left: 3 + margin-top: 3 + size: 258 14 + phantom: true + + UIButton + id: closeButton + anchors.top: parent.top + anchors.right: parent.right + margin-top: 2 + margin-right: 4 + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 28 0 14 14 + + $hover: + image-clip: 28 14 14 14 + + $pressed: + image-clip: 28 28 14 14 + + UIButton + id: minimizeButton + anchors.top: closeButton.top + anchors.right: closeButton.left + margin-right: 3 + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 0 0 14 14 + + $hover: + image-clip: 0 14 14 14 + + $pressed: + image-clip: 0 28 14 14 + + $on: + image-clip: 14 0 14 14 + + $on hover: + image-clip: 14 14 14 14 + + $on pressed: + image-clip: 14 28 14 14 + + UIButton + id: lockButton + anchors.top: minimizeButton.top + anchors.right: minimizeButton.left + margin-right: 2 + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 98 0 14 14 + + $hover: + image-clip: 98 14 14 14 + + $pressed: + image-clip: 98 28 14 14 + + $on: + image-clip: 84 0 14 14 + + $on hover: + image-clip: 84 14 14 14 + + $on pressed: + image-clip: 84 28 14 14 + + VerticalScrollBar + id: miniwindowScrollBar + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + step: 14 + margin-top: 18 + margin-right: 4 + margin-bottom: 3 + pixels-scroll: true + + $!on: + width: 0 + + ResizeBorder + id: bottomResizeBorder + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + height: 3 + minimum: 48 + margin-left: 3 + margin-right: 3 + background: #ffffff88 + +MiniWindowContents < ScrollablePanel + id: contentsPanel + anchors.fill: parent + anchors.right: miniwindowScrollBar.left + margin-left: 3 + margin-bottom: 3 + margin-top: 18 + margin-right: 1 + vertical-scrollbar: miniwindowScrollBar + +HeadlessMiniWindow < UIMiniWindow + font: verdana-11px-antialised + icon-rect: 4 2 13 12 + icon-clip: 0 0 20 20 + color: #8F8F8F + width: 190 + height: 200 + focusable: false + &minimizedHeight: 20 + + $on: + image-border-bottom: 2 + + $!on: + text: + icon: + + UIButton + id: minimizeButton + anchors.top: parent.top + anchors.right: parent.right + margin-right: 10 + margin-top: 1 + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 0 0 14 14 + + $hover: + image-clip: 0 14 14 14 + + $pressed: + image-clip: 0 28 14 14 + + $on: + image-clip: 14 0 14 14 + + $on hover: + image-clip: 14 14 14 14 + + $on pressed: + image-clip: 14 28 14 14 + + $!on: + size: 0 0 + + UIWidget + id: miniwindowTopBar + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + margin-right: 3 + margin-left: 3 + margin-top: 3 + size: 258 14 + phantom: true + + UIButton + id: closeButton + anchors.top: parent.top + anchors.right: parent.right + hidden: true + + VerticalScrollBar + id: miniwindowScrollBar + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + step: 14 + margin-top: 16 + margin-right: 4 + margin-bottom: 3 + pixels-scroll: true + + $!on: + width: 0 + + ResizeBorder + id: bottomResizeBorder + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + height: 3 + minimum: 48 + margin-left: 3 + margin-right: 3 + background: #ffffff88 diff --git a/layouts/retro/styles/40-console.otui b/layouts/retro/styles/40-console.otui new file mode 100644 index 0000000..b9369e4 --- /dev/null +++ b/layouts/retro/styles/40-console.otui @@ -0,0 +1,218 @@ +ConsoleLabel < UITextEdit + font: verdana-11px-antialised + height: 14 + color: yellow + margin-left: 1 + text-wrap: true + text-auto-resize: true + selection-color: #111416 + selection-background-color: #808080 + change-cursor-image: false + cursor-visible: false + editable: false + draggable: true + selectable: false + focusable: false + +ConsolePhantomLabel < UILabel + font: verdana-11px-antialised + height: 14 + color: yellow + text-wrap: true + text-auto-resize: true + selection-color: #111416 + selection-background-color: #999999 + +ConsoleTabBar < MoveableTabBar + height: 16 + +ConsoleTabBarPanel < MoveableTabBarPanel + id: consoleTab + + ScrollablePanel + id: consoleBuffer + anchors.fill: parent + margin-right: 12 + vertical-scrollbar: consoleScrollBar + layout: + type: verticalBox + align-bottom: true + border-width: 1 + border-color: #202327 + background: #00000066 + inverted-scroll: true + padding: 1 + + VerticalScrollBar + id: consoleScrollBar + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + step: 14 + pixels-scroll: true + +ConsoleTabBarButton < MoveableTabBarButton + height: 16 + padding: 15 + +ConsolePanel < Panel + image-source: /images/ui/panel_bottom + image-border: 7 + image-border-top: 29 + + $first: + anchors.fill: parent + + $!first: + anchors.top: prev.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + + CheckBox + id: toggleChat + !tooltip: tr('Disable chat mode, allow to walk using ASDW') + anchors.left: parent.left + anchors.top: parent.top + margin-left: 6 + margin-top: 3 + @onCheckChange: toggleChat() + + TabButton + id: prevChannelButton + icon: /images/game/console/leftarrow + anchors.left: toggleChat.right + anchors.top: parent.top + margin-top: 1 + size: 16 16 + + ConsoleTabBar + id: consoleTabBar + anchors.left: prev.right + anchors.top: parent.top + anchors.right: next.left + margin-top: 0 + tab-spacing: 2 + movable: true + + TabButton + id: nextChannelButton + icon: /images/game/console/rightarrow + anchors.right: next.left + anchors.top: parent.top + margin-top: 1 + size: 16 16 + margin-right: 5 + + TabButton + id: closeChannelButton + !tooltip: tr('Close this channel') .. ' (Ctrl+E)' + icon: /images/game/console/closechannel + anchors.right: next.left + anchors.top: parent.top + enabled: false + margin-right: 5 + margin-top: 1 + size: 16 16 + icon-clip: 0 0 16 16 + + $pressed: + icon-clip: 0 16 16 16 + + @onClick: removeCurrentTab() + + TabButton + id: clearChannelButton + !tooltip: tr('Clear current message window') + icon: /images/game/console/clearchannel + anchors.right: next.left + anchors.top: parent.top + margin-right: 5 + margin-top: 1 + size: 16 16 + icon-clip: 0 0 16 16 + + $pressed: + icon-clip: 0 16 16 16 + + @onClick: | + local consoleTabBar = self:getParent():getChildById('consoleTabBar') + clearChannel(consoleTabBar) + + TabButton + id: channelsButton + !tooltip: tr('Open new channel') .. ' (Ctrl+O)' + icon: /images/game/console/channels + anchors.right: next.left + anchors.top: parent.top + margin-right: 5 + margin-top: 1 + size: 16 16 + icon-clip: 0 0 16 16 + + $pressed: + icon-clip: 0 16 16 16 + + @onClick: g_game.requestChannels() + + TabButton + id: ignoreButton + !tooltip: tr('Ignore players') + icon: /images/game/console/ignore + anchors.right: parent.right + anchors.top: parent.top + margin-right: 5 + margin-top: 1 + size: 16 16 + icon-clip: 0 0 16 16 + + $pressed: + icon-clip: 0 16 16 16 + + @onClick: onClickIgnoreButton() + + Panel + id: consoleContentPanel + anchors.top: consoleTabBar.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: consoleTextEdit.top + margin-left: 6 + margin-right: 6 + margin-bottom: 2 + margin-top: 6 + padding: 1 + focusable: false + phantom: true + + TabButton + id: sayModeButton + icon: /images/game/console/say + !tooltip: tr('Adjust volume') + &sayMode: 2 + size: 18 18 + anchors.left: parent.left + anchors.bottom: parent.bottom + margin-left: 8 + margin-bottom: 4 + @onClick: sayModeChange() + + HorizontalSeparator + id: separator + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: prev.top + margin-bottom: 3 + margin-left: 7 + margin-right: 7 + + TextEdit + id: consoleTextEdit + anchors.left: sayModeButton.right + anchors.right: parent.right + anchors.bottom: parent.bottom + margin-right: 7 + margin-left: 2 + margin-bottom: 2 + shift-navigation: true + max-length: 255 diff --git a/layouts/retro/styles/40-entergame.otui b/layouts/retro/styles/40-entergame.otui new file mode 100644 index 0000000..7df877d --- /dev/null +++ b/layouts/retro/styles/40-entergame.otui @@ -0,0 +1,3 @@ +EnterGameWindow < StaticMainWindow + !text: tr('Enter Game') + size: 260 340 \ No newline at end of file diff --git a/layouts/retro/styles/40-gamebuttons.otui b/layouts/retro/styles/40-gamebuttons.otui new file mode 100644 index 0000000..d65b140 --- /dev/null +++ b/layouts/retro/styles/40-gamebuttons.otui @@ -0,0 +1,16 @@ +GameButtonsWindow < HeadlessMiniWindow + height: 52 + &forceOpen: true + &autoOpen: 4 + + MiniWindowContents + margin-top: 2 + + Panel + id: buttons + anchors.fill: parent + layout: + type: grid + cell-spacing: 3 + cell-size: 20 20 + flow: true \ No newline at end of file diff --git a/layouts/retro/styles/40-healthinfo.otui b/layouts/retro/styles/40-healthinfo.otui new file mode 100644 index 0000000..886af16 --- /dev/null +++ b/layouts/retro/styles/40-healthinfo.otui @@ -0,0 +1,154 @@ +ExperienceBar < ProgressBar + id: experienceBar + background-color: #B6E866 + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin: 1 + margin-top: 3 + +SoulLabel < GameLabel + id: soulLabel + text-align: right + color: white + font: verdana-11px-rounded + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.left: parent.horizontalCenter + margin-top: 5 + margin-right: 3 + on: true + + $!on: + visible: false + margin-top: 0 + height: 0 + +CapLabel < GameLabel + id: capLabel + color: white + font: verdana-11px-rounded + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.horizontalCenter + margin-top: 5 + margin-left: 3 + on: true + + $!on: + visible: false + margin-top: 0 + height: 0 + +ConditionWidget < UIWidget + size: 18 18 + + $!first: + margin-left: 2 + +HealthOverlay < UIWidget + id: healthOverlay + anchors.fill: parent + phantom: true + + HealthBar + id: topHealthBar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.horizontalCenter + phantom: true + + ManaBar + id: topManaBar + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.horizontalCenter + phantom: true + + UIProgressBar + id: healthCircle + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/left_empty + margin-right: 169 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: healthCircleFront + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/left_full + margin-right: 169 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: manaCircle + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/right_empty + margin-left: 130 + margin-bottom: 16 + opacity: 0.5 + phantom: true + + UIProgressBar + id: manaCircleFront + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + image-source: /images/game/circle/right_full + margin-left: 130 + margin-bottom: 16 + opacity: 0.4 + image-color: #0000FFFF + phantom: true + +HealthInfoWindow < HeadlessMiniWindow + icon: + text: + height: 100 + &forceOpen: true + icon: /images/topbuttons/healthinfo + !text: tr('Health Info') + + MiniWindowContents + margin-top: 2 + + HealthBar + id: healthBar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + margin: 2 + margin-top: 0 + phantom: true + + ManaBar + id: manaBar + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin: 2 + margin-bottom: 0 + phantom: true + + ExperienceBar + Panel + id: conditionPanel + layout: + type: horizontalBox + height: 22 + margin-top: 4 + padding: 2 + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + border-width: 1 + border-color: #00000077 + background-color: #ffffff11 + SoulLabel + CapLabel + diff --git a/layouts/retro/styles/40-inventory.otui b/layouts/retro/styles/40-inventory.otui new file mode 100644 index 0000000..65233ff --- /dev/null +++ b/layouts/retro/styles/40-inventory.otui @@ -0,0 +1,333 @@ +InventoryItem < Item + $on: + image-source: /images/ui/item-blessed + +HeadSlot < InventoryItem + id: slot1 + image-source: /images/game/slots/head + &position: {x=65535, y=1, z=0} + $on: + image-source: /images/game/slots/head-blessed + +BodySlot < InventoryItem + id: slot4 + image-source: /images/game/slots/body + &position: {x=65535, y=4, z=0} + $on: + image-source: /images/game/slots/body-blessed + +LegSlot < InventoryItem + id: slot7 + image-source: /images/game/slots/legs + &position: {x=65535, y=7, z=0} + $on: + image-source: /images/game/slots/legs-blessed + +FeetSlot < InventoryItem + id: slot8 + image-source: /images/game/slots/feet + &position: {x=65535, y=8, z=0} + $on: + image-source: /images/game/slots/feet-blessed + +NeckSlot < InventoryItem + id: slot2 + image-source: /images/game/slots/neck + &position: {x=65535, y=2, z=0} + $on: + image-source: /images/game/slots/neck-blessed + +LeftSlot < InventoryItem + id: slot6 + image-source: /images/game/slots/left-hand + &position: {x=65535, y=6, z=0} + $on: + image-source: /images/game/slots/left-hand-blessed + +FingerSlot < InventoryItem + id: slot9 + image-source: /images/game/slots/finger + &position: {x=65535, y=9, z=0} + $on: + image-source: /images/game/slots/finger-blessed + +BackSlot < InventoryItem + id: slot3 + image-source: /images/game/slots/back + &position: {x=65535, y=3, z=0} + $on: + image-source: /images/game/slots/back-blessed + +RightSlot < InventoryItem + id: slot5 + image-source: /images/game/slots/right-hand + &position: {x=65535, y=5, z=0} + $on: + image-source: /images/game/slots/right-hand-blessed + +AmmoSlot < InventoryItem + id: slot10 + image-source: /images/game/slots/ammo + &position: {x=65535, y=10, z=0} + $on: + image-source: /images/game/slots/ammo-blessed + +PurseButton < UIButton + id: purseButton + size: 34 12 + !tooltip: tr('Open purse') + icon-source: /images/game/slots/purse + icon-clip: 0 0 34 12 + + $on: + icon-clip: 0 12 34 12 + + $pressed: + icon-clip: 0 12 34 12 + +CombatBox < UICheckBox + size: 20 20 + image-clip: 0 0 20 20 + margin-left: 4 + + $checked: + image-clip: 0 20 20 20 + + +InventoryButton < Button + height: 18 + margin-top: 2 + text-align: center + font: cipsoftFont + color: white + size: 45 20 + text-offset: 2 2 + +SoulCapLabel < GameLabel + text-align: center + color: #FFFFFF + font: cipsoftFont + margin-top: 4 + text-offset: 0 3 + width: 36 + height: 20 + icon-source: /images/game/slots/soulcap + +FightOffensiveBox < CombatBox + image-source: /images/game/combatmodes/fightoffensive +FightBalancedBox < CombatBox + image-source: /images/game/combatmodes/fightbalanced +FightDefensiveBox < CombatBox + image-source: /images/game/combatmodes/fightdefensive +ChaseModeBox < CombatBox + image-source: /images/game/combatmodes/chasemode +SafeFightBox < CombatBox + image-source: /images/game/combatmodes/safefight + +MountButton < CombatBox + image-source: /images/game/combatmodes/mount + +InventoryWindow < HeadlessMiniWindow + icon: /images/topbuttons/inventory + height: 178 + id: inventoryWindow + @onClose: modules.game_inventory.onMiniWindowClose() + &save: true + &autoOpen: 3 + &forceOpen: true + + MiniWindowContents + anchors.left: parent.left + margin-top: 0 + + UIButton + id: minimizeButton + anchors.top: parent.top + anchors.left: parent.left + size: 14 14 + image-source: /images/ui/miniwindow_buttons + image-clip: 0 0 14 14 + margin-top: 3 + margin-left: 4 + + $hover: + image-clip: 0 14 14 14 + + $pressed: + image-clip: 0 28 14 14 + + $on: + image-clip: 14 0 14 14 + + $on hover: + image-clip: 14 14 14 14 + + $on pressed: + image-clip: 14 28 14 14 + + @onClick: | + self:getParent():getParent().minimizeButton:onClick() + + Panel + id: inventoryPanel + margin-right: 63 + margin-top: 2 + anchors.fill: parent + + HeadSlot + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + margin-top: 3 + + BodySlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + LegSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + FeetSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + NeckSlot + anchors.top: slot1.top + anchors.right: slot1.left + margin-top: 13 + margin-right: 5 + + LeftSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + FingerSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + BackSlot + anchors.top: slot1.top + anchors.left: slot1.right + margin-top: 13 + margin-left: 5 + + RightSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + AmmoSlot + anchors.top: prev.bottom + anchors.horizontalCenter: prev.horizontalCenter + margin-top: 3 + + SoulCapLabel + id: soulLabel + anchors.top: slot10.bottom + anchors.horizontalCenter: slot10.horizontalCenter + + SoulCapLabel + id: capLabel + anchors.top: slot9.bottom + anchors.horizontalCenter: slot9.horizontalCenter + + PurseButton + anchors.left: slot3.left + anchors.bottom: slot3.top + margin-bottom: 3 + + Panel + id: conditionPanel + layout: + type: horizontalBox + height: 22 + padding: 2 + anchors.top: slot8.bottom + anchors.left: slot6.left + anchors.right: slot5.right + margin-top: 4 + border-width: 1 + border-color: #00000077 + background-color: #ffffff22 + + Panel + margin-top: 5 + anchors.fill: parent + anchors.left: prev.right + + FightOffensiveBox + id: fightOffensiveBox + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + ChaseModeBox + id: chaseModeBox + anchors.left: prev.right + anchors.top: parent.top + + FightBalancedBox + id: fightBalancedBox + margin-top: 22 + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + SafeFightBox + id: safeFightBox + margin-top: 22 + anchors.left: prev.right + anchors.top: parent.top + + FightDefensiveBox + id: fightDefensiveBox + margin-top: 44 + anchors.left: parent.left + anchors.top: parent.top + margin-left: 8 + + MountButton + id: mountButton + margin-top: 44 + anchors.left: prev.right + anchors.top: parent.top + + Panel + id: buttonsPanel + margin-top: 4 + margin-right: 5 + anchors.fill: parent + anchors.top: prev.bottom + layout: + type: verticalBox + + UIButton + id: buttonPvp + height: 20 + icon: /images/game/combatmodes/pvp + icon-clip: 0 0 42 20 + + $on: + icon-clip: 0 20 42 20 + + InventoryButton + !text: tr('Stop') + @onClick: g_game.stop(); g_game.cancelAttackAndFollow() + + InventoryButton + !text: tr('Options') + @onClick: modules.client_options.toggle() + + InventoryButton + !text: tr('Hotkeys') + @onClick: modules.game_hotkeys.toggle() + + InventoryButton + !text: tr('Logout') + @onClick: modules.game_interface.tryLogout() + diff --git a/data/styles/30-minimap.otui b/layouts/retro/styles/40-minimap.otui similarity index 94% rename from data/styles/30-minimap.otui rename to layouts/retro/styles/40-minimap.otui index 09182b2..cc10a8d 100644 --- a/data/styles/30-minimap.otui +++ b/layouts/retro/styles/40-minimap.otui @@ -242,3 +242,20 @@ MinimapFlagWindow < MainWindow width: 64 anchors.right: parent.right anchors.bottom: parent.bottom + +MinimapWindow < HeadlessMiniWindow + height: 150 + &forceOpen: true + + MiniWindowContents + margin: 5 + + Minimap + id: minimap + anchors.fill: parent + + ResizeBorder + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + enabled: true \ No newline at end of file diff --git a/lua_functions/luafunctions_client.cpp b/lua_functions/luafunctions_client.cpp index 9c7db72..820640b 100644 --- a/lua_functions/luafunctions_client.cpp +++ b/lua_functions/luafunctions_client.cpp @@ -77,7 +77,8 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_things", "findItemTypesByString", &ThingTypeManager::findItemTypesByString, &g_things); g_lua.bindSingletonFunction("g_things", "findItemTypeByCategory", &ThingTypeManager::findItemTypeByCategory, &g_things); g_lua.bindSingletonFunction("g_things", "findThingTypeByAttr", &ThingTypeManager::findThingTypeByAttr, &g_things); - + g_lua.bindSingletonFunction("g_things", "getMarketCategories", &ThingTypeManager::getMarketCategories, &g_things); + g_lua.registerSingletonClass("g_houses"); g_lua.bindSingletonFunction("g_houses", "clear", &HouseManager::clear, &g_houses); g_lua.bindSingletonFunction("g_houses", "load", &HouseManager::load, &g_houses); @@ -103,6 +104,7 @@ void Client::registerLuaFunctions() #ifdef WITH_ENCRYPTION g_lua.bindSingletonFunction("g_sprites", "saveSpr", &SpriteManager::saveSpr, &g_sprites); g_lua.bindSingletonFunction("g_sprites", "dumpSprites", &SpriteManager::dumpSprites, &g_sprites); + g_lua.bindSingletonFunction("g_sprites", "encryptSprites", &SpriteManager::encryptSprites, &g_sprites); #endif g_lua.bindSingletonFunction("g_sprites", "unload", &SpriteManager::unload, &g_sprites); g_lua.bindSingletonFunction("g_sprites", "isLoaded", &SpriteManager::isLoaded, &g_sprites); @@ -206,6 +208,7 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "moveRaw", &Game::moveRaw, &g_game); g_lua.bindSingletonFunction("g_game", "moveToParentContainer", &Game::moveToParentContainer, &g_game); g_lua.bindSingletonFunction("g_game", "rotate", &Game::rotate, &g_game); + g_lua.bindSingletonFunction("g_game", "wrap", &Game::wrap, &g_game); g_lua.bindSingletonFunction("g_game", "use", &Game::use, &g_game); g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game); g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game); @@ -321,14 +324,21 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "openStore", &Game::openStore, &g_game); g_lua.bindSingletonFunction("g_game", "transferCoins", &Game::transferCoins, &g_game); g_lua.bindSingletonFunction("g_game", "openTransactionHistory", &Game::openTransactionHistory, &g_game); - + g_lua.bindSingletonFunction("g_game", "preyAction", &Game::preyAction, &g_game); + g_lua.bindSingletonFunction("g_game", "preyRequest", &Game::preyRequest, &g_game); + g_lua.bindSingletonFunction("g_game", "applyImbuement", &Game::applyImbuement, &g_game); + g_lua.bindSingletonFunction("g_game", "clearImbuement", &Game::clearImbuement, &g_game); + g_lua.bindSingletonFunction("g_game", "closeImbuingWindow", &Game::closeImbuingWindow, &g_game); + g_lua.bindSingletonFunction("g_game", "getMaxPreWalkingSteps", &Game::getMaxPreWalkingSteps, &g_game); g_lua.bindSingletonFunction("g_game", "setMaxPreWalkingSteps", &Game::setMaxPreWalkingSteps, &g_game); g_lua.bindSingletonFunction("g_game", "ignoreServerDirection", &Game::ignoreServerDirection, &g_game); g_lua.bindSingletonFunction("g_game", "showRealDirection", &Game::showRealDirection, &g_game); g_lua.bindSingletonFunction("g_game", "enableTileThingLuaCallback", &Game::enableTileThingLuaCallback, &g_game); g_lua.bindSingletonFunction("g_game", "isTileThingLuaCallbackEnabled", &Game::isTileThingLuaCallbackEnabled, &g_game); - + g_lua.bindSingletonFunction("g_game", "getRecivedPacketsCount", &Game::getRecivedPacketsCount, &g_game); + g_lua.bindSingletonFunction("g_game", "getRecivedPacketsSize", &Game::getRecivedPacketsSize, &g_game); + g_lua.registerSingletonClass("g_shaders"); g_lua.bindSingletonFunction("g_shaders", "createShader", &ShaderManager::createShader, &g_shaders); g_lua.bindSingletonFunction("g_shaders", "createFragmentShader", &ShaderManager::createFragmentShader, &g_shaders); @@ -516,6 +526,20 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("resetInformationColor", &Creature::resetInformationColor); g_lua.bindClassMemberFunction("setInformationOffset", &Creature::setInformationOffset); g_lua.bindClassMemberFunction("getInformationOffset", &Creature::getInformationOffset); + // widgets + g_lua.bindClassMemberFunction("addTopWidget", &Creature::addTopWidget); + g_lua.bindClassMemberFunction("addBottomWidget", &Creature::addBottomWidget); + g_lua.bindClassMemberFunction("addDirectionalWidget", &Creature::addDirectionalWidget); + g_lua.bindClassMemberFunction("removeTopWidget", &Creature::removeTopWidget); + g_lua.bindClassMemberFunction("removeBottomWidget", &Creature::removeBottomWidget); + g_lua.bindClassMemberFunction("removeDirectionalWidget", &Creature::removeDirectionalWidget); + g_lua.bindClassMemberFunction("getTopWidgets", &Creature::getTopWidgets); + g_lua.bindClassMemberFunction("getBottomWidgets", &Creature::getBottomWidgets); + g_lua.bindClassMemberFunction("getDirectionalWdigets", &Creature::getDirectionalWdigets); + g_lua.bindClassMemberFunction("clearWidgets", &Creature::clearWidgets); + g_lua.bindClassMemberFunction("clearTopWidgets", &Creature::clearTopWidgets); + g_lua.bindClassMemberFunction("clearBottomWidgets", &Creature::clearBottomWidgets); + g_lua.bindClassMemberFunction("clearDirectionalWidgets", &Creature::clearDirectionalWidgets); g_lua.registerClass(); g_lua.bindClassMemberFunction("getServerId", &ItemType::getServerId); @@ -624,6 +648,8 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("isFluidContainer", &Item::isFluidContainer); g_lua.bindClassMemberFunction("getMarketData", &Item::getMarketData); g_lua.bindClassMemberFunction("getClothSlot", &Item::getClothSlot); + g_lua.bindClassMemberFunction("getTooltip", &Item::getTooltip); + g_lua.bindClassMemberFunction("setTooltip", &Item::setTooltip); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return EffectPtr(new Effect); }); @@ -705,6 +731,8 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("autoWalk", &LocalPlayer::autoWalk); g_lua.bindClassMemberFunction("preWalk", &LocalPlayer::preWalk); g_lua.bindClassMemberFunction("dumpWalkMatrix", &LocalPlayer::dumpWalkMatrix); + g_lua.bindClassMemberFunction("startServerWalking", &LocalPlayer::startServerWalking); + g_lua.bindClassMemberFunction("finishServerWalking", &LocalPlayer::finishServerWalking); g_lua.registerClass(); g_lua.bindClassMemberFunction("clean", &Tile::clean); @@ -793,6 +821,9 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("isFixedCreatureSize", &UICreature::isFixedCreatureSize); g_lua.bindClassMemberFunction("setAutoRotating", &UICreature::setAutoRotating); g_lua.bindClassMemberFunction("setDirection", &UICreature::setDirection); + g_lua.bindClassMemberFunction("setScale", &UICreature::setScale); + g_lua.bindClassMemberFunction("getScale", &UICreature::getScale); + g_lua.bindClassMemberFunction("setRaw", &UICreature::setRaw); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return UIMapPtr(new UIMap); }); diff --git a/lua_functions/luafunctions_framework.cpp b/lua_functions/luafunctions_framework.cpp index 0077f01..03b6f2d 100644 --- a/lua_functions/luafunctions_framework.cpp +++ b/lua_functions/luafunctions_framework.cpp @@ -125,6 +125,10 @@ void Application::registerLuaFunctions() g_lua.bindSingletonFunction("g_platform", "getMemoryUsage", &Platform::getMemoryUsage, &g_platform); g_lua.bindSingletonFunction("g_platform", "getOSName", &Platform::getOSName, &g_platform); g_lua.bindSingletonFunction("g_platform", "getFileModificationTime", &Platform::getFileModificationTime, &g_platform); + g_lua.bindSingletonFunction("g_platform", "getMacAddresses", &Platform::getMacAddresses, &g_platform); + g_lua.bindSingletonFunction("g_platform", "getUserName", &Platform::getUserName, &g_platform); + g_lua.bindSingletonFunction("g_platform", "getDlls", &Platform::getDlls, &g_platform); + g_lua.bindSingletonFunction("g_platform", "getProcesses", &Platform::getProcesses, &g_platform); // Application g_lua.registerSingletonClass("g_app"); @@ -265,7 +269,9 @@ void Application::registerLuaFunctions() g_lua.bindSingletonFunction("g_resources", "fileChecksum", &ResourceManager::fileChecksum, &g_resources); g_lua.bindSingletonFunction("g_resources", "selfChecksum", &ResourceManager::selfChecksum, &g_resources); g_lua.bindSingletonFunction("g_resources", "updateClient", &ResourceManager::updateClient, &g_resources); - + g_lua.bindSingletonFunction("g_resources", "setLayout", &ResourceManager::setLayout, &g_resources); + g_lua.bindSingletonFunction("g_resources", "getLayout", &ResourceManager::getLayout, &g_resources); + // Config g_lua.registerClass(); g_lua.bindClassMemberFunction("save", &Config::save); @@ -399,6 +405,7 @@ void Application::registerLuaFunctions() g_lua.registerSingletonClass("g_ui"); g_lua.bindSingletonFunction("g_ui", "clearStyles", &UIManager::clearStyles, &g_ui); g_lua.bindSingletonFunction("g_ui", "importStyle", &UIManager::importStyle, &g_ui); + g_lua.bindSingletonFunction("g_ui", "importStyleFromString", &UIManager::importStyleFromString, &g_ui); g_lua.bindSingletonFunction("g_ui", "getStyle", &UIManager::getStyle, &g_ui); g_lua.bindSingletonFunction("g_ui", "getStyleClass", &UIManager::getStyleClass, &g_ui); g_lua.bindSingletonFunction("g_ui", "loadUI", &UIManager::loadUI, &g_ui); @@ -438,7 +445,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("lowerChild", &UIWidget::lowerChild); g_lua.bindClassMemberFunction("raiseChild", &UIWidget::raiseChild); g_lua.bindClassMemberFunction("moveChildToIndex", &UIWidget::moveChildToIndex); - g_lua.bindClassMemberFunction("reorderChildrens", &UIWidget::reorderChildrens); + g_lua.bindClassMemberFunction("reorderChildren", &UIWidget::reorderChildren); g_lua.bindClassMemberFunction("lockChild", &UIWidget::lockChild); g_lua.bindClassMemberFunction("unlockChild", &UIWidget::unlockChild); g_lua.bindClassMemberFunction("mergeStyle", &UIWidget::mergeStyle); @@ -856,6 +863,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("generateXteaKey", &Protocol::generateXteaKey); g_lua.bindClassMemberFunction("enableXteaEncryption", &Protocol::enableXteaEncryption); g_lua.bindClassMemberFunction("enableChecksum", &Protocol::enableChecksum); + g_lua.bindClassMemberFunction("enableBigPackets", &Protocol::enableBigPackets); // InputMessage g_lua.registerClass(); diff --git a/modules/client_background/background.otui b/modules/client_background/background.otui index 67ab015..ac202da 100644 --- a/modules/client_background/background.otui +++ b/modules/client_background/background.otui @@ -1,13 +1,6 @@ -Panel +Background id: background - image-source: /images/background - image-smooth: true - image-fixed-ratio: true - anchors.top: topMenu.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - margin-top: 1 + anchors.fill: parent focusable: false UILabel diff --git a/modules/client_entergame/characterlist.lua b/modules/client_entergame/characterlist.lua index 155a745..5c43f8c 100644 --- a/modules/client_entergame/characterlist.lua +++ b/modules/client_entergame/characterlist.lua @@ -30,7 +30,6 @@ local function tryLogin(charInfo, tries) end CharacterList.hide() - g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken, G.sessionKey) g_logger.info("Login to " .. charInfo.worldHost .. ":" .. charInfo.worldPort) loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...')) diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 19e8428..72d75dc 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -79,12 +79,12 @@ local function validateThings(things) local thingsNode = {} for thingtype, thingdata in pairs(things) do thingsNode[thingtype] = thingdata[1] - if not g_resources.fileExists("/data/things/" .. thingdata[1]) then + if not g_resources.fileExists("/things/" .. thingdata[1]) then incorrectThings = incorrectThings .. "Missing file: " .. thingdata[1] .. "\n" missingFiles = true versionForMissingFiles = thingdata[1]:split("/")[1] else - local localChecksum = g_resources.fileChecksum("/data/things/" .. thingdata[1]):lower() + local localChecksum = g_resources.fileChecksum("/things/" .. thingdata[1]):lower() if localChecksum ~= thingdata[2]:lower() and #thingdata[2] > 1 then if g_resources.isLoadedFromArchive() then -- ignore checksum if it's test/debug version incorrectThings = incorrectThings .. "Invalid checksum of file: " .. thingdata[1] .. " (is " .. localChecksum .. ", should be " .. thingdata[2]:lower() .. ")\n" @@ -393,8 +393,8 @@ function EnterGame.doLogin() g_game.setProtocolVersion(g_game.getClientProtocolVersion(G.clientVersion)) g_game.setCustomProtocolVersion(0) g_game.chooseRsa(G.host) - if #server_params <= 3 then - g_game.setCustomOs(2) -- set os to windows + if #server_params <= 3 and not g_game.getFeature(GameExtendedOpcode) then + g_game.setCustomOs(2) -- set os to windows if opcodes are disabled end -- extra features from init.lua diff --git a/modules/client_entergame/entergame.otui b/modules/client_entergame/entergame.otui index 68b1ff4..a425aa9 100644 --- a/modules/client_entergame/entergame.otui +++ b/modules/client_entergame/entergame.otui @@ -1,7 +1,3 @@ -EnterGameWindow < StaticMainWindow - !text: tr('Enter Game') - size: 260 354 - EnterGameWindow id: enterGame @onEnter: EnterGame.doLogin() diff --git a/modules/client_entergamev2/entergamev2.lua b/modules/client_entergamev2/entergamev2.lua index 608829f..59a93b5 100644 --- a/modules/client_entergamev2/entergamev2.lua +++ b/modules/client_entergamev2/entergamev2.lua @@ -370,12 +370,12 @@ function validateThings(things) local thingsNode = {} for thingtype, thingdata in pairs(things) do thingsNode[thingtype] = thingdata[1] - if not g_resources.fileExists("/data/things/" .. thingdata[1]) then + if not g_resources.fileExists("/things/" .. thingdata[1]) then incorrectThings = incorrectThings .. "Missing file: " .. thingdata[1] .. "\n" missingFiles = true versionForMissingFiles = thingdata[1]:split("/")[1] else - local localChecksum = g_resources.fileChecksum("/data/things/" .. thingdata[1]):lower() + local localChecksum = g_resources.fileChecksum("/things/" .. thingdata[1]):lower() if localChecksum ~= thingdata[2]:lower() and #thingdata[2] > 1 then if g_resources.isLoadedFromArchive() then -- ignore checksum if it's test/debug version incorrectThings = incorrectThings .. "Invalid checksum of file: " .. thingdata[1] .. " (is " .. localChecksum .. ", should be " .. thingdata[2]:lower() .. ")\n" diff --git a/modules/client_options/interface.otui b/modules/client_options/interface.otui index cc34275..a49b470 100644 --- a/modules/client_options/interface.otui +++ b/modules/client_options/interface.otui @@ -1,7 +1,33 @@ Panel + Label + width: 130 + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + id: layoutLabel + !text: tr("Layout (change requries client restart)") + + ComboBox + id: layout + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 3 + margin-right: 2 + margin-left: 2 + @onOptionChange: modules.client_options.setOption(self:getId(), self:getCurrentOption().text) + @onSetup: | + self:addOption("Default") + for _, file in ipairs(g_resources.listDirectoryFiles("/layouts", false, true)) do + if g_resources.directoryExists("/layouts/" .. file) then + self:addOption(file:gsub("^%l", string.upper)) + end + end + OptionCheckBox id: classicView !text: tr('Classic view') + margin-top: 5 OptionCheckBox id: cacheMap diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index 7621ad7..0d1778b 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -1,4 +1,5 @@ local defaultOptions = { + layout = DEFAULT_LAYOUT, -- set in init.lua vsync = true, showFps = true, showPing = true, @@ -33,8 +34,8 @@ local defaultOptions = { displayHealth = true, displayMana = true, displayHealthOnTop = false, - showHealthManaCircle = true, - hidePlayerBars = true, + showHealthManaCircle = false, + hidePlayerBars = false, highlightThingsUnderCursor = true, topHealtManaBar = true, displayText = true, @@ -141,6 +142,8 @@ function setup() setOption(k, g_settings.getBoolean(k), true) elseif type(v) == 'number' then setOption(k, g_settings.getNumber(k), true) + elseif type(v) == 'string' then + setOption(k, g_settings.getString(k), true) end end @@ -208,6 +211,7 @@ function setOption(key, value, force) end return end + if modules.game_interface == nil then return end @@ -219,8 +223,14 @@ function setOption(key, value, force) g_window.setVerticalSync(value) elseif key == 'showFps' then modules.client_topmenu.setFpsVisible(value) + if modules.game_stats and modules.game_stats.ui.fps then + modules.game_stats.ui.fps:setVisible(value) + end elseif key == 'showPing' then modules.client_topmenu.setPingVisible(value) + if modules.game_stats and modules.game_stats.ui.ping then + modules.game_stats.ui.ping:setVisible(value) + end elseif key == 'fullscreen' then g_window.setFullscreen(value) elseif key == 'enableAudio' then @@ -267,9 +277,9 @@ function setOption(key, value, force) if value == 1 then gameMapPanel:setCrosshair("") elseif value == 2 then - gameMapPanel:setCrosshair("/data/images/crosshair/default.png") + gameMapPanel:setCrosshair("/images/crosshair/default.png") elseif value == 3 then - gameMapPanel:setCrosshair("/data/images/crosshair/full.png") + gameMapPanel:setCrosshair("/images/crosshair/full.png") end elseif key == 'ambientLight' then graphicsPanel:getChildById('ambientLightLabel'):setText(tr('Ambient light: %s%%', value)) @@ -322,7 +332,7 @@ function setOption(key, value, force) generalPanel:getChildById('walkTeleportDelayLabel'):setText(tr('Walk delay after teleport: %s ms', value)) elseif key == 'walkCtrlTurnDelay' then generalPanel:getChildById('walkCtrlTurnDelayLabel'):setText(tr('Walk delay after ctrl turn: %s ms', value)) - end + end -- change value for keybind updates for _,panel in pairs(optionsTabBar:getTabsPanel()) do @@ -333,11 +343,15 @@ function setOption(key, value, force) elseif widget:getStyle().__class == 'UIScrollBar' then widget:setValue(value) elseif widget:getStyle().__class == 'UIComboBox' then - if valur ~= nil or value < 1 then + if type(value) == "string" then + widget:setCurrentOption(value, true) + break + end + if value == nil or value < 1 then value = 1 end if widget.currentIndex ~= value then - widget:setCurrentIndex(value) + widget:setCurrentIndex(value, true) end end break diff --git a/modules/client_options/options.otui b/modules/client_options/options.otui index 6d1367c..946d7bd 100644 --- a/modules/client_options/options.otui +++ b/modules/client_options/options.otui @@ -20,7 +20,7 @@ OptionScrollbar < HorizontalScrollBar MainWindow id: optionsWindow !text: tr('Options') - size: 480 420 + size: 480 460 @onEnter: modules.client_options.hide() @onEscape: modules.client_options.hide() @@ -38,6 +38,7 @@ MainWindow anchors.right: parent.right anchors.bottom: optionsTabBar.bottom margin-left: 10 + margin-top: 3 Button !text: tr('Ok') diff --git a/modules/client_stats/stats.lua b/modules/client_stats/stats.lua index bfb32b3..7040206 100644 --- a/modules/client_stats/stats.lua +++ b/modules/client_stats/stats.lua @@ -136,7 +136,10 @@ function sendStats() lua_mem_usage = gcinfo(), os_name = g_platform.getOSName(), platform = g_window.getPlatformType(), - uptime = g_clock.seconds() + uptime = g_clock.seconds(), + layout = g_resources.getLayout(), + packets = g_game.getRecivedPacketsCount(), + packets_size = g_game.getRecivedPacketsSize() } } if g_proxy then diff --git a/modules/client_styles/styles.lua b/modules/client_styles/styles.lua index f10cdab..ef6fc24 100644 --- a/modules/client_styles/styles.lua +++ b/modules/client_styles/styles.lua @@ -1,27 +1,74 @@ function init() local files - files = g_resources.listDirectoryFiles('/styles') + local loaded_files = {} + local layout = g_resources:getLayout() + + local style_files = {} + if layout:len() > 0 then + loaded_files = {} + files = g_resources.listDirectoryFiles('/layouts/' .. layout .. '/styles') + for _,file in pairs(files) do + if g_resources.isFileType(file, 'otui') then + table.insert(style_files, file) + loaded_files[file] = true + end + end + end + + files = g_resources.listDirectoryFiles('/data/styles') for _,file in pairs(files) do + if g_resources.isFileType(file, 'otui') and not loaded_files[file] then + table.insert(style_files, file) + end + end + + table.sort(style_files) + for _,file in pairs(style_files) do if g_resources.isFileType(file, 'otui') then g_ui.importStyle('/styles/' .. file) end end - files = g_resources.listDirectoryFiles('/fonts') - for _,file in pairs(files) do - if g_resources.isFileType(file, 'otfont') then - g_fonts.importFont('/fonts/' .. file) + if layout:len() > 0 then + files = g_resources.listDirectoryFiles('/layouts/' .. layout .. '/fonts') + loaded_files = {} + for _,file in pairs(files) do + if g_resources.isFileType(file, 'otfont') then + g_ui.importFont('/layouts/' .. layout .. '/fonts/' .. file) + loaded_files[file] = true + end end end - files = g_resources.listDirectoryFiles('/particles') + files = g_resources.listDirectoryFiles('/data/fonts') for _,file in pairs(files) do - if g_resources.isFileType(file, 'otps')then - g_particles.importParticle('/particles/' .. file) + if g_resources.isFileType(file, 'otfont') and not loaded_files[file] then + g_fonts.importFont('/data/fonts/' .. file) end end - g_mouse.loadCursors('/cursors/cursors') + if layout:len() > 0 then + files = g_resources.listDirectoryFiles('/layouts/' .. layout .. '/particles') + loaded_files = {} + for _,file in pairs(files) do + if g_resources.isFileType(file, 'otps') then + g_ui.importParticle('/layouts/' .. layout .. '/particles/' .. file) + loaded_files[file] = true + end + end + end + + files = g_resources.listDirectoryFiles('/data/particles') + for _,file in pairs(files) do + if g_resources.isFileType(file, 'otps') and not loaded_files[file] then + g_particles.importParticle('/data/particles/' .. file) + end + end + + g_mouse.loadCursors('/data/cursors/cursors') + if layout:len() > 0 and g_resources.directoryExists('/layouts/' .. layout .. '/cursors/cursors') then + g_mouse.loadCursors('/layouts/' .. layout .. '/cursors/cursors') + end end function terminate() diff --git a/modules/client_topmenu/topmenu.lua b/modules/client_topmenu/topmenu.lua index 499631d..245591d 100644 --- a/modules/client_topmenu/topmenu.lua +++ b/modules/client_topmenu/topmenu.lua @@ -1,17 +1,20 @@ -- private variables local topMenu local fpsUpdateEvent = nil - -local HIDE_TOPMENU = false +local statusUpdateEvent = nil -- private functions -local function addButton(id, description, icon, callback, panel, toggle, front) +local function addButton(id, description, icon, callback, panel, toggle, front, index) local class if toggle then class = 'TopToggleButton' else class = 'TopButton' end + + if topMenu.reverseButtons then + front = not front + end local button = panel:getChildById(id) if not button then @@ -31,6 +34,9 @@ local function addButton(id, description, icon, callback, panel, toggle, front) return true end end + if not button.index and type(index) == 'number' then + button.index = index + end return button end @@ -40,24 +46,15 @@ function init() onGameEnd = offline, onPingBack = updatePing }) - topMenu = g_ui.displayUI('topmenu') + topMenu = g_ui.createWidget('TopMenu', g_ui.getRootWidget()) g_keyboard.bindKeyDown('Ctrl+Shift+T', toggle) if g_game.isOnline() then - online() + scheduleEvent(online, 10) end - updateFps() - - if not Services or not Services.feedback or Services.feedback:len() < 4 then - topMenu.reportBug:setVisible(false) - topMenu.reportBug:setWidth(0) - end - - if HIDE_TOPMENU then - topMenu:setHeight(0) - topMenu:hide() - end + updateFps() + updateStatus() end function terminate() @@ -65,34 +62,59 @@ function terminate() onGameEnd = offline, onPingBack = updatePing }) removeEvent(fpsUpdateEvent) + removeEvent(statusUpdateEvent) + g_keyboard.unbindKeyDown('Ctrl+Shift+T') topMenu:destroy() end function online() + if topMenu.hideIngame then + hide() + else + modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom) + end + if topMenu.onlineLabel then + topMenu.onlineLabel:hide() + end + showGameButtons() - addEvent(function() - if modules.client_options.getOption('showPing') and (g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing)) then - topMenu.pingLabel:show() - else - topMenu.pingLabel:hide() - end - end) + if topMenu.pingLabel then + addEvent(function() + if modules.client_options.getOption('showPing') and (g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing)) then + topMenu.pingLabel:show() + else + topMenu.pingLabel:hide() + end + end) + end end function offline() + if topMenu.hideIngame then + show() + end + if topMenu.onlineLabel then + topMenu.onlineLabel:show() + end + hideGameButtons() - topMenu.pingLabel:hide() + if topMenu.pingLabel then + topMenu.pingLabel:hide() + end + updateStatus() end function updateFps() + if not topMenu.fpsLabel then return end fpsUpdateEvent = scheduleEvent(updateFps, 500) text = 'FPS: ' .. g_app.getFps() topMenu.fpsLabel:setText(text) end function updatePing(ping) + if not topMenu.pingLabel then return end if g_proxy and g_proxy.getPing() > 0 then ping = g_proxy.getPing() end @@ -117,49 +139,70 @@ function updatePing(ping) end function setPingVisible(enable) + if not topMenu.pingLabel then return end topMenu.pingLabel:setVisible(enable) - topMenu.reportBug:setVisible(enable) end function setFpsVisible(enable) + if not topMenu.fpsLabel then return end topMenu.fpsLabel:setVisible(enable) end -function addLeftButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.leftButtonsPanel, false, front) +function addLeftButton(id, description, icon, callback, front, index) + return addButton(id, description, icon, callback, topMenu.leftButtonsPanel, false, front, index) end -function addLeftToggleButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.leftButtonsPanel, true, front) +function addLeftToggleButton(id, description, icon, callback, front, index) + return addButton(id, description, icon, callback, topMenu.leftButtonsPanel, true, front, index) end -function addRightButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.rightButtonsPanel, false, front) +function addRightButton(id, description, icon, callback, front, index) + return addButton(id, description, icon, callback, topMenu.rightButtonsPanel, false, front, index) end -function addRightToggleButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.rightButtonsPanel, true, front) +function addRightToggleButton(id, description, icon, callback, front, index) + return addButton(id, description, icon, callback, topMenu.rightButtonsPanel, true, front, index) end -function addLeftGameButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.leftGameButtonsPanel, false, front) +function addLeftGameButton(id, description, icon, callback, front, index) + local button = addButton(id, description, icon, callback, topMenu.leftGameButtonsPanel, false, front, index) + if modules.game_buttons then + modules.game_buttons.takeButton(button) + end + return button end -function addLeftGameToggleButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.leftGameButtonsPanel, true, front) +function addLeftGameToggleButton(id, description, icon, callback, front, index) + local button = addButton(id, description, icon, callback, topMenu.leftGameButtonsPanel, true, front, index) + if modules.game_buttons then + modules.game_buttons.takeButton(button) + end + return button end -function addRightGameButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.rightGameButtonsPanel, false, front) +function addRightGameButton(id, description, icon, callback, front, index) + local button = addButton(id, description, icon, callback, topMenu.rightGameButtonsPanel, false, front, index) + if modules.game_buttons then + modules.game_buttons.takeButton(button) + end + return button end -function addRightGameToggleButton(id, description, icon, callback, front) - return addButton(id, description, icon, callback, topMenu.rightGameButtonsPanel, true, front) +function addRightGameToggleButton(id, description, icon, callback, front, index) + local button = addButton(id, description, icon, callback, topMenu.rightGameButtonsPanel, true, front, index) + if modules.game_buttons then + modules.game_buttons.takeButton(button) + end + return button end function showGameButtons() topMenu.leftGameButtonsPanel:show() topMenu.rightGameButtonsPanel:show() + if modules.game_buttons then + modules.game_buttons.takeButtons(topMenu.leftGameButtonsPanel:getChildren()) + modules.game_buttons.takeButtons(topMenu.rightGameButtonsPanel:getChildren()) + end end function hideGameButtons() @@ -176,23 +219,61 @@ function getTopMenu() end function toggle() - local menu = getTopMenu() - if not menu then + if not topMenu then return end - - if HIDE_TOPMENU then - return - end - - if menu:isVisible() then - menu:hide() - modules.client_background.getBackground():addAnchor(AnchorTop, 'parent', AnchorTop) - modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'parent', AnchorTop) + + if topMenu:isVisible() then + hide() else - menu:show() - topMenu:setHeight(36) - modules.client_background.getBackground():addAnchor(AnchorTop, 'topMenu', AnchorBottom) - modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom) + show() end end + +function hide() + topMenu:hide() + if not topMenu.hideIngame then + modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'parent', AnchorTop) + end + if modules.game_stats then + modules.game_stats.show() + end +end + +function show() + topMenu:show() + if not topMenu.hideIngame then + modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom) + end + if modules.game_stats then + modules.game_stats.hide() + end +end + +function updateStatus() + removeEvent(statusUpdateEvent) + if not Services or not Services.status or Services.status:len() < 4 then return end + if not topMenu.onlineLabel then return end + if g_game.isOnline() then return end + HTTP.getJSON(Services.status, function(data, err) + if err then + g_logger.warning("HTTP error for " .. Services.status .. ": " .. err) + statusUpdateEvent = scheduleEvent(updateStatus, 5000) + return + end + if data.online and topMenu.onlineLabel then + topMenu.onlineLabel:setText(data.online) + end + if data.discord_online and topMenu.discordLabel then + topMenu.discordLabel:setText(data.discord_online) + end + if data.discord_link and topMenu.discordLabel and topMenu.discord then + local discordOnClick = function() + g_platform.openUrl(data.discord_link) + end + topMenu.discordLabel.onClick = discordOnClick + topMenu.discord.onClick = discordOnClick + end + statusUpdateEvent = scheduleEvent(updateStatus, 60000) + end) +end \ No newline at end of file diff --git a/modules/client_topmenu/topmenu.otui b/modules/client_topmenu/topmenu.otui deleted file mode 100644 index bf9eab3..0000000 --- a/modules/client_topmenu/topmenu.otui +++ /dev/null @@ -1,57 +0,0 @@ -TopMenuPanel - id: topMenu - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - - TopMenuButtonsPanel - id: leftButtonsPanel - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - - TopMenuButtonsPanel - id: leftGameButtonsPanel - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: prev.right - visible: false - - TopMenuFrameCounterLabel - id: fpsLabel - text-auto-resize: true - anchors.top: parent.top - anchors.left: leftGameButtonsPanel.right - - TopMenuPingLabel - color: white - id: pingLabel - text-auto-resize: true - anchors.top: fpsLabel.bottom - anchors.left: fpsLabel.left - - Button - id: reportBug - text: Report bug - text-align: center - color: white - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: leftGameButtonsPanel.right - margin-left: 80 - margin-top: 5 - margin-bottom: 5 - @onClick: modules.client_feedback.show() - - TopMenuButtonsPanel - id: rightButtonsPanel - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - - TopMenuButtonsPanel - id: rightGameButtonsPanel - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: prev.left - visible: false diff --git a/modules/corelib/ui/uiminiwindow.lua b/modules/corelib/ui/uiminiwindow.lua index 485faac..d8c9639 100644 --- a/modules/corelib/ui/uiminiwindow.lua +++ b/modules/corelib/ui/uiminiwindow.lua @@ -34,7 +34,9 @@ function UIMiniWindow:minimize(dontSave) self:getChildById('contentsPanel'):hide() self:getChildById('miniwindowScrollBar'):hide() self:getChildById('bottomResizeBorder'):hide() - self:getChildById('minimizeButton'):setOn(true) + if self.minimizeButton then + self.minimizeButton:setOn(true) + end self.maximizedHeight = self:getHeight() self:setHeight(self.minimizedHeight) @@ -50,7 +52,9 @@ function UIMiniWindow:maximize(dontSave) self:getChildById('contentsPanel'):show() self:getChildById('miniwindowScrollBar'):show() self:getChildById('bottomResizeBorder'):show() - self:getChildById('minimizeButton'):setOn(false) + if self.minimizeButton then + self.minimizeButton:setOn(false) + end self:setHeight(self:getSettings('height') or self.maximizedHeight) if not dontSave then @@ -96,18 +100,21 @@ function UIMiniWindow:setup() self:close() end if self.forceOpen then - self:getChildById('closeButton'):hide() - self:getChildById('minimizeButton'):addAnchor(AnchorRight, 'parent', AnchorRight) + if self.closeButton then + self.closeButton:hide() + end end - self:getChildById('minimizeButton').onClick = - function() - if self:isOn() then - self:maximize() - else - self:minimize() + if(self.minimizeButton) then + self.minimizeButton.onClick = + function() + if self:isOn() then + self:maximize() + else + self:minimize() + end end - end + end local lockButton = self:getChildById('lockButton') if lockButton then diff --git a/modules/game_actionbar/actionbar.lua b/modules/game_actionbar/actionbar.lua index 6e2136e..c1692d7 100644 --- a/modules/game_actionbar/actionbar.lua +++ b/modules/game_actionbar/actionbar.lua @@ -38,7 +38,7 @@ function init() }) if g_game.isOnline() then - show() + online() end end @@ -51,14 +51,7 @@ function terminate() saveConfig() -- remove hotkeys - for index, panel in ipairs({actionPanel1, actionPanel2}) do - for i, child in ipairs(panel.tabBar:getChildren()) do - local gameRootPanel = modules.game_interface.getRootPanel() - if child.hotkey then - g_keyboard.unbindKeyPress(child.hotkey, child.callback, gameRootPanel) - end - end - end + offline() actionPanel1:destroy() actionPanel2:destroy() @@ -66,8 +59,6 @@ end function show() if not g_game.isOnline() then return end - setupActionPanel(1, actionPanel1) - setupActionPanel(2, actionPanel2) actionPanel1:setOn(g_settings.getBoolean("actionBar1", false)) actionPanel2:setOn(g_settings.getBoolean("actionBar2", false)) end @@ -88,6 +79,8 @@ function switchMode(newMode) end function online() + setupActionPanel(1, actionPanel1) + setupActionPanel(2, actionPanel2) show() end @@ -98,6 +91,15 @@ function offline() hotkeyAssignWindow = nil end saveConfig() + + for index, panel in ipairs({actionPanel1, actionPanel2}) do + for i, child in ipairs(panel.tabBar:getChildren()) do + local gameRootPanel = modules.game_interface.getRootPanel() + if child.hotkey then + g_keyboard.unbindKeyPress(child.hotkey, child.callback, gameRootPanel) + end + end + end end function setupActionPanel(index, panel) @@ -143,8 +145,14 @@ function setupAction(index, action, config) action.callback = function(k, c, ticks) executeAction(action, ticks) end if config then + if type(config.text) == 'number' then + config.text = tostring(config.text) + end + if type(config.hotkey) == 'number' then + config.hotkey = tostring(config.hotkey) + end action.hotkey = config.hotkey - if action.hotkey and action.hotkey:len() > 0 then + if type(action.hotkey) == 'string' and action.hotkey:len() > 0 then local gameRootPanel = modules.game_interface.getRootPanel() g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel) end @@ -156,6 +164,7 @@ function setupAction(index, action, config) if config.item > 0 then setupActionType(action, config.action) end + action.item:setOn(config.item > 0) action.item:setItemId(config.item) action.item:setItemCount(config.count) end @@ -274,6 +283,7 @@ function actionOnMouseRelease(action, mousePosition, mouseButton) menu:addSeparator() menu:addOption(tr('Set text'), function() modules.game_textedit.singlelineEditor(action.text:getText(), function(newText) + action.item:setOn(false) action.item:setItemId(0) action.text:setText(newText) if action.text:getText():len() > 0 then @@ -303,7 +313,7 @@ function actionOnMouseRelease(action, mousePosition, mouseButton) if action.hotkey and action.hotkey:len() > 0 then g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel) end - action.hotkey = assignWindow.comboPreview.keyCombo + action.hotkey = tostring(assignWindow.comboPreview.keyCombo) if action.hotkey and action.hotkey:len() > 0 then g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel) end @@ -338,6 +348,7 @@ function actionOnItemChange(widget) local action = widget:getParent() if action.item:getItemId() > 0 then action.text:setText("") + action.item:setOn(true) if action.item:getItem():isMultiUse() then if not action.actionType or action.actionType <= 1 then setupActionType(action, ActionTypes.USE_WITH) diff --git a/modules/game_actionbar/actionbar.otui b/modules/game_actionbar/actionbar.otui index 639ded1..50e5e8a 100644 --- a/modules/game_actionbar/actionbar.otui +++ b/modules/game_actionbar/actionbar.otui @@ -20,6 +20,9 @@ ActionButton < Panel &editable: false virtual: true + $!on: + image-source: /images/game/actionbarslot + Label id: text anchors.fill: parent @@ -43,8 +46,7 @@ Panel id: actionBar anchors.left: parent.left anchors.right: parent.right - image-source: /images/ui/panel_bottom - image-border: 6 + image-source: /images/ui/panel_map focusable: false $first: diff --git a/modules/game_battle/battle.lua b/modules/game_battle/battle.lua index 033d75d..92b2a3d 100644 --- a/modules/game_battle/battle.lua +++ b/modules/game_battle/battle.lua @@ -16,7 +16,7 @@ local ageNumber = 1 function init() g_ui.importStyle('battlebutton') - battleButton = modules.client_topmenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', '/images/topbuttons/battle', toggle) + battleButton = modules.client_topmenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', '/images/topbuttons/battle', toggle, false, 2) battleButton:setOn(true) battleWindow = g_ui.loadUI('battle', modules.game_interface.getRightPanel()) g_keyboard.bindKeyDown('Ctrl+B', toggle) diff --git a/modules/game_bot/bot.lua b/modules/game_bot/bot.lua index 129e8fb..357672d 100644 --- a/modules/game_bot/bot.lua +++ b/modules/game_bot/bot.lua @@ -33,7 +33,7 @@ function init() initCallbacks() - botButton = modules.client_topmenu.addRightGameToggleButton('botButton', tr('Bot'), '/images/topbuttons/bot', toggle) + botButton = modules.client_topmenu.addRightGameToggleButton('botButton', tr('Bot'), '/images/topbuttons/bot', toggle, false, 99999) botButton:setOn(false) botButton:hide() diff --git a/modules/game_bot/functions/ui_elements.lua b/modules/game_bot/functions/ui_elements.lua index a5f76a0..85115ed 100644 --- a/modules/game_bot/functions/ui_elements.lua +++ b/modules/game_bot/functions/ui_elements.lua @@ -17,11 +17,9 @@ UI.Container = function(callback, unique, parent) local updateItems = function() local items = widget:getItems() - widget:setItems(items) - + -- callback part - if not callback then return end - local somethingNew = false + local somethingNew = (#items ~= #oldItems) for i, item in ipairs(items) do if type(oldItems[i]) ~= "table" then somethingNew = true @@ -32,10 +30,13 @@ UI.Container = function(callback, unique, parent) break end end + if somethingNew then oldItems = items callback(items) end + + widget:setItems(items) end widget.setItems = function(self, items) diff --git a/modules/game_bot/ui/basic.otui b/modules/game_bot/ui/basic.otui index 0ddddb3..eb8f23e 100644 --- a/modules/game_bot/ui/basic.otui +++ b/modules/game_bot/ui/basic.otui @@ -42,6 +42,7 @@ BotSeparator < HorizontalSeparator BotSmallScrollBar < SmallScrollBar BotPanel < Panel + margin-top: 1 ScrollablePanel id: content anchors.fill: parent diff --git a/modules/game_buttons/buttons.lua b/modules/game_buttons/buttons.lua new file mode 100644 index 0000000..57af9ab --- /dev/null +++ b/modules/game_buttons/buttons.lua @@ -0,0 +1,40 @@ +buttonsWindow = nil +contentsPanel = nil + +function init() + buttonsWindow = g_ui.loadUI('buttons', modules.game_interface.getRightPanel()) + buttonsWindow:disableResize() + buttonsWindow:setup() + contentsPanel = buttonsWindow.contentsPanel + if not buttonsWindow.forceOpen or not contentsPanel.buttons then + buttonsWindow:close() + end +end + +function terminate() + buttonsWindow:destroy() +end + +function takeButtons(buttons) + if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end + for i, button in ipairs(buttons) do + takeButton(button, true) + end + updateOrder() +end + +function takeButton(button, dontUpdateOrder) + if not buttonsWindow.forceOpen or not contentsPanel.buttons then return end + button:setParent(contentsPanel.buttons) + if not dontUpdateOrder then + updateOrder() + end +end + +function updateOrder() + local children = contentsPanel.buttons:getChildren() + table.sort(children, function(a, b) + return (a.index or 1000) < (b.index or 1000) + end) + contentsPanel.buttons:reorderChildren(children) +end \ No newline at end of file diff --git a/modules/game_buttons/buttons.otmod b/modules/game_buttons/buttons.otmod new file mode 100644 index 0000000..3f807e6 --- /dev/null +++ b/modules/game_buttons/buttons.otmod @@ -0,0 +1,8 @@ +Module + name: game_buttons + description: Shows miniwindow with buttons + author: otclient@otclient.ovh + sandboxed: true + scripts: [ buttons ] + @onLoad: init() + @onUnload: terminate() diff --git a/modules/game_buttons/buttons.otui b/modules/game_buttons/buttons.otui new file mode 100644 index 0000000..963a541 --- /dev/null +++ b/modules/game_buttons/buttons.otui @@ -0,0 +1,6 @@ +GameButtonsWindow + id: buttons + &save: true + !text: tr("Buttons") + icon: /images/topbuttons/buttons + diff --git a/modules/game_console/console.otui b/modules/game_console/console.otui index ada0454..6f800e8 100644 --- a/modules/game_console/console.otui +++ b/modules/game_console/console.otui @@ -1,187 +1,3 @@ -ConsoleLabel < UITextEdit - font: verdana-11px-antialised - height: 14 - color: yellow - margin-left: 2 - text-wrap: true - text-auto-resize: true - selection-color: #111416 - selection-background-color: #999999 - change-cursor-image: false - cursor-visible: false - editable: false - draggable: true - selectable: false - focusable: false - -ConsolePhantomLabel < UILabel - font: verdana-11px-antialised - height: 14 - color: yellow - text-wrap: true - text-auto-resize: true - selection-color: #111416 - selection-background-color: #999999 - -ConsoleTabBar < MoveableTabBar - height: 28 - -ConsoleTabBarPanel < MoveableTabBarPanel - id: consoleTab - - ScrollablePanel - id: consoleBuffer - anchors.fill: parent - margin-right: 12 - vertical-scrollbar: consoleScrollBar - layout: - type: verticalBox - align-bottom: true - border-width: 1 - border-color: #202327 - background: #00000066 - inverted-scroll: true - padding: 1 - - VerticalScrollBar - id: consoleScrollBar - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - step: 14 - pixels-scroll: true - -ConsoleTabBarButton < MoveableTabBarButton - height: 28 - padding: 15 - -Panel +ConsolePanel id: consolePanel - image-source: /images/ui/panel_bottom - image-border: 4 phantom: false - - $first: - anchors.fill: parent - - $!first: - anchors.top: prev.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - - CheckBox - id: toggleChat - !tooltip: tr('Disable chat mode, allow to walk using ASDW') - anchors.left: parent.left - anchors.top: parent.top - margin-left: 13 - margin-top: 8 - @onCheckChange: toggleChat() - - TabButton - id: prevChannelButton - icon: /images/game/console/leftarrow - anchors.left: toggleChat.right - anchors.top: parent.top - margin-left: 3 - margin-top: 6 - - ConsoleTabBar - id: consoleTabBar - anchors.left: prev.right - anchors.top: parent.top - anchors.right: next.left - margin-left: 5 - margin-top: 3 - margin-right: 5 - tab-spacing: 2 - movable: true - - TabButton - id: nextChannelButton - icon: /images/game/console/rightarrow - anchors.right: next.left - anchors.top: parent.top - margin-right: 5 - margin-top: 6 - - TabButton - id: closeChannelButton - !tooltip: tr('Close this channel') .. ' (Ctrl+E)' - icon: /images/game/console/closechannel - anchors.right: next.left - anchors.top: parent.top - enabled: false - margin-right: 5 - margin-top: 6 - @onClick: removeCurrentTab() - - TabButton - id: clearChannelButton - !tooltip: tr('Clear current message window') - icon: /images/game/console/clearchannel - anchors.right: next.left - anchors.top: parent.top - margin-right: 5 - margin-top: 6 - @onClick: | - local consoleTabBar = self:getParent():getChildById('consoleTabBar') - clearChannel(consoleTabBar) - - TabButton - id: channelsButton - !tooltip: tr('Open new channel') .. ' (Ctrl+O)' - icon: /images/game/console/channels - anchors.right: next.left - anchors.top: parent.top - margin-right: 5 - margin-top: 6 - @onClick: g_game.requestChannels() - - TabButton - id: ignoreButton - !tooltip: tr('Ignore players') - icon: /images/game/console/ignore - anchors.right: parent.right - anchors.top: parent.top - margin-right: 5 - margin-top: 6 - @onClick: onClickIgnoreButton() - - Panel - id: consoleContentPanel - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: consoleTextEdit.top - margin-left: 6 - margin-right: 6 - margin-bottom: 4 - margin-top: 4 - padding: 1 - focusable: false - phantom: true - - TabButton - id: sayModeButton - icon: /images/game/console/say - !tooltip: tr('Adjust volume') - &sayMode: 2 - size: 20 20 - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-left: 6 - margin-bottom: 6 - @onClick: sayModeChange() - - TextEdit - id: consoleTextEdit - anchors.left: sayModeButton.right - anchors.right: parent.right - anchors.bottom: parent.bottom - margin-right: 6 - margin-left: 6 - margin-bottom: 6 - shift-navigation: true - max-length: 255 diff --git a/modules/game_containers/containers.lua b/modules/game_containers/containers.lua index 028c89c..3e08270 100644 --- a/modules/game_containers/containers.lua +++ b/modules/game_containers/containers.lua @@ -1,6 +1,4 @@ function init() - g_ui.importStyle('container') - connect(Container, { onOpen = onContainerOpen, onClose = onContainerClose, onSizeChange = onContainerChangeSize, @@ -50,10 +48,18 @@ function refreshContainerItems(container) end end -function toggleContainerPages(containerWindow, pages) - containerWindow:getChildById('miniwindowScrollBar'):setMarginTop(pages and 42 or 22) - containerWindow:getChildById('contentsPanel'):setMarginTop(pages and 42 or 22) - containerWindow:getChildById('pagePanel'):setVisible(pages) +function toggleContainerPages(containerWindow, hasPages) + if hasPages == containerWindow.pagePanel:isOn() then + return + end + containerWindow.pagePanel:setOn(hasPages) + if hasPages then + containerWindow.miniwindowScrollBar:setMarginTop(containerWindow.miniwindowScrollBar:getMarginTop() + containerWindow.pagePanel:getHeight()) + containerWindow.contentsPanel:setMarginTop(containerWindow.contentsPanel:getMarginTop() + containerWindow.pagePanel:getHeight()) + else + containerWindow.miniwindowScrollBar:setMarginTop(containerWindow.miniwindowScrollBar:getMarginTop() - containerWindow.pagePanel:getHeight()) + containerWindow.contentsPanel:setMarginTop(containerWindow.contentsPanel:getMarginTop() - containerWindow.pagePanel:getHeight()) + end end function refreshContainerPages(container) diff --git a/modules/game_cooldown/cooldown.lua b/modules/game_cooldown/cooldown.lua index 0d28fd4..bcfe909 100644 --- a/modules/game_cooldown/cooldown.lua +++ b/modules/game_cooldown/cooldown.lua @@ -18,7 +18,7 @@ function init() onSpellCooldown = onSpellCooldown }) cooldownButton = modules.client_topmenu.addRightGameToggleButton('cooldownButton', - tr('Cooldowns'), '/images/topbuttons/cooldowns', toggle) + tr('Cooldowns'), '/images/topbuttons/cooldowns', toggle, false, 5) cooldownButton:setOn(true) cooldownButton:hide() diff --git a/modules/game_features/features.lua b/modules/game_features/features.lua index eedcc35..78e2114 100644 --- a/modules/game_features/features.lua +++ b/modules/game_features/features.lua @@ -14,7 +14,7 @@ function updateFeatures(version) -- you can add custom features here, list of them is in the modules\gamelib\const.lua g_game.enableFeature(GameBot) - g_game.enableFeature(GameExtendedOpcode) + --g_game.enableFeature(GameExtendedOpcode) --g_game.enableFeature(GameMinimapLimitedToSingleFloor) -- it will generate minimap only for current floor --g_game.enableFeature(GameSpritesAlphaChannel) diff --git a/modules/game_healthinfo/healthinfo.lua b/modules/game_healthinfo/healthinfo.lua index 1590501..49777b8 100644 --- a/modules/game_healthinfo/healthinfo.lua +++ b/modules/game_healthinfo/healthinfo.lua @@ -45,11 +45,14 @@ function init() connect(g_game, { onGameEnd = offline }) - healthInfoButton = modules.client_topmenu.addRightGameToggleButton('healthInfoButton', tr('Health Information'), '/images/topbuttons/healthinfo', toggle) - healthInfoButton:setOn(true) - healthInfoWindow = g_ui.loadUI('healthinfo', modules.game_interface.getRightPanel()) healthInfoWindow:disableResize() + + if not healthInfoWindow.forceOpen then + healthInfoButton = modules.client_topmenu.addRightGameToggleButton('healthInfoButton', tr('Health Information'), '/images/topbuttons/healthinfo', toggle) + healthInfoButton:setOn(true) + end + healthBar = healthInfoWindow:recursiveGetChildById('healthBar') manaBar = healthInfoWindow:recursiveGetChildById('manaBar') experienceBar = healthInfoWindow:recursiveGetChildById('experienceBar') @@ -100,11 +103,14 @@ function terminate() disconnect(overlay, { onGeometryChange = onOverlayGeometryChange }) healthInfoWindow:destroy() - healthInfoButton:destroy() + if healthInfoButton then + healthInfoButton:destroy() + end overlay:destroy() end function toggle() + if not healthInfoButton then return end if healthInfoButton:isOn() then healthInfoWindow:close() healthInfoButton:setOn(false) @@ -140,7 +146,9 @@ end -- hooked events function onMiniWindowClose() - healthInfoButton:setOn(false) + if healthInfoButton then + healthInfoButton:setOn(false) + end end function onHealthChange(localPlayer, health, maxHealth) diff --git a/modules/game_healthinfo/healthinfo.otui b/modules/game_healthinfo/healthinfo.otui index a53e42f..8d55617 100644 --- a/modules/game_healthinfo/healthinfo.otui +++ b/modules/game_healthinfo/healthinfo.otui @@ -1,158 +1,5 @@ -HealthBar < ProgressBar - id: healthBar - background-color: #ff4444 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - margin: 1 - -ManaBar < ProgressBar - id: manaBar - background-color: #4444ff - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - margin: 1 - margin-top: 3 - -ExperienceBar < ProgressBar - id: experienceBar - background-color: #B6E866 - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - margin: 1 - margin-top: 3 - -SoulLabel < GameLabel - id: soulLabel - text-align: right - color: white - font: verdana-11px-rounded - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.left: parent.horizontalCenter - margin-top: 5 - margin-right: 3 - on: true - - $!on: - visible: false - margin-top: 0 - height: 0 - -CapLabel < GameLabel - id: capLabel - color: white - font: verdana-11px-rounded - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.horizontalCenter - margin-top: 5 - margin-left: 3 - on: true - - $!on: - visible: false - margin-top: 0 - height: 0 - -ConditionWidget < UIWidget - size: 18 18 - - $!first: - margin-left: 2 - -HealthOverlay < UIWidget - id: healthOverlay - anchors.fill: parent - phantom: true - - ProgressBar - id: topHealthBar - background-color: #ff4444 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.horizontalCenter - height: 16 - phantom: true - - ProgressBar - id: topManaBar - background-color: #4444ff - anchors.top: parent.top - anchors.right: parent.right - anchors.left: parent.horizontalCenter - height: 16 - phantom: true - - UIProgressBar - id: healthCircle - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - image-source: /images/game/circle/left_empty - margin-right: 169 - margin-bottom: 16 - opacity: 0.5 - phantom: true - - UIProgressBar - id: healthCircleFront - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - image-source: /images/game/circle/left_full - margin-right: 169 - margin-bottom: 16 - opacity: 0.5 - phantom: true - - UIProgressBar - id: manaCircle - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - image-source: /images/game/circle/right_empty - margin-left: 130 - margin-bottom: 16 - opacity: 0.5 - phantom: true - - UIProgressBar - id: manaCircleFront - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - image-source: /images/game/circle/right_full - margin-left: 130 - margin-bottom: 16 - opacity: 0.4 - image-color: #0000FFFF - phantom: true - -MiniWindow - icon: /images/topbuttons/healthinfo +HealthInfoWindow id: healthInfoWindow - !text: tr('Health Info') - height: 123 @onClose: modules.game_healthinfo.onMiniWindowClose() &save: true &autoOpen: 2 - - MiniWindowContents - HealthBar - ManaBar - ExperienceBar - Panel - id: conditionPanel - layout: - type: horizontalBox - height: 22 - margin-top: 4 - padding: 2 - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - border-width: 1 - border-color: #00000077 - background-color: #ffffff11 - SoulLabel - CapLabel - diff --git a/modules/game_hotkeys/hotkeys_manager.lua b/modules/game_hotkeys/hotkeys_manager.lua index a51738f..e85c388 100644 --- a/modules/game_hotkeys/hotkeys_manager.lua +++ b/modules/game_hotkeys/hotkeys_manager.lua @@ -43,7 +43,7 @@ configValueChanged = false -- public functions function init() - hotkeysButton = modules.client_topmenu.addLeftGameButton('hotkeysButton', tr('Hotkeys') .. ' (Ctrl+K)', '/images/topbuttons/hotkeys', toggle) + hotkeysButton = modules.client_topmenu.addLeftGameButton('hotkeysButton', tr('Hotkeys') .. ' (Ctrl+K)', '/images/topbuttons/hotkeys', toggle, false, 7) g_keyboard.bindKeyDown('Ctrl+K', toggle) hotkeysWindow = g_ui.displayUI('hotkeys_manager') hotkeysWindow:setVisible(false) diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index 779a3b3..21bff6f 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -553,9 +553,9 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing) if g_game.getFeature(GameBot) and useThing and useThing:isItem() then menu:addSeparator() if useThing:getSubType() > 1 then - menu:addOption("ID: " .. useThing:getId() .. " SubType: " .. useThing:getSubType()) + menu:addOption("ID: " .. useThing:getId() .. " SubType: " .. useThing:getSubType(), function() end) else - menu:addOption("ID: " .. useThing:getId()) + menu:addOption("ID: " .. useThing:getId(), function() end) end end @@ -877,7 +877,9 @@ function refreshViewMode() if classic then g_game.changeMapAwareRange(19, 15) - gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom) + if not modules.client_topmenu.getTopMenu().hideIngame then + gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom) + end gameMapPanel:addAnchor(AnchorLeft, 'gameLeftPanels', AnchorRight) gameMapPanel:addAnchor(AnchorRight, 'gameRightPanels', AnchorLeft) gameMapPanel:addAnchor(AnchorBottom, 'gameBottomPanel', AnchorTop) @@ -943,6 +945,9 @@ function updateSize() maxWidth = tileSize * (awareRange.width - 1) end gameMapPanel:setMarginTop(-tileSize) + if modules.game_stats then + modules.game_stats.ui:setMarginTop(tileSize) + end if g_settings.getBoolean("cacheMap") then gameMapPanel:setMarginLeft(0) gameMapPanel:setMarginRight(0) @@ -958,7 +963,11 @@ function updateSize() child.onGeometryChange(child) end end - end + end + else + if modules.game_stats then + modules.game_stats.ui:setMarginTop(0) + end end --[[ diff --git a/modules/game_interface/gameinterface.otui b/modules/game_interface/gameinterface.otui index 9936085..46417d4 100644 --- a/modules/game_interface/gameinterface.otui +++ b/modules/game_interface/gameinterface.otui @@ -23,7 +23,6 @@ GameMapPanel < UIGameMap UIWidget id: gameRootPanel anchors.fill: parent - anchors.top: topMenu.bottom GameMapPanel id: gameMapPanel @@ -77,4 +76,3 @@ UIWidget id: mouseGrabber focusable: false visible: false - diff --git a/modules/game_interface/interface.otmod b/modules/game_interface/interface.otmod index 93ababe..249fe28 100644 --- a/modules/game_interface/interface.otmod +++ b/modules/game_interface/interface.otmod @@ -6,6 +6,7 @@ Module sandboxed: true scripts: [ widgets/uigamemap, gameinterface ] load-later: + - game_buttons - game_hotkeys - game_questlog - game_textmessage @@ -37,6 +38,7 @@ Module - game_actionbar - game_prey - game_imbuing + - game_stats - game_bot @onLoad: init() @onUnload: terminate() diff --git a/modules/game_inventory/inventory.lua b/modules/game_inventory/inventory.lua index 2db769c..b50a680 100644 --- a/modules/game_inventory/inventory.lua +++ b/modules/game_inventory/inventory.lua @@ -34,7 +34,6 @@ inventoryWindow = nil inventoryPanel = nil inventoryButton = nil purseButton = nil -marketButton = nil combatControlsWindow = nil fightOffensiveBox = nil @@ -76,13 +75,6 @@ function init() end end - marketButton = inventoryWindow:recursiveGetChildById('marketButton') - marketButton.onClick = function() - if modules.game_shop then - modules.game_shop.toggle() - end - end - -- controls fightOffensiveBox = inventoryWindow:recursiveGetChildById('fightOffensiveBox') fightBalancedBox = inventoryWindow:recursiveGetChildById('fightBalancedBox') @@ -211,7 +203,6 @@ function refresh() end purseButton:setVisible(g_game.getFeature(GamePurseSlot)) - marketButton:setVisible(g_game.getFeature(GameIngameStore)) end function toggle() @@ -281,9 +272,9 @@ function update() safeFightButton:setChecked(not safeFight) if buttonPvp then if safeFight then - buttonPvp:setColor("#00BB00FF") + buttonPvp:setOn(false) else - buttonPvp:setColor("#FF0000FF") + buttonPvp:setOn(true) end end @@ -384,9 +375,9 @@ function onSetSafeFight(self, checked) g_game.setSafeFight(not checked) if buttonPvp then if not checked then - buttonPvp:setColor("#00BB00FF") + buttonPvp:setOn(false) else - buttonPvp:setColor("#FF0000FF") + buttonPvp:setOn(true) end end end diff --git a/modules/game_inventory/inventory.otui b/modules/game_inventory/inventory.otui index 08e6ead..dd01c02 100644 --- a/modules/game_inventory/inventory.otui +++ b/modules/game_inventory/inventory.otui @@ -1,299 +1,6 @@ -InventoryItem < Item - $on: - image-source: /images/ui/item-blessed - -HeadSlot < InventoryItem - id: slot1 - image-source: /images/game/slots/head - &position: {x=65535, y=1, z=0} - $on: - image-source: /images/game/slots/head-blessed - -BodySlot < InventoryItem - id: slot4 - image-source: /images/game/slots/body - &position: {x=65535, y=4, z=0} - $on: - image-source: /images/game/slots/body-blessed - -LegSlot < InventoryItem - id: slot7 - image-source: /images/game/slots/legs - &position: {x=65535, y=7, z=0} - $on: - image-source: /images/game/slots/legs-blessed - -FeetSlot < InventoryItem - id: slot8 - image-source: /images/game/slots/feet - &position: {x=65535, y=8, z=0} - $on: - image-source: /images/game/slots/feet-blessed - -NeckSlot < InventoryItem - id: slot2 - image-source: /images/game/slots/neck - &position: {x=65535, y=2, z=0} - $on: - image-source: /images/game/slots/neck-blessed - -LeftSlot < InventoryItem - id: slot6 - image-source: /images/game/slots/left-hand - &position: {x=65535, y=6, z=0} - $on: - image-source: /images/game/slots/left-hand-blessed - -FingerSlot < InventoryItem - id: slot9 - image-source: /images/game/slots/finger - &position: {x=65535, y=9, z=0} - $on: - image-source: /images/game/slots/finger-blessed - -BackSlot < InventoryItem - id: slot3 - image-source: /images/game/slots/back - &position: {x=65535, y=3, z=0} - $on: - image-source: /images/game/slots/back-blessed - -RightSlot < InventoryItem - id: slot5 - image-source: /images/game/slots/right-hand - &position: {x=65535, y=5, z=0} - $on: - image-source: /images/game/slots/right-hand-blessed - -AmmoSlot < InventoryItem - id: slot10 - image-source: /images/game/slots/ammo - &position: {x=65535, y=10, z=0} - $on: - image-source: /images/game/slots/ammo-blessed - -PurseButton < UIButton - id: purseButton - size: 24 24 - !tooltip: tr('Open purse') - icon-source: /images/game/slots/purse - icon-size: 24 24 - -MarketButton < UIButton - id: marketButton - size: 24 24 - !tooltip: tr('Open Market') - icon-source: /images/game/slots/coins - icon-size: 24 24 - -CombatBox < UICheckBox - size: 20 20 - image-clip: 0 0 20 20 - margin-left: 4 - - $checked: - image-clip: 0 20 20 20 - - -InventoryButton < Button - font: verdana-11px-antialised - height: 18 - margin-top: 1 - -SoulCapLabel < GameLabel - text-align: center - color: #FFFFFF - font: cipsoftFont - margin-top: 4 - text-offset: 0 3 - width: 36 - height: 20 - icon-source: /images/game/slots/soulcap - -FightOffensiveBox < CombatBox - image-source: /images/game/combatmodes/fightoffensive -FightBalancedBox < CombatBox - image-source: /images/game/combatmodes/fightbalanced -FightDefensiveBox < CombatBox - image-source: /images/game/combatmodes/fightdefensive -ChaseModeBox < CombatBox - image-source: /images/game/combatmodes/chasemode -SafeFightBox < CombatBox - image-source: /images/game/combatmodes/safefight - -MountButton < CombatBox - image-source: /images/game/combatmodes/mount - -MiniWindow +InventoryWindow id: inventoryWindow !text: tr('Inventory') - icon: /images/topbuttons/inventory - height: 200 @onClose: modules.game_inventory.onMiniWindowClose() &save: true &autoOpen: 3 - --&forceOpen: true - - MiniWindowContents - anchors.left: parent.left - - Panel - id: inventoryPanel - margin-right: 63 - margin-top: 2 - anchors.fill: parent - - HeadSlot - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - margin-top: 3 - - BodySlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - LegSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - FeetSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - NeckSlot - anchors.top: slot1.top - anchors.right: slot1.left - margin-top: 10 - margin-right: 5 - - LeftSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - FingerSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - BackSlot - anchors.top: slot1.top - anchors.left: slot1.right - margin-top: 10 - margin-left: 5 - - RightSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - AmmoSlot - anchors.top: prev.bottom - anchors.horizontalCenter: prev.horizontalCenter - margin-top: 3 - - SoulCapLabel - id: soulLabel - anchors.top: slot10.bottom - anchors.horizontalCenter: slot10.horizontalCenter - - SoulCapLabel - id: capLabel - anchors.top: slot9.bottom - anchors.horizontalCenter: slot9.horizontalCenter - - Panel - id: conditionPanel - layout: - type: horizontalBox - height: 22 - padding: 2 - anchors.top: slot8.bottom - anchors.left: slot6.left - anchors.right: slot5.right - margin-top: 4 - border-width: 1 - border-color: #00000077 - background-color: #ffffff11 - - Panel - margin-top: 5 - anchors.fill: parent - anchors.left: prev.right - - FightOffensiveBox - id: fightOffensiveBox - anchors.left: parent.left - anchors.top: parent.top - margin-left: 8 - - ChaseModeBox - id: chaseModeBox - anchors.left: prev.right - anchors.top: parent.top - - FightBalancedBox - id: fightBalancedBox - margin-top: 22 - anchors.left: parent.left - anchors.top: parent.top - margin-left: 8 - - SafeFightBox - id: safeFightBox - margin-top: 22 - anchors.left: prev.right - anchors.top: parent.top - - FightDefensiveBox - id: fightDefensiveBox - margin-top: 44 - anchors.left: parent.left - anchors.top: parent.top - margin-left: 8 - - MountButton - id: mountButton - margin-top: 44 - anchors.left: prev.right - anchors.top: parent.top - - Panel - id: buttonsPanel - margin-top: 4 - margin-right: 5 - anchors.fill: parent - anchors.top: prev.bottom - layout: - type: verticalBox - - InventoryButton - !text: tr('Stop') - @onClick: g_game.stop(); g_game.cancelAttackAndFollow() - - InventoryButton - !text: tr('Options') - @onClick: modules.client_options.toggle() - - InventoryButton - !text: tr('Hotkeys') - @onClick: modules.game_hotkeys.toggle() - - InventoryButton - !text: tr('Logout') - @onClick: modules.game_interface.tryLogout() - - MarketButton - anchors.left: buttonsPanel.left - anchors.bottom: buttonsPanel.bottom - margin-bottom: 3 - margin-left: 3 - - PurseButton - anchors.right: buttonsPanel.right - anchors.bottom: buttonsPanel.bottom - margin-bottom: 3 - margin-right: 2 diff --git a/modules/game_market/market.lua b/modules/game_market/market.lua index a07d0b8..eef86e9 100644 --- a/modules/game_market/market.lua +++ b/modules/game_market/market.lua @@ -832,18 +832,9 @@ local function initInterface() slotFilterList:addOption(MarketSlotFilters[255]) slotFilterList:setEnabled(false) - - for i = MarketCategory.First, MarketCategory.Last do - if i >= MarketCategory.Ammunition and i <= MarketCategory.WandsRods then - subCategoryList:addOption(getMarketCategoryName(i)) - else - categoryList:addOption(getMarketCategoryName(i)) - end - end - categoryList:addOption(getMarketCategoryName(255)) -- meta weapons - categoryList:setCurrentOption(getMarketCategoryName(MarketCategory.First)) - subCategoryList:setEnabled(false) - + + Market.updateCategories() + -- hook item filters categoryList.onOptionChange = onChangeCategory subCategoryList.onOptionChange = onChangeSubCategory @@ -897,6 +888,7 @@ function init() protocol.initProtocol() connect(g_game, { onGameEnd = Market.reset }) connect(g_game, { onGameEnd = Market.close }) + connect(g_game, { onGameStart = Market.updateCategories }) marketWindow = g_ui.createWidget('MarketWindow', rootWidget) marketWindow:hide() @@ -911,6 +903,7 @@ function terminate() protocol.terminateProtocol() disconnect(g_game, { onGameEnd = Market.reset }) disconnect(g_game, { onGameEnd = Market.close }) + disconnect(g_game, { onGameStart = Market.updateCategories }) destroyAmountWindow() marketWindow:destroy() @@ -929,6 +922,28 @@ function Market.reset() end end +function Market.updateCategories() + categoryList:clearOptions() + subCategoryList:clearOptions() + + local categories = {} + for _, c in ipairs(g_things.getMarketCategories()) do + table.insert(categories, getMarketCategoryName(c) or "Unknown") + end + table.sort(categories) + for _, c in ipairs(categories) do + categoryList:addOption(c) + end + + for i = MarketCategory.Ammunition, MarketCategory.WandsRods do + subCategoryList:addOption(getMarketCategoryName(i)) + end + + categoryList:addOption(getMarketCategoryName(255)) -- meta weapons + categoryList:setCurrentOption(getMarketCategoryName(MarketCategory.First)) + subCategoryList:setEnabled(false) +end + function Market.displayMessage(message) if marketWindow:isHidden() then return end @@ -1100,6 +1115,10 @@ function Market.loadMarketItems(category) category = MarketCategory.All end end + + if not marketItems[category] then + return + end if category == MarketCategory.All then -- loop all categories @@ -1107,7 +1126,6 @@ function Market.loadMarketItems(category) for i = 1, #marketItems[category] do local item = marketItems[category][i] if isItemValid(item, category, searchFilter) then - table.insert(currentItems, item) end end diff --git a/modules/game_market/ui/general/marketcombobox.otui b/modules/game_market/ui/general/marketcombobox.otui index 5177073..8009483 100644 --- a/modules/game_market/ui/general/marketcombobox.otui +++ b/modules/game_market/ui/general/marketcombobox.otui @@ -1,4 +1,4 @@ -MarketComboBoxPopupMenuButton < ComboBoxRoundedPopupMenuButton +MarketComboBoxPopupMenuButton < ComboBoxPopupMenuButton height: 18 font: verdana-11px-rounded text-offset: 2 2 @@ -10,9 +10,9 @@ MarketComboBoxPopupMenuSeparator < UIWidget height: 1 phantom: true -MarketComboBoxPopupMenu < ComboBoxRoundedPopupMenu +MarketComboBoxPopupMenu < ComboBoxPopupMenu -MarketComboBox < ComboBoxRounded +MarketComboBox < ComboBox font: verdana-11px-rounded size: 86 20 text-offset: 3 2 diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index 0cea327..9476a99 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -8,13 +8,15 @@ oldZoom = nil oldPos = nil function init() - minimapButton = modules.client_topmenu.addRightGameToggleButton('minimapButton', - tr('Minimap') .. ' (Ctrl+M)', '/images/topbuttons/minimap', toggle) - minimapButton:setOn(true) - minimapWindow = g_ui.loadUI('minimap', modules.game_interface.getRightPanel()) minimapWindow:setContentMinimumHeight(64) + if not minimapWindow.forceOpen then + minimapButton = modules.client_topmenu.addRightGameToggleButton('minimapButton', + tr('Minimap') .. ' (Ctrl+M)', '/images/topbuttons/minimap', toggle) + minimapButton:setOn(true) + end + minimapWidget = minimapWindow:recursiveGetChildById('minimap') local gameRootPanel = modules.game_interface.getRootPanel() @@ -64,10 +66,13 @@ function terminate() g_keyboard.unbindKeyDown('Ctrl+Shift+M') minimapWindow:destroy() - minimapButton:destroy() + if minimapButton then + minimapButton:destroy() + end end function toggle() + if not minimapButton then return end if minimapButton:isOn() then minimapWindow:close() minimapButton:setOn(false) @@ -78,7 +83,9 @@ function toggle() end function onMiniWindowClose() - minimapButton:setOn(false) + if minimapButton then + minimapButton:setOn(false) + end end function preload() @@ -104,12 +111,16 @@ function loadMap(clean) if otmm then local minimapFile = '/minimap.otmm' - if g_resources.fileExists(minimapFile) then + if g_resources.fileExists('/data' .. minimapFile) then + g_minimap.loadOtmm('/data' .. minimapFile) + elseif g_resources.fileExists(minimapFile) then g_minimap.loadOtmm(minimapFile) end else local minimapFile = '/minimap_' .. clientVersion .. '.otcm' - if g_resources.fileExists(minimapFile) then + if g_resources.fileExists('/data' .. minimapFile) then + g_map.loadOtcm('/data' .. minimapFile) + elseif g_resources.fileExists(minimapFile) then g_map.loadOtcm(minimapFile) end end diff --git a/modules/game_minimap/minimap.otui b/modules/game_minimap/minimap.otui index df16b19..61e358c 100644 --- a/modules/game_minimap/minimap.otui +++ b/modules/game_minimap/minimap.otui @@ -1,30 +1,7 @@ -MiniWindow +MinimapWindow id: minimapWindow !text: tr('Minimap') - height: 150 icon: /images/topbuttons/minimap @onClose: modules.game_minimap.onMiniWindowClose() &save: true &autoOpen: 1 - --&forceOpen: true - - Label - text: ? - text-align: center - phantom: false - !tooltip: tr('Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks\nPress Ctrl+Shift+M to view the entire game map') - anchors.top: lockButton.top - anchors.right: lockButton.left - margin-right: 3 - size: 14 14 - - MiniWindowContents - Minimap - id: minimap - anchors.fill: parent - - ResizeBorder - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - enabled: true diff --git a/modules/game_npctrade/npctrade.lua b/modules/game_npctrade/npctrade.lua index f8f5bb4..0562489 100644 --- a/modules/game_npctrade/npctrade.lua +++ b/modules/game_npctrade/npctrade.lua @@ -32,7 +32,7 @@ ignoreCapacity = nil ignoreEquipped = nil showAllItems = nil sellAllButton = nil - +sellAllWithDelayButton = nil playerFreeCapacity = 0 playerMoney = 0 tradeItems = {} @@ -41,6 +41,8 @@ selectedItem = nil cancelNextRelease = nil +sellAllWithDelayEvent = nil + function init() npcWindow = g_ui.displayUI('npctrade') npcWindow:setVisible(false) @@ -65,7 +67,7 @@ function init() ignoreEquipped = npcWindow:recursiveGetChildById('ignoreEquipped') showAllItems = npcWindow:recursiveGetChildById('showAllItems') sellAllButton = npcWindow:recursiveGetChildById('sellAllButton') - + sellAllWithDelayButton = npcWindow:recursiveGetChildById('sellAllWithDelayButton') buyTab = npcWindow:getChildById('buyTab') sellTab = npcWindow:getChildById('sellTab') @@ -95,7 +97,8 @@ end function terminate() initialized = false npcWindow:destroy() - + removeEvent(sellAllWithDelayEvent) + disconnect(g_game, { onGameEnd = hide, onOpenNpcTrade = onOpenNpcTrade, onCloseNpcTrade = onCloseNpcTrade, @@ -120,6 +123,8 @@ function show() end function hide() + removeEvent(sellAllWithDelayEvent) + npcWindow:hide() local layout = itemsPanel:getLayout() @@ -171,12 +176,14 @@ function onTradeTypeChange(radioTabs, selected, deselected) ignoreEquipped:setVisible(currentTradeType == SELL) showAllItems:setVisible(currentTradeType == SELL) sellAllButton:setVisible(currentTradeType == SELL) - + sellAllWithDelayButton:setVisible(currentTradeType == SELL) + refreshTradeItems() refreshPlayerGoods() end function onTradeClick() + removeEvent(sellAllWithDelayEvent) if getCurrentTradeType() == BUY then g_game.buyItem(selectedItem.ptr, quantityScroll:getValue(), ignoreCapacity:isChecked(), buyWithBackpack:isChecked()) else @@ -414,7 +421,6 @@ end function onOpenNpcTrade(items) tradeItems[BUY] = {} tradeItems[SELL] = {} - for key,item in pairs(items) do if item[4] > 0 then local newItem = {} @@ -502,6 +508,8 @@ end function checkSellAllTooltip() sellAllButton:setEnabled(true) sellAllButton:removeTooltip() + sellAllWithDelayButton:setEnabled(true) + sellAllWithDelayButton:removeTooltip() local total = 0 local info = '' @@ -527,8 +535,10 @@ function checkSellAllTooltip() if info ~= '' then info = info.."\nTotal: "..total.." gold" sellAllButton:setTooltip(info) + sellAllWithDelayButton:setTooltip(info) else sellAllButton:setEnabled(false) + sellAllWithDelayButton:setEnabled(false) end end @@ -547,14 +557,23 @@ function getMaxAmount() return 100 end -function sellAll() - for itemid,item in pairs(playerItems) do - local item = Item.create(itemid) - local amount = getSellQuantity(item) - while amount > 0 do - local maxAmount = math.min(amount, getMaxAmount()) - g_game.sellItem(item, maxAmount, ignoreEquipped:isChecked()) - amount = amount - maxAmount +function sellAll(delayed) + removeEvent(sellAllWithDelayEvent) + local queue = {} + for _,entry in ipairs(tradeItems[SELL]) do + local sellQuantity = getSellQuantity(entry.ptr) + while sellQuantity > 0 do + local maxAmount = math.min(sellQuantity, getMaxAmount()) + if delayed then + g_game.sellItem(entry.ptr, maxAmount, ignoreEquipped:isChecked()) + sellAllWithDelayEvent = scheduleEvent(function() sellAll(true) end, 1100) + return + end + table.insert(queue, {entry.ptr, maxAmount, ignoreEquipped:isChecked()}) + sellQuantity = sellQuantity - maxAmount end end + for _, entry in ipairs(queue) do + g_game.sellItem(entry[1], entry[2], entry[3]) + end end diff --git a/modules/game_npctrade/npctrade.otui b/modules/game_npctrade/npctrade.otui index 24e6615..bcac605 100644 --- a/modules/game_npctrade/npctrade.otui +++ b/modules/game_npctrade/npctrade.otui @@ -254,9 +254,19 @@ MainWindow checked: true @onCheckChange: modules.game_npctrade.onShowAllItemsChange() + Button + id: sellAllWithDelayButton + !text: tr('Sell all with delay') + width: 128 + anchors.right: next.left + anchors.bottom: parent.bottom + margin-right: 10 + visible: false + @onClick: modules.game_npctrade.sellAll(true) + Button id: sellAllButton - !text: tr('Sell All') + !text: tr('Sell all') width: 64 anchors.right: next.left anchors.bottom: parent.bottom diff --git a/modules/game_outfit/outfitwindow.otui b/modules/game_outfit/outfitwindow.otui index ae5afc4..116f3ba 100644 --- a/modules/game_outfit/outfitwindow.otui +++ b/modules/game_outfit/outfitwindow.otui @@ -20,6 +20,7 @@ MainWindow padding: 4 4 4 4 size: 96 96 fixed-creature-size: true + raw: true Label id: outfitName @@ -54,6 +55,7 @@ MainWindow padding: 4 4 4 4 size: 96 96 fixed-creature-size: true + raw: true Label id: mountName diff --git a/modules/game_playertrade/playertrade.lua b/modules/game_playertrade/playertrade.lua index a879bfb..4a39327 100644 --- a/modules/game_playertrade/playertrade.lua +++ b/modules/game_playertrade/playertrade.lua @@ -39,16 +39,20 @@ function fillTrade(name, items, counter) local tradeContainer local label + local countLabel if counter then tradeContainer = tradeWindow:recursiveGetChildById('counterTradeContainer') label = tradeWindow:recursiveGetChildById('counterTradeLabel') - + countLabel = tradeWindow:recursiveGetChildById('counterTradeCountLabel') tradeWindow:recursiveGetChildById('acceptButton'):enable() else tradeContainer = tradeWindow:recursiveGetChildById('ownTradeContainer') label = tradeWindow:recursiveGetChildById('ownTradeLabel') + countLabel = tradeWindow:recursiveGetChildById('ownTradeCountLabel') end label:setText(name) + countLabel:setText(tr("Items") .. ": " .. #items) + for index,item in ipairs(items) do local itemWidget = g_ui.createWidget('Item', tradeContainer) diff --git a/modules/game_playertrade/tradewindow.otui b/modules/game_playertrade/tradewindow.otui index 15708d1..da5c1ab 100644 --- a/modules/game_playertrade/tradewindow.otui +++ b/modules/game_playertrade/tradewindow.otui @@ -12,16 +12,43 @@ TradeWindow < MiniWindow margin-left: 4 MiniWindowContents - padding: 4 + padding: 2 + + Label + id: ownTradeLabel + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.horizontalCenter + + Label + id: counterTradeLabel + anchors.top: parent.top + anchors.left: parent.horizontalCenter + anchors.right: parent.right + + Label + id: ownTradeCountLabel + anchors.top: ownTradeLabel.bottom + anchors.left: ownTradeLabel.left + anchors.right: ownTradeLabel.right + font: verdana-9px-bold + text-align: center + + Label + id: counterTradeCountLabel + anchors.top: counterTradeLabel.bottom + anchors.left: counterTradeLabel.left + anchors.right: counterTradeLabel.right + font: verdana-9px-bold + text-align: center ScrollableFlatPanel id: ownTradeContainer - anchors.top: parent.top + anchors.top: ownTradeCountLabel.bottom anchors.bottom: acceptButton.top - anchors.left: parent.left - anchors.right: ownTradeScrollBar.left - margin-top: 16 - margin-bottom: 4 + anchors.left: ownTradeCountLabel.left + anchors.right: ownTradeCountLabel.right + margin-bottom: 3 padding: 2 layout: type: grid @@ -32,12 +59,9 @@ TradeWindow < MiniWindow VerticalScrollBar id: ownTradeScrollBar - anchors.top: parent.top - anchors.bottom: acceptButton.top + anchors.top: ownTradeContainer.top + anchors.bottom: ownTradeContainer.bottom anchors.right: parent.horizontalCenter - margin-top: 16 - margin-bottom: 4 - margin-right: 2 step: 14 pixels-scroll: true $!on: @@ -45,13 +69,11 @@ TradeWindow < MiniWindow ScrollableFlatPanel id: counterTradeContainer - anchors.top: parent.top + anchors.top: counterTradeCountLabel.bottom anchors.bottom: acceptButton.top - anchors.left: parent.horizontalCenter - anchors.right: counterTradeScrollBar.left - margin-top: 16 - margin-bottom: 4 - margin-left: 2 + anchors.left: counterTradeCountLabel.left + anchors.right: counterTradeCountLabel.right + margin-bottom: 3 padding: 2 layout: type: grid @@ -62,31 +84,14 @@ TradeWindow < MiniWindow VerticalScrollBar id: counterTradeScrollBar - anchors.top: parent.top - anchors.bottom: acceptButton.top + anchors.top: counterTradeContainer.top + anchors.bottom: counterTradeContainer.bottom anchors.right: parent.right - margin-top: 16 - margin-bottom: 4 - margin-right: 1 step: 14 pixels-scroll: true $!on: width: 0 - Label - id: ownTradeLabel - anchors.bottom: ownTradeContainer.top - anchors.left: ownTradeContainer.left - anchors.right: parent.horizontalCenter - margin-bottom: 2 - - Label - id: counterTradeLabel - anchors.bottom: counterTradeContainer.top - anchors.left: parent.horizontalCenter - anchors.right: counterTradeScrollBar.right - margin-bottom: 2 - Button !text: tr('Accept') id: acceptButton diff --git a/modules/game_prey/prey.lua b/modules/game_prey/prey.lua index 1e25a2f..762a6d9 100644 --- a/modules/game_prey/prey.lua +++ b/modules/game_prey/prey.lua @@ -129,7 +129,7 @@ function show() preyWindow:show() preyWindow:raise() preyWindow:focus() - g_game.preyRequest() -- update preys + --g_game.preyRequest() -- update preys, it's for tibia 12 end function toggle() @@ -201,7 +201,18 @@ function onPreyInactive(slot, timeUntilFreeReroll) prey.bonuses:hide() prey.button:hide() prey.bottomLabel:hide() - prey.bottomButton:hide() + + prey.bottomLabel:setText(tr("Free list reroll")..": \n" .. timeleftTranslation(timeUntilFreeReroll * 60)) + prey.bottomLabel:show() + if timeUntilFreeReroll > 0 then + prey.bottomButton:setText(tr("Buy list reroll")) + else + prey.bottomButton:setText(tr("Free list reroll")) + end + prey.bottomButton:show() + prey.bottomButton.onClick = function() + g_game.preyAction(slot, PREY_ACTION_LISTREROLL, 0) + end end function onPreyActive(slot, currentHolderName, currentHolderOutfit, bonusType, bonusValue, bonusGrade, timeLeft, timeUntilFreeReroll) diff --git a/modules/game_questlog/questlog.lua b/modules/game_questlog/questlog.lua index a7b1c8b..8b8973d 100644 --- a/modules/game_questlog/questlog.lua +++ b/modules/game_questlog/questlog.lua @@ -5,7 +5,7 @@ function init() g_ui.importStyle('questlogwindow') g_ui.importStyle('questlinewindow') - questLogButton = modules.client_topmenu.addLeftGameButton('questLogButton', tr('Quest Log'), '/images/topbuttons/questlog', function() g_game.requestQuestLog() end) + questLogButton = modules.client_topmenu.addLeftGameButton('questLogButton', tr('Quest Log'), '/images/topbuttons/questlog', function() g_game.requestQuestLog() end, false, 8) connect(g_game, { onQuestLog = onGameQuestLog, onQuestLine = onGameQuestLine, diff --git a/modules/game_shop/shop.lua b/modules/game_shop/shop.lua index 5ace658..5d1b8fc 100644 --- a/modules/game_shop/shop.lua +++ b/modules/game_shop/shop.lua @@ -122,7 +122,7 @@ function createShop() if shop then return end shop = g_ui.displayUI('shop') shop:hide() - shopButton = modules.client_topmenu.addRightGameToggleButton('shopButton', tr('Shop'), '/images/topbuttons/shop', toggle) + shopButton = modules.client_topmenu.addRightGameToggleButton('shopButton', tr('Shop'), '/images/topbuttons/shop', toggle, false, 8) connect(shop.categories, { onChildFocusChange = changeCategory }) end diff --git a/modules/game_shop/shop.otui b/modules/game_shop/shop.otui index b6349f7..9445af0 100644 --- a/modules/game_shop/shop.otui +++ b/modules/game_shop/shop.otui @@ -39,6 +39,7 @@ ShopCategoryCreature < ShopCategory margin-bottom: 2 margin-left: 2 size: 32 32 + raw: true ShopCategoryImage < ShopCategory Label @@ -116,7 +117,8 @@ ShopOfferCreature < ShopOffer margin-top: 4 margin-bottom: 4 margin-left: 2 - size: 64 64 + size: 48 48 + raw: true ShopOfferImage < ShopOffer Label diff --git a/modules/game_skills/skills.lua b/modules/game_skills/skills.lua index 3c54cc0..c68b53b 100644 --- a/modules/game_skills/skills.lua +++ b/modules/game_skills/skills.lua @@ -25,7 +25,7 @@ function init() onGameEnd = offline }) - skillsButton = modules.client_topmenu.addRightGameToggleButton('skillsButton', tr('Skills'), '/images/topbuttons/skills', toggle) + skillsButton = modules.client_topmenu.addRightGameToggleButton('skillsButton', tr('Skills'), '/images/topbuttons/skills', toggle, false, 1) skillsButton:setOn(true) skillsWindow = g_ui.loadUI('skills', modules.game_interface.getRightPanel()) diff --git a/modules/game_spelllist/spelllist.lua b/modules/game_spelllist/spelllist.lua index 1db1ca3..367f675 100644 --- a/modules/game_spelllist/spelllist.lua +++ b/modules/game_spelllist/spelllist.lua @@ -101,7 +101,7 @@ function init() spelllistWindow = g_ui.displayUI('spelllist', modules.game_interface.getRightPanel()) spelllistWindow:hide() - spelllistButton = modules.client_topmenu.addRightGameToggleButton('spelllistButton', tr('Spell List'), '/images/topbuttons/spelllist', toggle) + spelllistButton = modules.client_topmenu.addRightGameToggleButton('spelllistButton', tr('Spell List'), '/images/topbuttons/spelllist', toggle, false, 4) spelllistButton:setOn(false) nameValueLabel = spelllistWindow:getChildById('labelNameValue') diff --git a/modules/game_stats/stats.lua b/modules/game_stats/stats.lua new file mode 100644 index 0000000..df5912c --- /dev/null +++ b/modules/game_stats/stats.lua @@ -0,0 +1,58 @@ +ui = nil +updateEvent = nil + +function init() + ui = g_ui.loadUI('stats', modules.game_interface.getMapPanel()) + + if not modules.client_options.getOption("showPing") then + ui.fps:hide() + end + if not modules.client_options.getOption("showFps") then + ui.ping:hide() + end + + updateEvent = scheduleEvent(update, 200) +end + +function terminate() + removeEvent(updateEvent) +end + +function update() + updateEvent = scheduleEvent(update, 500) + if ui:isHidden() then return end + + text = 'FPS: ' .. g_app.getFps() + ui.fps:setText(text) + + local ping = g_game.getPing() + if g_proxy and g_proxy.getPing() > 0 then + ping = g_proxy.getPing() + end + + local text = 'Ping: ' + local color + if ping < 0 then + text = text .. "??" + color = 'yellow' + else + text = text .. ping .. ' ms' + if ping >= 500 then + color = 'red' + elseif ping >= 250 then + color = 'yellow' + else + color = 'green' + end + end + ui.ping:setText(text) + ui.ping:setColor(color) +end + +function show() + ui:setVisible(true) +end + +function hide() + ui:setVisible(false) +end \ No newline at end of file diff --git a/modules/game_stats/stats.otmod b/modules/game_stats/stats.otmod new file mode 100644 index 0000000..fc6a6c8 --- /dev/null +++ b/modules/game_stats/stats.otmod @@ -0,0 +1,9 @@ +Module + name: game_stats + description: Display ping and fps + author: otclient.ovh + website: http://otclient.ovh + sandboxed: true + scripts: [ stats ] + @onLoad: init() + @onUnload: terminate() diff --git a/modules/game_stats/stats.otui b/modules/game_stats/stats.otui new file mode 100644 index 0000000..33fcfb4 --- /dev/null +++ b/modules/game_stats/stats.otui @@ -0,0 +1,17 @@ +UIWidget + id: game_stats + anchors.top: parent.top + anchors.left: parent.left + margin-left: 3 + size: 100 100 + visible: false + layout: + type: verticalBox + + Label + id: fps + font: verdana-11px-rounded + + Label + id: ping + font: verdana-11px-rounded diff --git a/modules/game_textwindow/textwindow.lua b/modules/game_textwindow/textwindow.lua index 696157b..e4e4040 100644 --- a/modules/game_textwindow/textwindow.lua +++ b/modules/game_textwindow/textwindow.lua @@ -1,4 +1,4 @@ -local windows = {} +windows = {} function init() g_ui.importStyle('textwindow') diff --git a/modules/game_things/things.lua b/modules/game_things/things.lua index a56aa86..4145971 100644 --- a/modules/game_things/things.lua +++ b/modules/game_things/things.lua @@ -15,11 +15,11 @@ function load() local datPath, sprPath if things["data"] ~= nil and things["sprites"] ~= nil then - datPath = '/data/things/' .. things["data"] + datPath = '/things/' .. things["data"] if G.hdSprites and things["sprites_hd"] then - sprPath = '/data/things/' .. things["sprites_hd"] + sprPath = '/things/' .. things["sprites_hd"] else - sprPath = '/data/things/' .. things["sprites"] + sprPath = '/things/' .. things["sprites"] end else if filename then diff --git a/modules/game_viplist/viplist.lua b/modules/game_viplist/viplist.lua index 8e830f7..195664c 100644 --- a/modules/game_viplist/viplist.lua +++ b/modules/game_viplist/viplist.lua @@ -13,7 +13,7 @@ function init() g_keyboard.bindKeyDown('Ctrl+P', toggle) - vipButton = modules.client_topmenu.addRightGameToggleButton('vipListButton', tr('VIP List') .. ' (Ctrl+P)', '/images/topbuttons/viplist', toggle) + vipButton = modules.client_topmenu.addRightGameToggleButton('vipListButton', tr('VIP List') .. ' (Ctrl+P)', '/images/topbuttons/viplist', toggle, false, 3) vipButton:setOn(true) vipWindow = g_ui.loadUI('viplist', modules.game_interface.getRightPanel()) diff --git a/modules/gamelib/const.lua b/modules/gamelib/const.lua index 197cfbd..d0c25e8 100644 --- a/modules/gamelib/const.lua +++ b/modules/gamelib/const.lua @@ -158,6 +158,7 @@ GameIngameStoreServiceType = 75 GameAdditionalSkills = 76 GameDistanceEffectU16 = 77 GamePrey = 78 +GameDoubleMagicLevel = 79 GameExtendedOpcode = 80 GameMinimapLimitedToSingleFloor = 81 diff --git a/modules/gamelib/market.lua b/modules/gamelib/market.lua index 6c816f6..e88e5f8 100644 --- a/modules/gamelib/market.lua +++ b/modules/gamelib/market.lua @@ -46,11 +46,19 @@ MarketCategory = { WandsRods = 21, PremiumScrolls = 22, TibiaCoins = 23, + CreatureProducs = 24, + Unknown1 = 25, + Unknown2 = 26, + StashRetrieve = 27, + Unknown3 = 28, + Unknown4 = 29, + Gold = 30, + Unassigned = 31, MetaWeapons = 255 } MarketCategory.First = MarketCategory.Armors -MarketCategory.Last = MarketCategory.TibiaCoins +MarketCategory.Last = MarketCategory.Unassigned MarketCategoryWeapons = { [MarketCategory.Ammunition] = { slots = {255} }, @@ -86,6 +94,14 @@ MarketCategoryStrings = { [21] = 'Wands and Rods', [22] = 'Premium Scrolls', [23] = 'Tibia Coins', + [24] = 'Creature Products', + [25] = 'Unknown 1', + [26] = 'Unknown 2', + [27] = 'Stash Retrieve', + [28] = 'Unknown 3', + [29] = 'Unknown 4', + [30] = 'Gold', + [31] = 'Unassigned', [255] = 'Weapons' } diff --git a/otclient_dx.exe b/otclient_dx.exe index 7a2733f..c0f1ca0 100644 Binary files a/otclient_dx.exe and b/otclient_dx.exe differ diff --git a/otclient_gl.exe b/otclient_gl.exe index 1bf42d6..2154196 100644 Binary files a/otclient_gl.exe and b/otclient_gl.exe differ diff --git a/otclient_linux b/otclient_linux index 15cb0ac..90b8c68 100644 Binary files a/otclient_linux and b/otclient_linux differ diff --git a/pdb/otclient_dx.zip b/pdb/otclient_dx.zip deleted file mode 100644 index a29c36a..0000000 Binary files a/pdb/otclient_dx.zip and /dev/null differ diff --git a/pdb/otclient_gl.zip b/pdb/pdb.7z similarity index 63% rename from pdb/otclient_gl.zip rename to pdb/pdb.7z index fed239a..5766dfb 100644 Binary files a/pdb/otclient_gl.zip and b/pdb/pdb.7z differ