@@ -312,7 +312,9 @@ define([ | |||
config.push(menuItems.learn); | |||
else if (item.type === 'mtx') | |||
config.push(menuItems.activate); | |||
else if (item.type === 'toy' || item.type === 'consumable') { | |||
else if (item.type === 'toy' || item.type === 'consumable' || item.useText) { | |||
if (item.useText) | |||
menuItems.use.text = item.useText; | |||
config.push(menuItems.use); | |||
if (!item.has('quickSlot')) | |||
config.push(menuItems.quickSlot); | |||
@@ -285,7 +285,7 @@ define([ | |||
this.tooltip.find('.worth').html(item.worthText ? ('<br />value: ' + item.worthText) : ''); | |||
if ((item.effects) && (item.type !== 'mtx')) { | |||
if (item.effects && item.effects[0].text && item.type !== 'mtx') { | |||
let htmlEffects = ''; | |||
item.effects.forEach(function (e, i) { | |||
@@ -38,7 +38,7 @@ module.exports = { | |||
let e = { | |||
type: 'effects', | |||
effects: this.effects | |||
.map(f => f.save()) | |||
.map(f => f.save ? f.save() : f) | |||
.filter(f => !!f) | |||
}; | |||
@@ -222,6 +222,10 @@ module.exports = { | |||
effect.destroy(); | |||
this.syncRemove(effect.id, effect.type, noMsg || effect.noMsg); | |||
effects.splice(i, 1); | |||
if (effect.destroy) | |||
effect.destroy(); | |||
return; | |||
} | |||
} | |||
@@ -234,7 +238,11 @@ module.exports = { | |||
if (effect.type === effectName) { | |||
this.syncRemove(effect.id, effect.type, noMsg || effects.noMsg); | |||
effects.splice(i, 1); | |||
return; | |||
if (effect.destroy) | |||
effect.destroy(); | |||
return effect; | |||
} | |||
} | |||
}, | |||
@@ -252,7 +260,7 @@ module.exports = { | |||
continue; | |||
} | |||
if (e.ttl <= 0) | |||
if (e.ttl === 0) | |||
continue; | |||
let events = e.events; | |||
if (!events) | |||
@@ -307,6 +307,8 @@ module.exports = { | |||
let eLen = effects.length; | |||
for (let j = 0; j < eLen; j++) { | |||
let effect = effects[j]; | |||
if (!effect.events) | |||
continue; | |||
let effectEvent = effect.events.onConsumeItem; | |||
if (!effectEvent) | |||
@@ -536,9 +538,10 @@ module.exports = { | |||
statGenerator.generate(item); | |||
} else { | |||
let effectUrl = itemEffects.get(e.type); | |||
let effectModule = require('../' + effectUrl); | |||
e.events = effectModule.events; | |||
try { | |||
let effectModule = require('../' + effectUrl); | |||
e.events = effectModule.events; | |||
} catch (error) {} | |||
} | |||
}); | |||
} | |||
@@ -812,11 +815,11 @@ module.exports = { | |||
e.events = mtxModule.events; | |||
} else if (e.type) { | |||
let effectUrl = itemEffects.get(e.type); | |||
let effectModule = require('../' + effectUrl); | |||
e.text = effectModule.events.onGetText(item, e); | |||
e.events = effectModule.events; | |||
try { | |||
let effectModule = require('../' + effectUrl); | |||
e.text = effectModule.events.onGetText(item, e); | |||
e.events = effectModule.events; | |||
} catch (error) {} | |||
} | |||
}); | |||
} | |||
@@ -12,8 +12,8 @@ module.exports = { | |||
values[p] = value; | |||
} | |||
if (!this.expire) | |||
this.expire = (+new Date()) + (this.ttl * 350); | |||
if (!values.expire) | |||
values.expire = (+new Date()) + (this.ttl * 350); | |||
return values; | |||
}, | |||
@@ -0,0 +1,44 @@ | |||
module.exports = { | |||
type: 'mounted', | |||
oldCell: null, | |||
oldSheetName: null, | |||
init: function () { | |||
let obj = this.obj; | |||
this.oldCell = obj.cell; | |||
this.oldSheetName = obj.sheetName; | |||
obj.cell = 35; | |||
obj.sheetName = 'mobs'; | |||
let syncer = obj.syncer; | |||
syncer.set(false, null, 'cell', obj.cell); | |||
syncer.set(false, null, 'sheetName', obj.sheetName); | |||
}, | |||
simplify: function () { | |||
return { | |||
type: 'mounted', | |||
ttl: this.ttl | |||
}; | |||
}, | |||
destroy: function () { | |||
let obj = this.obj; | |||
obj.cell = this.oldCell; | |||
obj.sheetName = this.oldSheetName; | |||
let syncer = obj.syncer; | |||
syncer.set(false, null, 'cell', obj.cell); | |||
syncer.set(false, null, 'sheetName', obj.sheetName); | |||
}, | |||
events: { | |||
onBeforeTryMove: function (moveEvent) { | |||
moveEvent.sprintChance = 200; | |||
} | |||
} | |||
}; |
@@ -0,0 +1,66 @@ | |||
/* | |||
Example of a mount: | |||
{ | |||
name: 'Brown Horse\'s Reins', | |||
type: 'mount', | |||
quality: 2, | |||
noDrop: true, | |||
noDestroy: true, | |||
noSalvage: true, | |||
cdMax: 10, | |||
sprite: [0, 9], | |||
spritesheet: 'images/questItems.png', | |||
useText: 'mount', | |||
description: 'Stout, dependable and at least faster than you', | |||
effects: [{ | |||
type: 'mount', | |||
rolls: { | |||
speed: 150, | |||
cell: 5, | |||
sheetName: 'mobs' | |||
} | |||
}] | |||
} | |||
*/ | |||
module.exports = { | |||
name: 'Feature: Mounts', | |||
init: function () { | |||
this.events.on('onBeforeUseItem', this.onBeforeUseItem.bind(this)); | |||
this.events.on('onBeforeGetEffect', this.onBeforeGetEffect.bind(this)); | |||
}, | |||
onBeforeUseItem: function (obj, item, result) { | |||
if (item.type !== 'mount') | |||
return; | |||
let syncer = obj.syncer; | |||
let currentEffect = obj.effects.removeEffectByName('mounted', true); | |||
if (currentEffect) { | |||
let currentItem = currentEffect.source; | |||
currentItem.useText = 'mount'; | |||
currentItem.cdMax = 0; | |||
syncer.setArray(true, 'inventory', 'getItems', currentItem); | |||
if (currentItem === item) | |||
return; | |||
} | |||
let builtEffect = obj.effects.addEffect({ | |||
type: 'mounted', | |||
ttl: -1 | |||
}); | |||
builtEffect.source = item; | |||
item.useText = 'unmount'; | |||
syncer.setArray(true, 'inventory', 'getItems', item); | |||
}, | |||
onBeforeGetEffect: function (result) { | |||
if (result.type.toLowerCase() === 'mounted') | |||
result.url = `${this.relativeFolderName}/effects/effectMounted.js`; | |||
} | |||
}; |
@@ -219,14 +219,24 @@ module.exports = { | |||
return; | |||
if (q.action === 'move') { | |||
let maxDistance = 1; | |||
if ((this.actionQueue[0]) && (this.actionQueue[0].action === 'move')) { | |||
let sprintChance = this.stats.values.sprintChance || 0; | |||
let moveEvent = { | |||
sprintChance: this.stats.values.sprintChance || 0 | |||
}; | |||
this.fireEvent('onBeforeTryMove', moveEvent); | |||
let physics = this.instance.physics; | |||
if ((~~(Math.random() * 100) < sprintChance) && (!physics.isTileBlocking(q.data.x, q.data.y))) { | |||
q = this.dequeue(); | |||
q.isDouble = true; | |||
} | |||
let sprintChance = moveEvent.sprintChance; | |||
do { | |||
if ((~~(Math.random() * 100) < sprintChance) && (!physics.isTileBlocking(q.data.x, q.data.y))) { | |||
q = this.dequeue(); | |||
maxDistance++; | |||
} | |||
sprintChance -= 100; | |||
} while (sprintChance > 0 && this.actionQueue.length > 0); | |||
} | |||
q.maxDistance = maxDistance; | |||
let success = this.performMove(q); | |||
if (!success) | |||
this.clearQueue(); | |||
@@ -255,7 +265,7 @@ module.exports = { | |||
return true; | |||
} | |||
let maxDistance = action.isDouble ? 2 : 1; | |||
let maxDistance = action.maxDistance || 1; | |||
let deltaX = Math.abs(this.x - data.x); | |||
let deltaY = Math.abs(this.y - data.y); | |||
@@ -1,24 +1 @@ | |||
* Client side debuff icons aren't being removed | |||
Old | |||
* The `Pumpkin Sailor` and his ship spawn south of the `Crab Ruins` | |||
* New gather nodes: `Tiny Pumpkin`, `Pumpkin` and `Giant Pumpkin` that drop `Candy Corn` | |||
* Pumpkins have a chance to spawn `Soul Nibblers` that drop extra `Candy Corn` | |||
* `Soul Nibblers` also have a small chance to drop the `Summon Pumpkin Skeleton` | |||
* Killing `Soul Nibblers` grants reputation with the `Pumpkin Sailor` | |||
* Every few hours, `Lord Squash` spawns | |||
* `Lord Squash` has a few lines he'll speak globally | |||
* Killing `Lord Squash` grants a lot of reputation with the `Pumpkin Sailor` | |||
* `Lord Squash` drops a lot of `Candy Corn` and has a small chance to drop `Haunted Ice Spear` | |||
* `Lord Squash` has two abilities: `Scatter Pumpkin Pieces` and a 'target-all' `Projectile` | |||
* The `Pumpkin Sailor` has dialogue options that explain his backstory a bit | |||
* The `Pumpkin Sailor` has four rings for sale for different spirits. They each cost 400 `Candy Corn` and require you to be Friendly with his faction | |||
* The `Pumpkin Sailor` has the `Pumpkin-Head Necromancer` skin for sale which costs 1200 `Candy Corn` and requires you to be Honored with his faction | |||
New | |||
* Purchasable `Some Non Combat Pet` for x `Candy Corn` at y reputation from the `Pumpkin Sailor` | |||
* Purchasable `100% Sprint Chance Mount` for x `Candy Corn` at y reputation from the `Pumpkin Sailor` | |||
* `Lord Squash` has a small chance to drop a `Some Slot Item` that causes `Some Aura` to not reserve mana | |||
* The `Hermit's House` and houses in `Fjolgard` should be decorated festively | |||
* It should be possible to rarely fish up `Ghoslty Carp` that can be combined with `Emberleaf` to create a `Ghostly Elixir` which grants the player a ghostly aura | |||
* A rare version of `Some Mob` should spawn in the `The Estuary` which has a chance to drop `Some Belt` |