function bindName(k){
var v = this[k];
- if ( isFunction(v) )
+ if ( typeof v == 'function' )
this[k] = YFunction(v).bind(this);
}
return o;
if (arguments.length === 1)
names = core.map(o, op.nth(1));
- else if ( !(names instanceof Array) )
+ else if ( !isArray(names) )
names = slice.call(arguments, 1);
core.forEach(names, bindName, o);
return o;
'instance' : instance,
'cls' : cls,
'args' : Y(args)
- });
+ }, instance);
var initialise = instance.__initialise__;
if ( isFunction(initialise) )
'instance' : instance,
'cls' : cls,
'args' : Y(arguments)
- });
+ }, instance);
return instance;
}
// Record for metaprogramming
KNOWN_CLASSES[className] = NewClass;
+ NewClass.__bind__ = prototype.__bind__;
var mixins = NewClass.__mixins__ = Y([]).concat(members.__mixins__||[], SuperClass.__mixins__||[]).unique()
, statics = NewClass.__static__ = {}
, pstatics = SuperClass.__static__
}
NewClass.instantiate = instantiate.partial(NewClass);
- // prototype.__bind__ = Y([]).concat(prototype.__bind__||[], SuperClass.fn.__bind__||[]).unique();
+ NewClass.__bind__ = prototype.__bind__ = Y([]).concat(prototype.__bind__||[], SuperClass.__bind__||[]).unique();
// Notify mixins to let them finish up any customization
if (mixins.length)
'child' : NewClass,
'members' : members,
'prototype' : prototype
- });
+ }, NewClass);
return NewClass;
}
Class.fn = Class.prototype;
Class.fn.__class__ = Class.fn.constructor = Class;
Class.fn.__bases__ = Class.__bases__ = Y([ Object ]);
+Class.fn.__bind__ = Class.__bind__ = Y([]);
Class.className = Class.fn.className = "Class";
/* Class Methods */
*/
function mixin(cls, _mxn){
var proto = cls.fn
- , bases = cls.__bases__
- , cbinds = proto.__bind__
+ , bases = Y(cls.__bases__ || [])
+ , cbinds = Y(cls.__bind__ || [])
, cstatic = cls.__static__
, mxns = (Y.isArray(_mxn) ? _mxn.slice(0) : Y(arguments, 1))
;
var mproto = (typeof mxn === "function") ? mxn.fn : mxn
, statics = mxn.__static__
+ , binds = mxn.__bind__
, onCreate = mproto.onCreate
, firstMix = (bases && bases.indexOf(mxn) === -1)
;
}
}
+ // Add/ensure the mixin is at the front of bases
+ bases.remove(mxn).unshift(mxn);
+
+ // Collate binds from mixin
+ if (binds)
+ cls.__bind__ = proto.__bind__ = cbinds.concat(binds).unique();
+
// Only perform these actions the first time we mix into this class
if (!firstMix)
return;
- // Add to bases
- bases.unshift(mxn);
-
// Register onCreate to fire whenever a new instance is initialized
if ( isFunction(cls.on) && hasOwn.call(mproto,'onCreate') && isFunction(onCreate) )
cls.on('create', onCreate);
//#ensure "jquery"
var Y = require('Y').Y
, op = require('Y/op')
+
+, evt = require('evt')
+
, Vec = require('ezl/math/vec').Vec
, Loc = require('ezl/loc/loc').Loc
, BoundingBox = require('ezl/loc/boundingbox').BoundingBox
Layer =
exports['Layer'] =
-Y.subclass('Layer', {
+new evt.Class('Layer', {
+ __bind__ : [ 'tick' ],
+
/// Class Defaults ///
// _layer* is applied to this.layer (the DOM Element)
this.canvas = jQuery();
}
- this.tick = this.tick.bind(this);
+ // this.tick = this.tick.bind(this);
},
/// Scene Graph Heirarchy ///
return this;
},
- die : function die(reason){
+ die : function die(reason, trigger){
this.removeStatMods();
// var evt = 'buff.die.'+reason // We'll add this when we add polymorphic dispatchers
var evt = 'buff.die'
, data = { 'buff':this, 'unit':this.target, 'owner':this.owner };
- this.emit(evt, this.target, data);
- this.target.emit(evt, this, data);
+ this.emit(evt, trigger||this.target, data, this);
+ this.target.emit(evt, this, data, this);
return this;
},
--- /dev/null
+var Y = require('Y').Y
+, op = require('Y/op')
+, deepcopy = require('Y/types/object').deepcopy
+
+, Mixin = require('evt').Mixin
+, Item = require('tanks/thing/item').Item
+
+, kNull = op.K(null)
+,
+
+Container =
+exports['Container'] =
+Mixin.subclass('Container', {
+ __bind__ : [],
+
+
+ max : 1, // Container capacity
+ reqs : null, // Array of tag requirements to be stored here
+ equipsContents : false, // Whether held items are equipped
+
+ owner : null, // Owning unit
+ size : 0, // Number of items in container
+ items : null, // item id -> Item
+ slots : null, // Array of positions of items in container: container idx -> Item
+ children : null, // Nested containers: container id -> Container
+
+
+ onCreate : function initContainer(evt, owner, items){
+ this.owner = owner;
+ this.items = {};
+ this.children = {};
+ this.slots = new Array(this.max);
+
+ if ( typeof this.reqs == 'string' )
+ this.reqs = Y([ this.reqs ]);
+
+ if (items) items.forEach(this.moveItem, this);
+ },
+
+
+ /**
+ * @param {Item} [item] If present, also check whether item matches this container's requirements.
+ * @return {Boolean} Whether this container will accept this item.
+ */
+ canAddItem : function canAddItem(item){
+ var reqs = this.reqs;
+ return this.size < this.max &&
+ ( !item || !reqs || reqs.intersect(item.tags).length === reqs.length );
+ },
+
+ checkReqs : function checkReqs(item){
+ var reqs = this.reqs;
+ return !!item && ( !reqs || reqs.intersect(item.tags).length === reqs.length );
+ },
+
+ getItem : function getItem(idx){
+ if ( typeof idx == 'number' ) {
+ return this.slots[ (idx < 0 ? this.max+idx : idx) ];
+ } else {
+ if (idx && !idx.inv)
+ idx.inv = new InventoryMeta();
+ return idx;
+ }
+ },
+
+ /**
+ * @param {Number|Item} id The Item or Item ID for which to test.
+ * @return {Boolean} Whether the item is in this container.
+ */
+ hasItem : function hasItem(id){
+ if (id instanceof Item) id = id.__id__;
+ return !!this.items[id];
+ },
+
+ /**
+ * Adds an item to this container.
+ * @param {Item} item
+ * @return {this}
+ */
+ addItem : function addItem(item){
+ if ( this.hasItem(item) )
+ return this;
+ else
+ return this.moveItem(item, this._getEmptySlot());
+ },
+
+ /**
+ * Changes the position of the item in this container.
+ * @param {Item} item Item to move.
+ * @param {Number} idx Index in the container to which to move item.
+ * @return {this}
+ */
+ moveItem : function moveItem(item, idx){
+ item = this.getItem(item);
+ if (!item || typeof idx != "number")
+ return this;
+
+ idx = this._getIdx(idx);
+
+ // Note old slot info before we mutate anything
+ var inv = item.inv.clone()
+ , oldIdx = inv.idx
+ , oldBag = inv.bag
+
+ // Note item we're displacing, if any
+ , dispItem = this.slots[idx]
+ , didDisplace = dispItem && dispItem !== item
+ , sameOwner = this.owner && item.owner && this.owner === item.owner
+ , newPickup = !(oldBag && sameOwner)
+ , inventoryMove = sameOwner && !this.hasItem(item)
+ , localMove = sameOwner && !inventoryMove
+
+ , hasRoom = !(didDisplace && newPickup && this.size >= this.max)
+ ;
+
+ if ( !hasRoom )
+ return this;
+
+ // Check requirements and then attempt transaction
+ // TODO: if displaced item fails req check, we should try to find it a new home rather than giving up
+ if ( !( this.checkReqs(item) && ( !didDisplace || oldBag.checkReqs(dispItem) )
+ && this._putItem(item, idx, didDisplace)) )
+ return this;
+
+ // Updates meta + size
+ if ( inventoryMove )
+ oldBag._removeItem(item, oldIdx);
+ else if ( newPickup && oldBag )
+ oldBag.removeItem(item, { 'oldIdx':oldIdx });
+
+ if ( didDisplace ) {
+ this._removeItem(dispItem, idx);
+ if ( oldBag && sameOwner )
+ oldBag._putItem(dispItem, oldIdx);
+ else
+ this._putItem(dispItem, this._getEmptySlot());
+ }
+
+ var eq = this.equipsContents
+ , oldEq = oldBag.equipsContents
+ , isEquipped = sameOwner && oldEq
+ , evt = 'item'+(newPickup ? '.acquire' : '.move')+(eq ? (!isEquipped ? '.equip' : '') : (isEquipped ? '.unequip' : ''))
+ , dispEvt = 'item.move'+(!eq ? (oldEq ? '.equip' : '') : (!oldEq ? '.unequip' : ''))
+ ;
+
+ // metadata clone preserves original values in case of loss (displacement by a new pickup)
+ this._emitItemChange(evt, item, { 'idx':idx, 'oldBag':inv.bag, 'oldIdx':inv.idx });
+
+ if ( didDisplace ) {
+ oldBag._putItem(dispItem, oldIdx);
+ oldBag._emitItemChange('item.move', dispItem, { 'idx':oldIdx, 'oldBag':this, 'oldIdx':idx });
+ }
+
+ if ( inventoryMove ) {
+ if ( didDisplace ) {
+ oldBag._putItem(dispItem, oldIdx);
+ oldBag._emitItemChange('item.move', dispItem, { 'idx':oldIdx, 'oldBag':this, 'oldIdx':idx });
+ }
+ this._emitItemChange('item.move', item, { 'idx':idx, 'oldBag':inv.bag, 'oldIdx':inv.idx });
+ } else {
+ evt =
+ dispEvt = 'item.'+(oldBag.equipsContents ? '.equip' : '');
+ this._emitItemChange(evt, item, { 'idx':idx, 'oldBag':inv.bag, 'oldIdx':inv.idx });
+ }
+
+ return this;
+ },
+
+ /**
+ * Removes the item from this container and fires the appropriate events.
+ * @param {Item|Number} item Item or container index to remove.
+ * @param {Object} [options] Options are:
+ * * @option {Number} [oldIdx] In cases where `item.inv` has already been modified, the
+ * old index of the item is required to be manually supplied to clean up correctly.
+ * * @option {Boolean} [keepEquipped=false] If true, does not fire item.unequip event.
+ * * @option {Boolean} [drop=false] If true, Item is dropped and not just removed from
+ * this container. If Container `equipsContents`, this overrides `options.keepEquipped`.
+ * @return {Item} The removed item or null on failure.
+ */
+ removeItem : function removeItem(item, options){
+ options = options || {};
+ item = this.getItem(item);
+ if (!item)
+ return item;
+
+ var idx = (options.oldIdx !== undefined ? options.oldIdx : item.inv.idx);
+ if ( !this._removeItem(item, options.oldIdx) )
+ return null;
+
+ var unequip = this.equipsContents && (options.drop || !options.keepEquipped);
+ this._emitItemChange('item.lose'+(unequip ? '.unequip' : '')+(options.drop ? '.drop' : ''), item, { 'idx':idx });
+
+ return item;
+ },
+
+
+
+ /**
+ * @protected
+ * @return {Integer} Index of first empty slot in this container.
+ */
+ _getEmptySlot : function _getEmptySlot(){
+ var slots = this.slots
+ , max = this.max;
+
+ if (this.size >= max)
+ return -1;
+
+ for (var i=0, v=slots[i]; i<max; v=slots[++i])
+ if (v === undefined)
+ return i;
+
+ return -1;
+ },
+
+ /**
+ * @protected
+ * @param {Any} idx Index to test.
+ * @return {Number} The index, or the next empty index if non-number or -1.
+ */
+ _getIdx : function _getIdx(idx){
+ return (typeof idx == "number" && idx !== -1) ? idx : this._getEmptySlot();
+ },
+
+ /**
+ * @protected
+ * @param {Number} [idx] Slot index to test.
+ * @return {Boolean} Ok if index is a number in the container bounds.
+ */
+ _idxOk : function _idxOk(idx){
+ return (typeof idx == "number" && 0 <= idx && idx < this.max);
+ },
+
+ /**
+ * Inserts item into container at index, updating metadata.
+ * @protected
+ * @param {Item} item
+ * @param {Number} [idx] Container position at which to insert item. If missing, first open slot will be used.
+ * @return {Boolean}
+ */
+ _putItem : function _putItem(item, idx, didDisplace){
+ if (!item) return false;
+
+ var idx = this._getIdx(idx)
+ , id = item.__id__
+ , inv = item.inv
+ ;
+
+ // Bag bounds check
+ if ( 0 <= idx && idx < this.max )
+ return false;
+
+ // Already in bag? Remove from current slot
+ if ( this.items[id] )
+ delete this.slots[inv.idx];
+ else if (!didDisplace)
+ this.size++; // Otherwise increment size
+
+ this.items[id] = item;
+ this.slots[idx] = item;
+ inv.idx = idx;
+ inv.bag = this;
+
+ return true;
+ },
+
+ /**
+ * Removes item from container, updating metadata.
+ * @protected
+ * @param {Item} item
+ * @return {Boolean}
+ */
+ _removeItem : function removeItem(item, oldIdx){
+ if (!item) return false;
+
+ var id = item.__id__
+ , hasItem = !!this.items[id]
+ , itemMoved = oldIdx !== undefined
+ , inv = item.inv
+ , idx = itemMoved ? oldIdx : inv.idx
+ ;
+
+ delete this.items[id];
+
+ if ( hasItem ) {
+ this.size--;
+ if (this.slots[idx] === item)
+ delete this.slots[idx];
+ if (!itemMoved)
+ inv.idx = inv.bag = null;
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * @param {String} evt Event name.
+ * @param {Item} item Triggering item.
+ * @param {Object} [data] Additional data to add to the event.
+ * @return {this}
+ */
+ _emitItemChange : function _emitItemChange(evt, item, data){
+ data = Y.extend({ 'item':item, 'bag':this, 'unit':this.owner }, data || {});
+ this.emit(evt, item, data, item);
+ item.emit(evt, this, data, this);
+ // unit.emit(evt, item, data); // inventory should take care of this
+ return this;
+ }
+
+
+
+});
+
+function InventoryMeta(bag, idx, links){
+ this.bag = bag;
+ this.idx = idx;
+ this.links = links || [];
+}
+Y.core.extend(InventoryMeta.prototype, {
+ clear : function clear(){
+ this.bag = this.idx = null;
+ this.links = [];
+ return this;
+ },
+
+ clone : function clone(){
+ return new InventoryMeta(this.bag, this.idx, this.links); // Don't care about links
+ },
+
+ toString : function(){
+ return "BagLoc(idx="+this.idx+", bag="+this.bag+")";
+ }
+
+})
+++ /dev/null
-var Y = require('Y').Y
-, op = require('Y/op')
-, deepcopy = require('Y/types/object').deepcopy
-
-, Mixin = require('evt').Mixin
-, Item = require('tanks/thing/item').Item
-
-, kNull = op.K(null)
-,
-
-Container =
-exports['Container'] =
-Mixin.subclass('Container', {
- __bind__ : [],
-
- name : null, // Name of this container
- max : 1, // Container capacity
- reqs : null, // Array of tag requirements to be stored here
- equipContents : false, // Whether held items are equipped
-
- size : 0, // Number of items in container
- items : null, // item id -> Item
- slots : null, // Array of positions of items in container: container idx -> Item
-
-
- init : function initContainer(name, unit, items, options){
- this.name = name;
- this.unit = unit;
- Y.core.extend(this, options);
-
- this.items = {};
- this.slots = new Array(inv.max);
-
- if ( typeof this.reqs == 'string' )
- this.reqs = Y([ this.reqs ]);
-
- if (items) items.forEach(this.moveItem, this);
- },
-
-
- /**
- * @param {Item} [item] If present, also check whether item matches this container's requirements.
- * @return {Boolean} Whether this container will accept this item.
- */
- canAddItem : function canAddItem(item){
- var reqs = this.reqs;
- return this.size < this.max &&
- ( !item || !reqs || reqs.intersect(item.tags).length === reqs.length );
- },
-
- getItem : function getItem(idx){
- if (idx === undefined || idx === null || idx instanceof Item)
- return idx;
- else
- return this.slots[idx];
- },
-
- /**
- * @param {Number|Item} id The Item or Item ID for which to test.
- * @return {Boolean} Whether the item is in this container.
- */
- hasItem : function hasItem(id){
- if (id instanceof Item) id = id.__id__;
- return !!this.items[id];
- },
-
- /**
- * Adds an item to this container.
- * @param {Item} item
- * @return {this}
- */
- addItem : function addItem(item){
- if ( this.hasItem(item) )
- return this;
- else
- return this.moveItem(item, this._getEmptySlot());
- },
-
-
- /**
- * Changes the position of the item in this container.
- * @param {Item} item Item to move.
- * @param {Number} idx Index in the container to which to move item.
- * @return {this}
- */
- moveItem : function moveItem(item, idx){
- item = this.getItem(item);
- if (!item || typeof idx != "number")
- return this;
-
- // Make note of item we're displacing, if any
- var displacedItem = this.slots[idx]
- , oldIdx = item.ui.bpIdx
- , newItem = !this.hasItem(item)
- , evtName = 'item.move'
- ;
-
- if ( !this._putItem(item, idx) )
- return this;
-
- if (newItem)
- if (this.equipContents)
- evtName = 'item.equip'
- else
- evtName = 'item.move'
-
- idx = item.ui.bpIdx;
- this._emitItemChange(evtName, item, { 'idx':idx, 'oldIdx':oldIdx });
-
- if ( displacedItem && displacedItem !== item ) {
- displacedItem.ui.bpIdx = null;
- this._putItem(displacedItem, oldIdx);
- this._emitItemChange('item.move', displacedItem, { 'idx':displacedItem.ui.bpIdx, 'oldIdx':idx });
- }
-
- return this;
- },
-
- /**
- * Removes the item from this container.
- * @param {Item|Number} idx Item or container index to remove.
- * @param {Boolean} [drop=false] If true, Item is dropped and not just removed from this container.
- * @return {Item} The removed item.
- */
- removeItem : function removeItem(idx, drop){
- var item = this.getItem(idx);
- idx = item ? item.ui.bpIdx : -1; // ensures we have the index if given an Item
-
- // TODO: UI feedback on failure
- if ( !this._removeItem(item) )
- return null;
-
- this._emitItemChange('item.lose'+(drop ? '.drop' : ''), item, { 'idx':idx });
- return item;
- },
-
- equipItem : function equipItem(slot, item){
- item = this.getItem(item);
-
- var inv = this.inventory
- , eqs = inv.equipment;
-
- if ( !(slot in eqs) )
- throw new Error('Unit '+this+' does not have an equipment slot '+slot+'!');
-
- if ( !(item instanceof Item) )
- throw new Error('Unit '+this+' cannot equip item '+item+'!');
-
- // TODO: Ensure item has right tags for slot
- var oldIdx = item.backpack;
- this._removeItem(item);
-
- // TODO: UI feedback
- if ( eqs[slot] )
- this.unequipSlot(slot, oldIdx);
-
- this.items[item.__id__] = item;
- eqs[slot] = item;
- item.slot = slot;
-
- return this._emitItemChange('item.equip', item, { 'slot':slot });
- },
-
- unequipSlot : function unequipSlot(slot, idx){
- var inv = this.inventory
- , eqs = inv.equipment
- , item = eqs[slot]
- ;
- if (item) {
- // TODO: UI feedback on failure
- if ( !this._putItem(item, idx) )
- return this;
-
- eqs[slot] = null;
- item.slot = null;
- this._emitItemChange('item.unequip', item, { 'slot':slot, 'idx':idx });
- }
- return this;
- },
-
-
-
- /**
- * @return {Integer} Index of first empty slot in this unit's backpack.
- */
- _getEmptySlot : function _getEmptySlot(){
- var slots = this.slots
- , max = this.max;
-
- if (this.size >= max)
- return -1;
-
- for (var i=0, v=slots[i]; i<max; v=slots[++i])
- if (v === undefined)
- return i;
-
- return -1;
- },
-
-
- /**
- * Inserts item into backpack at index, updating metadata.
- * @protected
- * @param {Item} item
- * @param {Number} [idx] Backpack position at which to insert item. If missing, first open slot will be used.
- * @return {Boolean}
- */
- _putItem : function putItem(item, idx){
- if (!item) return false;
-
- // item = this.getItem(item);
- var idx = ( (typeof idx == "number") ? idx : this._getEmptySlot() )
- , id = item.__id__
- , ui = item.ui
- ;
-
- // Backpack bounds check
- if ( idx < 0 || idx >= this.max )
- return false;
-
- if ( this.items[id] )
- delete this.slots[ui.bpIdx]; // Already in backpack? Remove from current slot
- else
- this.size++; // Otherwise increment size
-
- this.items[id] = item;
- this.slots[idx] = item;
- ui.bpIdx = idx;
- ui.container = this;
-
- return true;
- },
-
-
- /**
- * Removes item from backpack, updating metadata.
- * @param {Item} item
- * @return {Boolean}
- */
- _removeItem : function removeItem(item){
- if (!item) return false;
-
- // item = this.getItem(item);
- var id = item.__id__
- , ui = item.ui
- , idx = ui.bpIdx
- , slot = ui.equipSlot
- , hasItem = !!this.items[id]
- ;
-
- delete this.items[id];
-
- if (hasItem) {
- // TODO: unequip slot
- item.clean();
- delete this.slots[idx];
- this.size--;
- return true;
- }
-
- return false;
- },
-
-
- _emitItemChange : function _emitItemChange(evt, item, data){
- data = Y.extend({ 'unit':this, 'item':item }, data || {});
- this.emit(evt, item, data);
- item.emit(evt, this, data);
- return this;
- }
-
-
-
-});
},
- onCreate : function initInventoried(evt){
- var self = evt.data.instance
- , clsInv = self.__class__.aggregate('inventory')
+ onCreate : function initInventoried(evt, self){
+ var clsInv = self.__class__.aggregate('inventory')
, inv = self.inventory = deepcopy(clsInv)
;
inv.items = {};
_emitItemChange : function _emitItemChange(evt, item, data){
data = Y.extend({ 'unit':this, 'item':item }, data || {});
- this.emit(evt, item, data);
- item.emit(evt, this, data);
+ this.emit(evt, item, data, item);
+ item.emit(evt, this, data, this);
return this;
},
exports['Meronomic'] =
Mixin.subclass('Meronomic', {
- onCreate : function initMeronomic(evt){
+ onCreate : function initMeronomic(evt, self){
}
Quantified =
exports['Quantified'] =
Mixin.subclass('Quantified', {
+ __bind__ : [ 'onBuffAcquired', 'onBuffLost' ],
stats : {},
cooldowns : {},
buffs : [],
- onCreate : function initQuantified(evt){
- var self = evt.data.instance;
+ onCreate : function initQuantified(evt, self){
self.buffs = Y([]);
- self.on('buff.conjure', self.onBuffAcquired.bind(self));
- self.on('buff.die', self.onBuffLost.bind(self));
+ self.on('buff.conjure', self.onBuffAcquired);
+ self.on('buff.die', self.onBuffLost);
+ // self.on('buff.conjure', self.onBuffAcquired.bind(self));
+ // self.on('buff.die', self.onBuffLost.bind(self));
},
stat : function stat(k){
exports['Item'] =
Thing.subclass('Item', {
// __mixins__ : [ ],
- __bind__ : [ 'onCollide', 'onAcquired', 'onLost', 'onEquip', 'onUnequip' ],
+ __bind__ : [ 'onCollide', 'onAcquired', 'onLost', 'onEquip', 'onUnequip', 'onBuffDeath' ],
align : 0, // 0 reserved for neutral units
owner : null, // {Unit} Owner when picked up.
currentBuffs : null, // {Buff...} Buffs applied to owner
+ isEquipped : false,
- // UI Bookkeeping
- inv : {
- idx : null, // {Integer} Index in owner's backpack
- container : null // {String} Slotname if equipped on owner
- },
+ // Inventory Bookkeeping
+ // inv : {
+ // links : [], // {Array} Pointers to Belts that link to this item
+ // idx : null, // {Integer} Index in bag
+ // bag : null // {Container} Containing bag
+ // },
init : function initItem(){
Thing.init.call(this, 0);
- this.clean();
this.effects = this.effects.clone();
this.passives = this.passives.clone();
- this.activeBuffs = new Y.YArray();
- this.passiveBuffs = new Y.YArray();
+ this.currentBuffs = new Y.YArray();
+ this.currentActive = new Y.YArray();
+ this.currentPassive = new Y.YArray();
this.activateGauge = new CooldownGauge(this.cooldowns.activate, REF_SIZE+1,REF_SIZE+1);
- this.on('collide', this.onCollide);
+ this.on('collide', this.onCollide);
this.on('item.acquire', this.onAcquired);
- this.on('item.lose', this.onLost);
- this.on('item.equip', this.onEquip);
- },
-
- /**
- * Resets UI bookkeeping.
- */
- clean : function clean(){
- this.inv = Y.core.map(this.inv, kNull);
- return this;
+ this.on('item.lose', this.onLost);
+ this.on('item.equip', this.onEquip);
+ this.on('item.unequip', this.onUnequip);
},
tick : function tick(elapsed, now, ticks){
console.log(this+' activated!');
if ( this.owner && this.cooldowns.activate.activate() ) {
- this.currentBuffs.extend( this.effects.invoke('instantiate', this.owner) );
+ var buffs = this.currentBuffs
+ , active = this.currentActive
+ ;
+ if ( active.length )
+ active.invoke('die', 'item.reactivated');
+
+ var activated = this.effects.invoke('instantiate', this.owner);
+ activated.invoke('on', 'buff.die', this.onBuffDeath);
+ buffs.extend(activated);
+ active.extend(activated);
}
return this;
},
- onEquip : function onEquip(){
+ onBuffDeath : function onBuffDeath(evt, buff){
+ this.currentBuffs.remove(buff);
+ this.currentActive.remove(buff);
+ this.currentPassive.remove(buff);
+ },
+
+ onEquip : function onEquip(evt){
console.log(this+' equipped!');
if ( this.owner ) {
- // TODO: Note buffs for unequip
- this.currentBuffs.extend( this.passives.invoke('instantiate', this.owner) );
+ this.isEquipped = true;
+ var buffs = this.currentBuffs
+ , passive = this.currentPassive
+ ;
+ if ( passive.length )
+ passive.invoke('die', 'item.reequipped');
+
+ var equipped = this.passives.invoke('instantiate', this.owner);
+ equipped.invoke('on', 'buff.die', this.onBuffDeath);
+ buffs.extend(equipped);
+ passive.extend(equipped);
}
+ return this;
},
onUnequip : function onUnequip(evt){
console.log(this+' unequipped!');
- // TODO: unequip buffs
+ this.isEquipped = false;
+ if ( this.owner ) {
+ this.currentPassive.invoke('die', 'item.unequipped');
+ }
+ return this;
},
// TODO: Add to correct container
unit.addItem(this);
},
- onAcquired : function onAcquired(evt){
+ onAcquired : function onAcquired(evt, container){
this.owner = evt.data.unit;
// console.log(this.owner+' acquired '+this+' ('+this.desc+')!');
- // this.currentBuffs = this.passives.invoke('instantiate', this.owner);
this.remove(); // removes map object
this.game.map.removeBlocker(this); // remove map zone
},
onLost : function onLost(evt){
- // if (!this.owner) return;
- if ( this.currentBuffs )
- this.currentBuffs.invoke('die', 'item.lost');
- var unit = this.owner;
+ var current = this.currentBuffs
+ , unit = this.owner
+ ;
+ if ( current.length )
+ current.invoke('die', 'item.lost');
+
// console.log(unit+' lost '+this+'!');
this.owner = null;
- // TODO: game to listen, re-add to level at unit.loc
+
+ if ( /\blost\.drop\b/.test(evt.type) )
+ unit.game.addUnit(this, unit.loc); // TODO: stop item from being instantly picked up.
},
render : function render(parent){