define(function (require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var Client = require('Core/Client'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./CardIllustration.html'); var cssText = require('text!./CardIllustration.css'); /** * Create Component */ var CardIllustration = new UIComponent('CardIllustration', htmlText, cssText); /** * Initialize events */ CardIllustration.init = function init() { this.ui.find('.close').click(this.remove.bind(this)); this.draggable(); }; /** * Show image * * @param {object} item */ CardIllustration.setCard = function setCard(item) { this.ui.find('.titlebar .text').text(item.identifiedDisplayName); this.ui.find('.content').css('backgroundImage', 'none'); Client.loadFile(DB.INTERFACE_PATH + 'cardbmp/' + item.illustResourcesName + '.bmp', function (data) { this.ui.find('.content').css('backgroundImage', 'url(' + data + ')'); }.bind(this)); }; /** * Create component and export it */ return UIManager.addComponent(CardIllustration); });
define(function(require) { "use strict"; /** * Dependencies */ var jQuery = require('Utils/jquery'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./Loading.html'); var cssText = require('text!./Loading.css'); var Context = require('Core/Context'); /** * Create Intro component */ var Loading = new UIComponent( 'Loading', htmlText, cssText ); /** * Initialize */ Loading.init = function Init() { }; /** * Appended */ Loading.onAppend = function OnAppend() { this.ui.find('.overlay.loading').show().animate({opacity:1}, 200); }; /** * Stored component and return it */ return UIManager.addComponent(Loading); });
define(function (require) { 'use strict'; /** * Dependencies */ var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./WinPopup.html'); var cssText = require('text!./WinPopup.css'); /** * Create Component */ var WinPopup = new UIComponent('WinPopup', htmlText, cssText); /** * Initialize popup */ WinPopup.init = function init() { this.ui.css({ top: (Renderer.height - 120) / 1.5 - 120, left: (Renderer.width - 280) / 2.0, zIndex: 100 }); }; /** * Create component based on view file and export it */ return UIManager.addComponent(WinPopup); });
define(function(require) { "use strict"; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Renderer = require('Renderer/Renderer'); var KEYS = require('Controls/KeyEventHandler'); var Client = require('Core/Client'); var Camera = require('Renderer/Camera'); // TODO: used to get player attached - changed it var PACKET = require('Network/PacketStructure'); var Network = require('Network/NetworkManager'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./ChatBox.html'); var cssText = require('text!./ChatBox.css'); var ProcessCommand = require('Controls/ProcessCommand'); /** * Constants */ var MAX_MSG = 50; var MAX_HISTORY = 50; /** * Create Basic Info component */ var ChatBox = new UIComponent( 'ChatBox', htmlText, cssText ); /** * Constants */ ChatBox.TYPE = { SELF: 1 << 0, PUBLIC: 1 << 1, PRIVATE: 1 << 2, PARTY: 1 << 3, GUILD: 1 << 4, ANNOUNCE: 1 << 5, ERROR: 1 << 6, INFO: 1 << 7, BLUE: 1 << 8, // TODO: find a better name }; /** * Initialize UI */ ChatBox.init = function Init() { this.history = []; this.historyIndex = 0; this.ui.css('top', (Renderer.height - ( this.ui.find('.content').height() + 53 )) + 'px'); this.draggable( this.ui.find('.input') ); // Setting chatbox scrollbar Client.loadFiles([DB.INTERFACE_PATH + "basic_interface/dialscr_down.bmp", DB.INTERFACE_PATH + "basic_interface/dialscr_up.bmp"], function( down, up ){ jQuery("style:first").append([ "#chatbox .content::-webkit-scrollbar { width: 10px; height: 10px;}", "#chatbox .content::-webkit-scrollbar-button:vertical:start:increment,", "#chatbox .content::-webkit-scrollbar-button:vertical:end:decrement { display: none;}", "#chatbox .content::-webkit-scrollbar-corner:vertical { display:none;}", "#chatbox .content::-webkit-scrollbar-resizer:vertical { display:none;}", "#chatbox .content::-webkit-scrollbar-button:start:decrement,", "#chatbox .content::-webkit-scrollbar-button:end:increment { display: block; border:none;}", "#chatbox .content::-webkit-scrollbar-button:vertical:increment { background: url('"+ down +"') no-repeat; height:10px;}", "#chatbox .content::-webkit-scrollbar-button:vertical:decrement { background: url('"+ up +"') no-repeat; height:10px;}", "#chatbox .content::-webkit-scrollbar-track-piece:vertical { background:black; border:none;}", "#chatbox .content::-webkit-scrollbar-thumb:vertical { background:grey; -webkit-border-image:none; border-color:transparent;border-width: 0px 0; }" ].join("\n")); }); // Input selection this.ui.find('.input input').mousedown(function( event ){ this.select(); event.stopImmediatePropagation(); return false; }); this.ui.find('.input .message').blur(function(){ var _this = this; setTimeout(function(){ if( document.activeElement.tagName !== 'INPUT' ) { _this.focus(); } }, 1); }); // Button change name this.ui.find('.header input').dblclick(function(){ this.type = 'text'; this.select(); }).blur(function(){ this.type = 'button'; }); // Change size this.ui.find('.input .size').mousedown(function( event ){ ChatBox.updateHeight(true); event.stopImmediatePropagation(); return false; }); // Scroll feature should block at each line this.ui.find('.content').on('scroll', function(){ this.scrollTop = Math.floor(this.scrollTop/14) * 14; }); }; /** * Clean up the box */ ChatBox.clean = function Clean() { this.ui.find('.content').empty(); this.ui.find('.input .message').val(''); this.ui.find('.input .username').val(''); }; /** * Once append to HTML */ ChatBox.onAppend = function OnAppend() { // Focus the input this.ui.find('.input .message').focus(); // Write memorized texts for( var i = 0, count = this.storage.length; i < count; ++i ) { this.addText.apply(this, this.storage[i]); } this.storage.length = 0; var content = this.ui.find('.content')[0]; content.scrollTop = content.scrollHeight; }; /** * Stop custom scroll */ ChatBox.onRemove = function OnRemove() { this.ui.find('.content').off('scroll'); }; /** * Key Event Handler * * @param {object} event - KeyEventHandler * @return {boolean} */ ChatBox.onKeyDown = function OnKeyDown( event ) { var is_focus = document.activeElement === this.ui.find('.input .message')[0]; switch( event.which ) { default: return true; case KEYS.TAB: if( document.activeElement === this.ui.find('.input .message')[0] ) { this.ui.find('.input .username').select().focus(); } else if( document.activeElement === this.ui.find('.input .username')[0] ) { this.ui.find('.input .message').select().focus(); } else { return true; } break; case KEYS.UP: if( !is_focus || jQuery('#NpcMenu').length ) { return true; } if( this.historyIndex > 0 ) { this.historyIndex--; } this.ui.find('.input .message').val( this.history[ this.historyIndex ] ).select(); break; case KEYS.DOWN: if( !is_focus || jQuery('#NpcMenu').length ) { return true; } if( this.historyIndex < this.history.length ) { this.historyIndex++; } this.ui.find('.input .message').val( this.history[ this.historyIndex ] ).select(); break; case KEYS.F10: this.updateHeight(false); break; case KEYS.ENTER: if( document.activeElement.tagName === 'INPUT' && !is_focus ) { return true; } if( jQuery('#NpcMenu').length || jQuery('#NpcBox').length ) { return true; } this.ui.find('.input .message').focus(); this.submit(); break; } event.stopImmediatePropagation(); return false; }; /** * Process ChatBox message */ ChatBox.submit = function Submit() { var $user = this.ui.find('.input .username'); var $text = this.ui.find('.input .message'); var user = $user.val(); var text = $text.val(); // block. if( !text.length ) { return; } if( user.length && text[0] !== '/' ) { this.PrivateMessageStorage.nick = user; this.PrivateMessageStorage.msg = text; } // Save in history if( this.history[this.historyIndex] !== text ) { if( this.history.length >= MAX_HISTORY ) { this.history.shift(); } this.history.push(text); } this.historyIndex = this.history.length; $text.val(''); if( text[0] === '/' ) { ProcessCommand.call( ChatBox, text.substr(1) ); return; } this.onRequestTalk( user, text ); }; /** * Storage to cache the private messages */ ChatBox.PrivateMessageStorage = { nick: "", msg: "" }; /** * If server want to display text but UI not loaded yet, store message and process later */ ChatBox.storage = []; /** * Add text to chatbox * * @param {string} text * @param {number} type * @param {string} color */ ChatBox.addText = function addText( text, type, color ) { if( !this.__loaded ) { this.storage.push(arguments); return; } var $content = this.ui.find('.content'); if( !color ) { if( (type & ChatBox.TYPE.PUBLIC) && (type & ChatBox.TYPE.SELF) ) { color = '#00FF00'; } else if( type & ChatBox.TYPE.PRIVATE ) { color = '#FFFF00'; } else if( type & ChatBox.TYPE.ERROR ) { color = '#FF0000'; } else if( type & ChatBox.TYPE.INFO ) { color = '#FFFF63'; } else if( type & ChatBox.TYPE.BLUE ) { color = "#00FFFF"; } else { color = 'white'; } } $content.append( jQuery('<div/>'). css('color', color). text(text) ); // If there is too many line, remove the older one var list = $content.find('div'); if( list.length > MAX_MSG ) { list.find(':first').remove(); } // Always put the scroll at the bottom $content[0].scrollTop = $content[0].scrollHeight; }; /** * @var {number} Chatbox position's index */ ChatBox.heightIndex = 2; /** * Change chatbox's height */ ChatBox.updateHeight = function changeHeight( AlwaysVisible ) { var HeightList = [ 0, 0, 3*14, 6*14, 9*14, 12*14, 15*14 ]; this.heightIndex = (this.heightIndex + 1) % HeightList.length; var $content = this.ui.find('.content'); var height = HeightList[ this.heightIndex ]; var top = parseInt( this.ui.css('top'), 10); this.ui.css('top', top - (height - $content.height()) ); $content.height(height); // Don't remove UI if( this.heightIndex === 0 && AlwaysVisible ) { this.heightIndex++; } switch( this.heightIndex ) { case 0: this.ui.hide(); break; case 1: this.ui.show(); this.ui.find('.header, .body').hide(); this.ui.find('.input').addClass('fix'); break; default: this.ui.find('.input').removeClass('fix'); this.ui.find('.header, .body').show(); break; } $content[0].scrollTop = $content[0].scrollHeight; }; /** * Talk feature * * @param {string} user * @param {string} text */ ChatBox.onRequestTalk = function OnRequestTalk( user, text ) { var pkt; if( user.length ) { pkt = new PACKET.CZ.WHISPER(); pkt.receiver = user; pkt.msg = text; } else if( text[0] === '%' ) { pkt = new PACKET.CZ.REQUEST_CHAT_PARTY(); pkt.msg = Camera.target.display.name + ' : ' + text.substr(1); } else if( text[0] === '$' ) { pkt = new PACKET.CZ.GUILD_CHAT(); pkt.msg = Camera.target.display.name + ' : ' + text.substr(1); } else { pkt = new PACKET.CZ.REQUEST_CHAT(); pkt.msg = Camera.target.display.name + ' : ' + text; } Network.sendPacket(pkt); }; /** * Create componentand export it */ return UIManager.addComponent(ChatBox); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var Renderer = require('Renderer/Renderer'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./WinList.html'); var cssText = require('text!./WinList.css'); /** * Create WinList namespace */ var WinList = new UIComponent( 'WinList', htmlText, cssText ); /** * Initialize UI */ WinList.init = function init() { // Show at center. this.ui.css({ top: (Renderer.height - 280)/1.5, left: (Renderer.width - 280)/2 }); this.draggable(); this.ui_list = this.ui.find('.list:first'); this.list = null; this.index = 0; // Click Events this.ui.find('.ok').click( this.selectIndex.bind(this) ); this.ui.find('.cancel').click( this.exit.bind(this) ); }; /** * Add elements to the list * * @param {Array} list object to display */ WinList.setList = function setList( list ) { var i, count; this.list = list; this.ui_list.empty(); for (i = 0, count = list.length; i < count; ++i) { this.ui_list.append( jQuery('<div/>'). addClass('menu_node'). text(list[i]). data('id', i). mousedown(function(){ WinList.setIndex( jQuery(this).data('id') ); }). dblclick( this.selectIndex.bind(this) ) ); } this.setIndex( 0 ); }; /** * Cancel window */ WinList.exit = function exit() { WinList.onExitRequest(); }; /** * Callback to use */ WinList.onExitRequest = function onExitRequest(){}; WinList.onIndexSelected = function onIndexSelected(){}; /** * Change selection * * @param {number} id in list */ WinList.setIndex = function setIndex( id ) { if (id > -1 && id < this.list.length) { this.ui_list.find('div:eq('+ this.index +')').css('backgroundColor', 'transparent'); this.ui_list.find('div:eq('+ id +')').css('backgroundColor', '#cde0ff'); this.index = id; } }; /** * Select a server, callback */ WinList.selectIndex = function selectIndex() { this.onIndexSelected( this.index ); }; /** * Key Management * * @param {object} event */ WinList.onKeyDown = function onKeyDown( event ) { switch (event.which) { default: return; case KEYS.ENTER: this.selectIndex(); break; case KEYS.ESCAPE: this.exit(); break; case KEYS.UP: this.setIndex( this.index - 1 ); break; case KEYS.DOWN: this.setIndex( this.index + 1 ); break; } event.stopImmediatePropagation(); }; /** * Free variables once removed from HTML */ WinList.onRemove = function onRemove() { this.ui_list.empty(); this.list = null; this.index = 0; }; /** * Create component based on view file and export it */ return UIManager.addComponent(WinList); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var SkillInfo = require('DB/Skills/SkillInfo'); var KEYS = require('Controls/KeyEventHandler'); var Mouse = require('Controls/MouseEventHandler'); var jQuery = require('Utils/jquery'); var Renderer = require('Renderer/Renderer'); var Entity = require('Renderer/Entity/Entity'); var EntityManager = require('Renderer/EntityManager'); var Controls = require('Preferences/Controls'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var Cursor = require('UI/CursorManager'); /** * Create Announce component */ var SkillTargetSelection = new UIComponent( 'SkillTargetSelection' ); /** * @var {constant} */ SkillTargetSelection.TYPE = { ENEMY: 1, PLACE: 2, SELF: 4, FRIEND: 16, TRAP: 32, TARGET: 1|2|16|32, PET: 64 }; /** * @var {number} target type (see constants) */ var _target = 0; /** * @var {Skill} skill structure */ var _skill; /** * @var {CanvasElement} container for skill name */ var _skillName; /** * @var {CanvasElement} container for desciption */ var _description; /** * Initialize component */ SkillTargetSelection.init = function init() { _skillName = document.createElement('canvas'); _description = document.createElement('canvas'); _skillName.style.position = 'absolute'; _skillName.style.top = '45px'; _skillName.style.zIndex = 100; _skillName.style.borderRadius = '3px'; _skillName.style.border = '1px solid #555'; _description.style.position = 'absolute'; _description.style.bottom = '60px'; _description.style.zIndex = 100; _description.style.borderRadius = '3px'; _description.style.border = '1px solid #555'; render( DB.getMessage(234), _description); this.ui = jQuery('<div id ="SkillTargetSelection"/>'); // just to not break things this.ui.append(); }; /** * Append to body */ SkillTargetSelection.onAppend = function onAppend() { var events; if (!_skillName.parentNode) { document.body.appendChild(_skillName); } if (!_description.parentNode) { document.body.appendChild(_description); } // Execute onKeyDown BEFORE the one executed by Escape window events = jQuery._data( window, 'events').keydown; events.unshift( events.pop() ); // Execute before *request move* / *request attack* jQuery(window).one('mousedown.targetselection', intersectEntity); events = jQuery._data(window, 'events').mousedown; events.unshift( events.pop() ); }; /** * Possible to exit using ESCAPE */ SkillTargetSelection.onKeyDown = function onKeyDown(event) { if (event.which === KEYS.ESCAPE) { this.remove(); event.stopImmediatePropagation(); return false; } return true; }; /** * Remove from body */ SkillTargetSelection.onRemove = function onRemove() { jQuery(window).off('mousedown.targetselection'); Cursor.blockMagnetism = false; Cursor.freeze = false; Cursor.setType(Cursor.ACTION.DEFAULT); if (_skillName.parentNode) { document.body.removeChild(_skillName); } if (_description.parentNode) { document.body.removeChild(_description); } }; /** * Set informations for the target * * @param {object} skill * @param {number} skill type * @param {string} description name (optional) */ SkillTargetSelection.set = function set( skill, target, description ) { _target = target; _skill = skill; if (!_target) { return; } if (_target & (SkillTargetSelection.TYPE.PLACE|SkillTargetSelection.TYPE.TRAP)) { Cursor.blockMagnetism = true; } // Render skillName var sk = SkillInfo[ skill.SKID ]; render(description || sk.SkillName, _skillName); Cursor.setType( Cursor.ACTION.TARGET); Cursor.freeze = true; }; /** * Render text into the canvas * * @param {string} text to render * @param {CanvasElement} canvas node */ function render(text, canvas) { var fontSize = 12; var ctx = canvas.getContext('2d'); ctx.font = fontSize + 'px Arial'; canvas.width = ctx.measureText(text).width + 7 * 2; canvas.height = 23; ctx.font = fontSize + 'px Arial'; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = 'rgba(0,0,0,0.5)'; ctx.fillRect( 0, 0, canvas.width, canvas.height); ctx.fillStyle = 'black'; ctx.fillText( text, 8, 17); ctx.fillStyle = '#00FF00'; ctx.fillText( text, 7, 16); canvas.style.left = ((Renderer.width - canvas.width) >> 1) + 'px'; } /** * Intersect entity when clicking */ function intersectEntity(event) { SkillTargetSelection.remove(); if (event.which !== 1) { return true; } if (_target & (SkillTargetSelection.TYPE.PLACE|SkillTargetSelection.TYPE.TRAP)) { SkillTargetSelection.onUseSkillToPos(_skill.SKID, _skill.level, Mouse.world.x, Mouse.world.y); event.stopImmediatePropagation(); return false; } var entity = EntityManager.getOverEntity(); var target = 0; if (entity) { switch (entity.objecttype) { case Entity.TYPE_MOB: target = SkillTargetSelection.TYPE.ENEMY | SkillTargetSelection.TYPE.PET; break; case Entity.TYPE_PC: target = SkillTargetSelection.TYPE.FRIEND; break; default: break; } if (target & _target || KEYS.SHIFT || Controls.noshift) { if (_target === SkillTargetSelection.TYPE.PET) { SkillTargetSelection.onPetSelected(entity.GID); } else { SkillTargetSelection.onUseSkillToId(_skill.SKID, _skill.level, entity.GID); } } } event.stopImmediatePropagation(); return false; } /** * Functions to define */ SkillTargetSelection.onUseSkillToId = function onUseSkillToId(/*id, level, GID*/){}; SkillTargetSelection.onUseSkillToPos = function onUseSkillToId(/*id, level, x, y*/){}; /** * Create component and return it */ return UIManager.addComponent(SkillTargetSelection); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var Client = require('Core/Client'); var Events = require('Core/Events'); var Renderer = require('Renderer/Renderer'); var Entity = require('Renderer/Entity/Entity'); var SpriteRenderer = require('Renderer/SpriteRenderer'); /** * Create SlotMachine UI */ var SlotMachine = new UIComponent('SlotMachine'); /** * @var {Sprite,Action} objects */ var _sprite, _action; /** * @var {number} type */ var _type = 0; /** * @var {boolean} result */ var _result = false; /** * @var {CanvasRenderingContext2D} */ var _ctx; /** * @var {Entity} */ var _entity = new Entity(); /** * @var {number} start tick */ var _start = 0; /** * Initialize UI */ SlotMachine.init = function init() { // Initialize UI. this.ui = jQuery('<canvas/>') .attr({ width: 270, height: 260, id: 'SlotMachine' }) .css({ zIndex: 500, position: 'absolute', top: (Renderer.height / 2) - 130, left: (Renderer.width / 2) - 135 }); _ctx = this.ui[0].getContext('2d'); // Loading sprite, start animation Client.loadFiles(['data/sprite/slotmachine.spr', 'data/sprite/slotmachine.act'], function(spr, act) { _sprite = spr; _action = act; _type = 0; _start = Renderer.tick; if (this.ui[0].parentNode) { Renderer.render(rendering); } }.bind(this)); // Don't propagate to map scene this.ui.mousedown(function(event) { if (_type === 0) { SlotMachine.onTry(); event.stopImmediatePropagation(); return false; } }); }; /** * Once append to body */ SlotMachine.onAppend = function onAppend() { _type = 0; _start = Renderer.tick; if (_sprite && _action) { Renderer.render(rendering); } }; /** * Once removed from body */ SlotMachine.onRemove = function onRemove() { Renderer.stop(rendering); }; /** * Set the result * * @param {boolean} result */ SlotMachine.setResult = function setResult(result) { _type = 1; _result = result; _start = Renderer.tick; }; /** * Rendering animation */ var rendering = function renderingClosure() { var position = new Uint16Array([0, 0]); return function rendering() { var i, count, max; var action, animation, anim; switch (_type) { case 0: // waiting action = _action.actions[0]; anim = Math.floor((Renderer.tick - _start) / action.delay * 2); break; case 1: // pending action = _action.actions[1]; max = action.animations.length + (_result ? 7 : 3); anim = Renderer.tick - _start; anim = Math.floor(anim / action.delay); anim = Math.min(anim, max); if (anim === max) { _type = _result ? 2 : 3; _start = Renderer.tick; } break; case 2: // success case 3: // fail action = _action.actions[_type]; max = action.animations.length; anim = Renderer.tick - _start; anim = Math.floor(anim / action.delay); if (anim >= max) { Renderer.stop(rendering); Events.setTimeout(function(){ SlotMachine.remove(); }, 500); } break; } animation = action.animations[anim % action.animations.length]; // Initialize context SpriteRenderer.bind2DContext(_ctx, 140, 165); _ctx.clearRect(0, 0, _ctx.canvas.width, _ctx.canvas.height); // Render layers for (i = 0, count = animation.layers.length; i < count; ++i) { _entity.renderLayer( animation.layers[i], _sprite, _sprite, 1.0, position, false); } }; }(); /** * Functions defined in Engine/MapEngine/Pet.js */ SlotMachine.onTry = function onTry(){}; /** * Export */ return UIManager.addComponent(SlotMachine); });
define(function(require) { "use strict"; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Renderer = require('Renderer/Renderer'); var Mouse = require('Controls/MouseEventHandler'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo') var Equipment = require('UI/Components/Equipment/Equipment'); var htmlText = require('text!./Inventory.html'); var cssText = require('text!./Inventory.css'); /** * Create Component */ var Inventory = new UIComponent( 'Inventory', htmlText, cssText ); /** * Item type constants */ Inventory.ITEM = { HEALING: 0, USABLE: 2, ETC: 3, WEAPON: 4, EQUIP: 5, CARD: 6, PETEGG: 7, PETEQUIP: 8, AMMO: 10, USABLE_SKILL: 11, USABLE_UNK: 18 }; /** * Tab constant */ Inventory.TAB = { USABLE: 0, EQUIP: 1, ETC: 2 }; /** * Store inventory items */ Inventory.list = []; /** * @var {number} tab */ Inventory.tab = Inventory.TAB.USABLE; /** * @var {number} used to remember the window height */ Inventory.realSize = 0; /** * Initialize UI */ Inventory.init = function Init() { // Preferences structure this.preferences = Preferences.get('Inventory', { x: 200, y: 200, width: 7, height: 4, show: false, reduce: false, tab: this.TAB.USABLE }, 1.0); // Bind buttons this.ui.find('.titlebar .mini').click(this.toggleReduction.bind(this)); this.ui.find('.tabs button').mousedown(this.switchTab); this.ui.find('.footer .extend').mousedown( this.extend.bind(this) ); this.ui.find('.titlebar .close').click(function(){ Inventory.ui.hide(); return false; }); var overlay = this.ui.find('.overlay'); this.ui.find('.container .content') // Scroll feature should block at each line .on('scroll', function(){ this.scrollTop = Math.floor( this.scrollTop / 32 ) * 32; }) // TODO: move all this part to GenericItemSkill.js // Title feature .on('mouseover', '.item', function(){ var i, count; var items = Inventory.list; var idx = parseInt( this.className.match(/ (\d+)$/)[1], 10); for( i = 0, count = items.length; i < count ; ++i ) { if( items[i].index === idx ) { // Get back data var item = items[i]; var it = DB.getItemInfo( item.ITID ); var pos = jQuery(this).position(); // Display box overlay.show(); overlay.css({top: pos.top, left:pos.left+35}); overlay.html( ( item.RefiningLevel ? '+' + item.RefiningLevel + ' ' : '') + ( item.IsIdentified ? it.identifiedDisplayName : it.unidentifiedDisplayName ) + ( it.slotCount ? ' [' + it.slotCount + ']' : '') + ' ' + ( item.count || 1 ) + ' ea' ); if( item.IsIdentified ) { overlay.removeClass('grey'); } else { overlay.addClass('grey'); } break; } } }) // Stop title feature .on('mouseout', '.item', function(){ overlay.hide(); }) // Item drag drop feature .on('dragstart', '.item', function(event){ // Set image to the drag drop element var img = new Image(); img.src = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1]; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var list, i, count; for( i = 0, list = Inventory.list, count = list.length; i < count; ++i ) { if( list[i].index === index ) { event.originalEvent.dataTransfer.setData("Text", JSON.stringify( window._OBJ_DRAG_ = { type: "item", data: list[i] }) ); break; } } // Stop component to be draggable jQuery(window).trigger('mouseup'); overlay.hide(); }) // Clean up .on('dragend', '.item', function(event){ delete window._OBJ_DRAG_; }) // Right click on item .on('contextmenu', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var list; var i, count; for( i = 0, list = Inventory.list, count = list.length; i < count; ++i ) { if( list[i].index === index ) { // Don't add the same UI twice, remove it if( ItemInfo.uid === list[i].ITID ) { ItemInfo.remove(); break; } // Add ui to window ItemInfo.append(); ItemInfo.uid = list[i].ITID; ItemInfo.setItem( list[i] ); break; } } event.stopImmediatePropagation(); return false; }) // Equip/Use item .on('dblclick', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var list; var i, count; for( i = 0, list = Inventory.list, count = list.length; i < count; ++i ) { if( list[i].index === index ) { switch( list[i].type ) { // Usable item case Inventory.ITEM.HEALING: case Inventory.ITEM.USABLE: //case Inventory.ITEM.USABLE_SKILL: case Inventory.ITEM.USABLE_UNK: Inventory.onUseItem( index ); overlay.hide(); break; // Equip item case Inventory.ITEM.WEAPON: case Inventory.ITEM.EQUIP: case Inventory.ITEM.PETEQUIP: if( list[i].IsIdentified && !list[i].IsDamaged ) { Inventory.onEquipItem( index, list[i].location ); overlay.hide(); } break; } break; } } event.stopImmediatePropagation(); return false; }); this.draggable(); }; /** * Apply preferences once append to body */ Inventory.onAppend = function OnAppend() { // Apply preferences if( !this.preferences.show ) { this.ui.hide(); } this.tab = this.preferences.tab; Client.loadFile("basic_interface/tab_itm_0"+ (this.tab+1) +".bmp", function(data){ Inventory.ui.find('.tabs').css('backgroundImage', 'url("' + data + '")'); }); this.resize( this.preferences.width, this.preferences.height ); this.ui.css({ top: Math.min( Math.max( 0, this.preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, this.preferences.x), Renderer.width - this.ui.width()) }); Inventory.realSize = this.preferences.reduce ? 0 : this.ui.height(); this.ui.find('.titlebar .mini').trigger('mousedown'); }; /** * Remove Inventory from window (and so clean up items) */ Inventory.onRemove = function OnRemove() { this.ui.find('.container .content').empty(); this.list.length = 0; jQuery('.ItemInfo').remove(); // Save preferences this.preferences.show = this.ui.is(':visible'); this.preferences.reduce = !!this.realSize; this.preferences.tab = this.tab; this.preferences.y = parseInt(this.ui.css('top'), 10); this.preferences.x = parseInt(this.ui.css('left'), 10); this.preferences.width = Math.floor( (this.ui.width() - (23 + 16 + 16 - 30)) / 32 ); this.preferences.height = Math.floor( (this.ui.height() - (31 + 19 - 30 )) / 32 ); this.preferences.save(); }; /** * Key Listener * * @param {object} event * @return {boolean} */ Inventory.onKeyDown = function OnKeyDown( event ) { if( KEYS.ALT && event.which === KEYS.E ) { this.ui.toggle(); event.stopImmediatePropagation(); return false; } return true; }; /** * Extend inventory window size */ Inventory.extend = function Extend( event ) { var ui = this.ui; var content = ui.find('.container .content'); var hide = ui.find('.hide'); var top = ui.position().top; var left = ui.position().left; var lastWidth = 0; var lastHeight = 0; var _Interval; function Resizing() { var extraX = 23 + 16 + 16 - 30; var extraY = 31 + 19 - 30; var w = Math.floor( (Mouse.screen.x - left - extraX) / 32 ); var h = Math.floor( (Mouse.screen.y - top - extraY) / 32 ); // Maximum and minimum window size w = Math.min( Math.max(w, 6), 9); h = Math.min( Math.max(h, 2), 6); if( w === lastWidth && h === lastHeight ) { return; } Inventory.resize( w, h ); lastWidth = w; lastHeight = h; //Show or hide scrollbar if( content.height() === content[0].scrollHeight ) { hide.show(); } else { hide.hide(); } } // Start resizing _Interval = setInterval( Resizing, 30); // Stop resizing jQuery(window).one('mouseup', function(event){ // Only on left click if ( event.which === 1 ) { clearInterval(_Interval); } }); event.stopImmediatePropagation(); return false; }; /** * Extend inventory window size */ Inventory.resize = function Resize( width, height ) { width = Math.min( Math.max(width, 6), 9); height = Math.min( Math.max(height, 2), 6); this.ui.find('.container .content').css({ width: width * 32 + 13, // 13 = scrollbar height: height * 32 }); this.ui.css({ width: 23 + 16 + 16 + width * 32, height: 31 + 19 + height * 32 }); }; /** * Modify tab, filter display entries */ Inventory.switchTab = function SwitchTab( event ) { var idx = jQuery(this).index(); Inventory.tab = idx; Client.loadFile("basic_interface/tab_itm_0"+ (idx+1) +".bmp", function(data){ Inventory.ui.find('.tabs').css('backgroundImage', 'url("' + data + '")'); Inventory.filter(idx); }); event.stopImmediatePropagation(); return false; }; /** * Hide/show inventory's content */ Inventory.toggleReduction = function ToggleReduction( event ) { // TODO: fix this part if( this.realSize ) { this.ui.find('.panel').show(); this.ui.height(this.realSize); this.realSize = 0; } else { this.realSize = this.ui.height(); this.ui.height(17); this.ui.find('.panel').hide(); } event.stopImmediatePropagation(); return false; }; /** * Add items to the list */ Inventory.setItems = function SetItems(items) { var i, count; for( i = 0, count = items.length; i < count ; ++i ) { if( this.addItemSub( items[i] ) ) { this.list.push( items[i] ); } } }; /** * Insert Item to inventory * * @param {object} Item */ Inventory.addItem = function AddItem( item ) { var i, size; for( i = 0, size = this.list.length; i < size; ++i ) { if( this.list[i].index === item.index ) { this.list[i].count += item.count; this.ui.find('.item.'+ item.index + ' .count').text( this.list[i].count ) return; } } if( this.addItemSub(item) ) { this.list.push(item); } }; /** * Add item to inventory * * @param {object} Item */ Inventory.addItemSub = function AddItemSub( item ) { var tab; var ui = this.ui; switch( item.type ) { case Inventory.ITEM.HEALING: case Inventory.ITEM.USABLE: case Inventory.ITEM.USABLE_SKILL: case Inventory.ITEM.USABLE_UNK: tab = Inventory.TAB.USABLE; break; case Inventory.ITEM.WEAPON: case Inventory.ITEM.EQUIP: case Inventory.ITEM.PETEGG: case Inventory.ITEM.PETEQUIP: tab = Inventory.TAB.EQUIP; break; default: case Inventory.ITEM.ETC: case Inventory.ITEM.CARD: case Inventory.ITEM.AMMO: tab = Inventory.TAB.ETC; break; } // Equip item if( item.WearState ) { Equipment.equip(item); return false; } if( tab === this.tab ) { var it = DB.getItemInfo( item.ITID ); Client.loadFile( DB.INTERFACE_PATH + 'item/' + ( item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName ) + '.bmp', function(data){ var content = ui.find('.container .content'); content.append( '<div class="item '+ item.index +'" draggable="true">' + '<button style="background-image:url(' + data + ')"></button>' + '<div class="amount">'+ (item.count ? '<span class="count">' + item.count + '</span>' + ' ' : '') + '</div>' + '</div>' ); if( content.height() < content[0].scrollHeight ) { ui.find('.hide').hide(); } }); } return true; }; /** * Remove item from inventory * * @param {number} index in inventory */ Inventory.removeItem = function RemoveItem( index, count ) { var i, size; for( i = 0, size = this.list.length; i < size; ++i ) { if( this.list[i].index === index ) { if( this.list[i].count ) { this.list[i].count -= count; if( this.list[i].count > 0 ) { this.ui.find('.item.'+index + ' .count').text( this.list[i].count ) return this.list[i]; } } var item = this.list[i]; this.list.splice( i, 1 ); this.ui.find('.item.'+index).remove(); var content = this.ui.find('.container .content'); if( content.height() === content[0].scrollHeight ) { this.ui.find('.hide').show(); } return item; } } return null; }; /** * Update tabulation */ Inventory.filter = function Filter(tab) { this.ui.find('.container .content').empty(); var i, count; for( i = 0, count = this.list.length; i < count; ++i ) { this.addItemSub( this.list[i] ); } }; /** * Abstract function to define */ Inventory.onUseItem = function OnUseItem( index ){}; Inventory.onEquipItem = function OnEquipItem( index, location ){}; /** * Create component and export it */ return UIManager.addComponent(Inventory); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var Client = require('Core/Client'); var Events = require('Core/Events'); var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./ItemObtain.html'); var cssText = require('text!./ItemObtain.css'); /** * Create component */ var ItemObtain = new UIComponent( 'ItemObtain', htmlText, cssText ); /** * @var {TimeOut} timer */ var _timer = 0; /** * @var {number} time to display */ var _life = 5 * 1000; /** * Initialize component */ ItemObtain.init = function init() { this.ui.css('zIndex', 45); // Between Interface and Game Announce }; /** * Once append to body */ ItemObtain.onAppend = function onAppend() { this.ui.css('left', ( Renderer.width - (this.ui.width()) ) >> 1 ); }; /** * Once removed from HTML, clean timer */ ItemObtain.onRemove = function onRemove() { if (_timer) { Events.clearTimeout(_timer); _timer = 0; } }; /** * Timer end, cleaning box */ ItemObtain.timeEnd = function timeEnd() { this.remove(); }; /** * Add item informations * * @param {number} itemid * @param {boolean} identify * @param {number} amount */ ItemObtain.set = function set( itemid, identify, amount ) { var it = DB.getItemInfo( itemid ); var display = identify ? it.identifiedDisplayName : it.unidentifiedDisplayName; var resource = identify ? it.identifiedResourceName : it.unidentifiedResourceName; this.ui.find('.content').html( '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" class="'+ itemid +'" width="24" height="24" /> ' + display + ' ' + DB.getMessage(696).replace('%d', amount) ); this.ui.css('left', ( Renderer.width - (this.ui.width()) ) >> 1 ); Client.loadFile( DB.INTERFACE_PATH + 'item/' + resource + '.bmp', (function(url){ this.ui.find('img.' + itemid).attr('src', url); }).bind(this)); // Start tomer if (_timer) { Events.clearTimeout(_timer); } _timer = Events.setTimeout( this.timeEnd.bind(this), _life ); }; /** * Create component and return it */ return UIManager.addComponent(ItemObtain); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var DB = require('DB/DBManager'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Session = require('Engine/SessionStorage'); var Mouse = require('Controls/MouseEventHandler'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var InputBox = require('UI/Components/InputBox/InputBox'); var ChatBox = require('UI/Components/ChatBox/ChatBox'); var Inventory = require('UI/Components/Inventory/Inventory'); var htmlText = require('text!./NpcStore.html'); var cssText = require('text!./NpcStore.css'); /** * Create NPC Menu component */ var NpcStore = new UIComponent( 'NpcStore', htmlText, cssText ); /** * @var {enum} Store type */ NpcStore.Type = { BUY: 0, SELL: 1 }; /** * @var {Preferences} */ var _preferences = Preferences.get('NpcStore', { inputWindow: { x: 100, y: 100, height: 7 }, outputWindow: { x: 100 + 280 + 10, y: 100 + (7*32) - (2*32), height: 2 }, select_all: false }, 1.0); /** * @var {Array} item list */ var _input = []; /** * @var {Array} output list */ var _output = []; /** * @var {number} type (buy/sell) */ var _type; /** * Initialize component */ NpcStore.init = function init() { var ui = this.ui; var InputWindow = ui.find('.InputWindow'); var OutputWindow = ui.find('.OutputWindow'); // Client do not send packet ui.find('.btn.cancel').click(this.remove.bind(this)); ui.find('.btn.buy, .btn.sell').click(this.submit.bind(this)); ui.find('.selectall').mousedown(function(){ _preferences.select_all = !_preferences.select_all; Client.loadFile(DB.INTERFACE_PATH + 'checkbox_' + (_preferences.select_all ? 1 : 0) + '.bmp', function(data){ this.style.backgroundImage = 'url('+ data +')'; }.bind(this)); }); // Resize InputWindow.find('.resize').mousedown(function(event){ onResize(InputWindow); event.stopImmediatePropagation(); return false; }); OutputWindow.find('.resize').mousedown(function(event){ onResize(OutputWindow); event.stopImmediatePropagation(); return false; }); ui.find('.content') .on('mousewheel DOMMouseScroll', onScroll) .on('contextmenu', '.icon', onItemInfo) .on('dblclick', '.item', onItemSelected) .on('mousedown', '.item', onItemFocus) .on('dragstart', '.item', onDragStart) .on('dragend', '.item', function(){ delete window._OBJ_DRAG_; }); // Drop items ui.find('.InputWindow, .OutputWindow') .on('drop', onDrop) .on('dragover', function(event) { event.stopImmediatePropagation(); return false; }); // Hacky drag drop this.draggable.call({ui: InputWindow }); this.draggable.call({ui: OutputWindow }); }; /** * Player should not be able to move when the store is opened */ NpcStore.onAppend = function onAppend() { var InputWindow = this.ui.find('.InputWindow'); var OutputWindow = this.ui.find('.OutputWindow'); Mouse.intersect = false; InputWindow.css({ top: _preferences.inputWindow.y, left: _preferences.inputWindow.x }); OutputWindow.css({ top: _preferences.outputWindow.y, left: _preferences.outputWindow.x }); Client.loadFile(DB.INTERFACE_PATH + 'checkbox_' + (_preferences.select_all ? 1 : 0) + '.bmp', function(data){ this.ui.find('.selectall:first').css('backgroundImage', 'url('+ data +')'); }.bind(this)); resize( InputWindow.find('.content'), _preferences.inputWindow.height ); resize( OutputWindow.find('.content'), _preferences.outputWindow.height ); // Seems like "EscapeWindow" is execute first, push it before. var events = jQuery._data( window, 'events').keydown; events.unshift( events.pop() ); }; /** * Released movement and save preferences */ NpcStore.onRemove = function onRemove() { var InputWindow = this.ui.find('.InputWindow'); var OutputWindow = this.ui.find('.OutputWindow'); Mouse.intersect = true; _input.length = 0; _output.length = 0; _preferences.inputWindow.x = parseInt( InputWindow.css('left'), 10); _preferences.inputWindow.y = parseInt( InputWindow.css('top'), 10); _preferences.inputWindow.height = InputWindow.find('.content').height() / 32 | 0; _preferences.outputWindow.x = parseInt( OutputWindow.css('left'), 10); _preferences.outputWindow.y = parseInt( OutputWindow.css('top'), 10); _preferences.outputWindow.height = OutputWindow.find('.content').height() / 32 | 0; _preferences.save(); this.ui.find('.content').empty(); this.ui.find('.total .result').text(0); }; /** * Key Listener * * Remove the UI when Escape key is pressed */ NpcStore.onKeyDown = function onKeyDown( event ) { if (event.which === KEYS.ESCAPE) { this.remove(); event.stopImmediatePropagation(); return false; } return true; }; /** * Specify the type of the shop * * @param {number} type (see NpcStore.Type.*) */ NpcStore.setType = function setType(type) { switch (type) { case NpcStore.Type.BUY: this.ui.find('.WinSell').hide(); this.ui.find('.WinBuy').show(); break; case NpcStore.Type.SELL: this.ui.find('.WinBuy').hide(); this.ui.find('.WinSell').show(); break; } _type = type; }; /** * Add items to list * * @param {Array} item list */ NpcStore.setList = function setList( items ) { var i, count; var it, item, out, content; this.ui.find('.content').empty(); this.ui.find('.total .result').text(0); _input.length = 0; _output.length = 0; content = this.ui.find('.InputWindow .content'); switch (_type) { case NpcStore.Type.BUY: for (i = 0, count = items.length; i < count; ++i) { items[i].index = i; items[i].count = items[i].count || Infinity; out = jQuery.extend({}, items[i]); out.count = 0; addItem( content, items[i]); _input.push(items[i]); _output.push(out); } break; case NpcStore.Type.SELL: for (i = 0, count = items.length; i < count; ++i) { it = Inventory.getItemByIndex(items[i].index); if (it) { item = jQuery.extend({}, it); item.price = items[i].price; item.overchargeprice = items[i].overchargeprice; item.count = ('count' in item) ? item.count : 1; out = jQuery.extend({}, item); out.count = 0; addItem( content, item); _input[item.index] = item; _output[item.index] = out; } } break; } }; /** * Submit data to send items */ NpcStore.submit = function submit() { var output; var i, count; output = []; count = _output.length; for (i = 0; i < count; ++i) { if (_output[i] && _output[i].count) { output.push(_output[i]); } } NpcStore.onSubmit( output ); }; /** * Calculate the cost of all items in the output box * * @return {number} */ NpcStore.calculateCost = function calculateCost() { var i, count, total; total = 0; count = _output.length; for (i = 0; i < count; ++i) { if (_output[i]) { total += (_output[i].discountprice || _output[i].overchargeprice || _output[i].price) * _output[i].count; } } this.ui.find('.total .result').text(total); return total; }; /** * Add item to the list * * @param {jQuery} content element * @param {Item} item info */ function addItem( content, item ) { var it = DB.getItemInfo( item.ITID ); var element = content.find('.item[data-index='+ item.index +']:first'); // 0 as amount ? remove it if (item.count === 0) { if (element.length) { element.remove(); } return; } // Already here, update it // Note: just the amount can be updated ? if (element.length) { element.find('.amount').text(isFinite(item.count) ? item.count : ''); return; } // Create it content.append( '<div class="item" draggable="true" data-index="'+ item.index +'">' + '<div class="icon"></div>' + '<div class="amount">' + (isFinite(item.count) ? item.count : '') + '</div>' + '<div class="name">'+ it.identifiedDisplayName +'</div>' + '<div class="price">'+ (item.discountprice || item.overchargeprice || item.price) +'</div>' + '<div class="unity">Z</div>' + '</div>' ); // Add the icon once loaded Client.loadFile( DB.INTERFACE_PATH + 'item/' + it.identifiedResourceName + '.bmp', function(data){ content.find('.item[data-index="'+ item.index +'"] .icon').css('backgroundImage', 'url('+ data +')'); }); } /** * Resize the content * * @param {jQueryElement} content * @param {number} height */ function resize( content, height ) { height = Math.min( Math.max(height, 2), 9); content.css('height', height * 32); } /** * Resizing window * * @param {jQueryElement} ui element */ function onResize( ui ) { var top = ui.position().top; var content = ui.find('.content:first'); var lastHeight = 0; var interval; function resizing() { var extraY = 31 + 19 - 30; var h = Math.floor( (Mouse.screen.y - top - extraY) / 32 ); // Maximum and minimum window size h = Math.min( Math.max(h, 2), 9); if (h === lastHeight) { return; } resize( content, h ); lastHeight = h; } // Start resizing interval = setInterval( resizing, 30); // Stop resizing jQuery(window).one('mouseup', function(event){ // Only on left click if (event.which === 1) { clearInterval(interval); } }); } /** * Transfer item from input to output (or the inverse) * * @param {jQueryElement} from content (input / output) * @param {jQueryElement} to content (input / output) * @param {boolean} is adding the content to the output element * @param {number} item index * @param {number} amount */ var transferItem = function transferItemQuantityClosure() { var tmpItem = { ITID: 0, count: 0, price: 0, index: 0 }; return function transferItem(fromContent, toContent, isAdding, index, count) { // Add item to the list if (isAdding) { // You don't have enough zeny if (_type === NpcStore.Type.BUY) { if (NpcStore.calculateCost() + _input[index].discountprice * count > Session.zeny) { ChatBox.addText( DB.msgstringtable[55], ChatBox.TYPE.ERROR); return; } } _output[index].count = Math.min( _output[index].count + count, _input[index].count); // Update input ui item amount tmpItem.ITID = _input[index].ITID; tmpItem.count = _input[index].count - _output[index].count; tmpItem.price = _input[index].price; tmpItem.index = _input[index].index; addItem( fromContent, tmpItem); addItem( toContent, _output[index]); } // Remove item else { count = Math.min(count, _output[index].count); if (!count) { return; } _output[index].count -= count; // Update input ui item amount tmpItem.ITID = _input[index].ITID; tmpItem.count = _input[index].count + _output[index].count; tmpItem.price = _input[index].price; tmpItem.index = _input[index].index; addItem( fromContent, _output[index]); addItem( toContent, tmpItem); } NpcStore.calculateCost(); }; }(); /** * Request move item from box to another * * @param {number} item index * @param {jQueryElement} from the content * @param {jQueryElement} to the content * @param {boolean} add the content to the output box ? */ function requestMoveItem( index, fromContent, toContent, isAdding) { var item, count; var isStackable; item = isAdding ? _input[index] : _output[index]; isStackable = ( item.type !== Inventory.ITEM.WEAPON && item.type !== Inventory.ITEM.EQUIP && item.type !== Inventory.ITEM.PETEGG && item.type !== Inventory.ITEM.PETEQUIP ); if (isAdding) { count = isFinite(_input[index].count) ? _input[index].count : 1; } else { count = _output[index].count; } // Can't buy more than one same stackable item if (_type === NpcStore.Type.BUY && !isStackable && isAdding) { if (toContent.find('.item[data-index="'+ item.index +'"]:first').length) { return false; } } // Just one item amount if (item.count === 1 || (_type === NpcStore.Type.SELL && _preferences.select_all) || !isStackable) { transferItem(fromContent, toContent, isAdding, index, isFinite(item.count) ? item.count : 1 ); return false; } // Have to specify an amount InputBox.append(); InputBox.setType('number', false, count); InputBox.onSubmitRequest = function(count) { InputBox.remove(); if (count > 0) { transferItem(fromContent, toContent, isAdding, index, count); } }; } /** * Drop an input in the InputWindow or OutputWindow * * @param {jQueryEvent} event */ function onDrop( event ) { var data; event.stopImmediatePropagation(); try { data = JSON.parse(event.originalEvent.dataTransfer.getData('Text')); } catch(e) { return false; } // Just allow item from store if (data.type !== 'item' || data.from !== 'store' || data.container === this.className) { return false; } requestMoveItem( data.index, jQuery('.' + data.container + ' .content'), jQuery(this).find('.content'), this.className === 'OutputWindow' ); return false; } /** * Get informations about an item */ function onItemInfo(event) { var index = parseInt( this.parentNode.getAttribute('data-index'), 10); var item = _input[index]; event.stopImmediatePropagation(); if (!item) { return false; } // Don't add the same UI twice, remove it if (ItemInfo.uid === item.ITID) { ItemInfo.remove(); return false; } // Add ui to window ItemInfo.append(); ItemInfo.uid = item.ITID; ItemInfo.setItem(item); return false; } /** * Select an item, put it on the other box */ function onItemSelected() { var input, from, to; if (_type === NpcStore.Type.BUY) { return; } input = NpcStore.ui.find('.InputWindow:first'); if (jQuery.contains(input.get(0), this)) { from = input; to = NpcStore.ui.find('.OutputWindow:first'); } else { from = NpcStore.ui.find('.OutputWindow:first'); to = input; } requestMoveItem( parseInt( this.getAttribute('data-index'), 10), from.find('.content:first'), to.find('.content:first'), from === input ); } /** * Focus an item */ var onItemFocus = function onItemFocusClosure() { var $window = jQuery(window); function stopDragDrop() { $window.trigger('mouseup'); } return function onItemFocus( event ) { NpcStore.ui.find('.item.selected').removeClass('selected'); jQuery(this).addClass('selected'); setTimeout( stopDragDrop, 4); event.stopImmediatePropagation(); }; }(); /** * Update scroll by block (32px) */ function onScroll( event ) { var delta; if (event.originalEvent.wheelDelta) { delta = event.originalEvent.wheelDelta / 120 ; if (window.opera) { delta = -delta; } } else if (event.originalEvent.detail) { delta = -event.originalEvent.detail; } this.scrollTop = Math.floor(this.scrollTop/32) * 32 - (delta * 32); return false; } /** * Start dragging an item */ function onDragStart( event ) { var container, img, url; var InputWindow, OutputWindow; InputWindow = NpcStore.ui.find('.InputWindow:first').get(0); OutputWindow = NpcStore.ui.find('.OutputWindow:first').get(0); container = (jQuery.contains(InputWindow, this) ? InputWindow : OutputWindow).className; img = new Image(); url = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1].replace(/"/g, ''); img.src = url; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: 'item', from: 'store', container: container, index: this.getAttribute('data-index') }) ); } /** * Exports */ NpcStore.onSubmit = function onSubmit(/* itemList */) {}; /** * Create componentand export it */ return UIManager.addComponent(NpcStore); });
define(function(require) { "use strict"; /** * Dependencies */ var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Thread = require('Core/Thread'); var Memory = require('Core/MemoryManager'); var KEYS = require('Controls/KeyEventHandler'); var Sprite = require('Loaders/Sprite'); var Targa = require('Loaders/Targa'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./GrfViewer.html'); var cssText = require('text!./GrfViewer.css'); var History = require('./History'); // Ugly, require api.js to display models and map require('../../../../api'); /** * Create GRFViewer component */ var Viewer = new UIComponent( 'GRFViewer', htmlText, cssText ); /** * @var {number} The display is done asynchronus, keep reference of the thread */ Viewer.thread = 0; /** * @var {number} action id, to stop doing things when the action change */ Viewer.actionID = 0; /** * Initialize Component */ Viewer.init = function Init() { Thread.hook("THREAD_READY", function(){ if( window.ROConfig && ROConfig.remoteClient ) { Thread.send( "SET_HOST", ROConfig.remoteClient ); } }); Thread.init(); jQuery('head:first').append( '<style type="text/css">\ #previous { background-image:url(' + require.toUrl('./Icons/arw-left.png') + '); }\ #next { background-image:url(' + require.toUrl('./Icons/arw-right.png') + '); }\ #progress { background-image:url(' + require.toUrl('./Icons/load.gif') + '); }\ </style>' ); // Drag drop the GRF. var box = this.ui.find('#info'); box .on('dragover', function(){ box.css('background', '#DFD'); return false; }) .on('dragleave', function(){ box.css('background', '#EEE'); return false; }) .on('drop', function(event){ box.css('background', '#EEE'); Viewer.processGRF(event.originalEvent); return false; }); this.ui.find('#file').change(Viewer.processGRF); // Initialize toolbar Viewer.initToolBar(); // Initialize history History.init( this.ui.find('#previous'), this.ui.find('#next') ); }; /** * Once append to body, initialize elements */ Viewer.onAppend = function OnAppend() { Viewer.moveToDirectory('/', true ); }; /** * Initialize tool bar */ Viewer.initToolBar = function InitToolBar() { // Path submit this.ui.find('#path').keydown(function(event){ if ( event.which === KEYS.ENTER ) { var value = this.value.replace(/^\s+|\s+$/g, ''); if ( value.substr(-1) !== "/" ) { value += "/"; } Viewer.moveToDirectory( value, true ); } }); // History before this.ui.find('#previous').click(function(){ var path = History.previous(); if( path ) { Viewer.moveToDirectory( path, false ); } }); // History after this.ui.find('#next').click(function(){ var path = History.next(); if( path ) { Viewer.moveToDirectory( path, false ); } }); // Search toolbar this.ui.find('#search') .focus(function(){ this.value = '' }) .blur(function(){ this.value = this.value || 'Search...' }) .keydown( function(event) { if ( event.which === KEYS.ENTER ) { var value = this.value.replace(/^\s+|\s+$/g, ''); if ( value.length > 2 ) { Viewer.moveToDirectory( 'search/' + value, true ); } } }); }; /** * Context Menu feature * * @param {HTMLElement} icon * @param {object} event */ Viewer.showContextMenu = function ShowContextMenu( icon, event ) { var _contextmenu = this.ui.find('#contextmenu'); var _overlay = this.ui.find('.overlay'); var _open = _contextmenu.find('.open:first'); var _save = _contextmenu.find('.save:first'); var _info = _contextmenu.find('.info:first'); var _icon = jQuery(icon); _contextmenu.css({ left: event.pageX, top: event.pageY }).show(); _overlay.one('mousedown', function(){ _contextmenu.hide(); _overlay.hide(); }).show(); // Clean up _open.removeClass('disable').off('mousedown'); _save.removeClass('disable').off('mousedown'); _info.removeClass('disable').off('mousedown'); // Open if( _icon.hasClass('file') ) { _open.addClass('disable'); } else { _open.one('mousedown', function(){ _icon.click(); _overlay.mousedown(); }) } // Save if( _icon.hasClass('directory') ) { _save.addClass('disable'); _save.attr('href', 'javascript:void(0)'); _save.get(0).removeAttribute('download'); } else { _save.one('mouseup', function(){ _overlay.mousedown(); }); Client.getFile( _icon.data('path'), function( buffer) { // Create temporary url, move to it and release it var url = URL.createObjectURL(new Blob([buffer],{type: "application/octet-stream"})); _save.attr({ href:url, download:_icon.text().trim()}); }); } // Properties // not supported yet. _info.addClass('disable'); }; /** * Move to a path * * @param {string} path to move * @param {boolean} save in history */ Viewer.moveToDirectory = function MoveToDirectory( path, save ) { path = decodeURIComponent(path) || '/'; path = path.replace(/\\/g, '/'); if ( path.substr(0,1) === '/' ) { path = path.substr(1); } if ( path.match(/^search\//) ) { Viewer.search( path.substr(7) ); } else { Viewer.showDirectory( path ); } // Update history if( save ) { History.push( path ); } }; /** * Load GRF files * * @param {object} event * @return {boolean} false */ Viewer.processGRF = function(event) { Client.onFilesLoaded = function(){ Viewer.moveToDirectory('data/', true); }; Client.init( (event.dataTransfer || event.target).files ); event.preventDefault(); event.stopPropagation(); return false; }; /** * Move to a specify path * * @param {string} path */ Viewer.showDirectory = function ShowDirectory( path ) { // Stop displaying clearTimeout(Viewer.thread); // Clean up Input path = decodeURIComponent(path) || '/'; path = path.replace(/\\/g, '/'); if ( path.substr(0,1) === '/' ) { path = path.substr(1); } // Build regex var directory = path.replace( /\//g, '\\\\'); var reg = directory + "([^(\\0|\\\\)]+)"; // Clean windows this.ui.find('#path').val(path); this.ui.find('.icon').unbind().remove(); this.ui.find('#progress').show(); this.ui.find('#msg').hide(); // Go back to the home if ( !path.length ) { this.ui.find('#info').show(); this.renderFiles(['data']); return; } this.ui.find('#info').hide(); // Changing action to avoid conflict var actionID = ++this.actionID; // Send request Client.search( new RegExp(reg, "gi"), function( list ) { // Request something else, stop. if ( actionID !== Viewer.actionID ) { return; } // Organize files and directory and render them list.sort(Viewer.sortFiles); Viewer.renderFiles( list ); }); }; /** * Search files (apply a regex on fileList) and show the result * * @param {string} keyword */ Viewer.search = function Search( keyword ) { // Escape regex, and complete it var search = keyword.replace(/(\.|\\|\+|\*|\?|\[|\^|\]|\$|\(|\)|\{|\}|\=|\!|\<|\>|\||\:|\-)/g, '\\$1'); var reg = "data\\\\([^(\\0\\)]+)?" + search + "([^(\\0|\\\\)]+)?"; // Clean path this.ui.find('.icon').unbind().remove(); this.ui.find('#progress').show(); this.ui.find('#info').hide(); this.ui.find('#msg').hide(); // Avoid merging requests var actionID = ++this.actionID; // Send request Client.search( new RegExp(reg, "gi"), function( list ) { // Request something else, stop. if ( actionID !== Viewer.actionID ) { return; } // Organize files and directory and render them list.sort(Viewer.sortFiles); Viewer.renderFiles( list ); }); }; /** * Organize file listing * Directory first, and organized by alpha * * @param {string} a file's name * @param {string} b file's name * @return {number} */ Viewer.sortFiles = function SortFiles( a, b ) { var _a, _b; a = a.replace(/.*\\/,''); b = b.replace(/.*\\/,''); _a = a.indexOf('.') !== -1; _b = b.indexOf('.') !== -1; if ( _a === _b ) return a > b ? 1 : -1; if ( _a ) return 1; return -1; }; /** * Showing file list on the screen * * @param {Array} list of files and directories */ Viewer.renderFiles = function RenderFiles( list ) { // Show this.ui.find('#progress').hide(); // No file in directory ? (or error : the file isn't a directory) if ( !list.length ) { this.ui.find('#msg').text('No file found.').show(); return; } var i, count, img; var reg = /(.*\\)/; var type, attr; i = 0; count = list.length; // Avoid freeze, stream to display files function StreamExecute() { var j; var html = ""; for ( j=0; j<200 && i+j < count; ++j ) { type = Viewer.getFileIcon(list[j+i]); attr = ''; // Binding event in html instead of in javascript is far faster because of a native parsing (tested). if ( type === 'directory' ) attr = ' onclick="Viewer.onDirectoryClick.call(this)"'; else if ( type === 'audio' ) attr = ' onclick="Viewer.onAudioClick.call(this)"'; else if ( type === 'img' ) attr = ' onclick="Viewer.onImageClick.call(this)"'; else if ( type === '3d' ) attr = ' onclick="Viewer.onObjectClick.call(this)"'; else if ( type === 'txt' ) attr = ' onclick="Viewer.onTextClick.call(this)"'; else if ( type === 'map' ) attr = ' onclick="Viewer.onWorldClick.call(this)"'; html += '<div class="icon '+ type +'" data-path="'+ list[j+i] +'"'+ attr +' oncontextmenu="Viewer.showContextMenu(this,event); return false;">\ <img src="'+ require.toUrl('./Icons/' + type +'.png') + '" width="48" height="48"/><br/>\ '+ list[j+i].replace(reg,'') +'\ </div>'; } jQuery(html).appendTo('#grfviewer'); i += j; if ( i < count ) { Viewer.thread = setTimeout( StreamExecute, 4 ); } } StreamExecute(); Viewer.displayImagesThumbnail( count ); }; /** * Get file thumbnail based on its extention * * @param {string} filename * @return {string} icon name */ Viewer.getFileIcon = function GetFileIcon( filename ) { var ext = filename.split(/\.([^\.]+)$/)[1] || 'dir'; var img = ''; switch( ext.toLowerCase() ) { default: img = 'file'; break; case 'dir': img = 'directory'; break; case 'xml': case 'txt': case 'lua': img = 'txt'; break; case 'jpg': case 'bmp': case 'tga': case 'jpeg': case 'spr': case 'pal': img = 'img'; break; case 'wav': case 'mp3': img = 'audio'; break; case 'rsm': img = '3d'; break; case 'rsw': img = 'map'; break; } return img; }; /** * Display real thumbnails for each known file */ Viewer.displayImagesThumbnail = function DisplayImagesTumbnail() { // Stored action to know if user act during the process var actionID = this.actionID + 0; function Process() { // Stop here if we change page. if ( actionID !== Viewer.actionID ) { return; } var nodes = jQuery('.img:lt(5)'); var load = 0; var total = nodes.length; // All thumbnails are already rendered if( !total ) { return; } // Work with current loaded files nodes.each(function(){ var self = jQuery(this); Client.getFile( self.data('path'), function( data ) { // Clean from memory... // and avoid to fetch it later Memory.remove(self.data('path')); self.removeClass('img'); var url = Viewer.getImageThumbnail( self.data('path'), data ); // Display image if( url ) { self.find('img:first').attr('src', url ); // There is a limit of blob url the browser can support if( url.match(/^blob\:/) ){ URL.revokeObjectURL(url); } } // Fetch next range. if ( (++load) >= total ) { setTimeout( Process, 4 ); } }); }); } Process(); }; /** * Generate thumbnail for a file * * @param {string} filename * @param {ArrayBuffer} data * @return {string|null} url generated */ Viewer.getImageThumbnail = function GetImageThumbnail( filename, data ) { var canvas; var ext = filename.substr(-3).toLowerCase(); switch( ext ) { // Sprite support case 'spr': var spr = new Sprite( data ); canvas = spr.getCanvasFromFrame(0); return canvas.toDataURL(); // Palette support case 'pal': canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); var imageData, i, count; var palette = new Uint8Array(data); // 16 * 16 = 256 canvas.width = 16; canvas.height = 16; imageData = ctx.createImageData( canvas.width, canvas.height ); for ( i = 0, count = imageData.data.length; i < count; i += 4 ) { imageData.data[i+0] = palette[i+0]; imageData.data[i+1] = palette[i+1]; imageData.data[i+2] = palette[i+2]; imageData.data[i+3] = 255; } ctx.putImageData( imageData, 0, 0 ); return canvas.toDataURL(); // Targa support case 'tga': var tga = new Targa(); tga.load( new Uint8Array(data) ); return tga.getDataURL(); // Image Support default: return URL.createObjectURL( new Blob( [data], { type: "image/" + ext }) ); } }; /** * User click on directory, open it */ Viewer.onDirectoryClick = function OnDirectoryClick() { Viewer.moveToDirectory( jQuery(this).data('path') + '/', true ); }; /** * User click on an audio file, play it */ Viewer.onAudioClick = function OnAudioClick() { var path = jQuery(this).data('path'); var box = Viewer.ui.find('#preview .box'); Viewer.ui.find('#progress').show(); Client.loadFile( path, function(url) { // Create audio var audio = document.createElement('audio'); audio.src = url; audio.controls = true; audio.play(); // Show it on a box box .css('top', ( jQuery(window).height() - 100 ) / 2 ) .html( jQuery(audio).click(function(event){ event.stopPropagation(); })); jQuery('#progress').hide(); jQuery('#preview').show().one('click',function(){ jQuery(this).hide(); box.find('audio').unbind(); }); }); }; /** * User click on an image, render it */ Viewer.onImageClick = function OnImageClick() { var ui = Viewer.ui; var path = jQuery(this).data('path'); var box = ui.find('#preview .box').html(''); ui.find('#progress').show(); Client.getFile( path, function(data) { var i, count, canvas; switch( path.substr(-3) ) { // Sprite support case 'spr': var spr = new Sprite(data); box .css('top', 200) .html(''); for ( i = 0, count = spr.frames.length; i < count; ++i ) { canvas = spr.getCanvasFromFrame( i ); if( canvas ) { box.append(canvas); } } break; // Palette support case 'pal': var palette = new Uint8Array(data); canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = 128; canvas.height = 128; for ( i = 0, count = palette.length; i < count; i += 4 ) { ctx.fillStyle = "rgb(" + palette[i+0] + "," + palette[i+1] + "," + palette[i+2] + ")"; ctx.fillRect( ( (i/4|0) % 16 ) * 8, ( (i/4|0) / 16 | 0 ) * 8, 8, 8 ); } box .css('top', jQuery(window).height() / 2 - 64 ) .html( canvas ); break; // Targa support case 'tga': var tga = new Targa(); tga.load( new Uint8Array(data) ); box .css('top', jQuery(window).height() / 2 - 64 ) .html( tga.getCanvas() ); break; // Image Support default: var url = URL.createObjectURL( new Blob( [data], { type: "image/" + path.substr(-3) }) ); var img = new Image(); img.src = url; img.onload = function() { box .css('top', (jQuery(window).height()-this.height)/2 ) .html(this); URL.revokeObjectURL(url); }; break; } // Display progress bar ui.find('#preview').show(); ui.find('#progress').hide(); ui.find('#preview').one('click',function(){ jQuery(this).hide(); }); }); }; /** * User click on a model, render it using ModelViewer */ Viewer.onObjectClick = function OnObjectClick() { var path = jQuery(this).data('path'); var ready = false; Viewer.ui.find('#progress').show(); // Show iframe jQuery('#preview .box').css('top', (jQuery(window).height()-300)* 0.5 ); jQuery('#preview').show(); jQuery('#progress').hide(); // Include App var App = new ROBrowser({ target: jQuery('#preview .box').get(0), type: ROBrowser.TYPE.FRAME, application: ROBrowser.APP.MODELVIEWER, development: ROConfig.development, api: true, width: 500, height: 300 }); App.start(); // Ressource sharing function OnMessage(event) { ready = true; switch( event.data.type ) { case 'SYNC': case 'SET_HOST': case 'CLEAN_GRF': return; default: Thread.send( event.data.type, event.data.data, function(){ App._APP.postMessage({ arguments: Array.prototype.slice.call(arguments, 0), uid: event.data.uid }, location.origin); }); } } // Wait for synchronisation with frame function Synchronise(){ if( !ready ) { App._APP.postMessage('SYNC', location.origin); setTimeout(Synchronise, 4); } } // Once app is ready App.onReady = function(){ App._APP.location.hash = path.replace(/\\/g,'/'); App._APP.frameElement.style.border = "1px solid grey"; App._APP.frameElement.style.backgroundColor = "#45484d"; window.addEventListener("message", OnMessage, false); Synchronise(); }; // Unload app jQuery('#preview').one('click',function(){ jQuery(this).hide(); window.removeEventListener('message', OnMessage, false); }); }; /** * User click on a map, render it using MapViewer */ Viewer.onWorldClick = function OnWorldClick() { var path = jQuery(this).data('path'); var ready = false; Viewer.ui.find('#progress').show(); // Show iframe jQuery('#preview .box').css('top', (jQuery(window).height()-600)* 0.5 ); jQuery('#preview').show(); jQuery('#progress').hide(); document.body.style.overflow = "hidden"; // Include App var App = new ROBrowser({ target: jQuery('#preview .box').get(0), type: ROBrowser.TYPE.FRAME, application: ROBrowser.APP.MAPVIEWER, development: ROConfig.development, api: true, width: 800, height: 600 }); App.start(); // Wait for synchronisation with frame function Synchronise(){ if( !ready ) { App._APP.postMessage('SYNC', location.origin); setTimeout(Synchronise, 4); } } // Ressource sharing function OnMessage(event) { ready = true; switch( event.data.type ) { case 'SYNC': case 'SET_HOST': case 'CLEAN_GRF': return; default: Thread.send( event.data.type, event.data.data, function(){ App._APP.postMessage({ arguments: Array.prototype.slice.call(arguments, 0), uid: event.data.uid }, location.origin); }); } } // Redirect Thread result to frame function ThreadRedirect( type ) { Thread.hook( type, function(data){ App._APP.postMessage({ type: type, data: data }, location.origin ); }); } // Once app is ready App.onReady = function(){ App._APP.location.hash = path.replace(/\\/g,'/'); App._APP.frameElement.style.border = "1px solid grey"; App._APP.frameElement.style.backgroundColor = "#45484d"; // Hook Tread Map loading ThreadRedirect('MAP_PROGRESS'); ThreadRedirect('MAP_WORLD'); ThreadRedirect('MAP_GROUND'); ThreadRedirect('MAP_ALTITUDE'); ThreadRedirect('MAP_MODELS'); window.addEventListener("message", OnMessage, false); Synchronise(); }; // Unload app jQuery('#preview').one('click',function(){ jQuery(this).hide(); document.body.style.overflow = "auto"; window.removeEventListener('message', OnMessage, false); }); }; /** * User click on text, display it */ Viewer.onTextClick = function OnTextClick() { var path = jQuery(this).data('path'); var progress = Viewer.ui.find('#progress'); var box = Viewer.ui.find('#preview .box'); progress.show(); Client.loadFile( path, function( text ) { box .css('top', ( jQuery(window).height()-300 ) / 2 ) .html( jQuery('<pre/>') .text(text) .click(function(event){ event.stopPropagation() }) .css({ background:'white', width:'500px', display:'inline-block', height:'300px', overflow:'scroll', textAlign:'left', padding:'10px' }) ); progress.hide(); jQuery('#preview') .show() .one('click',function(){ jQuery(this).hide(); box.find('pre').unbind(); }); }); }; /** * Export it as global variable * (need to be use to reference HTML event) */ window.Viewer = Viewer; /** * Stored component and return it */ return UIManager.addComponent(Viewer); });
define(function(require) { "use strict"; /** * Dependencies */ var DB = require('DB/DBManager'); var Client = require('Core/Client'); var jQuery = require('Utils/jquery'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var MiniMap = require('UI/Components/MiniMap/MiniMap'); var Inventory = require('UI/Components/Inventory/Inventory'); var Equipment = require('UI/Components/Equipment/Equipment'); var htmlText = require('text!./BasicInfo.html'); var cssText = require('text!./BasicInfo.css'); /** * Create Basic Info component */ var BasicInfo = new UIComponent( 'BasicInfo', htmlText, cssText ); /** * Stored data */ BasicInfo.base_exp = 0; BasicInfo.base_exp_next = 1; BasicInfo.job_exp = 0; BasicInfo.job_exp_next =-1; BasicInfo.weight = 0; BasicInfo.weight_max = 1; /** * Initialize UI */ BasicInfo.init = function Init() { this.ui.find('.topbar .right').click(BasicInfo.toggleMode.bind(this)); this.ui.find('.toggle_btns').mousedown(BasicInfo.toggleButtons.bind(this)); this.ui.find('.buttons button').mousedown(function(){ switch( this.className ) { case 'item': Inventory.ui.toggle(); break; case 'info': Equipment.ui.toggle(); break; case 'map': case 'party': case 'guild': case 'quest': case 'option': case 'skill': } }); this.draggable(); }; /** * Stack to store things if the UI is not in html */ BasicInfo.stack = []; /** * Execute elements in memory */ BasicInfo.onAppend = function OnAppend() { var i, count; for( i = 0, count = this.stack.length; i < count; ++i ) { this.update.apply( this, this.stack[i]); } this.stack.length = 0; }; /** * Key Listener * * @param {object} event * @return {boolean} */ BasicInfo.onKeyDown = function OnKeyDown( event ) { if( KEYS.ALT && event.which === KEYS.V ) { this.toggleMode(); event.stopImmediatePropagation(); return false; } return true; }; /** * Switch window size */ BasicInfo.toggleMode = function ToggleMode() { this.ui.toggleClass('small large'); if( this.ui.hasClass('large') ) { this.ui.find('.buttons').show(); } else { this.ui.find('.toggle_btns').css('backgroundImage', 'url(' + Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/viewon.bmp') + ')'); this.ui.find('.buttons').hide(); } }; /** * Toggle the list of buttons */ BasicInfo.toggleButtons = function ToggleButtons() { var datauri; var buttons = this.ui.find('.buttons'); if( buttons.is(':hidden') ) { buttons.show(); datauri = Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/viewoff.bmp'); } else { buttons.hide(); datauri = Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/viewon.bmp'); } jQuery(this).css('backgroundImage', 'url(' + datauri + ')'); }; /** * Update UI elements * * @param {string} type identifier * @param {number} val1 * @param {number} val2 (optional) */ BasicInfo.update = function Update( type, val1, val2 ) { if( !this.__loaded ){ BasicInfo.stack.push(arguments); return; } switch( type ) { case 'name': case 'blvl': case 'jlvl': this.ui.find('.'+ type +'_value').text(val1); break; case 'zeny': var list = val1.toString().split(""); var i, count = list.length; var str = ""; for( i=0; i<count; i++ ) { str = list[count-i-1] + (i && i%3 ===0 ? ',' : '') + str } this.ui.find('.'+ type +'_value').text(str); break; case 'job': this.ui.find('.job_value').text(DB.mobname[val1]); break; case 'bexp': case 'jexp': if( !val2 ) { this.ui.find('.' + type).hide(); break; } this.ui.find('.'+ type).show(); this.ui.find('.'+ type +' div').css('width', Math.min( 100, Math.floor(val1 * 100 / val2) ) + '%'); this.ui.find('.'+ type +'_value').text( (Math.floor(val1 * 1000 / val2) * 0.1).toFixed(1) + '%'); break; case 'weight': this.ui.find('.weight_value').text(val1); this.ui.find('.weight_total').text(val2); this.ui.find('.weight').css('color', val1 < (val2>>2) * 3 ? '' : 'red'); break; case 'hp': case 'sp': var perc = Math.floor(val1 * 100 / val2); var color = perc < 25 ? "red" : "blue"; this.ui.find('.'+ type +'_value').text(val1); this.ui.find('.'+ type +'_max_value').text(val2); this.ui.find('.'+ type +'_perc').text( perc + '%'); if( perc <= 0 ) { this.ui.find('.'+ type +'_bar div').css('backgroundImage', 'none'); } else { Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_left.bmp', function(url){ BasicInfo.ui.find('.'+ type +'_bar_left').css('backgroundImage', 'url('+ Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_left.bmp') +')'); }); Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_mid.bmp', function(url){ BasicInfo.ui.find('.'+ type +'_bar_middle').css({ backgroundImage: 'url('+ Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_mid.bmp') +')', width: Math.floor( Math.min( perc, 100 ) * 1.27 ) + 'px' }); }); Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_right.bmp', function(url){ BasicInfo.ui.find('.'+ type +'_bar_right').css({ backgroundImage: 'url('+ Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/gze'+ color +'_right.bmp') +')', left: Math.floor( Math.min( perc, 100) * 1.27 ) + 'px' }); }); } break; } }; /** * Create component and export it */ return UIManager.addComponent(BasicInfo); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var Client = require('Core/Client'); var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var Inventory = require('UI/Components/Inventory/Inventory'); var htmlText = require('text!./ItemSelection.html'); var cssText = require('text!./ItemSelection.css'); /** * Create ItemSelection namespace */ var ItemSelection = new UIComponent( 'ItemSelection', htmlText, cssText ); /** * Initialize UI */ ItemSelection.init = function init() { // Show at center. this.ui.css({ top: (Renderer.height- 200)/2, left: (Renderer.width - 200)/2 }); this.list = this.ui.find('.list:first'); this.index = 0; this.draggable(); // Click Events this.ui.find('.ok').click( this.selectIndex.bind(this) ); this.ui.find('.cancel').click(function(){ this.index = -1; this.selectIndex(); }.bind(this) ); // Bind events this.ui .on('dblclick', '.item', this.selectIndex.bind(this)) .on('mousedown', '.item', function(){ ItemSelection.setIndex( Math.floor(this.getAttribute('data-index')) ); }); }; /** * Add elements to the list * * @param {Array} list object to display */ ItemSelection.setList = function setList( list, isSkill ) { var i, count; var item, it, file, name; ItemSelection.list.empty(); for (i = 0, count = list.length; i < count; ++i) { if (isSkill) { item = SkillInfo[list[i]]; file = item.Name; name = item.SkillName; } else { item = Inventory.getItemByIndex(list[i]); it = DB.getItemInfo( item.ITID ); file = item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName; name = item.IsIdentified ? it.identifiedDisplayName : it.unidentifiedDisplayName; } addElement( DB.INTERFACE_PATH + 'item/' + file + '.bmp', list[i], name); } this.setIndex(list[0]); }; /** * Add an element to the list * * @param {string} image url * @param {index} index in list * @param {string} element name */ function addElement( url, index, name) { ItemSelection.list.append( '<div class="item" data-index="'+ index +'">' + '<div class="icon"></div>' + '<span class="name">' + name + '</span>' + '</div>' ); Client.loadFile( url, function(data){ ItemSelection.list .find('div[data-index='+ index +'] .icon') .css('backgroundImage', 'url('+ data +')'); }); } /** * Change selection * * @param {number} id in list */ ItemSelection.setIndex = function setIndex( id ) { this.list.find('div[data-index='+ this.index +']').css('backgroundColor', 'transparent'); this.list.find('div[data-index='+ id +']').css('backgroundColor', '#cde0ff'); this.index = id; }; /** * Select a server, callback */ ItemSelection.selectIndex = function selectIndex() { this.onIndexSelected( this.index ); this.remove(); }; /** * Free variables once removed from HTML */ ItemSelection.onRemove = function onRemove() { this.index = 0; }; /** * Set new window name * * @param {string} title */ ItemSelection.setTitle = function setTitle( title ) { this.ui.find('.head .text').text( title ); }; /** * Functions to define */ ItemSelection.onIndexSelected = function onIndexSelected(){}; /** * Create component based on view file and export it */ return UIManager.addComponent(ItemSelection); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./Intro.html'); var cssText = require('text!./Intro.css'); var Context = require('Core/Context'); var Particle = require('./Particle'); var Preferences = require('./Preferences'); var FileSystem = require('./FileSystem'); /** * Create Intro component */ var Intro = new UIComponent( 'Intro', htmlText, cssText ); /** * @var {FileList} */ Intro.files = []; /** * Manage Escape key to exit */ Intro.onKeyDown = function OnKeyDown( event ) { // Exit fullScreen mode if (event.which === KEYS.ESCAPE) { if (Context.isFullScreen()) { Context.cancelFullScreen(); } event.stopImmediatePropagation(); return false; } return true; }; /** * Initialize Metaling */ Intro.init = function init() { window.ROConfig = window.ROConfig || {}; if (!ROConfig.servers) { ROConfig.serverEditMode = true; } var ui = this.ui; preloadImages(); // About page ui.find('.btn_about') .mousedown(function(){ var $about = ui.find('.overlay.about'); $about .show() .animate({opacity:1}, 200) .click(function(){ $about.animate({opacity:0}, 200, function(){ $about.hide(); }); }); }); // Settings page ui.find('.btn_settings') .mousedown(function(){ Preferences.load( ui ); ui.find('.overlay.settings') .show() .animate({opacity:1}, 200); }); // Box to set files ui.find('.box') .mouseover(function(){ jQuery(this).addClass('over'); }) .mouseout(function(){ jQuery(this).removeClass('over'); }) .click(function(){ ui.find('input[type="file"]').click(); }) .on('drop', process ) .on('dragover', function(){ jQuery(this).addClass('over'); return false; }) .on('dragleave', function(){ jQuery(this).removeClass('over'); return false; }); // Set file by clicking the box ui.find('input[type="file"]') .on('change', process ); // Modify quality ui.find('.quality') .on('change', function(){ ui.find('.quality_result').text( this.value + '%' ); }); // Clean cache ui.find('.clean') .click(function(){ var parent = jQuery(this).hide().parent(); parent.append( '<span><img src="'+ require.toUrl('./images/loading.gif') +'"/> <i>Cleaning cache...</i></span>' ); FileSystem.cleanup(function(){ parent.find('span').remove(); Intro.ui.find('.msg').text(''); }); }); // Stop propagation in overlay to avoid hiding the page ui.find('.overlay') .on('click', 'input[type="text"], a, button', function( event ){ if (this.nodeName === 'INPUT') { this.select(); } event.stopImmediatePropagation(); }); // Not allow to edit server list if (!ROConfig.serverEditMode) { ui.find('.serveredit').hide(); } // Modify volume ui.find('.bgmvol') .on('change', function(){ ui.find('.bgmvol_result').text( this.value + '%' ); }); ui.find('.soundvol') .on('change', function(){ ui.find('.soundvol_result').text( this.value + '%' ); }); // Add Server ui.find('.btn_add') .on('click', function(){ var $serverlist = ui.find('.servers'); var count = $serverlist.find('tr').length; $serverlist.append( '<tr>' + ' <td><input type="text" class="display" value="Server '+ count +'"/></td>' + ' <td><input type="text" class="address" value="127.0.0.1:6900"/></td>' + ' <td><input type="text" class="version"value="22"/></td>' + ' <td><input type="text" class="langtype" value="12"/></td>' + ' <td><input type="text" class="packetver"value="auto"/></td>' + ' <td><button class="btn_delete"></button></td>' + '</tr>' ); $serverlist.find('tr :eq('+ count +') input:first').focus(); }); ui.find('.btn_save') .on('click', function(){ Preferences.save( ui ); ui.find('.overlay') .animate({opacity:0}, 200, function(){ ui.find('.overlay').hide(); }); }); ui.find('.serverlist tbody') .on('click', '.btn_delete', function(){ jQuery(this).parent().parent().remove(); }); // Start roBrowser ui.find('.btn_play') .click(function(){ ui.find('.overlay.loading') .show() .animate({opacity:1}, 200); Intro.onFilesSubmit( Intro.files ); }); }; /** * Once append to body */ Intro.onAppend = function onAppend() { // Can't resize the window if it's not a popup/App if (!Context.Is.POPUP) { this.ui.find('.resolution').hide(); } // Show content saved this.ui.find('.clean').hide(); FileSystem.getSize(function(used){ var msg = ''; if (used) { if (used > 1024 * 1024 * 1024) { msg = (used / 1024 / 1024 / 1024).toFixed(2) + ' Go saved'; } else if (used > 1024 * 1024) { msg = (used / 1024 / 1024).toFixed(2) + ' Mo saved'; } else { msg = (used / 1024).toFixed(2) + ' Mo saved'; } this.ui.find('.msg').text(msg); this.ui.find('.clean').show(); } }.bind(this)); // Hook resize var $window = jQuery(window); var $intro = this.ui.find('.intro'); $window.on('resize.intro',function(){ $intro.css( 'transform', 'scale('+ $window.width() / $intro.width() + ',' + $window.height() / $intro.height() + ')' ); }); $window.trigger('resize.intro'); // Initialize window and particle Particle.init( 100, this.ui.find('canvas')[0] ); }; /** * Once removed */ Intro.onRemove = function onRemove() { jQuery(window).off('resize.intro'); Particle.stop(); this.ui.find('.overlay').hide(); }; /** * Start loading images */ function preloadImages() { // Background images jQuery('style:first').append([ '#intro .intro { background-image:url(' + require.toUrl('./images/background.jpg') + '); }', '#intro .ribbon { background-image:url(' + require.toUrl('./images/ribbon.png') + '); }', '#intro .box { background-image:url(' + require.toUrl('./images/box.jpg') + '); }', '#intro .btn_play { background-image:url(' + require.toUrl('./images/play.png') + '); }', '#intro .btn_play:hover { background-image:url(' + require.toUrl('./images/play-down.png') + '); }', '#intro .btn_add { background-image:url('+ require.toUrl('./images/add-server.jpg') +'); }', '#intro .btn_save { background-image:url('+ require.toUrl('./images/save.jpg') + '); }', '#intro .btn_delete { background-image:url('+ require.toUrl('./images/delete.png') + '); }' ].join('\n')); // Add images to IMG tag Intro.ui.find('.icon img').attr('src', require.toUrl('./images/icon.png') ); Intro.ui.find('.btn_about img').attr('src', require.toUrl('./images/about.png') ); Intro.ui.find('.btn_settings img').attr('src', require.toUrl('./images/settings.png') ); // Preload image (new Image()).src = require.toUrl('./images/play-down.png'); } /** * User submit files, get back files * @param {object} event * @return {boolean} false */ function process( event ) { var i, count; var _dir_count = 0; var _dir_loaded = 0; var _file_count = 0; var _file_loaded = 0; var _files = []; event.stopImmediatePropagation(); jQuery(this).removeClass('over'); function processing(files) { if (files.length) { Intro.files.push.apply( Intro.files, files ); Intro.ui.find('.msg').text( Intro.files.length + ' files selected' ); } } // Extract files from directory function recursiveReader(entry, skip){ if (entry.isFile) { ++_file_count; entry.file(function(file){ file.fullPath = entry.fullPath.substr(skip); // get rid of the "/" _files.push(file); if ((++_file_loaded) === _file_count && _dir_loaded === _dir_count) { processing(_files); } }); } else if (entry.isDirectory) { ++_dir_count; entry.createReader().readEntries(function(entries){ for (var i = 0, count = entries.length; i < count; ++i) { recursiveReader(entries[i], skip); } if ((++_dir_loaded) === _dir_count && _file_loaded === _file_count) { processing(_files); } }); } } // input[type="file"] if ('files' in this) { // In wekit we select the folder, not files. // we have to rewrite the relativePath to remove the main folder from it if (this.files.length) { var token = 'webkitRelativePath' in this.files[0] ? 'webkitRelativePath' : 'relativePath' in this.files[0] ? 'relativePath' : null; if (token) { var i, count = this.files.length; var baseFolder = /^[^(\/|\\)]+(\/|\\)/; for (i = 0; i < count; ++i) { this.files[i].fullPath = this.files[i][token].replace(baseFolder, ''); } } } processing(this.files); return false; } // drag drop if (event.originalEvent.dataTransfer) { var data = event.originalEvent.dataTransfer; // Read directory content if (data.items && data.items.length && data.items[0].webkitGetAsEntry) { // If select a directory, have to remove the root folder for all files // inside this directory var skip = 1; var entry = data.items[0].webkitGetAsEntry(); if (data.items.length === 1 && entry.isDirectory) { skip = entry.fullPath.split('/')[1].length + 2; } for (i = 0, count = data.items.length; i < count; ++i) { recursiveReader( data.items[i].webkitGetAsEntry(), skip); } return false; } // Read files directly else if (data.files) { processing(data.files); return false; } } processing(_files); return false; } /** * Callback to used. */ Intro.onFilesSubmit = function OnFilesSubmit(){}; /** * Stored component and return it */ return UIManager.addComponent(Intro); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var DB = require('DB/DBManager'); var Network = require('Network/NetworkManager'); var PACKET = require('Network/PacketStructure'); var ItemType = require('DB/Items/ItemType'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Session = require('Engine/SessionStorage'); var Mouse = require('Controls/MouseEventHandler'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var InputBox = require('UI/Components/InputBox/InputBox'); var ChatBox = require('UI/Components/ChatBox/ChatBox'); var CartItems = require('UI/Components/CartItems/CartItems'); var htmlText = require('text!./Vending.html'); var cssText = require('text!./Vending.css'); /** * Create NPC Menu component */ var Vending = new UIComponent( 'Vending', htmlText, cssText ); /** * Freeze the mouse */ //Vending.mouseMode = UIComponent.MouseMode.FREEZE; /** * @var {Preferences} */ var _preferences = Preferences.get('Vending', { inputWindow: { x: 100, y: 100, height: 2 }, outputWindow: { x: 100 + 280 + 10, y: 100 + (7*32) - (2*32), height: 5 }, select_all: false }, 1.0); /** * @var {Array} item list */ var _input = []; /** * @var {Array} output list */ var _output = []; /** * @var {number} type (buy/sell) */ var _type; var _shopname = ''; /** * Initialize component */ Vending.init = function init() { var ui = this.ui; var InputWindow = ui.find('.InputWindow'); var OutputWindow = ui.find('.OutputWindow'); // Client do not send packet //ui.find('.btn.cancel').click(this.remove.bind(this)); ui.find('.btn.sell').click(function(){ Vending.onSubmit(); }); this.ui.find('.btn.cancel').click(function(){ Vending.onRemove(); }); // Items options ui.find('.content') .on('mousewheel DOMMouseScroll', onScroll) .on('contextmenu', '.icon', onItemInfo) .on('dblclick', '.item', onItemSelected) .on('mousedown', '.item', onItemFocus) .on('dragstart', '.item', onDragStart) .on('dragend', '.item', function(){ delete window._OBJ_DRAG_; }); // Drop items ui.find('.InputWindow, .OutputWindow') .on('drop', onDrop) .on('dragover', function(event) { event.stopImmediatePropagation(); return false; }) .on('mousedown', function(){ Vending.focus(); }); // Hacky drag drop this.draggable.call({ui: InputWindow }, InputWindow.find('.titlebar')); this.draggable.call({ui: OutputWindow }, OutputWindow.find('.titlebar')); }; /** * Player should not be able to move when the store is opened */ Vending.onAppend = function onAppend() { var InputWindow = this.ui.find('.InputWindow'); var OutputWindow = this.ui.find('.OutputWindow'); InputWindow.css({ top: _preferences.inputWindow.y, left: _preferences.inputWindow.x }); OutputWindow.css({ top: _preferences.outputWindow.y, left: _preferences.outputWindow.x }); resize( InputWindow.find('.content'), _preferences.inputWindow.height ); resize( OutputWindow.find('.content'), _preferences.outputWindow.height ); // Seems like "EscapeWindow" is execute first, push it before. //var events = jQuery._data( window, 'events').keydown; //events.unshift( events.pop() ); this.ui.hide(); }; /** * Resize the content * * @param {jQueryElement} content * @param {number} height */ function resize( content, height ) { height = Math.min( Math.max(height, 2), 9); content.css('height', height * 32); } /** * Released movement and save preferences */ Vending.onRemove = function onRemove() { var InputWindow = this.ui.find('.InputWindow'); var OutputWindow = this.ui.find('.OutputWindow'); _input.length = 0; _output.length = 0; _preferences.inputWindow.x = parseInt( InputWindow.css('left'), 10); _preferences.inputWindow.y = parseInt( InputWindow.css('top'), 10); _preferences.inputWindow.height = InputWindow.find('.content').height() / 32 | 0; _preferences.outputWindow.x = parseInt( OutputWindow.css('left'), 10); _preferences.outputWindow.y = parseInt( OutputWindow.css('top'), 10); _preferences.outputWindow.height = OutputWindow.find('.content').height() / 32 | 0; _preferences.save(); this.ui.find('.content').empty(); this.ui.hide(); }; /** * Key Listener * * Remove the UI when Escape key is pressed */ Vending.onKeyDown = function onKeyDown( event ) { if (event.which === KEYS.ESCAPE) { this.remove(); event.stopImmediatePropagation(); return false; } return true; }; /** * Add items to list * * @param {Array} item list */ Vending.setList = function setList( items ) { var i, count; var it, item, out, content; this.ui.find('.content').empty(); _input.length = 0; _output.length = 0; content = this.ui.find('.InputWindow .content'); { for (i = 0, count = items.length; i < count; ++i) { if (!('index' in items[i])) { items[i].index = i; } items[i].count = items[i].count || Infinity; items[i].IsIdentified = true; out = jQuery.extend({}, items[i]); out.count = 0; addItem( content, items[i], true); _input[items[i].index] = items[i]; _output[items[i].index] = out; } } }; /** * Prettify zeny : 1000000 -> 1,000,000 * * @param {number} zeny * @param {boolean} use color * @return {string} */ function prettyZeny( val, useStyle ) { var list = val.toString().split(''); var i, count = list.length; var str = ''; for (i = 0; i < count; i++) { str = list[count-i-1] + (i && i%3 ===0 ? ',' : '') + str; } if (useStyle) { var style = [ 'color:#000000; text-shadow:1px 0px #00ffff;', // 0 - 9 'color:#0000ff; text-shadow:1px 0px #ce00ce;', // 10 - 99 'color:#0000ff; text-shadow:1px 0px #00ffff;', // 100 - 999 'color:#ff0000; text-shadow:1px 0px #ffff00;', // 1,000 - 9,999 'color:#ff18ff;', // 10,000 - 99,999 'color:#0000ff;', // 100,000 - 999,999 'color:#000000; text-shadow:1px 0px #00ff00;', // 1,000,000 - 9,999,999 'color:#ff0000;', // 10,000,000 - 99,999,999 'color:#000000; text-shadow:1px 0px #cece63;', // 100,000,000 - 999,999,999 'color:#ff0000; text-shadow:1px 0px #ff007b;', // 1,000,000,000 - 9,999,999,999 ]; str = '<span style="' + style[count-1] + '">' + str + '</span>'; } return str; } /** * Add item to the list * * @param {jQuery} content element * @param {Item} item info */ function addItem( content, item , isinput) { var it = DB.getItemInfo(item.ITID); var element = content.find('.item[data-index='+ item.index +']:first'); var price; // 0 as amount ? remove it if (item.count === 0) { if (element.length) { element.remove(); } return; } // Already here, update it // Note: just the amount can be updated ? if (element.length) { element.find('.amount').text(isFinite(item.count) ? item.count : ''); return; } if(isinput==false)price = prettyZeny(item.price, false); //price = item.price; // Create it if(isinput == true) { content.append( '<div class="item" draggable="true" data-index="'+ item.index +'">' + '<div class="icon"></div>' + '<div class="amount">' + (isFinite(item.count) ? item.count : '') + '</div>' + '<div class="name">'+ jQuery.escape(DB.getItemName(item)) +'</div>' + '</div>' ); } else { content.append( '<div class="item" draggable="true" data-index="'+ item.index +'">' + '<div class="icon"></div>' + '<div class="amount">' + (isFinite(item.count) ? item.count : '') + '</div>' + '<div class="name">'+ jQuery.escape(DB.getItemName(item)) +'</div>' + '<div class="price">Price: '+ price +'</div>' + '</div>' ); } // Add the icon once loaded Client.loadFile( DB.INTERFACE_PATH + 'item/' + (item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName) + '.bmp', function(data){ content.find('.item[data-index="'+ item.index +'"] .icon').css('backgroundImage', 'url('+ data +')'); }); } /** * Transfer item from input to output (or the inverse) * * @param {jQueryElement} from content (input / output) * @param {jQueryElement} to content (input / output) * @param {boolean} is adding the content to the output element * @param {number} item index * @param {number} amount */ var transferItem = function transferItemQuantityClosure() { var tmpItem = { ITID: 0, count: 0, price: 0, index: 0 }; return function transferItem(fromContent, toContent, isAdding, index, count) { // Add item to the list if (isAdding) { _output[index].count = Math.min( _output[index].count + count, _input[index].count); // Update input ui item amount tmpItem.ITID = _input[index].ITID; tmpItem.count = _input[index].count - _output[index].count; tmpItem.price = _input[index].price; tmpItem.index = _input[index].index; addItem( fromContent, tmpItem, true); addItem( toContent, _output[index], false); } // Remove item else { count = Math.min(count, _output[index].count); if (!count) { return; } _output[index].count -= count; // Update input ui item amount tmpItem.ITID = _input[index].ITID; tmpItem.count = _input[index].count + _output[index].count; tmpItem.price = _input[index].price; tmpItem.index = _input[index].index; addItem( fromContent, _output[index], false); addItem( toContent, tmpItem, true); } //Vending.calculateCost(); }; }(); /** * Request move item from box to another * * @param {number} item index * @param {jQueryElement} from the content * @param {jQueryElement} to the content * @param {boolean} add the content to the output box ? */ function requestMoveItem( index, fromContent, toContent, isAdding) { var item, count, item_price; var isStackable; item = isAdding ? _input[index] : _output[index]; isStackable = ( item.type !== ItemType.WEAPON && item.type !== ItemType.EQUIP && item.type !== ItemType.PETEGG && item.type !== ItemType.PETEQUIP ); if (isAdding) { count = isFinite(_input[index].count) ? _input[index].count : 1; } else { count = _output[index].count; } /*// Can't buy more than one same stackable item if ((_type === Vending.Type.BUY || _type === Vending.Type.VENDING_STORE) && !isStackable && isAdding) { if (toContent.find('.item[data-index="'+ item.index +'"]:first').length) { return false; } }*/ // Just one item amount if (item.count === 1 || !isStackable/* || (_type === Vending.Type.SELL && _preferences.select_all)*/) { if(isAdding) { // Have to specify an price InputBox.append(); InputBox.setType('price', false, item_price); InputBox.onSubmitRequest = function(item_price) { InputBox.remove(); _output[index].price = item_price; if(item_price > 0) { transferItem(fromContent, toContent, isAdding, index, isFinite(item.count) ? item.count : 1 ); } }; } else { transferItem(fromContent, toContent, isAdding, index, isFinite(item.count) ? item.count : 1 ); } return false; } // Have to specify an amount InputBox.append(); InputBox.setType('number', false, count); InputBox.onSubmitRequest = function(count) { InputBox.remove(); if (count > 0) { if(isAdding) { // Have to specify an price InputBox.append(); InputBox.setType('price', false, item_price); InputBox.onSubmitRequest = function(item_price) { InputBox.remove(); _output[index].price = item_price; if(item_price > 0) { transferItem(fromContent, toContent, isAdding, index, count); } }; } else { transferItem(fromContent, toContent, isAdding, index, count); } } }; } /** * Drop an input in the InputWindow or OutputWindow * * @param {jQueryEvent} event */ function onDrop( event ) { var data; event.stopImmediatePropagation(); try { data = JSON.parse(event.originalEvent.dataTransfer.getData('Text')); } catch(e) { return false; } // Just allow item from store if (data.type !== 'item' || data.from !== 'Vending' || data.container === this.className) { return false; } requestMoveItem( data.index, jQuery('.' + data.container + ' .content'), jQuery(this).find('.content'), this.className === 'OutputWindow' ); return false; } /** * Get informations about an item */ function onItemInfo(event) { var index = parseInt( this.parentNode.getAttribute('data-index'), 10); var item = _input[index]; event.stopImmediatePropagation(); if (!item) { return false; } // Don't add the same UI twice, remove it if (ItemInfo.uid === item.ITID) { ItemInfo.remove(); return false; } // Add ui to window ItemInfo.append(); ItemInfo.uid = item.ITID; ItemInfo.setItem(item); return false; } /** * Select an item, put it on the other box */ function onItemSelected() { var input, from, to; if (_type === Vending.Type.BUY || _type === Vending.Type.VENDING_STORE) { return; } input = Vending.ui.find('.InputWindow:first'); if (jQuery.contains(input.get(0), this)) { from = input; to = Vending.ui.find('.OutputWindow:first'); } else { from = Vending.ui.find('.OutputWindow:first'); to = input; } requestMoveItem( parseInt( this.getAttribute('data-index'), 10), from.find('.content:first'), to.find('.content:first'), from === input ); } /** * Focus an item */ function onItemFocus() { Vending.ui.find('.item.selected').removeClass('selected'); jQuery(this).addClass('selected'); } /** * Update scroll by block (32px) */ function onScroll( event ) { var delta; if (event.originalEvent.wheelDelta) { delta = event.originalEvent.wheelDelta / 120 ; if (window.opera) { delta = -delta; } } else if (event.originalEvent.detail) { delta = -event.originalEvent.detail; } this.scrollTop = Math.floor(this.scrollTop/32) * 32 - (delta * 32); return false; } /** * Start dragging an item */ function onDragStart( event ) { var container, img, url; var InputWindow, OutputWindow; InputWindow = Vending.ui.find('.InputWindow:first').get(0); OutputWindow = Vending.ui.find('.OutputWindow:first').get(0); container = (jQuery.contains(InputWindow, this) ? InputWindow : OutputWindow).className; img = new Image(); url = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1].replace(/"/g, ''); img.src = url; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: 'item', from: 'Vending', container: container, index: this.getAttribute('data-index') }) ); } Vending.onVendingSkill = function onVendingSkill() { //console.log("Vending.onVendingSkill"); this.setList(CartItems.list); this.ui.show(); }; Vending.onSubmit = function onSubmit() { var output; var i, count,shopname,ctr = 0; output = []; count = _output.length; shopname = this.ui.find('.shopname').val(); for (i = 0; i < count; ++i) { if (_output[i] && _output[i].count) { output.push(_output[i]); ctr++; } } if(ctr < 1) { this.onRemove(); return; } var pkt = new PACKET.CZ.REQ_OPENSTORE2(); pkt.storeName = shopname; pkt.result = 1; pkt.storeList = output; if(!shopname) { InputBox.append(); InputBox.setType('shopname', false, shopname); InputBox.onSubmitRequest = function(shopname) { InputBox.remove(); pkt.storeName = shopname; if(shopname) { this._shopname = shopname; Network.sendPacket(pkt); } }; } else { this._shopname = shopname; Network.sendPacket(pkt); } this.onRemove(); }; /** * Create componentand export it */ return UIManager.addComponent(Vending); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Session = require('Engine/SessionStorage'); var Renderer = require('Renderer/Renderer'); var Altitude = require('Renderer/Map/Altitude'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./MiniMap.html'); var cssText = require('text!./MiniMap.css'); /** * Create MiniMap component */ var MiniMap = new UIComponent( 'MiniMap', htmlText, cssText ); /** * Mouse can cross this UI */ MiniMap.mouseMode = UIComponent.MouseMode.CROSS; /** * @var {boolean} do not focus this UI */ MiniMap.needFocus = false; /** * @var {Preferences} */ var _preferences = Preferences.get('MiniMap', { zoom: 1.0, opacity: 2 }); /** * @var {Array} party members marker */ var _party = []; /** * @var {Array} guild members marker */ var _guild = []; /** * @var {Array} others markers */ var _markers = []; /** * @var {Image} arrow image */ var _arrow = new Image(); /** * @var {Image} minimap image */ var _map = new Image(); /** * @var {CanvasRenderingContext2D} canvas context */ var _ctx; /** * Initialize minimap */ MiniMap.init = function init() { function genericUpdateZoom( value ) { return function() { MiniMap.updateZoom( value ); }; } _ctx = this.ui.find('canvas')[0].getContext('2d'); this.zoom = 0.0; this.opacity = 2; Client.loadFile( DB.INTERFACE_PATH + 'map/map_arrow.bmp', function(dataURI){ _arrow.src = dataURI; }); // Bind DOM elements this.ui.find('.plus').mousedown(genericUpdateZoom(+1)); this.ui.find('.minus').mousedown(genericUpdateZoom(-1)); }; /** * Once append to HTML */ MiniMap.onAppend = function onAppend() { // Set preferences this.updateZoom( _preferences.zoom ); this.toggleOpacity( _preferences.opacity + 1 ); Renderer.render(render); }; /** * Set map * * @param {string} mapname */ MiniMap.setMap = function setMap( mapname ) { _map.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='; var path = DB.INTERFACE_PATH.replace('data/texture/', '') + 'map/' + mapname.replace(/\..*/,'.bmp'); path = path.replace(/\//g, '\\'); // normalize path separator path = DB.mapalias[path] || path; Client.loadFile( 'data/texture/' + path, function(dataURI){ _map.src = dataURI; }); }; /** * KeyDown Handler * * @param {object} event * @return {boolean} */ MiniMap.onKeyDown = function onKeyDown( event ) { // Will not work on Chrome :( if (event.which === KEYS.TAB && KEYS.CTRL) { this.toggleOpacity(); event.stopImmediatePropagation(); return false; } return true; }; /** * Once removed from HTML */ MiniMap.onRemove = function onRemove() { // Clean up memory _party.length = 0; _guild.length = 0; _markers.length = 0; }; /** * Add a party mark to minimap * * @param {number} key account id * @param {number} x position * @param {number} y position */ MiniMap.addPartyMemberMark = function addPartyMember( key, x, y) { var i, count = _party.length; var r = Math.random; for (i = 0; i < count; ++i) { if (_party[i].key === key) { _party[i].x = x; _party[i].y = y; return; } } _party.push({ key: key, x: x, y: y, color: 'rgb('+ [ r()*255 | 0, r()*255 | 0, r()*255 | 0] +')' }); }; /** * Remove a party mark from minimap * * @param {number} key account id */ MiniMap.removePartyMemberMark = function removePartyMemberMark( key ) { var i, count = _party.length; for (i = 0; i < count; ++i) { if (_party[i].key === key) { _party.splice(i, 1); break; } } }; /** * Add a guild mark to minimap * * @param {number} key account id * @param {number} x position * @param {number} y position */ MiniMap.addGuildMemberMark = function addGuildMemberMark( key, x, y ) { var i, count = _guild.length; for (i = 0; i < count; ++i) { if (_guild[i].key === key) { _guild[i].x = x; _guild[i].y = y; return; } } _guild.push({ key: key, x: x, y: y }); }; /** * Remove a guild mark from minimap * * @param {number} key account id */ MiniMap.removeGuildMemberMark = function removeGuildMemberMark( key ) { var i, count = _guild.length; for (i = 0; i < count; ++i) { if (_guild[i].key === key) { _guild.splice(i, 1); break; } } }; /** * Add a npc mark to minimap * * @param {number} key id * @param {number} x position * @param {number} y position * @param {Array} color */ MiniMap.addNpcMark = function addNPCMark( key, x, y, lcolor, time ) { var i, count = _markers.length; var color = [ ( lcolor & 0x00ff0000 ) >> 16, ( lcolor & 0x0000ff00 ) >> 8, ( lcolor & 0x000000ff ) ]; for (i = 0; i < count; ++i) { if (_markers[i].key === key) { _markers[i].x = x; _markers[i].y = y; _markers[i].color = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')'; _markers[i].tick = Renderer.tick + time; return; } } _markers.push({ key: key, x: x, y: y, color: 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')', tick: Renderer.tick + time }); }; /** * Remove a NPC mark from minimap * * @param {number} key id */ MiniMap.removeNpcMark = function removeNPCMark( key ) { var i, count = _markers.length; for (i = 0; i < count; ++i) { if (_markers[i].key === key) { _markers.splice(i, 1); break; } } }; /** * Change zoom * TODO: implement zoom feature in minimap. */ MiniMap.updateZoom = function updateZoom( value ) { // _preferences.zoom = ...; // _preferences.save(); }; /** * Change window opacity */ MiniMap.toggleOpacity = function toggleOpacity( opacity ) { this.opacity = ( ( arguments.length ? opacity : this.opacity ) + 2 ) % 3; _preferences.opacity = this.opacity; _preferences.save(); switch (this.opacity) { case 0: this.ui.hide(); break; case 1: _ctx.globalAlpha = 0.5; this.ui.show(); break; case 2: _ctx.globalAlpha = 1.0; this.ui.show(); break; } }; /** * Render GUI */ function render( tick ) { var width = Altitude.width; var height = Altitude.height; var pos = Session.Entity.position; var max = Math.max(width, height); var f = 1 / max * 128; var start_x = (max-width) / 2 * f; var start_y = (height-max) / 2 * f; var i, count, dot; // Rendering map _ctx.clearRect( 0, 0, 128, 128 ); if (_map.complete && _map.width) { _ctx.drawImage( _map, 0, 0, 128, 128 ); } // Render attached player arrow if (_arrow.complete && _arrow.width) { _ctx.save(); _ctx.translate( start_x + pos[0] * f, start_y + 128 - pos[1] * f ); _ctx.rotate( ( Session.Entity.direction + 4 ) * 45 * Math.PI / 180 ); _ctx.drawImage( _arrow, -_arrow.width * 0.5, -_arrow.height * 0.5 ); _ctx.restore(); } // Render NPC mark if (tick % 1000 > 500) { // blink effect count = _markers.length; for (i = 0; i < count; ++i) { dot = _markers[i]; // Auto remove feature if (dot.tick < Renderer.tick) { _markers.splice( i, 1 ); i--; count--; continue; } // Render mark _ctx.fillStyle = dot.color; _ctx.fillRect( start_x + dot.x * f - 1, start_y + 128 - dot.y * f - 4, 2, 8 ); _ctx.fillRect( start_x + dot.x * f - 4, start_y + 128 - dot.y * f - 1, 8, 2 ); } } // Render party members count = _party.length; for (i = 0; i < count; ++i) { dot = _party[i]; _ctx.fillStyle = 'white'; _ctx.fillRect( start_x + dot.x * f - 3, start_y + 128 - dot.y * f - 3, 6, 6 ); _ctx.fillStyle = dot.color; _ctx.fillRect( start_x + dot.x * f - 2, start_y + 128 - dot.y * f - 2, 4, 4 ); } // Render guild members count = _guild.length; if (count) { _ctx.fillStyle = 'rgb(245,175,200)'; _ctx.strokeStyle = 'white'; for (i = 0; i < count; ++i) { dot = _guild[i]; _ctx.moveTo( start_x + dot.x * f + 0, start_y + 128 - dot.y * f - 3 ); _ctx.lineTo( start_x + dot.x * f + 3, start_y + 128 - dot.y * f + 3 ); _ctx.lineTo( start_x + dot.x * f - 3, start_y + 128 - dot.y * f + 3 ); } _ctx.stroke(); _ctx.fill(); } } /** * Create component and return it */ return UIManager.addComponent(MiniMap); });
define(function( require ) { 'use strict'; /** * Dependencies */ var StatusTable = require('DB/Status/StatusInfo'); var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Texture = require('Utils/Texture'); var Client = require('Core/Client'); var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var cssText = require('text!./StatusIcons.css'); /** * Create component */ var StatusIcons = new UIComponent( 'StatusIcons', null, cssText); /** * Mouse can cross this UI */ StatusIcons.mouseMode = UIComponent.MouseMode.CROSS; /** * @var {boolean} do not focus this UI */ StatusIcons.needFocus = false; /** * @var {Array} status list */ var _status = {}; /** * Initialize component */ StatusIcons.init = function init() { this.ui = jQuery('<div/>').attr('id', 'StatusIcons'); }; /** * Start rendering icons */ StatusIcons.onAppend = function onAppend() { Renderer.render(rendering); }; /** * Stop rendering icons */ StatusIcons.onRemove = function onRemove() { Renderer.stop(rendering); }; /** * Clean up component */ StatusIcons.clean = function clean() { this.ui.empty(); _status = {}; }; /** * Update icon on screen * * @param {number} status id * @param {number} enable/disable * @param {number} life time */ StatusIcons.update = function update( index, state, life ) { // Not in DB, no icons... if (!(index in StatusTable) || !StatusTable[index].icon) { return; } // Remove it if (!state) { removeElementIndex(index); resetElementsPosition(); return; } // Intialize slot if (!(index in _status)) { createElement(index); } // Save tick for progressbar _status[index].start = Renderer.tick; _status[index].end = Renderer.tick + life; // 9999 means Infinity in official client (lol) if (life === 9999) { _status[index].end = Infinity; } // Image already loaded if (_status.img) { return; } // Load image Client.loadFile( 'data/texture/effect/' + StatusTable[index].icon, function(data){ Texture.load( data, function(){ if (_status[index] && !_status[index].img) { _status[index].img = this; addElement(_status[index].element); } }); }); }; /** * Reset elements position. * * Used when one element is removed. */ function resetElementsPosition() { var element, i, count, x, y; var elements = StatusIcons.ui.find('.state'); count = elements.length; x = 0; y = 0; for (i = 0; i < count; ++i, y += 36) { if (y > Renderer.height - 166) { y = 0; x += 45; } element = elements[i]; element.style.top = y + 'px'; element.style.right = x + 'px'; } } /** * Remove an element from list and DOM * * @param {number} index */ function removeElementIndex( index ) { if (!(index in _status)) { return; } var element = _status[index].element; if (element && element.parentNode) { element.parentNode.removeChild(element); } delete _status[index]; } /** * Create an element * * @param {number} index */ function createElement( index ) { var state, canvas; state = document.createElement('div'); state.className = 'state'; canvas = document.createElement('canvas'); canvas.width = 32; canvas.height = 32; state.appendChild(canvas); _status[index] = {}; _status[index].element = state; _status[index].ctx = canvas.getContext('2d'); // Add description if (StatusTable[index].descript) { var i, count, time; var info, lines; info = document.createElement('div'); info.className = 'description'; lines = StatusTable[index].descript; count = lines.length; for (i = 0; i < count; ++i) { var line = document.createElement('div'); line.textContent = lines[i][0]; // Custom color if (lines[i][1]) { line.style.color = lines[i][1]; } // Time value line.innerHTML = line.innerHTML.replace('%s', '<span class="time">0</span>'); info.appendChild(line); } time = info.getElementsByClassName('time'); if (time.length) { _status[index].time = time[0]; _status[index].timeTick = 0; } state.appendChild(info); } } /** * Add element to the list, helper for multi-column * * @param {CanvasElement} */ function addElement(element) { var x, y, count; var elements = StatusIcons.ui.find('.state'); var max = (Renderer.height-166) / 36 | 0; count = elements.length; x = (count / max | 0) * 45; y = (count % max) * 36; element.style.top = y + 'px'; element.style.right = x + 'px'; StatusIcons.ui.append(element); } /** * Rendering a status icon * * @param {object} status * @param {number} tick */ function renderStatus(status, now) { var start, end, perc; var color, ctx; if (!status.img) { return; } ctx = status.ctx; start = status.start; end = status.end; if (now > end) { end = now; } if (end < now + 60000) { color = 'rgba(255,150,50,0.65)'; perc = 1 - (end-now)/60000; } else { color = 'rgba(255,255,255,0.65)'; perc = (now-start) / (end-60000-start); } ctx.clearRect(0, 0, 32, 32); ctx.drawImage(status.img, 0, 0); ctx.fillStyle = color; ctx.beginPath(); ctx.arc(16, 16, 24, 1.5 * Math.PI, ((1.5 + perc*2) % 2) * Math.PI); ctx.lineTo(16, 16); ctx.fill(); if (status.time && status.timeTick + 1000 < now) { status.timeTick = now; var tick = (end-now) / 1000 | 0; var seconds = tick % 60; var minutes = (tick / 60) | 0 status.time.textContent = (now >= end || end === Infinity) ? '' : ( (minutes ? minutes + ' ' + DB.getMessage(1807, 'minute') + ' ' : '') + seconds + ' ' + DB.getMessage(1808, 'second') ); } } /** * Rendering status icons progressbar * * @param {number} tick */ function rendering(tick) { var i, count; var indexes; indexes = Object.keys(_status); count = indexes.length; for (i = 0; i < count; ++i) { renderStatus(_status[indexes[i]], tick); } } /** * Create component and return it */ return UIManager.addComponent(StatusIcons); });
define(function (require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var Renderer = require('Renderer/Renderer'); var KEYS = require('Controls/KeyEventHandler'); var DB = require('DB/DBManager'); var MsgStringIDs = require('DB/MsgStringIds'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./InputBox.html'); var cssText = require('text!./InputBox.css'); /** * Create NpcBox component */ var InputBox = new UIComponent('InputBox', htmlText, cssText); /** * Initialize GUI */ InputBox.init = function Init() { this.draggable(); this.ui.css({ top: (Renderer.height - 120) / 1.5 - 49, left: (Renderer.width - 280) / 2 + 1 }); this.ui.find('button').click(validate.bind(this)); this.overlay = jQuery('<div/>') .addClass('win_popup_overlay') .css('zIndex', 30) .click(function () { this.remove(); }.bind(this)); }; /** * Once in HTML, focus the input */ InputBox.onAppend = function OnAppend() { this.ui.find('input').select(); }; /** * Remove data from UI */ InputBox.onRemove = function OnRemove() { this.ui.find('input').val(''); this.ui.find('.text').text(''); this.overlay.detach(); }; /** * Key Listener * * @param {object} event * @return {boolean} */ InputBox.onKeyDown = function OnKeyDown(event) { if (!this.isPersistent && event.which === KEYS.ENTER) { validate.call(this); event.stopImmediatePropagation(); return false; } return true; }; /** * Validate input * * @param {ClickEvent} */ function validate() { var text = this.ui.find('input').val(); if (!this.isPersistent || text.length) { if (this.ui.hasClass('number')) { text = parseInt(text, 10) | 0; } this.onSubmitRequest(text); } } /** * Set input type * * @param {string} input type (number or text) * @param {boolean} is the popup persistent ? false : clicking in any part of the game will remove the input * @param {string|number} default value to show in the input */ InputBox.setType = function setType(type, isPersistent, defaultVal) { this.isPersistent = !!isPersistent; if (!this.isPersistent) { this.overlay.appendTo('body'); } switch (type) { case 'number': this.ui.addClass('number'); this.ui.find('.text').text(DB.getMessage(MsgStringIDs.MSI_INPUT_NUMBER)); this.ui.find('input').attr('type', 'text'); defaultVal = defaultVal || 0; break; case 'text': this.ui.removeClass('number'); this.ui.find('.text').text(''); this.ui.find('input').attr('type', 'text'); break; case 'pass': this.ui.removeClass('number'); this.ui.find('.text').text(''); this.ui.find('input').attr('type', 'password'); break; case 'mail': this.ui.removeClass('number'); this.ui.find('.text').text(DB.getMessage(MsgStringIDs.MSI_ENTER_EMAIL_TOOLTIP)); this.ui.find('input').attr('type', 'password'); break; } if (typeof defaultVal !== 'undefined') { this.ui.find('input') .val(defaultVal) .select(); } }; /** * Callback to define */ InputBox.onSubmitRequest = function OnSubmitRequest() { }; /** * Stored component and return it */ return UIManager.addComponent(InputBox); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var SkillInfo = require('DB/SkillInfo'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Renderer = require('Renderer/Renderer'); var Mouse = require('Controls/MouseEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var SkillTargetSelection = require('UI/Components/SkillTargetSelection/SkillTargetSelection'); var SkillDescription = require('UI/Components/SkillDescription/SkillDescription'); var htmlText = require('text!./SkillList.html'); var cssText = require('text!./SkillList.css'); /** * Create Component */ var SkillList = new UIComponent( 'SkillList', htmlText, cssText ); /** * @var {Preferences} window preferences */ var _preferences = Preferences.get('SkillList', { x: 100, y: 200, width: 8, height: 8, show: false, }, 1.0); /** * @var {Array} Skill List * { SKID, type, level, spcost, attackRange, skillName, upgradable } */ var _list = []; /** * @var {jQuery} level up button reference */ var _levelupBtn; /** * @var {number} skill points */ var _points = 0; /** * Initialize UI */ SkillList.init = function init() { // Don't activate drag drop when clicking on buttons this.ui.find('.titlebar .base').mousedown(function(event){ event.stopImmediatePropagation(); return false; }); // Bind buttons this.ui.find('.footer .extend').mousedown(onResize); this.ui.find('.titlebar .close').click(function(){ SkillList.ui.hide(); return false; }); // Get level up button _levelupBtn = this.ui.find('.btn.levelup').detach(); _levelupBtn.click(function(){ var index = this.parentNode.parentNode.getAttribute('data-index'); SkillList.onIncreaseSkill( parseInt(index, 10) ); }); // TODO: this.ui // Use skill .on('dblclick', '.skill .icon, .skill .name', function(){ var main = jQuery(this).parent(); if (!main.hasClass('skill')) { main = main.parent(); } SkillList.useSkill(parseInt(main.data('index'), 10)); }) // Skill info .on('contextmenu', '.skill .icon, .skill .name', function(){ var index = parseInt(this.parentNode.getAttribute('data-index'), 10); var skill = getSkillById(index); SkillDescription.append(); SkillDescription.setSkill(skill.SKID); }) // background color .on('mousedown', '.selectable', function(event){ var main = jQuery(this).parent(); if (!main.hasClass('skill')) { main = main.parent(); } SkillList.ui.find('.skill').removeClass('selected'); main.addClass('selected'); event.stopImmediatePropagation(); }) // Stop drag drop .on('mousedown', '.skill', function(event){ event.stopImmediatePropagation(); }) // Item drag drop feature .on('dragstart', '.skill', function(event){ var index = parseInt(this.getAttribute('data-index'), 10); var skill = getSkillById(index); // Can't drag a passive skill (or disabled) if (!skill || !skill.level || !skill.type) { event.stopImmediatePropagation(); return false; } var img = new Image(); img.src = this.firstChild.firstChild.src; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: 'skill', from: 'skilllist', data: skill }) ); }) // Clean up .on('dragend', '.skill', function(){ delete window._OBJ_DRAG_; }); this.draggable(); }; /** * Apply preferences once append to body */ SkillList.onAppend = function onAppend() { // Apply preferences if (!_preferences.show) { this.ui.hide(); } resize(_preferences.width, _preferences.height); this.ui.css({ top: Math.min( Math.max( 0, _preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, _preferences.x), Renderer.width - this.ui.width()) }); }; /** * Remove Skill window from DROM */ SkillList.onRemove = function onRemove() { // Save preferences _preferences.show = this.ui.is(':visible'); _preferences.y = parseInt(this.ui.css('top'), 10); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.width = Math.floor( this.ui.find('.content').width() / 32 ); _preferences.height = Math.floor( this.ui.find('.content').height() / 32 ); _preferences.save(); }; /** * Process shortcut * * @param {object} key */ SkillList.onShortCut = function onShortCut( key ) { switch (key.cmd) { case 'TOGGLE': this.ui.toggle(); // Fix zIndex if (this.ui.is(':visible')) { this.ui[0].parentNode.appendChild(this.ui[0]); } break; } }; /** * Add skills to the list */ SkillList.setSkills = function setSkills( skills ) { var i, count; for (i = 0, count = _list.length; i < count; ++i) { this.onUpdateSkill( _list[i].SKID, 0); } _list.length = 0; this.ui.find('.content table').empty(); for (i = 0, count = skills.length; i < count; ++i) { this.addSkill( skills[i] ); } }; /** * Insert skill to list * * @param {object} skill */ SkillList.addSkill = function addSkill( skill ) { // Custom skill ? if (!(skill.SKID in SkillInfo)) { return; } // Already in list, update it instead of duplicating it if (this.ui.find('.skill .id' + skill.SKID + ':first').length) { this.updateSkill( skill ); return; } var sk = SkillInfo[ skill.SKID ]; Client.loadFile( DB.INTERFACE_PATH + 'item/' + sk.Name + '.bmp', function(data){ var levelup = _levelupBtn.clone(true); var className = !skill.level ? 'disabled' : skill.type ? 'active' : 'passive'; var element = jQuery( '<tr class="skill id' + skill.SKID + ' ' + className + '" data-index="'+ skill.SKID +'" draggable="true">' + '<td class="icon"><img src="'+ data +'" width="24" height="24" /></td>' + '<td class="levelupcontainer"></td>' + '<td class=selectable>' + '<div class="name">' + sk.SkillName +'<br/>' + '<span class="level">' + ( sk.bSeperateLv ? 'Lv : <span class="current">'+ skill.level + '</span> / <span class="max">' + skill.level + '</span>' : 'Lv : <span class="current">'+ skill.level +'</span>' ) + '</span>' + '</div>' + '</td>' + '<td class="selectable type">' + '<div class="consume">' + ( skill.type ? 'Sp : <span class="spcost">' + skill.spcost + '</span>' : 'Passive' ) + '</div>' + '</td>' + '</tr>' ); if (!skill.upgradable || !_points) { levelup.hide(); } element.find('.levelupcontainer').append( levelup ); SkillList.ui.find('.content table').append(element); }); _list.push(skill); this.onUpdateSkill( skill.SKID, skill.level); }; /** * Remove skill from list */ SkillList.removeSkill = function removeSkill() { }; /** * Update skill * * @param {object} skill : { SKID, level, spcost, attackRange, upgradable } */ SkillList.updateSkill = function updateSkill( skill ) { var target = getSkillById(skill.SKID); var element; if (!target) { return; } // Update Memory target.level = skill.level; target.spcost = skill.spcost; target.attackRange = skill.attackRange; target.upgradable = skill.upgradable; // Update UI element = this.ui.find('.skill .id' + skill.SKID + ':first'); element.find('.level .current, .level .max').text(skill.level); element.find('.spcost').text(skill.spcost); element.removeClass('active passive disabled'); element.addClass(!skill.level ? 'disabled' : skill.type ? 'active' : 'passive'); if (skill.upgradable) { element.find('.levelup').show(); } else { element.find('.levelup').hide(); } this.onUpdateSkill( skill.SKID, skill.level); }; /** * Use a skill * * @param {number} skill id */ SkillList.useSkill = function useSkill( id ) { var skill = getSkillById(id); if (!skill || !skill.level || !skill.type) { return; } // Self if (skill.type & SkillTargetSelection.TYPE.SELF) { this.onUseSkill( skill.SKID, skill.level); } // no elseif intended (see flying kick). if (skill.type & SkillTargetSelection.TYPE.TARGET) { SkillTargetSelection.append(); SkillTargetSelection.set(skill, skill.type); } }; /** * Set skill points amount * * @param {number} skill points count */ SkillList.setPoints = function SetPoints( amount ) { var i, count; this.ui.find('.skpoints_count').text(amount); // Do not need to update the UI if ((!_points) === (!amount)) { _points = amount; return; } _points = amount; count = _list.length; for (i = 0; i < count; ++i) { if (_list[i].upgradable && amount) { this.ui.find('.skill.id' + _list[i].SKID + ' .levelup').show(); } else { this.ui.find('.skill.id' + _list[i].SKID + ' .levelup').hide(); } } }; /** * Find a skill by it's id * * @param {number} skill id * @returns {Skill} */ function getSkillById( id ) { var i, count = _list.length; for (i = 0; i < count; ++i) { if (_list[i].SKID === id) { return _list[i]; } } return null; } /** * Extend SkillList window size */ function onResize( event ) { var ui = SkillList.ui; var top = ui.position().top; var left = ui.position().left; var lastWidth = 0; var lastHeight = 0; var _Interval; function resizing() { var extraX = -6; var extraY = 32; var w = Math.floor( (Mouse.screen.x - left - extraX) / 32 ); var h = Math.floor( (Mouse.screen.y - top - extraY) / 32 ); // Maximum and minimum window size w = Math.min( Math.max(w, 8), 8); h = Math.min( Math.max(h, 4), 10); if (w === lastWidth && h === lastHeight) { return; } resize( w, h ); lastWidth = w; lastHeight = h; } // Start resizing _Interval = setInterval(resizing, 30); // Stop resizing on left click jQuery(window).one('mouseup', function(event){ if (event.which === 1) { clearInterval(_Interval); } }); event.stopImmediatePropagation(); return false; } /** * Extend SkillList window size * * @param {number} width * @param {number} height */ function resize( width, height ) { width = Math.min( Math.max(width, 8), 8); height = Math.min( Math.max(height, 4), 10); SkillList.ui.find('.content').css({ width: width * 32, height: height * 32 }); } /** * Abstract function to define */ SkillList.onUseSkill = function onUseItem(){}; SkillList.onIncreaseSkill = function onIncreaseSkill() {}; SkillList.onUpdateSkill = function onUpdateSkill(){}; SkillList.getSkillById = getSkillById; /** * Create component and export it */ return UIManager.addComponent(SkillList); });
define(function(require) { 'use strict'; /** * Dependencies */ var KEYS = require('Controls/KeyEventHandler'); var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var SoundOption = require('UI/Components/SoundOption/SoundOption'); var GraphicsOption = require('UI/Components/GraphicsOption/GraphicsOption'); var htmlText = require('text!./Escape.html'); var cssText = require('text!./Escape.css'); /** * Create Escape window component */ var Escape = new UIComponent( 'Escape', htmlText, cssText ); /** * Initialize UI */ Escape.init = function init() { this.ui.css({ top: (Renderer.height-this.ui.height()) * 0.75, left:(Renderer.width -this.ui.width()) * 0.5 }); this.draggable(); this.ui.find('.node').mousedown(function(event){ event.stopImmediatePropagation(); return false; }); // Only used in specific case this.ui.find('button').show(); this.ui.find('.resurection, .savepoint').hide(); this.ui.find('.sound').click(onToggleSoundUI); this.ui.find('.graphics').click(onToggleGraphicUI); this.ui.find('.resurection').click(this.onResurectionRequest); this.ui.find('.savepoint').click(this.onReturnSavePointRequest); this.ui.find('.charselect').click(this.onCharSelectionRequest); this.ui.find('.exit').click(this.onExitRequest); this.ui.find('.cancel').click(function(){ Escape.ui.hide(); }); }; /** * Window must not be visible once append * but need to be here to manage key event */ Escape.onAppend = function onAppend() { this.ui.hide(); }; /** * Reset buttons once UI is removed */ Escape.onRemove = function onRemove() { this.ui.hide(); this.ui.find('.savepoint').hide(); this.ui.find('.graphics, .sound, .hotkey').show(); }; /** * Key Listener * * @param {object} event * @return {boolean} */ Escape.onKeyDown = function onKeyDown( event ) { if (event.which === KEYS.ESCAPE) { this.ui.toggle(); if (this.ui.is(':visible')) { this.focus(); } event.stopImmediatePropagation(); return false; } return true; }; /** * Click on Sound button, toggle the UI */ function onToggleSoundUI() { if (!SoundOption.ui || !SoundOption.ui[0].parentNode) { SoundOption.append(); } else { SoundOption.remove(); } } /** * Click on Graphic button, toggle the UI */ function onToggleGraphicUI() { if (!GraphicsOption.ui || !GraphicsOption.ui[0].parentNode) { GraphicsOption.append(); } else { GraphicsOption.remove(); } } /** * @var {function} callback when player want to resuret using Token of Siegfried */ Escape.onResurectionRequest = function onResurectionRequest(){}; /** * @var {function} callback to define to disconnect from game */ Escape.onExitRequest = function onExitRequest(){}; /** * @var {function} callback when player want to resurect using Token of Siegfried */ Escape.onReturnSavePointRequest = function onReturnSavePointRequest(){}; /** * @var {function} callback when player want to return to char selection */ Escape.onCharSelectionRequest = function onCharSelectionRequest(){}; /** * Create component and export it */ return UIManager.addComponent(Escape); });
define(function(require) { "use strict"; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Session = require('Engine/SessionStorage'); var Renderer = require('Renderer/Renderer'); var Camera = require('Renderer/Camera'); var SpriteRenderer = require('Renderer/SpriteRenderer'); var Entity = require('Renderer/Entity/Entity'); var KEYS = require('Controls/KeyEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var WinStats = require('UI/Components/WinStats/WinStats'); var htmlText = require('text!./Equipment.html'); var cssText = require('text!./Equipment.css'); /** * Create Component */ var Equipment = new UIComponent( 'Equipment', htmlText, cssText ); /** * Location constants */ Equipment.LOCATION = { HEAD_BOTTOM: 1 << 0, WEAPON: 1 << 1, GARMENT: 1 << 2, ACCESSORY1: 1 << 3, ARMOR: 1 << 4, SHIELD: 1 << 5, SHOES: 1 << 6, ACCESSORY2: 1 << 7, HEAD_TOP: 1 << 8, HEAD_MID: 1 << 9 }; /** * Storage to store equipment list */ Equipment.list = {}; /** * Initialize UI */ Equipment.init = function Init() { // Preferences structure this.preferences = Preferences.get('Equipment', { x: 480, y: 200, show: false, reduce: false, stats: true }, 1.0); this.ctx = this.ui.find('canvas')[0].getContext('2d'); this.entity = new Entity(Session.Entity); this.showEquip = false; // Append WinStats to content WinStats.prepare(); WinStats.__loaded = true; this.ui.find('.status_component').append(WinStats.ui); this.draggable(); // Don't activate drag drop when clicking on buttons this.ui.find('.titlebar .base').mousedown(function( event ){ event.stopImmediatePropagation(); }) // Bind events this.ui.find('.titlebar .mini').click(function(){ Equipment.ui.find('.panel').toggle(); }); this.ui.find('.titlebar .close').click(function(){ Equipment.ui.hide(); return false; }); // Show Status ? this.ui.find('.view_status').mousedown(this.toggleStatus); this.ui.find('.show_equip').mousedown(this.toggleEquip); // drag, drop items this.ui.on('dragover', this.onDragOver.bind(this) ); this.ui.on('dragleave', this.onDragLeave.bind(this) ); this.ui.on('drop', this.onDrop.bind(this) ); // Bind items this.ui.find('.content') // Right click on item .on('contextmenu', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var item = Equipment.list[index]; if( item ) { // Don't add the same UI twice, remove it if( ItemInfo.uid === item.ITID ) { ui.remove(); } // Add ui to window else { ItemInfo.append(); ItemInfo.uid = item.ITID; ItemInfo.setItem( item ); } } event.stopImmediatePropagation(); return false; }) // Want to unequip .on('dblclick', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); Equipment.onUnEquip( index ); }); }; /** * Append to body */ Equipment.onAppend = function OnAppend() { // Apply preferences this.ui.css({ top: Math.min( Math.max( 0, this.preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, this.preferences.x), Renderer.width - this.ui.width()) }); // Hide window ? if( !this.preferences.show ) { this.ui.hide(); } // Reduce window ? if( this.preferences.reduce ) { this.ui.find('.panel').hide(); } // Show status window ? if( !this.preferences.stats ) { this.ui.find('.status_component').hide(); Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/viewon.bmp', function(data){ Equipment.ui.find('.view_status').css('backgroundImage', 'url(' + data + ')'); }); } Renderer.render(this.renderCharacter); }; /** * Remove Inventory from window (and so clean up items) */ Equipment.onRemove = function OnRemove() { // Stop rendering Renderer.stop(this.renderCharacter); // Clean equipments this.list = {}; this.ui.find('.col1, .col3').empty(); // Save preferences this.preferences.show = this.ui.is(':visible'); this.preferences.reduce = this.ui.find('.panel').css('display') === 'none'; this.preferences.stats = this.ui.find('.status_component').css('display') !== 'none'; this.preferences.y = parseInt(this.ui.css('top'), 10); this.preferences.x = parseInt(this.ui.css('left'), 10); this.preferences.save(); }; /** * Key Listener * * @param {object} event * @return {boolean} */ Equipment.onKeyDown = function OnKeyDown( event ) { if( KEYS.ALT && event.which === KEYS.Q ) { this.ui.toggle(); if( this.ui.is(':visible') ) { this.ui[0].parentNode.appendChild(this.ui[0]); } event.stopImmediatePropagation(); return false; } return true; }; /** * Show or hide equipment * * @param {boolean} on */ Equipment.setEquipConfig = function SetEquipConfig( on ) { Equipment.showEquip = on; Client.loadFile( DB.INTERFACE_PATH + 'checkbox_' + ( on ? '1' : '0' ) + '.bmp', function(data){ Equipment.ui.find('.show_equip').css('backgroundImage', 'url(' + data + ')'); }); }; /** * Display or not status window */ Equipment.toggleStatus = function ToggleStatus() { var ui = this; var status = Equipment.ui.find('.status_component'); var state = status.is(':visible') ? 'on' : 'off'; status.toggle(); Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/view' + state + '.bmp', function(data){ ui.style.backgroundImage = 'url(' + data + ')'; }); return false; }; /** * Does player can see your equipment ? */ Equipment.toggleEquip = function ToggleEquip() { Equipment.onConfigUpdate( 0, !Equipment.showEquip ? 1 : 0 ); return false; }; /** * Rendering character */ Equipment.renderCharacter = function RenderCharacter() { // 2D render use much CPU, dont render it if not visible. if( Equipment.ui.is(':visible') ) { var ctx = Equipment.ctx; // Rendering SpriteRenderer.bind2DContext( ctx, 30, 130 ); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height ); Camera.direction = 4; Equipment.entity._renderSub(0); } }; /** * Find elements in html base on item location * * @param {number} location * @returns {string} selector */ function GetSelectorFromLocation( location ) { var selector = []; if( location & Equipment.LOCATION.HEAD_TOP ) selector.push(".head_top"); if( location & Equipment.LOCATION.HEAD_MID ) selector.push(".head_mid"); if( location & Equipment.LOCATION.HEAD_BOTTOM ) selector.push(".head_bottom"); if( location & Equipment.LOCATION.ARMOR ) selector.push(".armor"); if( location & Equipment.LOCATION.WEAPON ) selector.push(".weapon"); if( location & Equipment.LOCATION.SHIELD ) selector.push(".shield"); if( location & Equipment.LOCATION.GARMENT ) selector.push(".garment"); if( location & Equipment.LOCATION.SHOES ) selector.push(".shoes"); if( location & Equipment.LOCATION.ACCESSORY1 ) selector.push(".accessory1"); if( location & Equipment.LOCATION.ACCESSORY2 ) selector.push(".accessory2"); return selector.join(', '); } /** * Add an equipment to the window * * @param {Item} item */ Equipment.equip = function Equip( item, location ) { this.list[ item.index] = item; var it = DB.getItemInfo( item.ITID ); var ui = this.ui.find( GetSelectorFromLocation( arguments.length === 2 ? location : item.location ) ); Client.loadFile( DB.INTERFACE_PATH + 'item/' + it.identifiedResourceName + '.bmp', function(data){ var name = ( item.RefiningLevel ? '+' + item.RefiningLevel + ' ' : '') + it.identifiedDisplayName; var lines = [] while( name.length ) { lines.push( name.substr(0,13) ); name = name.substr(13); } ui.html( '<div class="item '+ item.index +'">' + '<button style="background-image:url(' + data + ')"></button>' + '<span>' + lines.join("\n") + '</span>' + '</div>' ); }); }; /** * Remove equipment from window * * @param {number} item index * @param {number} item location */ Equipment.unEquip = function( index, location ) { var selector = GetSelectorFromLocation( location ); this.ui.find( selector ).empty(); var item = this.list[ index ]; delete this.list[ index ]; return item; }; /** * Drag an item over the equipment, show where to place the item */ Equipment.onDragOver = function OnDragOver( event ) { if( window._OBJ_DRAG_ ) { var data = window._OBJ_DRAG_; var item, selector, ui; // Just support items for now ? if( data.type === "item") { item = data.data; // Only for TYPE.WEAPON and TYPE.EQUIP if( (item.type === 4 || item.type === 5) && item.IsIdentified && !item.IsDamaged ) { selector = GetSelectorFromLocation( item.location ); ui = this.ui.find(selector); Client.loadFile( DB.INTERFACE_PATH + "basic_interface/item_invert.bmp", function(data){ ui.css('backgroundImage', 'url('+ data + ')'); }); } } } event.stopImmediatePropagation(); return false; }; /** * Drag out the window */ Equipment.onDragLeave = function OnDragLeave( event ) { this.ui.find('td').css('backgroundImage','none'); event.stopImmediatePropagation(); return false; }; /** * Drop an item in the equipment, equip it if possible */ Equipment.onDrop = function OnDrop( event ) { var item, data; try { data = JSON.parse( event.originalEvent.dataTransfer.getData("Text") ); } catch(e) {} // Just support items for now ? if( data && data.type === "item") { item = data.data; // Only for TYPE.WEAPON and TYPE.EQUIP if( (item.type === 4 || item.type === 5) && item.IsIdentified && !item.IsDamaged ) { this.ui.find('td').css('backgroundImage','none'); this.onEquipItem( item.index, item.location ); } } event.stopImmediatePropagation(); return false; }; /** * Abstract method to define */ Equipment.onUnEquip = function OnUnEquip( index ){}; Equipment.onConfigUpdate = function OnConfigUpdate( type, value ){}; Equipment.onEquipItem = function OnEquipItem( index, location ){}; /** * Create component and export it */ return UIManager.addComponent(Equipment); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var MonsterTable = require('DB/Monsters/MonsterTable'); var Preferences = require('Core/Preferences'); var KEYS = require('Controls/KeyEventHandler'); var Renderer = require('Renderer/Renderer'); var Entity = require('Renderer/Entity/Entity'); var SpriteRenderer = require('Renderer/SpriteRenderer'); var Camera = require('Renderer/Camera'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./CharSelect.html'); var cssText = require('text!./CharSelect.css'); /** * Create Chararacter Selection namespace */ var CharSelect = new UIComponent( 'CharSelect', htmlText, cssText ); /** * @var {Preferences} save where the cursor position is */ var _preferences = Preferences.get('CharSelect', { index: 0 }, 1.0 ); /** * @var {number} max slots */ var _maxSlots = 3 * 9; /** * var {Array} list of characters */ var _list = []; /** * @var {Array} list of characters (index by slot) */ var _slots = []; /** * @var {Array} list of entities (index by slot) */ var _entitySlots = []; /** * @var {number} selector index */ var _index = 0; /** * @var {Array} canvas context */ var _ctx = []; /** * var {number} sex */ var _sex = 0; /** * Initialize UI */ CharSelect.init = function Init() { var ui = this.ui; ui.css({ top: (Renderer.height-342)/2, left: (Renderer.width-576)/2 }); // Bind buttons ui.find('.ok' ).click(connect); ui.find('.cancel').click(cancel); ui.find('.make' ).click(create); ui.find('.delete').click(suppress); ui.find('.arrow.left' ).mousedown(genericArrowDown(-1)); ui.find('.arrow.right').mousedown(genericArrowDown(+1)); // Bind canvas ui.find('.slot1').mousedown(genericCanvasDown(0)); ui.find('.slot2').mousedown(genericCanvasDown(1)); ui.find('.slot3').mousedown(genericCanvasDown(2)); ui.find('canvas'). dblclick(function(){ if (_slots[_index]) { connect(); } else { create(); } }). each(function(){ _ctx.push( this.getContext('2d') ); }); this.draggable(); }; /** * Once append to body */ CharSelect.onAppend = function onAppend() { _index = _preferences.index; this.ui.find('.slotinfo .number').text( _list.length + ' / ' + _maxSlots ); this.ui.find('.pageinfo .count').text( _maxSlots / 3 ); // Update values moveCursorTo(_index); // Start rendering Renderer.render(render); }; /** * Stop rendering */ CharSelect.onRemove = function onRemove() { _preferences.index = _index; _preferences.save(); Renderer.stop(); }; /** * Bind Key events * * @param {object} event */ CharSelect.onKeyDown = function onKeyDown( event ) { switch (event.which) { case KEYS.ESCAPE: cancel(); break; case KEYS.LEFT: moveCursorTo(_index-1); break; case KEYS.RIGHT: moveCursorTo(_index+1); break; case KEYS.SUPR: if (_slots[_index]) { suppress(); } break; case KEYS.ENTER: if (_slots[_index]) { connect(); } else { create(); } break; default: return true; } event.stopImmediatePropagation(); return false; }; /** * Add players to window * * @param {object} pkt - packet structure */ CharSelect.setInfo = function setInfo( pkt ) { _maxSlots = Math.floor((pkt.TotalSlotNum + pkt.PremiumStartSlot) || 9); // default 9 ? _sex = pkt.sex; _slots.length = 0; _entitySlots.length = 0; _list.length = 0; if (pkt.charInfo) { var i, count = pkt.charInfo.length; for (i = 0; i < count; ++i) { CharSelect.addCharacter( pkt.charInfo[i] ); // Guess the max slot // required if the client is < 20100413 and have more than 9 slots _maxSlots = Math.max( _maxSlots, Math.floor(pkt.charInfo[i].CharNum / 3 + 1) * 3 ); } } this.ui.find('.slotinfo .number').text( _list.length + ' / ' + _maxSlots ); this.ui.find('.pageinfo .count').text( _maxSlots / 3 ); moveCursorTo( _index ); }; /** * Answer from server to delete a character * * @param {number} error id */ CharSelect.deleteAnswer = function DeleteAnswer( error ) { this.on('keydown'); switch (error) { // Do nothing, just re-set the keydown case -2: return; // Success (clean up character) case -1: delete _slots[_index]; delete _entitySlots[_index]; var i = 0; var count = _list.length; while (i < count) { if (_list[i].CharNum === _index) { _list.splice( i, 1 ); --count; } else { i++; } } // Refresh UI moveCursorTo( _index ); this.ui.find('.slotinfo .number').text( _list.length + ' / ' + _maxSlots ); return; default: // Others error ? case 0: // Incorrect adress email UIManager.showMessageBox( DB.getMessage(301), 'ok' ); break; } }; /** * Adding a Character to the list * * @param {object} character data */ CharSelect.addCharacter = function addCharacter( character ) { character.sex = _sex; _list.push( character ); _slots[ character.CharNum ] = character; _entitySlots[ character.CharNum ] = new Entity(); _entitySlots[ character.CharNum ].set( character ); }; /** * Callback to use */ CharSelect.onExitRequest = function onExitRequest(){}; CharSelect.onDeleteRequest = function onDeleteRequest(){}; CharSelect.onCreateRequest = function onCreateRequest(){}; CharSelect.onConnectRequest = function onConnectRequest(){}; /** * Generic method to handle mousedown on arrow * * @param {number} value to move */ function genericArrowDown( value ) { return function( event ) { moveCursorTo((_index + _maxSlots + value) % _maxSlots ); event.stopImmediatePropagation(); return false; }; } /** * Generic method to handle mousedown on arrow * * @param {number} value to move */ function genericCanvasDown( value ) { return function( event ) { moveCursorTo( Math.floor(_index / 3) * 3 + value ); event.stopImmediatePropagation(); return false; }; } /** * Press "cancel" or ESCAPE key */ function cancel() { UIManager.showPromptBox( DB.getMessage(17), 'ok', 'cancel', function(){ CharSelect.onExitRequest(); }, null); } /** * Jumping to Character creation window */ function create() { CharSelect.onCreateRequest( _index ); } /** * Select Player, connect */ function connect() { if (_slots[_index]) { _preferences.index = _index; _preferences.save(); CharSelect.onConnectRequest( _slots[_index] ); } } /** * Delete a character */ function suppress() { if (_slots[_index]) { CharSelect.off('keydown'); CharSelect.onDeleteRequest( _slots[_index].GID ); } } /** * Move cursor, update window value * * @param {number} index */ function moveCursorTo( index ) { var ui = CharSelect.ui; var $charinfo = ui.find('.charinfo'); // Set the last entity to idle var entity = _entitySlots[_index]; if (entity) { entity.setAction({ action: entity.ACTION.IDLE, frame: 0, play: true, repeat: true }); } // Move _index = (index + _maxSlots) % _maxSlots; ui.find('.box_select'). removeClass('slot1 slot2 slot3'). addClass('slot' + (_index % 3 + 1)); // Set page ui.find('.pageinfo .current').text( Math.floor( _index / 3) + 1 ); // Not found, just clean up. entity = _entitySlots[_index]; if (!entity) { $charinfo.find('div').empty(); ui.find('.make').show(); ui.find('.delete').hide(); ui.find('.ok').hide(); return; } // Animate the character entity.setAction({ action: entity.ACTION.READYFIGHT, frame: 0, play: true, repeat: true }); // Bind new value ui.find('.make').hide(); ui.find('.delete').show(); ui.find('.ok').show(); var info = _slots[_index]; $charinfo.find('.name').text( info.name ); $charinfo.find('.job').text( MonsterTable[info.job] || '' ); $charinfo.find('.lvl').text( info.level ); $charinfo.find('.exp').text( info.exp ); $charinfo.find('.hp').text( info.hp ); $charinfo.find('.sp').text( info.sp ); //TODO: Check win_select.bmp size to insert it if needed ? //$charinfo.find('.map').text( info.lastMap || '' ); $charinfo.find('.str').text( info.Str ); $charinfo.find('.agi').text( info.Agi ); $charinfo.find('.vit').text( info.Vit ); $charinfo.find('.int').text( info.Int ); $charinfo.find('.dex').text( info.Dex ); $charinfo.find('.luk').text( info.Luk ); } /** * Render sprites to canvas */ function render() { var i, count, idx; Camera.direction = 4; idx = Math.floor(_index / 3) * 3; count = _ctx.length; for (i = 0; i < count; ++i) { _ctx[i].clearRect(0, 0, _ctx[i].canvas.width, _ctx[i].canvas.height); if (_entitySlots[idx+i]) { SpriteRenderer.bind2DContext(_ctx[i], 63, 130); _entitySlots[idx+i].renderEntity(); } } } /** * Create componentand export it */ return UIManager.addComponent(CharSelect); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Renderer = require('Renderer/Renderer'); var Mouse = require('Controls/MouseEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var InputBox = require('UI/Components/InputBox/InputBox'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var Equipment = require('UI/Components/Equipment/Equipment'); var htmlText = require('text!./Inventory.html'); var cssText = require('text!./Inventory.css'); /** * Create Component */ var Inventory = new UIComponent( 'Inventory', htmlText, cssText ); /** * Item type constants */ Inventory.ITEM = { HEALING: 0, USABLE: 2, ETC: 3, WEAPON: 4, EQUIP: 5, CARD: 6, PETEGG: 7, PETEQUIP: 8, AMMO: 10, USABLE_SKILL: 11, USABLE_UNK: 18 }; /** * Tab constant */ Inventory.TAB = { USABLE: 0, EQUIP: 1, ETC: 2 }; /** * Store inventory items */ Inventory.list = []; /** * @var {number} tab */ var _tab = Inventory.TAB.USABLE; /** * @var {number} used to remember the window height */ var _realSize = 0; /** * Initialize UI */ Inventory.init = function Init() { // Preferences structure this.preferences = Preferences.get('Inventory', { x: 200, y: 200, width: 7, height: 4, show: false, reduce: false, tab: this.TAB.USABLE }, 1.0); // Don't activate drag drop when clicking on buttons this.ui.find('.titlebar .base').mousedown(function( event ){ event.stopImmediatePropagation(); return false; }); // Bind buttons this.ui.find('.titlebar .mini').click(ToggleReduction.bind(this)); this.ui.find('.tabs button').mousedown(SwitchTab); this.ui.find('.footer .extend').mousedown(OnResize.bind(this)); this.ui.find('.titlebar .close').click(function(){ Inventory.ui.hide(); return false; }); // on drop item this.ui .on('drop', OnDrop) .on('dragover', function(event){ event.stopImmediatePropagation(); return false; }); var overlay = this.ui.find('.overlay'); this.ui.find('.container .content') // Scroll feature should block at each line .on('mousewheel DOMMouseScroll', onScroll) // Title feature .on('mouseover', '.item', function(){ var idx = parseInt( this.className.match(/ (\d+)$/)[1], 10); var item = Inventory.getItemByIndex(idx); if (!item) { return; } // Get back data var it = DB.getItemInfo( item.ITID ); var pos = jQuery(this).position(); // Display box overlay.show(); overlay.css({top: pos.top, left:pos.left+35}); overlay.html( ( item.RefiningLevel ? '+' + item.RefiningLevel + ' ' : '') + ( item.IsIdentified ? it.identifiedDisplayName : it.unidentifiedDisplayName ) + ( it.slotCount ? ' [' + it.slotCount + ']' : '') + ' ' + ( item.count || 1 ) + ' ea' ); if (item.IsIdentified) { overlay.removeClass('grey'); } else { overlay.addClass('grey'); } }) // Stop title feature .on('mouseout', '.item', function(){ overlay.hide(); }) // Stop drag drop feature .on('mousedown', '.item', function(event){ event.stopImmediatePropagation(); }) // Item drag drop feature .on('dragstart', '.item', function(event){ // Set image to the drag drop element var img = new Image(); var url = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1]; url = url = url.replace(/^\"/, '').replace(/\"$/, ''); // Firefox bug img.src = url; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var item = Inventory.getItemByIndex(index); if (!item) { return; } event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: 'item', from: 'inventory', data: item }) ); // Stop component to be draggable jQuery(window).trigger('mouseup'); overlay.hide(); }) // Clean up .on('dragend', '.item', function(){ delete window._OBJ_DRAG_; }) // Right click on item .on('contextmenu', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var item = Inventory.getItemByIndex(index); event.stopImmediatePropagation(); if (!item) { return false; } // Don't add the same UI twice, remove it if (ItemInfo.uid === item.ITID) { ItemInfo.remove(); return false; } // Add ui to window ItemInfo.append(); ItemInfo.uid = item.ITID; ItemInfo.setItem(item); return false; }) // Equip/Use item .on('dblclick', '.item', function(event) { var matches = this.className.match(/(\w+) (\d+)/); var index = parseInt(matches[2], 10); var item = Inventory.getItemByIndex(index); if (item) { Inventory.useItem(item); overlay.hide(); } event.stopImmediatePropagation(); return false; }); this.draggable(); }; /** * Apply preferences once append to body */ Inventory.onAppend = function OnAppend() { // Apply preferences if (!this.preferences.show) { this.ui.hide(); } _tab = this.preferences.tab; Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/tab_itm_0'+ (_tab+1) +'.bmp', function(data){ Inventory.ui.find('.tabs').css('backgroundImage', 'url("' + data + '")'); }); this.resize( this.preferences.width, this.preferences.height ); this.ui.css({ top: Math.min( Math.max( 0, this.preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, this.preferences.x), Renderer.width - this.ui.width()) }); _realSize = this.preferences.reduce ? 0 : this.ui.height(); this.ui.find('.titlebar .mini').trigger('mousedown'); }; /** * Remove Inventory from window (and so clean up items) */ Inventory.onRemove = function OnRemove() { this.ui.find('.container .content').empty(); this.list.length = 0; jQuery('.ItemInfo').remove(); // Save preferences this.preferences.show = this.ui.is(':visible'); this.preferences.reduce = !!_realSize; this.preferences.tab = _tab; this.preferences.y = parseInt(this.ui.css('top'), 10); this.preferences.x = parseInt(this.ui.css('left'), 10); this.preferences.width = Math.floor( (this.ui.width() - (23 + 16 + 16 - 30)) / 32 ); this.preferences.height = Math.floor( (this.ui.height() - (31 + 19 - 30 )) / 32 ); this.preferences.save(); }; /** * Process shortcut * * @param {object} key */ Inventory.onShortCut = function onShurtCut( key ) { switch (key.cmd) { case 'TOGGLE': this.ui.toggle(); if (this.ui.is(':visible')) { this.ui[0].parentNode.appendChild(this.ui[0]); } else { // Fix Mouse.intersect bug this.ui.trigger('mouseleave'); } break; } }; /** * Extend inventory window size */ function OnResize( event ) { var ui = this.ui; var content = ui.find('.container .content'); var hide = ui.find('.hide'); var top = ui.position().top; var left = ui.position().left; var lastWidth = 0; var lastHeight = 0; var _Interval; function Resizing() { var extraX = 23 + 16 + 16 - 30; var extraY = 31 + 19 - 30; var w = Math.floor( (Mouse.screen.x - left - extraX) / 32 ); var h = Math.floor( (Mouse.screen.y - top - extraY) / 32 ); // Maximum and minimum window size w = Math.min( Math.max(w, 6), 9); h = Math.min( Math.max(h, 2), 6); if (w === lastWidth && h === lastHeight) { return; } Inventory.resize( w, h ); lastWidth = w; lastHeight = h; //Show or hide scrollbar if (content.height() === content[0].scrollHeight) { hide.show(); } else { hide.hide(); } } // Start resizing _Interval = setInterval( Resizing, 30); // Stop resizing jQuery(window).one('mouseup', function(event){ // Only on left click if (event.which === 1) { clearInterval(_Interval); } }); event.stopImmediatePropagation(); return false; } /** * Extend inventory window size * * @param {number} width * @param {number} height */ Inventory.resize = function Resize( width, height ) { width = Math.min( Math.max(width, 6), 9); height = Math.min( Math.max(height, 2), 6); this.ui.find('.container .content').css({ width: width * 32 + 13, // 13 = scrollbar height: height * 32 }); this.ui.css({ width: 23 + 16 + 16 + width * 32, height: 31 + 19 + height * 32 }); }; /** * Modify tab, filter display entries */ function SwitchTab( event ) { var idx = jQuery(this).index(); _tab = idx; Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/tab_itm_0'+ (idx+1) +'.bmp', function(data){ Inventory.ui.find('.tabs').css('backgroundImage', 'url(' + data + ')'); Filter.call(Inventory, idx); }); event.stopImmediatePropagation(); return false; } /** * Hide/show inventory's content */ function ToggleReduction( event ) { // TODO: fix this part if (_realSize) { this.ui.find('.panel').show(); this.ui.height(_realSize); _realSize = 0; } else { _realSize = this.ui.height(); this.ui.height(17); this.ui.find('.panel').hide(); } event.stopImmediatePropagation(); return false; } /** * Update tabulation */ function Filter() { this.ui.find('.container .content').empty(); var i, count; for (i = 0, count = this.list.length; i < count; ++i) { this.addItemSub( this.list[i] ); } } /** * Search in a list for an item by its index * * @param {number} index * @returns {Item} */ Inventory.getItemByIndex = function getItemByIndex( index ) { var i, count; var list = Inventory.list; for (i = 0, count = list.length; i < count; ++i) { if (list[i].index === index) { return list[i]; } } return null; }; /** * Drop an item from storage to inventory * * @param {event} */ function OnDrop( event ) { var item, data; event.stopImmediatePropagation(); try { data = JSON.parse(event.originalEvent.dataTransfer.getData('Text')); item = data.data; } catch(e) { return false; } // Just allow item from storage if (data.type !== 'item' || data.from !== 'storage') { return false; } // Have to specify how much if (item.count > 1) { InputBox.append(); InputBox.setType('number', false, item.count); InputBox.onSubmitRequest = function OnSubmitRequest( count ) { InputBox.remove(); require('UI/Components/Storage/Storage').reqRemoveItem( item.index, parseInt(count, 10 ) ); }; } // Only one, don't have to specify else { require('UI/Components/Storage/Storage').reqRemoveItem( item.index, 1 ); } return false; } /** * Block the scroll to move 32px at each move */ function onScroll( event ) { var delta; if (event.originalEvent.wheelDelta) { delta = event.originalEvent.wheelDelta / 120 ; if (window.opera) { delta = -delta; } } else if (event.originalEvent.detail) { delta = -event.originalEvent.detail; } this.scrollTop = Math.floor(this.scrollTop/32) * 32 - (delta * 32); event.stopImmediatePropagation(); return false; } /** * Add items to the list */ Inventory.setItems = function SetItems(items) { var i, count; for (i = 0, count = items.length; i < count ; ++i) { if (this.addItemSub( items[i] )) { this.list.push( items[i] ); } } }; /** * Insert Item to inventory * * @param {object} Item */ Inventory.addItem = function AddItem( item ) { var object = this.getItemByIndex(item.index); if (object) { object.count += item.count; this.ui.find('.item.'+ item.index + ' .count').text( object.count ); this.onUpdateItem(object.ITID, object.count); return; } if (this.addItemSub(item)) { this.list.push(item); this.onUpdateItem(item.ITID, item.count); } }; /** * Add item to inventory * * @param {object} Item */ Inventory.addItemSub = function AddItemSub( item ) { var tab; var ui = this.ui; switch (item.type) { case Inventory.ITEM.HEALING: case Inventory.ITEM.USABLE: case Inventory.ITEM.USABLE_SKILL: case Inventory.ITEM.USABLE_UNK: tab = Inventory.TAB.USABLE; break; case Inventory.ITEM.WEAPON: case Inventory.ITEM.EQUIP: case Inventory.ITEM.PETEGG: case Inventory.ITEM.PETEQUIP: tab = Inventory.TAB.EQUIP; break; default: case Inventory.ITEM.ETC: case Inventory.ITEM.CARD: case Inventory.ITEM.AMMO: tab = Inventory.TAB.ETC; break; } // Equip item (if not arrow) if (item.WearState && item.WearState !== 32768) { Equipment.equip(item); return false; } if (tab === _tab) { var it = DB.getItemInfo( item.ITID ); Client.loadFile( DB.INTERFACE_PATH + 'item/' + ( item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName ) + '.bmp', function(data){ var content = ui.find('.container .content'); content.append( '<div class="item '+ item.index +'" draggable="true">' + '<div class="icon" style="background-image:url(' + data + ')"></div>' + '<div class="amount">'+ (item.count ? '<span class="count">' + item.count + '</span>' + ' ' : '') + '</div>' + '</div>' ); if (content.height() < content[0].scrollHeight) { ui.find('.hide').hide(); } }); } return true; }; /** * Remove item from inventory * * @param {number} index in inventory * @param {number} count */ Inventory.removeItem = function RemoveItem( index, count ) { var item = this.getItemByIndex(index); // Emulator failed to complete the operation // do not remove item from inventory if (!item || count <= 0) { return null; } if (item.count) { item.count -= count; if (item.count > 0) { this.ui.find('.item.' + index + ' .count').text( item.count ); this.onUpdateItem(item.ITID, item.count); return item; } } this.list.splice( this.list.indexOf(item), 1 ); this.ui.find('.item.' + index).remove(); this.onUpdateItem(item.ITID, 0); var content = this.ui.find('.container .content'); if (content.height() === content[0].scrollHeight) { this.ui.find('.hide').show(); } return item; }; /** * Remove item from inventory * * @param {number} index in inventory * @param {number} count */ Inventory.updateItem = function UpdateItem( index, count ) { var item = this.getItemByIndex(index); if (!item) { return; } item.count = count; // Update quantity if (item.count > 0) { this.ui.find('.item.' + index + ' .count').text( item.count ); this.onUpdateItem(item.ITID, item.count); return; } // no quantity, remove this.list.splice( this.list.indexOf(item), 1 ); this.ui.find('.item.' + index).remove(); this.onUpdateItem(item.ITID, 0); var content = this.ui.find('.container .content'); if (content.height() === content[0].scrollHeight) { this.ui.find('.hide').show(); } }; /** * Use an item * * @param {Item} item */ Inventory.useItem = function UseItem( item ) { switch (item.type) { // Usable item case Inventory.ITEM.HEALING: case Inventory.ITEM.USABLE: case Inventory.ITEM.USABLE_UNK: Inventory.onUseItem( item.index ); break; case Inventory.ITEM.USABLE_SKILL: break; // Equip item case Inventory.ITEM.WEAPON: case Inventory.ITEM.EQUIP: case Inventory.ITEM.PETEQUIP: if (item.IsIdentified && !item.IsDamaged) { Inventory.onEquipItem( item.index, item.location ); } break; case Inventory.ITEM.AMMO: break; } return; }; /** * Get item object * * @param {number} id * @returns {Item} */ Inventory.getItemById = function GetItemById( id ) { var i, count; var list = Inventory.list; for (i = 0, count = list.length; i < count; ++i) { if (list[i].ITID === id) { return list[i]; } } return null; }; /** * functions to define */ Inventory.onUseItem = function OnUseItem(/* index */){}; Inventory.onEquipItem = function OnEquipItem(/* index, location */){}; Inventory.onUpdateItem = function OnUpdateItem(/* index, amount */){}; /** * Create component and export it */ return UIManager.addComponent(Inventory); });
define(function(require) { "use strict"; /** * Dependencies */ var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var KEYS = require('Controls/KeyEventHandler'); var Renderer = require('Renderer/Renderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./NpcMenu.html'); var cssText = require('text!./NpcMenu.css'); /** * Create NPC Menu component */ var NpcMenu = new UIComponent( 'NpcMenu', htmlText, cssText ); /** * @var {number} index selected in menu */ NpcMenu.index = 0; /** * Initialize component */ NpcMenu.init = function OnInit() { this.ui.find('.ok').click( this.validate.bind(this) ); this.ui.find('.cancel').click( this.cancel.bind(this) ); this.ui.css({ top: Math.max(376, Renderer.height/2 + 76 ), left: Math.max( Renderer.width/3, 20) }); this.draggable(); // Scroll feature should block at each line this.ui.find('.content').on('scroll', function(){ this.scrollTop = Math.floor(this.scrollTop/20) * 20; }); }; /** * Bind KeyDown event */ NpcMenu.onKeyDown = function(event) { switch( event.which ) { case KEYS.ENTER: this.validate(); break; case KEYS.ESCAPE: this.cancel(); break; case KEYS.UP: this.ui.find('div').removeClass('selected'); this.index = Math.max( this.index - 1, 0); this.ui.find('.content div:eq('+ this.index +')').addClass('selected'); var content = this.ui.find('.content')[0]; var top = this.index * 20; if( top < content.scrollTop ) { content.scrollTop = top; } break; case KEYS.DOWN: this.ui.find('div').removeClass('selected'); this.index = Math.min( this.index + 1, this.list.length -1 ); this.ui.find('.content div:eq('+ this.index +')').addClass('selected'); var content = this.ui.find('.content')[0]; var top = this.index * 20; if( top >= content.scrollTop + 80 ) { content.scrollTop = top - 60; } break; default: return true; } event.stopImmediatePropagation(); return false; }; /** * Initialize menu * * @param {string} menu * @param {number} gid - npc id */ NpcMenu.setMenu = function SetMenu( menu, gid ) { this.ownerID = gid; this.list = menu.split(':'); this.index = 0; var content = this.ui.find('.content'); var i, count; content.empty(); for( i = 0, count = this.list.length; i < count; ++i ) { // Don't display empty menu if( this.list[i].length ) { jQuery('<div/>') .text( this.list[i] ) .data('index', i) .appendTo(content); } } content.find('div') .mousedown( this.selectIndex ) .dblclick( this.validate.bind(this) ); content.find('div:first') .addClass('selected'); }; /** * Submit an index */ NpcMenu.validate = function Validate() { this.onSelectMenu( this.ownerID, this.index + 1 ); }; /** * Pressed cancel, client send "255" as value */ NpcMenu.cancel = function Cancel() { this.onSelectMenu( this.ownerID, 255 ); }; /** * Select an index, change background color */ NpcMenu.selectIndex = function SelectIndex() { NpcMenu.ui.find('.content div').removeClass('selected'); NpcMenu.index = +jQuery(this).data('index'); NpcMenu.ui.find('.content div:eq('+ NpcMenu.index +')').addClass('selected'); }; /** * Abstract callback to define */ NpcMenu.onSelectMenu = function OnSelectMenu( gid, index ){}; /** * Create componentand export it */ return UIManager.addComponent(NpcMenu); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Renderer = require('Renderer/Renderer'); var Mouse = require('Controls/MouseEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var InputBox = require('UI/Components/InputBox/InputBox'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var htmlText = require('text!./Storage.html'); var cssText = require('text!./Storage.css'); /** * Create Component */ var Storage = new UIComponent( 'Storage', htmlText, cssText ); /** * Item type constants */ Storage.ITEM = { HEALING: 0, USABLE: 2, ETC: 3, WEAPON: 4, EQUIP: 5, CARD: 6, PETEGG: 7, PETEQUIP: 8, AMMO: 10, USABLE_SKILL: 11, USABLE_UNK: 18 }; /** * Tab constant */ Storage.TAB = { ITEM: 0, KAFRA: 1, ARMS: 2, ARMOR: 3, AMMO: 4, CARD: 5, ETC: 6 }; /** * @var {Array} inventory items */ var _list = []; /** * @var {Preference} structure to save */ var _preferences = Preferences.get('Storage', { x: 200, y: 500, height: 8, tab: Storage.TAB.ITEM }, 1.0); /** * Initialize UI */ Storage.init = function Init() { // Bind buttons this.ui.find('.tabs button').mousedown(switchTab); this.ui.find('.footer .extend').mousedown(onResize); this.ui.find('.footer .close').click(this.onClosePressed.bind(this)); // drag, drop items this.ui.on('drop', onDrop); this.ui.on('dragover', function(event){ event.stopImmediatePropagation(); return false; }); var overlay = this.ui.find('.overlay'); this.ui.find('.container .content') // Scroll feature should block at each line .on('mousewheel DOMMouseScroll', onScroll) // Title feature .on('mouseover', '.item', function(){ var idx = parseInt( this.getAttribute('data-index'), 10); var i = getItemIndexById(idx); // Not found if (i < 0) { return; } // Get back data var item = _list[i]; var it = DB.getItemInfo( item.ITID ); var pos = jQuery(this).position(); // Display box overlay.show(); overlay.css({top: pos.top-10, left:pos.left+35}); overlay.html( ( item.RefiningLevel ? '+' + item.RefiningLevel + ' ' : '') + ( item.IsIdentified ? it.identifiedDisplayName : it.unidentifiedDisplayName ) + ( it.slotCount ? ' [' + it.slotCount + ']' : '') + ' ' + ( item.count || 1 ) + ' ea' ); if (item.IsIdentified) { overlay.removeClass('grey'); } else { overlay.addClass('grey'); } }) // Stop title feature .on('mouseout', '.item', function(){ overlay.hide(); }) // Stop drag drop feature .on('mousedown', '.item', function(event){ event.stopImmediatePropagation(); }) // Item drag drop feature .on('dragstart', '.item', function(event){ // Set image to the drag drop element var img = new Image(); var url = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1]; url = url = url.replace(/^\"/, '').replace(/\"$/, ''); // Firefox bug img.src = url; var index = parseInt(this.getAttribute('data-index'), 10); var i = getItemIndexById(index); if (i > -1) { event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: 'item', from: 'storage', data: _list[i] }) ); } // Stop component to be draggable jQuery(window).trigger('mouseup'); overlay.hide(); }) // Clean up .on('dragend', '.item', function(){ delete window._OBJ_DRAG_; }) // Right click on item .on('contextmenu', '.item', function(event) { var index = parseInt(this.getAttribute('data-index'), 10); var i = getItemIndexById(index); if (i > -1) { // Don't add the same UI twice, remove it if (ItemInfo.uid === _list[i].ITID) { ItemInfo.remove(); } // Add ui to window ItemInfo.append(); ItemInfo.uid = _list[i].ITID; ItemInfo.setItem( _list[i] ); } event.stopImmediatePropagation(); return false; }); this.draggable(); }; /** * Apply preferences once append to body */ Storage.onAppend = function onAppend() { Client.loadFile( DB.INTERFACE_PATH + 'basic_interface/tab_itm_ex_0'+ (_preferences.tab+1) +'.bmp', function(data){ Storage.ui.find('.tabs').css('backgroundImage', 'url("' + data + '")'); }); resizeHeight(_preferences.height); this.ui.css({ top: Math.min( Math.max( 0, _preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, _preferences.x), Renderer.width - this.ui.width()) }); }; /** * Remove Storage from window (and so clean up items) */ Storage.onRemove = function onRemove() { this.ui.find('.container .content').empty(); _list.length = 0; // Save preferences _preferences.y = parseInt(this.ui.css('top'), 10); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.height = Math.floor( (this.ui.height() - (31 + 19 - 30)) / 32 ); _preferences.save(); }; /** * Add items to the list * * @param {Array} item list */ Storage.setItems = function setItems(items) { var i, count; for (i = 0, count = items.length; i < count ; ++i) { if (this.addItemSub( items[i])) { _list.push(items[i]); } } }; /** * Insert Item to Storage * * @param {object} Item */ Storage.addItem = function addItem( item ) { var i = getItemIndexById(item.index); // Found, update quantity if (i > -1) { _list[i].count += item.count; this.ui.find('.item[data-index="'+ item.index +'"] .count').text(_list[i].count); return; } if (this.addItemSub(item)) { _list.push(item); } }; /** * Add item to Storage * * @param {object} Item */ Storage.addItemSub = function addItemSub( item ) { var tab; switch (item.type) { case Storage.ITEM.HEALING: case Storage.ITEM.USABLE: case Storage.ITEM.USABLE_SKILL: case Storage.ITEM.USABLE_SKILL_UNK: tab = Storage.TAB.ITEM; break; // TOFIX: WTH is it for ? // tab = Storage.TAB.KAFRA; // break; case Storage.ITEM.EQUIP: case Storage.ITEM.PETEQUIP: tab = Storage.TAB.ARMOR; break; case Storage.ITEM.WEAPON: tab = Storage.TAB.ARMS; break; case Storage.ITEM.AMMO: tab = Storage.TAB.AMMO; break; case Storage.ITEM.CARD: tab = Storage.TAB.CARD; break; default: case Storage.ITEM.ETC: case Storage.ITEM.PETEGG: tab = Storage.TAB.ETC; break; } if (tab === _preferences.tab) { var it = DB.getItemInfo( item.ITID ); this.ui.find('.container .content').append( '<div class="item" data-index="' + item.index +'" draggable="true">' + '<div class="icon"></div>' + '<div class="amount">'+ (item.count ? '<span class="count">' + item.count + '</span>' + ' ' : '') + '</div>' + '<span class="name">' + ( item.RefiningLevel ? '+' + item.RefiningLevel + ' ' : '') + ( item.IsIdentified ? it.identifiedDisplayName : it.unidentifiedDisplayName ) + '</span>' + '</div>' ); Client.loadFile( DB.INTERFACE_PATH + 'item/' + ( item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName ) + '.bmp', function(data){ this.ui.find('.item[data-index="'+ item.index +'"] .icon').css('backgroundImage', 'url('+ data +')'); }.bind(this)); } return true; }; /** * Remove item from Storage * * @param {number} index in Storage */ Storage.removeItem = function removeItem( index, count ) { var i = getItemIndexById(index); var item; // Not found if (i < 0) { return null; } if (_list[i].count) { _list[i].count -= count; if (_list[i].count > 0) { this.ui.find('.item[data-index="'+ index +'"] .count').text(_list[i].count); return _list[i]; } } // Remove item item = _list[i]; _list.splice( i, 1 ); this.ui.find('.item[data-index="'+ index +'"]').remove(); return item; }; /** * Update or set the current amount of items in storage in ui */ Storage.setItemInfo = function setItemInfo( current, limit ) { this.ui.find('.footer .current').text(current); this.ui.find('.footer .limit').text(limit); }; /** * Extend Storage window size */ function onResize( event ) { var ui = Storage.ui; var top = ui.position().top; var lastHeight = 0; var _Interval; function resizing() { var extraY = 31 + 19 - 30; var h = Math.floor( (Mouse.screen.y - top - extraY) / 32 ); // Maximum and minimum window size h = Math.min( Math.max(h, 8), 17); if (h === lastHeight) { return; } resizeHeight(h); lastHeight = h; } // Start resizing _Interval = setInterval( resizing, 30); // Stop resizing jQuery(window).one('mouseup', function(event){ // Only on left click if (event.which === 1) { clearInterval(_Interval); } }); event.stopImmediatePropagation(); return false; } /** * Extend Storage window size */ function resizeHeight(height) { height = Math.min( Math.max(height, 8), 17); Storage.ui.find('.container .content').css('height', height * 32); Storage.ui.css('height', 31 + 19 + height * 32); } /** * Modify tab, filter display entries */ function switchTab( event ) { var idx = jQuery(this).index(); _preferences.tab = idx; Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/tab_itm_ex_0'+ (idx+1) +'.bmp', function(data){ Storage.ui.find('.tabs').css('backgroundImage', 'url("' + data + '")'); filter(idx); }); event.stopImmediatePropagation(); return false; } /** * Drop from inventory to storage */ function onDrop( event ) { var item, data; try { data = JSON.parse( event.originalEvent.dataTransfer.getData('Text') ); } catch(e) {} event.stopImmediatePropagation(); // Just support items for now ? if (!data || data.type !== 'item' || data.from !== 'inventory') { return false; } item = data.data; // Have to specify how much if (item.count > 1) { InputBox.append(); InputBox.setType('number', false, item.count); InputBox.onSubmitRequest = function OnSubmitRequest( count ) { InputBox.remove(); Storage.reqAddItem( item.index, parseInt(count, 10 ) ); }; return false; } Storage.reqAddItem( item.index, 1 ); return false; } /** * Change tab, * Update its content */ function filter() { Storage.ui.find('.container .content').empty(); var i, count; for (i = 0, count = _list.length; i < count; ++i) { Storage.addItemSub(_list[i]); } } /** * Get item index in list base on it's ID * * @param {number} item id */ function getItemIndexById( index ) { var i, count; for (i = 0, count = _list.length; i < count; ++i) { if (_list[i].index === index) { return i; } } return -1; } /** * Update scroll by block (32px) */ function onScroll( event ) { var delta; if (event.originalEvent.wheelDelta) { delta = event.originalEvent.wheelDelta / 120 ; if (window.opera) { delta = -delta; } } else if (event.originalEvent.detail) { delta = -event.originalEvent.detail; } this.scrollTop = Math.floor(this.scrollTop/32) * 32 - (delta * 32); return false; } /** * Callbacks */ Storage.onClosePressed = function onClosedPressed(){}; Storage.reqAddItem = function reqAddItem(){}; Storage.reqRemoveItem = function reqRemoveItem(){}; /** * Create component and export it */ return UIManager.addComponent(Storage); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var jQuery = require('Utils/jquery'); var Renderer = require('Renderer/Renderer'); var Client = require('Core/Client'); var Events = require('Core/Events'); var Preferences = require('Core/Preferences'); var KEYS = require('Controls/KeyEventHandler'); var BattleMode = require('Controls/BattleMode'); var History = require('./History'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ContextMenu = require('UI/Components/ContextMenu/ContextMenu'); var htmlText = require('text!./ChatBox.html'); var cssText = require('text!./ChatBox.css'); var ProcessCommand = require('Controls/ProcessCommand'); /** * @var {number} max message in the chatbox */ var MAX_MSG = 50; /** * @var {History} message cached in history */ var _historyMessage = new History(); /** * @var {History} nickname cached in history */ var _historyNickName = new History(true); /** * @var {number} Chatbox position's index */ var _heightIndex = 2; /** * @var {Preferences} structure */ var _preferences = Preferences.get('ChatBox', { x: 5, y: Infinity, height: 2 }, 1.0); /** * Create Basic Info component */ var ChatBox = new UIComponent( 'ChatBox', htmlText, cssText ); /** * Constants */ ChatBox.TYPE = { SELF: 1 << 0, PUBLIC: 1 << 1, PRIVATE: 1 << 2, PARTY: 1 << 3, GUILD: 1 << 4, ANNOUNCE: 1 << 5, ERROR: 1 << 6, INFO: 1 << 7, BLUE: 1 << 8, // TODO: find a better name ADMIN: 1 << 9, }; /** * @var {number} target message ? */ var _sendTo = ChatBox.TYPE.PUBLIC; /** * Storage to cache the private messages * Ugly system used by official client, can lead to errors */ ChatBox.PrivateMessageStorage = { nick: '', msg: '' }; /** * Initialize UI */ ChatBox.init = function init() { _heightIndex = _preferences.height - 1; ChatBox.updateHeight(); this.ui.css({ top: Math.min( Math.max( 0, _preferences.y - this.ui.height()), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, _preferences.x), Renderer.width - this.ui.width()) }); this.draggable( this.ui.find('.input') ); // Sorry for this un-documented code (see UIComponent for more informations) this.__mouseStopBlock = this.ui.find('.input'); // Setting chatbox scrollbar Client.loadFiles([DB.INTERFACE_PATH + 'basic_interface/dialscr_down.bmp', DB.INTERFACE_PATH + 'basic_interface/dialscr_up.bmp'], function( down, up ){ jQuery('style:first').append([ '#chatbox .content::-webkit-scrollbar { width: 10px; height: 10px;}', '#chatbox .content::-webkit-scrollbar-button:vertical:start:increment,', '#chatbox .content::-webkit-scrollbar-button:vertical:end:decrement { display: none;}', '#chatbox .content::-webkit-scrollbar-corner:vertical { display:none;}', '#chatbox .content::-webkit-scrollbar-resizer:vertical { display:none;}', '#chatbox .content::-webkit-scrollbar-button:start:decrement,', '#chatbox .content::-webkit-scrollbar-button:end:increment { display: block; border:none;}', '#chatbox .content::-webkit-scrollbar-button:vertical:increment { background: url('+ down +') no-repeat; height:10px;}', '#chatbox .content::-webkit-scrollbar-button:vertical:decrement { background: url('+ up +') no-repeat; height:10px;}', '#chatbox .content::-webkit-scrollbar-track-piece:vertical { background:black; border:none;}', '#chatbox .content::-webkit-scrollbar-thumb:vertical { background:grey; -webkit-border-image:none; border-color:transparent;border-width: 0px 0; }' ].join('\n')); }); // Input selection this.ui.find('.input input').mousedown(function( event ){ this.select(); event.stopImmediatePropagation(); return false; }); this.ui.find('.input .message').blur(function(){ Events.setTimeout(function(){ if (!document.activeElement.tagName.match(/input|select|textarea/i)) { this.focus(); } }.bind(this), 1); }); // Button change name this.ui.find('.header input').dblclick(function(){ this.type = 'text'; this.select(); }).blur(function(){ this.type = 'button'; }); // Private message selection this.ui.find('.input .list').click(function(){ var names = _historyNickName.list; var i, count = names.length; var pos = jQuery(this).offset(); var ui = ContextMenu.ui.find('.menu'); if (!count) { ChatBox.addText( DB.getMessage(192), ChatBox.TYPE.ERROR); return; } ContextMenu.remove(); ContextMenu.append(); for (i = 0; i < count; ++i) { ContextMenu.addElement(names[i], onPrivateMessageUserSelection(names[i])); } ContextMenu.addElement('', onPrivateMessageUserSelection('')); ui.css({ top: pos.top - ui.height() - 5, left: pos.left - ui.width() - 5 }); }).mousedown(function(event){ event.stopImmediatePropagation(); return false; }); // Send message to... this.ui.find('.input .filter').click(function(){ var pos = jQuery(this).offset(); var ui = ContextMenu.ui.find('.menu'); ContextMenu.remove(); ContextMenu.append(); ContextMenu.addElement(DB.getMessage(85), onChangeTargetMessage(ChatBox.TYPE.PUBLIC)); ContextMenu.addElement(DB.getMessage(86), onChangeTargetMessage(ChatBox.TYPE.PARTY)); ContextMenu.addElement(DB.getMessage(437), onChangeTargetMessage(ChatBox.TYPE.GUILD)); ui.css({ top: pos.top - ui.height() - 5, left: pos.left - ui.width() + 25 }); }).mousedown(function(event){ event.stopImmediatePropagation(); return false; }); // Change size this.ui.find('.input .size').click(function( event ){ ChatBox.updateHeight(true); event.stopImmediatePropagation(); return false; }); // Scroll feature should block at each line this.ui.find('.content').on('mousewheel DOMMouseScroll', onScroll); }; /** * Clean up the box */ ChatBox.clean = function Clean() { var matches, i, count; matches = this.ui.find('.content').html().match(/(blob:[^"]+)/g); if (matches) { for (i = 0, count = matches.length; i < count; ++i) { window.URL.revokeObjectURL(matches[i]); } } this.ui.find('.content').empty(); this.ui.find('.input .message').val(''); this.ui.find('.input .username').val(''); _historyMessage.clear(); _historyNickName.clear(); }; /** * Once append to HTML */ ChatBox.onAppend = function OnAppend() { // Focus the input this.ui.find('.input .message').focus(); var content = this.ui.find('.content')[0]; content.scrollTop = content.scrollHeight; }; /** * Stop custom scroll */ ChatBox.onRemove = function OnRemove() { this.ui.find('.content').off('scroll'); _preferences.y = parseInt(this.ui.css('top'), 10) + this.ui.height(); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.height = _heightIndex; _preferences.save(); }; /** * BattleMode processing * * @param {number} key id to check * @return {boolean} found a shortcut ? */ ChatBox.processBattleMode = function processBattleMode( keyId ) { // Direct process if (this.ui.find('.battlemode').is(':visible') || KEYS.ALT || KEYS.SHIFT || KEYS.CTRL || (keyId >= KEYS.F1 && keyId <= KEYS.F24)) { return BattleMode.process(keyId); } var messageBox = this.ui.find('.input .message'); var text = messageBox.val(); // Hacky, need to wait the browser to add text in the input // If there is no change, send the shortcut. Events.setTimeout(function(){ // Nothing rendered, can process the shortcut if (messageBox.val() === text) { BattleMode.process(keyId); } }.bind(this), 4); return false; }; /** * Key Event Handler * * @param {object} event - KeyEventHandler * @return {boolean} */ ChatBox.onKeyDown = function OnKeyDown( event ) { var messageBox = this.ui.find('.input .message'); var nickBox = this.ui.find('.input .username'); switch (event.which) { // Battle mode system default: if (ChatBox.processBattleMode(event.which)) { event.stopImmediatePropagation(); return false; } return true; // Switch from user name, to message input case KEYS.TAB: if (document.activeElement === messageBox[0]) { nickBox.select().focus(); break; } if (document.activeElement === nickBox[0]) { messageBox.select().focus(); break; } return true; // Get back message from history case KEYS.UP: if (!jQuery('#NpcMenu').length) { if (document.activeElement === messageBox[0]) { messageBox.val(_historyMessage.previous()).select(); break; } if (document.activeElement === nickBox[0]) { nickBox.val(_historyNickName.previous()).select(); break; } } return true; // Message from history case KEYS.DOWN: if (!jQuery('#NpcMenu').length) { if (document.activeElement === messageBox[0]) { messageBox.val(_historyMessage.next()).select(); break; } if (document.activeElement === nickBox[0]) { nickBox.val(_historyNickName.next()).select(); break; } } return true; // Update chat height case KEYS.F10: this.updateHeight(false); break; // Send message case KEYS.ENTER: if (document.activeElement.tagName === 'INPUT' && document.activeElement !== messageBox[0]) { return true; } if (jQuery('#NpcMenu, #NpcBox').length) { return true; } messageBox.focus(); this.submit(); break; } event.stopImmediatePropagation(); return false; }; /** * Process ChatBox message */ ChatBox.submit = function Submit() { var input = this.ui.find('.input'); var $user = input.find('.username'); var $text = input.find('.message'); var user = $user.val(); var text = $text.val(); // Battle mode if (!text.length) { input.toggle(); this.ui.find('.battlemode').toggle(); if (input.is(':visible')) { $text.focus(); } return; } // Private message if (user.length && text[0] !== '/') { this.PrivateMessageStorage.nick = user; this.PrivateMessageStorage.msg = text; _historyNickName.push(user); _historyNickName.previous(); } // Save in history _historyMessage.push(text); $text.val(''); // Command if (text[0] === '/') { ProcessCommand.call(this, text.substr(1) ); return; } this.onRequestTalk( user, text, _sendTo ); }; /** * Add text to chatbox * * @param {string} text * @param {number} type * @param {string} color * @param {boolean} default false, html or text ? */ ChatBox.addText = function addText( text, type, color, override ) { var $content = this.ui.find('.content'); if (!color) { if ((type & ChatBox.TYPE.PUBLIC) && (type & ChatBox.TYPE.SELF)) { color = '#00FF00'; } else if (type & ChatBox.TYPE.PARTY) { color = ( type & ChatBox.TYPE.SELF ) ? 'rgb(200, 200, 100)' : 'rgb(230,215,200)'; } else if (type & ChatBox.TYPE.GUILD) { color = 'rgb(180, 255, 180)'; } else if (type & ChatBox.TYPE.PRIVATE) { color = '#FFFF00'; } else if (type & ChatBox.TYPE.ERROR) { color = '#FF0000'; } else if (type & ChatBox.TYPE.INFO) { color = '#FFFF63'; } else if (type & ChatBox.TYPE.BLUE) { color = '#00FFFF'; } else if (type & ChatBox.TYPE.ADMIN) { color = '#FFFF00'; } else { color = 'white'; } } $content.append( jQuery('<div/>'). css('color', color) [ !override ? 'text' : 'html' ](text) ); // If there is too many line, remove the older one var list = $content.find('div'); if (list.length > MAX_MSG) { var element, matches; var i, count; //Check if theres any blob url object to be released from buffer (Check Controls/ScreenShot.js) element = list.eq(0); matches = element.html().match(/(blob:[^"]+)/g); if (matches) { for (i = 0, count = matches.length; i < count; ++i) { window.URL.revokeObjectURL(matches[i]); } } element.remove(); } // Always put the scroll at the bottom $content[0].scrollTop = $content[0].scrollHeight; }; /** * Change chatbox's height */ ChatBox.updateHeight = function changeHeight( AlwaysVisible ) { var HeightList = [ 0, 0, 3*14, 6*14, 9*14, 12*14, 15*14 ]; _heightIndex = (_heightIndex + 1) % HeightList.length; var $content = this.ui.find('.content'); var height = HeightList[ _heightIndex ]; var top = parseInt( this.ui.css('top'), 10); this.ui.css('top', top - (height - $content.height()) ); $content.height(height); // Don't remove UI if (_heightIndex === 0 && AlwaysVisible) { _heightIndex++; } switch (_heightIndex) { case 0: this.ui.hide(); break; case 1: this.ui.show(); this.ui.find('.header, .body').hide(); this.ui.find('.input').addClass('fix'); break; default: this.ui.find('.input').removeClass('fix'); this.ui.find('.header, .body').show(); break; } $content[0].scrollTop = $content[0].scrollHeight; }; /** * Save user name to nick name history * * @param {string} nick name */ ChatBox.saveNickName = function saveNickName( pseudo ) { _historyNickName.push(pseudo); }; /** * Update scroll by block (14px) */ function onScroll( event ) { var delta; if (event.originalEvent.wheelDelta) { delta = event.originalEvent.wheelDelta / 120 ; if (window.opera) { delta = -delta; } } else if (event.originalEvent.detail) { delta = -event.originalEvent.detail; } this.scrollTop = Math.floor(this.scrollTop/14) * 14 - (delta * 14); return false; } /** * Change private message nick name * * @param {string} nick name * @return {function} callback closure */ function onPrivateMessageUserSelection(name) { return function onPrivateMessageUserSelectionClosure() { ChatBox.ui.find('.input .username').val(name); }; } /** * Change target of global chat (party, guild) * * @param {number} type constant */ function onChangeTargetMessage(type) { return function onChangeTargetMessageClosure() { var $input = ChatBox.ui.find('.input .message'); $input.removeClass('guild party'); if (type & ChatBox.TYPE.PARTY) { $input.addClass('party'); } else if (type & ChatBox.TYPE.GUILD) { $input.addClass('guild'); } _sendTo = type; }; } /** * Create componentand export it */ return UIManager.addComponent(ChatBox); });
define(function (require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var StatusConst = require('DB/Status/StatusState'); var EquipLocation = require('DB/Items/EquipmentLocation'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Session = require('Engine/SessionStorage'); var Renderer = require('Renderer/Renderer'); var Camera = require('Renderer/Camera'); var SpriteRenderer = require('Renderer/SpriteRenderer'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var WinStats = require('UI/Components/WinStats/WinStats'); var htmlText = require('text!./Equipment.html'); var cssText = require('text!./Equipment.css'); /** * Create Component */ var Equipment = new UIComponent('Equipment', htmlText, cssText); /** * @var {Preference} window preferences */ var _preferences = Preferences.get('Equipment', { x: 480, y: 200, show: false, reduce: false, stats: true }, 1.0); /** * @var {Array} equipment list */ var _list = {}; /** * @var {CanvasRenderingContext2D} canvas context */ var _ctx; /** * @var {boolean} show equipment to other people ? */ var _showEquip = false; /** * @var {jQuery} button that appeared when level up */ var _btnLevelUp; /** * Initialize UI */ Equipment.init = function init() { // Get button to open skill when level up _btnLevelUp = jQuery('#lvlup_base').detach(); _btnLevelUp.click(function () { _btnLevelUp.detach(); if (!Equipment.ui.is(':visible')) { Renderer.render(renderCharacter); } Equipment.ui.show(); Equipment.ui.parent().append(Equipment.ui); }); _ctx = this.ui.find('canvas')[0].getContext('2d'); // Append WinStats to content (hacked) WinStats.prepare(); WinStats.__loaded = true; this.ui.find('.status_component').append(WinStats.ui); this.draggable(); // Don't activate drag drop when clicking on buttons this.ui.find('.titlebar .base').mousedown(function (event) { event.stopImmediatePropagation(); }); // Bind events this.ui.find('.titlebar .mini').click(function () { Equipment.ui.find('.panel').toggle(); }); this.ui.find('.titlebar .close').click(function () { Equipment.ui.hide(); return false; }); this.ui.find('.removeOption').click(this.onRemoveOption); // Show Status ? this.ui.find('.view_status').mousedown(toggleStatus); this.ui.find('.show_equip').mousedown(toggleEquip); // drag, drop items this.ui.on('dragover', onDragOver); this.ui.on('dragleave', onDragLeave); this.ui.on('drop', onDrop); // Bind items this.ui.find('.content') // Right click on item .on('contextmenu', '.item', function (event) { var index = parseInt(this.getAttribute('data-index'), 10); var item = _list[index]; if (item) { // Don't add the same UI twice, remove it if (ItemInfo.uid === item.ITID) { ItemInfo.remove(); } // Add ui to window else { ItemInfo.append(); ItemInfo.uid = item.ITID; ItemInfo.setItem(item); } } event.stopImmediatePropagation(); return false; }) // Want to unequip .on('dblclick', '.item', function () { var index = parseInt(this.getAttribute('data-index'), 10); Equipment.onUnEquip(index); Equipment.ui.find('.overlay').hide(); }) // Stop drag drop feature .on('mousedown', '.item', function (event) { event.stopImmediatePropagation(); }) // Title feature .on('mouseover', 'button', function () { var idx = parseInt(this.parentNode.getAttribute('data-index'), 10); var item = _list[idx]; if (!item) { return; } // Get back data var overlay = Equipment.ui.find('.overlay'); var pos = jQuery(this).position(); // Possible jquery error if (!pos.top && !pos.left) { return; } // Display box overlay.show(); overlay.css({ top: pos.top - 22, left: pos.left - 22 }); overlay.html(DB.getItemName(item)); }) // Stop title feature .on('mouseout', 'button', function () { Equipment.ui.find('.overlay').hide(); }); }; /** * Append to body */ Equipment.onAppend = function onAppend() { // Apply preferences this.ui.css({ top: Math.min(Math.max(0, _preferences.y), Renderer.height - this.ui.height()), left: Math.min(Math.max(0, _preferences.x), Renderer.width - this.ui.width()) }); // Hide window ? if (!_preferences.show) { this.ui.hide(); } // Reduce window ? if (_preferences.reduce) { this.ui.find('.panel').hide(); } // Show status window ? if (!_preferences.stats) { this.ui.find('.status_component').hide(); Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/viewon.bmp', function (data) { this.ui.find('.view_status').css('backgroundImage', 'url(' + data + ')'); }.bind(this)); } if (this.ui.find('canvas').is(':visible')) { Renderer.render(renderCharacter); } }; /** * Remove Inventory from window (and so clean up items) */ Equipment.onRemove = function onRemove() { _btnLevelUp.detach(); // Stop rendering Renderer.stop(renderCharacter); // Clean equipments _list = {}; this.ui.find('.col1, .col3, .ammo').empty(); // Save preferences _preferences.show = this.ui.is(':visible'); _preferences.reduce = this.ui.find('.panel').css('display') === 'none'; _preferences.stats = this.ui.find('.status_component').css('display') !== 'none'; _preferences.y = parseInt(this.ui.css('top'), 10); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.save(); }; /** * Start/stop rendering character in UI */ Equipment.toggle = function toggle() { this.ui.toggle(); if (this.ui.is(':visible')) { Renderer.render(renderCharacter); } else { Renderer.stop(renderCharacter); } }; /** * Process shortcut * * @param {object} key */ Equipment.onShortCut = function onShurtCut(key) { switch (key.cmd) { case 'TOGGLE': this.ui.toggle(); if (this.ui.is(':visible')) { Renderer.render(renderCharacter); this.ui[0].parentNode.appendChild(this.ui[0]); } else { Renderer.stop(renderCharacter); // Fix Mouse.intersect bug this.ui.trigger('mouseleave'); } break; } }; /** * Show or hide equipment * * @param {boolean} on */ Equipment.setEquipConfig = function setEquipConfig(on) { _showEquip = on; Client.loadFile(DB.INTERFACE_PATH + 'checkbox_' + (on ? '1' : '0') + '.bmp', function (data) { Equipment.ui.find('.show_equip').css('backgroundImage', 'url(' + data + ')'); }); }; /** * Add an equipment to the window * * @param {Item} item */ Equipment.equip = function equip(item, location) { var it = DB.getItemInfo(item.ITID); _list[item.index] = item; if (arguments.length === 1) { if ('WearState' in item) { location = item.WearState; } else if ('location' in item) { location = item.location; } } this.ui.find(getSelectorFromLocation(location)).html( '<div class="item" data-index="' + item.index + '">' + '<button></button>' + '<span>' + DB.getItemName(item) + '</span>' + '</div>' ); Client.loadFile(DB.INTERFACE_PATH + 'item/' + it.identifiedResourceName + '.bmp', function (data) { this.ui.find('.item[data-index="' + item.index + '"] button').css('backgroundImage', 'url(' + data + ')'); }.bind(this)); }; /** * Remove equipment from window * * @param {number} item index * @param {number} item location */ Equipment.unEquip = function unEquip(index, location) { var selector = getSelectorFromLocation(location); var item = _list[index]; this.ui.find(selector).empty(); delete _list[index]; return item; }; /** * Add the button when leveling up */ Equipment.onLevelUp = function onLevelUp() { _btnLevelUp.appendTo('body'); }; /** * Display or not status window */ function toggleStatus() { var status = Equipment.ui.find('.status_component'); var self = Equipment.ui.find('.view_status'); var state = status.is(':visible') ? 'on' : 'off'; status.toggle(); Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/view' + state + '.bmp', function (data) { self.style.backgroundImage = 'url(' + data + ')'; }); return false; } /** * Does player can see your equipment ? */ function toggleEquip() { Equipment.onConfigUpdate(0, !_showEquip ? 1 : 0); return false; } /** * Rendering character */ var renderCharacter = function renderCharacterClosure() { var _lastState = 0; var _hasCart = 0; var _cleanColor = new Float32Array([1.0, 1.0, 1.0, 1.0]); var _savedColor = new Float32Array(4); var _animation = { tick: 0, frame: 0, repeat: true, play: true, next: false, delay: 0, save: false }; // Current removable options var OptionFlag = StatusConst.EffectState.FALCON | StatusConst.EffectState.RIDING | StatusConst.EffectState.DRAGON1 | StatusConst.EffectState.DRAGON2 | StatusConst.EffectState.DRAGON3 | StatusConst.EffectState.DRAGON4 | StatusConst.EffectState.DRAGON5 | StatusConst.EffectState.MADOGEAR | StatusConst.EffectState.CART1 | StatusConst.EffectState.CART2 | StatusConst.EffectState.CART3 | StatusConst.EffectState.CART4 | StatusConst.EffectState.CART5; return function rencerCharacter() { var character = Session.Entity; var direction = character.direction; var headDir = character.headDir; var action = character.action; var animation = character.animation; // If state change, we have to check if the new option is removable. if (character.effectState !== _lastState || _hasCart !== Session.hasCart) { _lastState = character.effectState; _hasCart = Session.hasCart; if (_lastState & OptionFlag || _hasCart) { Equipment.ui.find('.removeOption').show(); } else { Equipment.ui.find('.removeOption').hide(); } } // Set action Camera.direction = 4; character.direction = 4; character.headDir = 0; character.action = character.ACTION.IDLE; character.animation = _animation; _savedColor.set(character.effectColor); character.effectColor.set(_cleanColor); // Rendering SpriteRenderer.bind2DContext(_ctx, 30, 130); _ctx.clearRect(0, 0, _ctx.canvas.width, _ctx.canvas.height); character.renderEntity(); // Revert changes character.direction = direction; character.headDir = headDir; character.action = action; character.animation = animation; character.effectColor.set(_savedColor); }; }(); /** * Find elements in html base on item location * * @param {number} location * @returns {string} selector */ function getSelectorFromLocation(location) { var selector = []; if (location & EquipLocation.HEAD_TOP) selector.push('.head_top'); if (location & EquipLocation.HEAD_MID) selector.push('.head_mid'); if (location & EquipLocation.HEAD_BOTTOM) selector.push('.head_bottom'); if (location & EquipLocation.ARMOR) selector.push('.armor'); if (location & EquipLocation.WEAPON) selector.push('.weapon'); if (location & EquipLocation.SHIELD) selector.push('.shield'); if (location & EquipLocation.GARMENT) selector.push('.garment'); if (location & EquipLocation.SHOES) selector.push('.shoes'); if (location & EquipLocation.ACCESSORY1) selector.push('.accessory1'); if (location & EquipLocation.ACCESSORY2) selector.push('.accessory2'); if (location & EquipLocation.AMMO) selector.push('.ammo'); return selector.join(', '); } /** * Drag an item over the equipment, show where to place the item */ function onDragOver(event) { if (window._OBJ_DRAG_) { var data = window._OBJ_DRAG_; var item, selector, ui; // Just support items for now ? if (data.type === 'item') { item = data.data; // Only for TYPE.WEAPON and TYPE.EQUIP if ((item.type === 4 || item.type === 5 || item.type === 10) && item.IsIdentified && !item.IsDamaged) { selector = getSelectorFromLocation('location' in item ? item.location : item.WearLocation); ui = Equipment.ui.find(selector); Client.loadFile(DB.INTERFACE_PATH + 'basic_interface/item_invert.bmp', function (data) { ui.css('backgroundImage', 'url(' + data + ')'); }); } } } event.stopImmediatePropagation(); return false; } /** * Drag out the window */ function onDragLeave(event) { Equipment.ui.find('td').css('backgroundImage', 'none'); event.stopImmediatePropagation(); return false; } /** * Drop an item in the equipment, equip it if possible */ function onDrop(event) { var item, data; try { data = JSON.parse( event.originalEvent.dataTransfer.getData('Text') ); } catch (e) { } // Just support items for now ? if (data && data.type === 'item') { item = data.data; // Only for TYPE.WEAPON and TYPE.EQUIP if ((item.type === 4 || item.type === 5 || item.type === 10) && item.IsIdentified && !item.IsDamaged) { Equipment.ui.find('td').css('backgroundImage', 'none'); Equipment.onEquipItem(item.index, 'location' in item ? item.location : item.WearState); } } event.stopImmediatePropagation(); return false; } /** * Method to define */ Equipment.onUnEquip = function onUnEquip(/* index */) { }; Equipment.onConfigUpdate = function onConfigUpdate(/* type, value*/) { }; Equipment.onEquipItem = function onEquipItem(/* index, location */) { }; Equipment.onRemoveCart = function onRemoveCart() { }; /** * Create component and export it */ return UIManager.addComponent(Equipment); });
define(function(require) { 'use strict'; /** * Dependencies */ var DB = require('DB/DBManager'); var ItemType = require('DB/Items/ItemType'); var SkillInfo = require('DB/Skills/SkillInfo'); var jQuery = require('Utils/jquery'); var Client = require('Core/Client'); var Preferences = require('Core/Preferences'); var Renderer = require('Renderer/Renderer'); var Mouse = require('Controls/MouseEventHandler'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ItemInfo = require('UI/Components/ItemInfo/ItemInfo'); var Inventory = require('UI/Components/Inventory/Inventory'); var SkillWindow = require('UI/Components/SkillList/SkillList'); var SkillDescription = require('UI/Components/SkillDescription/SkillDescription'); var SkillTargetSelection = require('UI/Components/SkillTargetSelection/SkillTargetSelection'); var htmlText = require('text!./ShortCut.html'); var cssText = require('text!./ShortCut.css'); /** * Create Component */ var ShortCut = new UIComponent( 'ShortCut', htmlText, cssText ); /** * @var {Array} ShortCut list */ var _list = []; /** * @var {number} max number of rows */ var _rowCount = 0; /** * @var {Preference} structure to save informations about shortcut */ var _preferences = Preferences.get('ShortCut', { x: 480, y: 0, size: 1, }, 1.0); /** * Initialize UI */ ShortCut.init = function init() { this.ui.find('.resize').mousedown(onResize); this.ui.find('.close').click(function(event){ ShortCut.ui.css('height', 0); _preferences.size = 0; _preferences.save(); event.stopImmediatePropagation(); return false; }); // Dropping to the shortcut this.ui.on('drop', '.container', onDrop); this.ui.on('dragover', '.container', function(event){ event.stopImmediatePropagation(); return false; }); // Drag from the shortcut from somewhere else this.ui.on('dragstart', '.icon', onDrag); this.ui.on('dragend', '.icon', function(){ delete window._OBJ_DRAG_; }); // Click. this.ui.on('dblclick', '.icon', function(event){ var index = parseInt(this.parentNode.getAttribute('data-index'), 10); clickElement(index); event.stopImmediatePropagation(); return false; }); this.ui.on('contextmenu', '.icon', onElementInfo); // Stop drag drop feature this.ui.on('mousedown', '.icon', function(event){ event.stopImmediatePropagation(); }); this.draggable(); }; /** * Append to body */ ShortCut.onAppend = function onAppend() { // Apply preferences this.ui.css({ top: Math.min( Math.max( 0, _preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, _preferences.x), Renderer.width - this.ui.width()), height: 34 * _preferences.size }); }; /** * When removed, clean up */ ShortCut.onRemove = function onRemove() { // Save preferences _preferences.y = parseInt(this.ui.css('top'), 10); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.size = Math.floor( parseInt(this.ui.css('height'),10) / 34 ); _preferences.save(); }; /** * Request to clean the list * Used only from MapEngine when exiting the game */ ShortCut.clean = function clean() { _list.length = 0; this.ui.find('.container').empty(); }; /** * Process shortcut * * @param {object} key */ ShortCut.onShortCut = function onShurtCut( key ) { switch (key.cmd.replace(/\d+$/, '')) { case 'EXECUTE': clickElement( parseInt( key.cmd.match(/\d+$/).toString(), 10) ); break; case 'EXTEND': _preferences.size = (_preferences.size + 1) % (_rowCount + 1); _preferences.save(); this.ui.css('height', _preferences.size * 34 ); break; } }; /** * Bind UI with list of shortcut * * @param {Array} shortcut list */ ShortCut.setList = function setList( list ) { var i, count; var skill; this.ui.find('.container').empty(); _list.length = list.length; _rowCount = Math.min( 4, Math.floor(list.length / 9) ); for (i = 0, count = list.length; i < count; ++i) { if (list[i].isSkill) { skill = SkillWindow.getSkillById(list[i].ID); if (skill && skill.level) { addElement( i, true, list[i].ID, list[i].count || skill.level ); } else { if (!_list[i]) { _list[i] = {}; } _list[i].isSkill = true; _list[i].ID = list[i].ID; _list[i].count = list[i].count; } } else { addElement( i, list[i].isSkill, list[i].ID, list[i].count ); } } }; /** * Resizing hotkey window */ function onResize( event ) { var ui = ShortCut.ui; var top = ui.position().top; var lastHeight = 0; var _Interval; function resizing() { var h = Math.floor( (Mouse.screen.y - top ) / 34 + 1 ); // Maximum and minimum window size h = Math.min( Math.max(h, 1), _rowCount); if (h === lastHeight) { return; } ui.css('height', h * 34); _preferences.size = h; _preferences.save(); lastHeight = h; } // Start resizing _Interval = setInterval( resizing, 30); // Stop resizing jQuery(window).one('mouseup', function(event){ // Only on left click if (event.which === 1) { clearInterval(_Interval); } }); event.stopImmediatePropagation(); return false; } /** * Add an element to shortcut * * @param {number} index of the element * @param {boolean} is a skill ? * @param {number} ID * @param {number} count or level */ function addElement( index, isSkill, ID, count ) { var file, name; var ui = ShortCut.ui.find('.container:eq(' + index + ')').empty(); if (!_list[index]) { _list[index] = {}; } _list[index].isSkill = isSkill; _list[index].ID = ID; _list[index].count = count; if (isSkill) { // Do not display if no level. if (!count) { return; } file = SkillInfo[ID].Name; name = SkillInfo[ID].SkillName; } else { var item = Inventory.getItemById(ID); // Do not display items not in inventory if (!item) { return; } var it = DB.getItemInfo(ID); file = item.IsIdentified ? it.identifiedResourceName : it.unidentifiedResourceName; name = DB.getItemName(item); // If equipment, do not display count if (item.type === ItemType.WEAPON || item.type === ItemType.EQUIP) { count = 1; } // Get item count else { count = item.count; } // Do not display item if there is none in the inventory if (!count) { return; } } Client.loadFile( DB.INTERFACE_PATH + 'item/' + file + '.bmp', function(data){ ui.html( '<div draggable="true" class="icon">' + '<div class="img" style="background-image:url(' + data + ')"></div>' + '<div class="amount">'+ count + '</div>' + '<span class="name">' + name + '</span>' + '</div>' ); }); } /** * Remove an element from shortcut * * @param {boolean} is a skill ? * @param {number} ID of the element to remove * @param {number} row id */ function removeElement( isSkill, ID, row ) { var i, count; // Do not need to modify empty slot if (!ID) { return; } for (i = row * 9, count = Math.min(_list.length, row * 9 + 9); i < count; ++i) { if (_list[i] && _list[i].isSkill == isSkill && _list[i].ID === ID) { ShortCut.ui.find('.container:eq(' + i + ')').empty(); _list[i].isSkill = 0; _list[i].ID = 0; _list[i].count = 0; ShortCut.onChange( i, 0, 0, 0); } } } /** * Set element data * * @param {boolean} is a skill ? * @param {number} id * @param {number} count */ ShortCut.setElement = function setElement( isSkill, ID, count ) { var i, size; for (i = 0, size = _list.length; i < size; ++i) { if (_list[i] && _list[i].isSkill == isSkill && _list[i].ID === ID) { addElement( i, isSkill, ID, count); } } }; /** * Drop something in the shortcut * Does the client allow other source than shortcut, inventory * and skill window to save to shortcut ? */ function onDrop( event ) { var data, element; var index = parseInt(this.getAttribute('data-index'), 10); var row = Math.floor( index / 9 ); event.stopImmediatePropagation(); try { data = JSON.parse(event.originalEvent.dataTransfer.getData('Text')); element = data.data; } catch(e) { return false; } // Do not process others things than item and skill if (data.type !== 'item' && data.type !== 'skill') { return false; } switch (data.from) { case 'skilllist': ShortCut.onChange( index, true, element.SKID, element.level); removeElement( true, element.SKID, row); addElement( index, true, element.SKID, element.level); break; case 'inventory': ShortCut.onChange( index, false, element.ITID, 0); removeElement( false, element.ITID, row); addElement( index, false, element.ITID, 0); break; case 'shortcut': ShortCut.onChange( index, element.isSkill, element.ID, element.count); removeElement( element.isSkill, element.ID, row); addElement( index, element.isSkill, element.ID, element.count); break; } return false; } /** * Prepare data to be store in the dragged element * to change prosition in the shortcut. */ function onDrag( event ) { var img, index; index = parseInt(this.parentNode.getAttribute('data-index'), 10); // Extract image from css to get it when dragging the element img = new Image(); img.src = this.firstChild.style.backgroundImage.match(/\(([^\)]+)/)[1]; event.originalEvent.dataTransfer.setDragImage( img, 12, 12 ); event.originalEvent.dataTransfer.setData('Text', JSON.stringify( window._OBJ_DRAG_ = { type: _list[index].isSkill ? 'skill' : 'item', from: 'shortcut', data: _list[index] }) ); // Stop component to be draggable jQuery(window).trigger('mouseup'); } /** * Get informations from a skill/item when * using right click on it. */ function onElementInfo( event ) { var index = parseInt(this.parentNode.getAttribute('data-index'), 10); var element = _list[index]; event.stopImmediatePropagation(); // Display skill informations if (element.isSkill) { SkillDescription.append(); SkillDescription.setSkill( _list[index].ID ); } // Display item informations else { if (ItemInfo.uid === _list[index].ID) { ItemInfo.remove(); return false; } ItemInfo.append(); ItemInfo.uid = _list[index].ID; ItemInfo.setItem(Inventory.getItemById(_list[index].ID )); } return false; } /** * Clicking on a shortcut * * @param {number} shortcut index */ function clickElement( index ) { var shortcut = _list[index]; SkillTargetSelection.remove(); // Nothing here ? if (!shortcut) { return; } // Execute skill if (shortcut.isSkill) { SkillWindow.useSkillID(shortcut.ID); } // Use the item else { var item = Inventory.getItemById( _list[index].ID ); if (item) { Inventory.useItem( item ); } } } /** * Hook Inventory, get informations when there is a change * to update the shortcut * * @param {number} index * @param {number} count */ Inventory.onUpdateItem = function( index, count) { ShortCut.setElement( false, index, count); }; /** * Hook Skill List, get informations when there is a change * to update the shortcut * * @param {number} skill id * @param {number} level */ SkillWindow.onUpdateSkill = function( id, level) { ShortCut.setElement( true, id, level); }; /** * Method to define to notify a change. * * @param {number} index * @param {boolean} isSkill * @param {number} id * @param {number} count */ ShortCut.onChange = function OnConfigUpdate(/*index, isSkill, ID, count*/){}; /** * Create component and export it */ return UIManager.addComponent(ShortCut); });
define(function(require) { 'use strict'; /** * Dependencies */ var jQuery = require('Utils/jquery'); var DB = require('DB/DBManager'); var KEYS = require('Controls/KeyEventHandler'); var Renderer = require('Renderer/Renderer'); var Preferences = require('Core/Preferences'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var ChatRoom = require('UI/Components/ChatRoom/ChatRoom'); var htmlText = require('text!./ChatRoomCreate.html'); var cssText = require('text!./ChatRoomCreate.css'); /** * Create Component */ var ChatRoomCreate = new UIComponent( 'ChatRoomCreate', htmlText, cssText ); /** * @var {string} chat room title */ ChatRoomCreate.title = ''; /** * @var {number} chat room limit */ ChatRoomCreate.limit = 20; /** * @var {number} type * 0 = Private * 1 = Public */ ChatRoomCreate.type = 1; /** * @var {string} password */ ChatRoomCreate.password = ''; /** * @var {Preference} structure to save */ var _preferences = Preferences.get('ChatRoomCreate', { x: 480, y: 200, show: false }, 1.0); /** * Initialize UI */ ChatRoomCreate.init = function init() { // Bindings this.ui.find('.close, .cancel').on('click', this.hide.bind(this)); this.ui.find('.ok').on('click', parseChatSetup.bind(this) ); this.ui.find('.setup').submit(function() { return false; }); // Do not activate drag this.ui.find('input, button, select').mousedown(function(event) { event.stopImmediatePropagation(); }); this.draggable(); this.ui.hide(); }; /** * Once append to body */ ChatRoomCreate.onAppend = function OnAppend() { if (!_preferences.show) { this.ui.hide(); } this.ui.css({ top: Math.min( Math.max( 0, _preferences.y), Renderer.height - this.ui.height()), left: Math.min( Math.max( 0, _preferences.x), Renderer.width - this.ui.width()) }); // Escape key order var events = jQuery._data( window, 'events').keydown; events.unshift( events.pop() ); }; /** * Once removed from DOM, save preferences */ ChatRoomCreate.onRemove = function OnRemove() { _preferences.show = this.ui.is(':visible'); _preferences.y = parseInt(this.ui.css('top'), 10); _preferences.x = parseInt(this.ui.css('left'), 10); _preferences.save(); }; /** * Show the setup for room creation */ ChatRoomCreate.show = function showSetup() { this.ui.show(); this.ui.find('.title').focus(); _preferences.show = true; }; /** * Hide the setup ui */ ChatRoomCreate.hide = function hideSetup() { this.ui.hide(); this.ui.find('.setup')[0].reset(); _preferences.show = false; }; /** * Key Listener * * @param {object} event * @return {boolean} */ ChatRoomCreate.onKeyDown = function onKeyDown( event ) { var isVisible = this.ui.is(':visible'); if (KEYS.ALT && event.which === KEYS.C && !ChatRoom.isOpen) { if (isVisible) { this.hide(); } else { this.show(); } event.stopImmediatePropagation(); return false; } if (isVisible) { if (event.which === KEYS.ENTER) { parseChatSetup.call(this); event.stopImmediatePropagation(); return false; } else if (event.which === KEYS.ESCAPE) { this.hide(); event.stopImmediatePropagation(); return false; } } return true; }; /** * Pseudo functions :) */ ChatRoomCreate.requestRoom = function requestRoom(){}; /** * Parse and send chat room request */ function parseChatSetup() { this.title = this.ui.find('input[name=title]').val(); this.limit = parseInt( this.ui.find('select[name=limit]').val(), 10); this.type = parseInt( this.ui.find('input[name=public]:checked').val(), 10); this.password = this.ui.find('input[name=password]').val(); if (this.title.length < 1) { var overlay = document.createElement('div'); overlay.className = 'win_popup_overlay'; document.body.appendChild(overlay); var popup = UIManager.showMessageBox( DB.msgstringtable[13], 'ok', function(){ document.body.removeChild(overlay); }, true); popup.ui.css({ top: parseInt(this.ui.css('top'), 10) - 120, left: parseInt(this.ui.css('left'), 10) }); return; } this.requestRoom(); this.hide(); } /** * Create component and export it */ return UIManager.addComponent(ChatRoomCreate); });
define(function(require) { 'use strict'; /** * Load dependencies */ var glMatrix = require('Utils/gl-matrix'); var Client = require('Core/Client'); var Renderer = require('Renderer/Renderer'); var EffectManager = require('Renderer/EffectManager'); var StrEffect = require('Renderer/Effects/StrEffect'); var Camera = require('Renderer/Camera'); var UIManager = require('UI/UIManager'); var UIComponent = require('UI/UIComponent'); var htmlText = require('text!./StrViewer.html'); var cssText = require('text!./StrViewer.css'); var mat4 = glMatrix.mat4; /** * @var {object} fog structure */ var _fog = { use: false, exist: true, far: 30, near: 180, factor: 1.0, color: new Float32Array([1,1,1]) }; /** * @var {object} model View mat */ var _modelView = mat4.create(); /** * @var {StrEffect} current effect */ var _strObject = null; /** * Create GRFViewer component */ var Viewer = new UIComponent( 'StrViewer', htmlText, cssText ); /** * Initialize Component */ Viewer.init = function Init() { // Initialize WebGL Renderer.init({ alpha: false, depth: true, stencil: false, antialias: true, premultipliedAlpha: false, }); Renderer.show(); EffectManager.init(Renderer.getContext()); Client.init([]); // Initialize the dropdown if (!ROConfig.API) { initDropDown( this.ui.find('select').get(0) ); } else { var hash = decodeURIComponent(location.hash); location.hash = hash; loadEffect( hash.substr(1) ); } }; /** * Initialise Drop Down list * * @param {HTMLElement} drop down */ function initDropDown( select ) { // Search RSMs from the client Client.search(/data\\[^\0]+\.str/gi, function( list ) { var i, count; var hash; list.sort(); // Add selection for (i = 0, count = list.length; i < count; ++i){ list[i] = list[i].replace(/\\/g,'/'); select.add( new Option(list[i], list[i]), null ); } // Bind change select.onchange = function() { loadEffect(location.hash = this.value); }; // Start loading a model ? hash = decodeURIComponent(location.hash); location.hash = hash; // Load RSM from url ? if (hash.indexOf('.rsm' ) !== -1) { loadEffect( hash.substr(1) ); select.value = hash.substr(1); } else { loadEffect( select.value ); } Viewer.ui.find('.head').show(); select.focus(); }); } /** * Start loading an effect * * @param {string} filename */ function loadEffect( filename ) { stop(); Client.loadFile( filename, function(buf) { if (_strObject) { _strObject._needCleanUp = true; } _strObject = new StrEffect( filename, [0,0,0], Renderer.tick); _strObject._needCleanUp = false; // Hacky way Object.defineProperty( _strObject, 'needCleanUp', { // Get stat get: function(){ return this._needCleanUp; }, // Repeat set: function(val){ if (val) { this.startTick = Renderer.tick; } } }); EffectManager.add( _strObject, 0); Renderer.render(render); }); } /** * Stop to render */ function stop() { var gl = Renderer.getContext(); Renderer.stop(); EffectManager.free(gl); gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); } /** * Rendering scene * * @param {number} tick * @param {object} webgl context */ function render( tick, gl ) { // Updating camera position mat4.identity( _modelView ); mat4.translate( _modelView, _modelView, [ 0, -3, -50] ); mat4.rotateX( _modelView, _modelView, (50/180) * Math.PI ); // Clear screen, update camera gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); EffectManager.render( gl, _modelView, Camera.projection, _fog, tick, false); } /** * Exports methods */ Viewer.loadEffect = loadEffect; Viewer.stop = stop; /** * Stored component and return it */ return UIManager.addComponent(Viewer); });