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);
});
Exemple #2
0
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);
});
Exemple #3
0
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);
});
Exemple #4
0
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);
});
Exemple #5
0
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);
});
Exemple #7
0
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);
});
Exemple #8
0
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);
});
Exemple #9
0
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);
});
Exemple #10
0
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);
});
Exemple #11
0
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);
});
Exemple #12
0
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);
});
Exemple #13
0
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);
});
Exemple #14
0
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);
});
Exemple #15
0
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);
});
Exemple #16
0
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);
});
Exemple #17
0
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);
});
Exemple #18
0
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);
});
Exemple #19
0
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);
});
Exemple #20
0
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);
});
Exemple #21
0
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);
});
Exemple #22
0
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);
});
Exemple #23
0
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);
});
Exemple #24
0
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);
});
Exemple #25
0
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);
});
Exemple #26
0
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);
});
Exemple #27
0
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);
});
Exemple #28
0
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);
});
Exemple #29
0
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);
});
Exemple #30
0
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);
});