Master See merge request Isleward/isleward!459tags/v0.4.4
@@ -1,4 +1,6 @@ | |||
node_modules | |||
package-lock.json | |||
storage.db | |||
*.sublime-project | |||
*.sublime-workspace | |||
@@ -13,4 +15,6 @@ helpers/sqlite-to-rethink/rethinkdb_data | |||
helpers/sqlite-to-rethink/tmp | |||
helpers/sqlite-to-rethink/log_file | |||
helpers/sqlite-to-rethink/rethinkdb.exe | |||
.idea | |||
.vscode |
@@ -39,6 +39,8 @@ | |||
@purpleD: #393268; | |||
@pinkA: #fc66f7; | |||
@pinkB: #de43ae; | |||
@pinkC: #b4347a; | |||
@pinkD: #933159; | |||
@grayB: #c0c3cf; | |||
@grayC: #929398; | |||
@grayD: #69696e; | |||
@@ -243,3 +243,6 @@ body { | |||
.color-purpleA { | |||
color: @purpleA !important; | |||
} | |||
.color-tealB { | |||
color: @tealB !important;} |
@@ -71,6 +71,7 @@ define([ | |||
init: function () { | |||
PIXI.settings.GC_MODE = PIXI.GC_MODES.AUTO; | |||
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST; | |||
PIXI.settings.SPRITE_MAX_TEXTURES = Math.min(PIXI.settings.SPRITE_MAX_TEXTURES, 16); | |||
events.on('onGetMap', this.onGetMap.bind(this)); | |||
events.on('onToggleFullscreen', this.toggleScreen.bind(this)); | |||
@@ -175,31 +176,31 @@ define([ | |||
let container = this.layers.tileSprites; | |||
for (let i = 0; i < w; i++) { | |||
let ii = i / 10; | |||
let ii = i / 7.5; | |||
for (let j = 0; j < h; j++) { | |||
let roll = Math.sin(((j * 0.2) % 5) + Math.cos(ii % 8)); | |||
let tile = 5; | |||
let tile = 74; | |||
if (roll < -0.2) | |||
tile = 3; | |||
tile = 108; | |||
else if (roll < 0.2) | |||
tile = 4; | |||
tile = 107; | |||
else if (roll < 0.5) | |||
tile = 53; | |||
tile = 79; | |||
let alpha = mRandom(); | |||
if ([5, 53].indexOf(tile) > -1) | |||
if ([73, 79].indexOf(tile) > -1) | |||
alpha *= 2; | |||
alpha = Math.min(Math.max(0.15, alpha), 0.65); | |||
if (mRandom() < 0.35) { | |||
tile = { | |||
5: 6, | |||
3: 0, | |||
4: 1, | |||
53: 54 | |||
74: 94, | |||
108: 110, | |||
107: 97, | |||
79: 119 | |||
}[tile]; | |||
} | |||
@@ -4,22 +4,36 @@ define([ | |||
'ui/factory', | |||
'html!ui/templates/characters/template', | |||
'html!ui/templates/characters/templateListItem', | |||
'css!ui/templates/characters/styles' | |||
'css!ui/templates/characters/styles', | |||
'js/system/globals' | |||
], function ( | |||
events, | |||
client, | |||
uiFactory, | |||
template, | |||
templateListItem, | |||
styles | |||
styles, | |||
globals | |||
) { | |||
return { | |||
tpl: template, | |||
centered: true, | |||
characterInfo: {}, | |||
selected: null, | |||
deleteCount: 0, | |||
beforeRender: function () { | |||
const { clientConfig: { logoPath } } = globals; | |||
if (!logoPath) | |||
return; | |||
const tempEl = $(this.tpl); | |||
tempEl.find('.logo').attr('src', logoPath); | |||
this.tpl = tempEl.prop('outerHTML'); | |||
}, | |||
postRender: function () { | |||
this.find('.btnPlay').on('click', this.onPlayClick.bind(this)); | |||
this.find('.btnNew').on('click', this.onNewClick.bind(this)); | |||
@@ -91,7 +105,7 @@ define([ | |||
.forEach(function (c, i) { | |||
let charName = c.name; | |||
if (c.level !== null) | |||
charName += '<font class="color-yellowB"> (' + c.level + ')</font>'; | |||
charName += '<font class="color-tealB"> (' + c.level + ')</font>'; | |||
let html = templateListItem | |||
.replace('$NAME$', charName); | |||
@@ -103,7 +103,7 @@ | |||
} | |||
.btn { | |||
background-color: @blueC; | |||
background-color: @pinkB; | |||
width: calc((100% - (16px * 2)) / 3); | |||
float: left; | |||
margin-right: 16px; | |||
@@ -114,7 +114,7 @@ | |||
} | |||
&:hover { | |||
background-color: @blueB; | |||
background-color: @pinkB; | |||
} | |||
&.deleting { | |||
@@ -3,13 +3,15 @@ define([ | |||
'js/system/client', | |||
'html!ui/templates/createCharacter/template', | |||
'css!ui/templates/createCharacter/styles', | |||
'ui/factory' | |||
'ui/factory', | |||
'js/system/globals' | |||
], function ( | |||
events, | |||
client, | |||
template, | |||
styles, | |||
uiFactory | |||
uiFactory, | |||
globals | |||
) { | |||
return { | |||
tpl: template, | |||
@@ -22,6 +24,17 @@ define([ | |||
prophecies: [], | |||
beforeRender: function () { | |||
const { clientConfig: { logoPath } } = globals; | |||
if (!logoPath) | |||
return; | |||
const tempEl = $(this.tpl); | |||
tempEl.find('.logo').attr('src', logoPath); | |||
this.tpl = tempEl.prop('outerHTML'); | |||
}, | |||
postRender: function () { | |||
this.getSkins(); | |||
@@ -130,7 +130,7 @@ | |||
} | |||
.btn { | |||
background-color: @blueC; | |||
background-color: @pinkC; | |||
width: calc((100% - @boxPadding) / 2); | |||
float: left; | |||
margin-right: @boxPadding; | |||
@@ -141,7 +141,7 @@ | |||
} | |||
&:hover { | |||
background-color: @blueB; | |||
background-color: @pinkB; | |||
} | |||
} | |||
@@ -176,7 +176,7 @@ | |||
.heading { | |||
margin-bottom: @boxPadding; | |||
color: @blueA; | |||
color: @tealB; | |||
} | |||
.list { | |||
@@ -104,7 +104,7 @@ define([ | |||
itemEl | |||
.data('item', item) | |||
.on('click', this.onClick.bind(this, item)) | |||
.on('click', this.onClick.bind(this, item, false)) | |||
.on('mousedown', clickHandler) | |||
.on('mouseup', this.onMouseDown.bind(this, null, null, false)) | |||
.on('mousemove', moveHandler) | |||
@@ -130,7 +130,7 @@ define([ | |||
.addClass(className); | |||
}, | |||
onClick: function (item) { | |||
onClick: function (item, forceCtrl) { | |||
let msg = { | |||
item: item, | |||
success: true | |||
@@ -140,7 +140,7 @@ define([ | |||
if (!msg.success) | |||
return; | |||
if (!input.isKeyDown('ctrl', true)) | |||
if (!forceCtrl && !input.isKeyDown('ctrl', true)) | |||
return; | |||
client.request({ | |||
@@ -305,6 +305,10 @@ define([ | |||
text: 'split stack', | |||
callback: this.splitStackStart.bind(this, item) | |||
}, | |||
link: { | |||
text: 'link', | |||
callback: this.onClick.bind(this, item, true) | |||
}, | |||
divider: '----------' | |||
}; | |||
@@ -361,6 +365,8 @@ define([ | |||
if ((!item.noDrop) && (!item.quest)) | |||
ctxConfig.push(menuItems.mail); | |||
ctxConfig.push(menuItems.link); | |||
if (isMobile) | |||
this.hideTooltip(null, this.hoverItem); | |||
@@ -4,18 +4,32 @@ define([ | |||
'ui/factory', | |||
'html!ui/templates/login/template', | |||
'css!ui/templates/login/styles', | |||
'js/rendering/renderer' | |||
'js/rendering/renderer', | |||
'js/system/globals' | |||
], function ( | |||
events, | |||
client, | |||
uiFactory, | |||
template, | |||
styles, | |||
renderer | |||
renderer, | |||
globals | |||
) { | |||
return { | |||
tpl: template, | |||
centered: true, | |||
beforeRender: function () { | |||
const { clientConfig: { logoPath } } = globals; | |||
if (!logoPath) | |||
return; | |||
const tempEl = $(this.tpl); | |||
tempEl.find('.logo').attr('src', logoPath); | |||
this.tpl = tempEl.prop('outerHTML'); | |||
}, | |||
postRender: function () { | |||
this.onEvent('onHandshake', this.onHandshake.bind(this)); | |||
@@ -46,7 +46,7 @@ | |||
.label { | |||
width: 30%; | |||
padding-top: 10px; | |||
color: @green; | |||
color: @tealC; | |||
} | |||
input { | |||
@@ -78,7 +78,7 @@ | |||
margin-top: 36px; | |||
float: left; | |||
text-align: center; | |||
color: @orangeA; | |||
color: @pinkA; | |||
filter: brightness(100%) | |||
drop-shadow(0px -4px 0px @blackD) | |||
drop-shadow(0px 4px 0px @blackD) | |||
@@ -96,7 +96,7 @@ | |||
height: 35px; | |||
.btn { | |||
background-color: @blueC; | |||
background-color: @pinkC; | |||
width: calc((100% - @boxPadding) / 2); | |||
float: left; | |||
margin-right: @boxPadding; | |||
@@ -107,7 +107,7 @@ | |||
} | |||
&:hover { | |||
background-color: @blueB; | |||
background-color: @pinkB; | |||
} | |||
} | |||
@@ -146,7 +146,7 @@ | |||
padding-left: 10px; | |||
padding-right: 10px; | |||
margin-left: 10px; | |||
background-color: @blueD; | |||
background-color: @pinkD; | |||
color: @white; | |||
&:first-child { | |||
@@ -154,7 +154,7 @@ | |||
} | |||
&:hover { | |||
background-color: @blueC; | |||
background-color: @pinkC; | |||
} | |||
} | |||
@@ -11,11 +11,11 @@ | |||
</div> | |||
<div class="message"></div> | |||
</div> | |||
<div class="news" location="https://gitlab.com/Isleward/isleward/tags/v0.4.3">[ Latest Release Notes ]</div> | |||
<div class="news" location="https://gitlab.com/Isleward/isleward/tags/v0.4.4">[ Latest Release Notes ]</div> | |||
<div class="extra"> | |||
<div class="el btn btnPatreon" location="https://patreon.com/bigbadwaffle">Pledge on Patreon</div> | |||
<div class="el btn btnPaypal" location="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BR2CC82WUAVEA">Donate on Paypal</div> | |||
<div class="el btn btnWiki" location="http://wiki.isleward.com/Main_Page">Access the Wiki</div> | |||
</div> | |||
<div class="version" location="https://gitlab.com/Isleward/isleward/tags/v0.4.3">v0.4.3</div> | |||
<div class="version" location="https://gitlab.com/Isleward/isleward/tags/v0.4.4">v0.4.4</div> | |||
</div> |
@@ -301,8 +301,14 @@ define([ | |||
el.addClass('info'); | |||
if (m.item) { | |||
let clickHander = () => {}; | |||
let moveHandler = this.showItemTooltip.bind(this, el, m.item); | |||
if (isMobile) | |||
[clickHander, moveHandler] = [moveHandler, clickHander]; | |||
el.find('span') | |||
.on('mousemove', this.showItemTooltip.bind(this, el, m.item)) | |||
.on('mousemove', moveHandler) | |||
.on('mousedown', clickHander) | |||
.on('mouseleave', this.hideItemTooltip.bind(this)); | |||
} | |||
@@ -357,7 +363,9 @@ define([ | |||
}; | |||
} | |||
events.emit('onShowItemTooltip', item, ttPos, true, true); | |||
let bottomAlign = !isMobile; | |||
events.emit('onShowItemTooltip', item, ttPos, true, bottomAlign); | |||
}, | |||
toggle: function (show, isFake, e) { | |||
@@ -242,14 +242,18 @@ define([ | |||
let elQuantity = elMaterial.find('.quantity'); | |||
let invMaterial = items.find(i => i.name === itemMaterial.name) || { quantity: 0 }; | |||
let newText = elQuantity.html().split('/'); | |||
newText = invMaterial.quantity + '/' + newText[1]; | |||
let currentText = elQuantity.html().split('/'); | |||
let newText = invMaterial.quantity + '/' + currentText[1]; | |||
elQuantity.html(newText); | |||
let elButton = this.find('.actionButton').removeClass('disabled'); | |||
if (invMaterial.quantity < newText[1]) { | |||
if (invMaterial.quantity < currentText[1]) { | |||
elButton.addClass('disabled'); | |||
elQuantity.addClass('red'); | |||
} else { | |||
elButton.removeClass('disabled'); | |||
elQuantity.removeClass('red'); | |||
} | |||
}, | |||
@@ -137,3 +137,11 @@ | |||
text-align: center; | |||
} | |||
} | |||
.mobile .uiTooltipItem { | |||
z-index: 9999999999; | |||
> * { | |||
z-index: 9999999999; | |||
} | |||
} |
@@ -18,6 +18,9 @@ define([ | |||
if (this.container) | |||
container += ' > ' + this.container; | |||
if (this.beforeRender) | |||
this.beforeRender(); | |||
this.el = $(this.tpl) | |||
.appendTo(container) | |||
.data('ui', this); | |||
@@ -237,6 +237,9 @@ module.exports = { | |||
//If the item has been used up, find another one with the same name | |||
const item = inventory.findItem(this.quickSlots[0]); | |||
if (!item) | |||
return; | |||
inventory.useItem(this.quickSlots[0]); | |||
if (item.uses <= 0 && !item.quantity) | |||
@@ -103,17 +103,35 @@ module.exports = { | |||
let messageText = msg.message; | |||
if (messageText[0] !== '/') | |||
return; | |||
msg.ignore = true; | |||
messageText = messageText.substr(1).split(' '); | |||
let actionName = messageText.splice(0, 1)[0].toLowerCase(); | |||
actionName = Object.keys(commandRoles).find(a => (a.toLowerCase() === actionName)); | |||
if (!actionName) | |||
if (!actionName) { | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'color-redA', | |||
message: 'Invalid command.', | |||
type: 'info' | |||
}] | |||
}] | |||
}); | |||
return; | |||
else if (this.roleLevel < commandRoles[actionName]) | |||
} else if (this.roleLevel < commandRoles[actionName]) { | |||
this.obj.socket.emit('events', { | |||
onGetMessages: [{ | |||
messages: [{ | |||
class: 'color-redA', | |||
message: 'You do not have the required permissions.', | |||
type: 'info' | |||
}] | |||
}] | |||
}); | |||
return; | |||
msg.ignore = true; | |||
} | |||
let config = {}; | |||
if ((messageText.length === 1) && (messageText[0].indexOf('=') === -1)) | |||
@@ -258,6 +276,11 @@ module.exports = { | |||
return; | |||
} | |||
if (target === this.obj.name) { | |||
this.sendMessage('You cannot block yourself', 'color-redA'); | |||
return; | |||
} | |||
this.blockedPlayers.push(target); | |||
this.sendMessage(`Successfully blocked ${target}`, 'color-yellowB'); | |||
@@ -314,7 +337,8 @@ module.exports = { | |||
messages: [{ | |||
class: 'color-grayB', | |||
message: `${this.obj.name} rolled ${roll}`, | |||
type: 'chat' | |||
type: 'chat', | |||
source: this.obj.name | |||
}] | |||
} | |||
}); | |||
@@ -441,6 +465,9 @@ module.exports = { | |||
}, | |||
getItem: function (config) { | |||
if (typeof config !== 'object') | |||
return; | |||
if (config.slot === 'set') { | |||
configSlots.slots.forEach(function (s) { | |||
if (s === 'tool') | |||
@@ -6,6 +6,8 @@ module.exports = { | |||
lifetime: -1, | |||
maxDistance: 10, | |||
alwaysFollowMaster: false, | |||
lastMasterPos: { | |||
x: 0, | |||
y: 0 | |||
@@ -85,6 +87,24 @@ module.exports = { | |||
}, -1); | |||
}, | |||
followMaster: function (distance) { | |||
const { obj, maxDistance, master: { x, y }, lastMasterPos: { x: lx, y: ly } } = this; | |||
if (distance < maxDistance) | |||
return; | |||
const masterDistanceFromLastPos = Math.max(Math.abs(x - lx), Math.abs(y - ly)); | |||
if (masterDistanceFromLastPos <= maxDistance) | |||
return; | |||
obj.mob.goHome = true; | |||
obj.mob.originX = x; | |||
obj.mob.originY = y; | |||
this.lastMasterPos.x = x; | |||
this.lastMasterPos.y = y; | |||
}, | |||
update: function () { | |||
if (this.lifetime > 0) { | |||
this.lifetime--; | |||
@@ -106,6 +126,12 @@ module.exports = { | |||
let maxDistance = this.maxDistance; | |||
let distance = Math.max(Math.abs(obj.x - master.x), Math.abs(obj.y - master.y)); | |||
if (this.alwaysFollowMaster) { | |||
this.followMaster(distance); | |||
return; | |||
} | |||
if (obj.aggro) | |||
attacker = this.fGetHighest.inCombat(); | |||
@@ -1,4 +1,5 @@ | |||
let qualityGenerator = require('../items/generators/quality'); | |||
let { isItemStackable } = require('./inventory/helpers'); | |||
module.exports = { | |||
type: 'gatherer', | |||
@@ -27,6 +28,11 @@ module.exports = { | |||
let firstNode = nodes[0]; | |||
if (!this.hasSpace(firstNode)) { | |||
this.sendAnnouncement('Your bags are too full to gather any more resources.'); | |||
return; | |||
} | |||
this.gathering = firstNode; | |||
let ttlMax = firstNode.resourceNode.ttl || this.defaultTtlMax; | |||
@@ -49,20 +55,25 @@ module.exports = { | |||
update: function () { | |||
let gathering = this.gathering; | |||
if (!gathering) | |||
return; | |||
if (gathering.destroyed) { | |||
let isFish = (gathering.resourceNode.nodeType === 'fish'); | |||
let hasSpace = this.hasSpace(this.gathering); | |||
if (gathering.destroyed || !hasSpace) { | |||
this.gathering = null; | |||
this.gatheringTtl = 0; | |||
this.obj.syncer.set(false, 'gatherer', 'progress', 100); | |||
this.obj.syncer.set(true, 'gatherer', 'progress', 100); | |||
this.obj.syncer.set(true, 'gatherer', 'action', 'Fishing'); | |||
if (isFish) | |||
this.obj.syncer.set(true, 'gatherer', 'action', 'Fishing'); | |||
if (!hasSpace) | |||
this.sendAnnouncement('Your bags are too full to gather any more resources.'); | |||
return; | |||
} | |||
let isFish = (gathering.resourceNode.nodeType === 'fish'); | |||
if (this.gatheringTtl > 0) { | |||
if ((this.gatheringTtl === this.gatheringTtlMax) && (gathering.width)) { | |||
['x', 'y', 'width', 'height'].forEach(function (p) { | |||
@@ -182,6 +193,25 @@ module.exports = { | |||
this.gathering = null; | |||
}, | |||
hasSpace: function (node) { | |||
// By default, the player is allowed to gather "nothing" | |||
if (!node.inventory || !node.inventory.items) | |||
return true; | |||
let items = node.inventory.items; | |||
let slots = this.obj.inventory.inventorySize - this.obj.inventory.items.filter(f => !f.eq).length; | |||
for (const item of items) { | |||
if (isItemStackable(item)) { | |||
let ownedItem = this.obj.inventory.items.find(owned => (owned.name === item.name) && (isItemStackable(owned))); | |||
if (ownedItem) | |||
continue; | |||
} | |||
slots--; | |||
} | |||
return (slots >= 0); | |||
}, | |||
enter: function (node) { | |||
let gatherResult = extend({ | |||
nodeName: node.name | |||
@@ -5,6 +5,9 @@ let classes = require('../config/spirits'); | |||
let mtx = require('../mtx/mtx'); | |||
let factions = require('../config/factions'); | |||
let itemEffects = require('../items/itemEffects'); | |||
const events = require('../misc/events'); | |||
const { isItemStackable } = require('./inventory/helpers'); | |||
const transactions = require('../security/transactions'); | |||
const { applyItemStats } = require('./equipment/helpers'); | |||
@@ -295,7 +298,7 @@ module.exports = { | |||
if ((!fromItem) || (!toItem)) | |||
return; | |||
else if ((!fromItem.quantity) || (!toItem.quantity)) | |||
else if ((!isItemStackable(fromItem)) || (!isItemStackable(toItem))) | |||
return; | |||
toItem.quantity += fromItem.quantity; | |||
@@ -402,6 +405,7 @@ module.exports = { | |||
} | |||
this.obj.fireEvent('afterDestroyItem', item, amount); | |||
events.emit('afterPlayerDestroyItem', this.obj, item, amount); | |||
return item; | |||
}, | |||
@@ -437,6 +441,8 @@ module.exports = { | |||
this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id); | |||
this.createBag(dropCell.x, dropCell.y, [item]); | |||
events.emit('afterPlayerDropItem', this.obj, item); | |||
}, | |||
moveItem: function (msgs) { | |||
@@ -698,7 +704,7 @@ module.exports = { | |||
if (this.inventorySize !== -1) { | |||
if (item) { | |||
let exists = this.items.find(i => (i.name === item.name)); | |||
if (exists && !noStack && (exists.quantity || item.quantity)) | |||
if ((exists) && (!noStack) && (isItemStackable(item) && isItemStackable(exists))) | |||
return true; | |||
} | |||
@@ -1,3 +1,6 @@ | |||
const events = require('../../misc/events'); | |||
const { isItemStackable } = require('./helpers'); | |||
const getNextId = items => { | |||
let id = 0; | |||
let iLen = items.length; | |||
@@ -14,6 +17,7 @@ const getNextId = items => { | |||
module.exports = (cpnInv, item, hideMessage, noStack, hideAlert) => { | |||
const obj = cpnInv.obj; | |||
obj.instance.eventEmitter.emit('onBeforeGetItem', item, obj); | |||
events.emit('beforePlayerGetItem', obj, item); | |||
//We need to know if a mob dropped it for quest purposes | |||
let fromMob = item.fromMob; | |||
@@ -25,7 +29,7 @@ module.exports = (cpnInv, item, hideMessage, noStack, hideAlert) => { | |||
let quantity = item.quantity; | |||
let exists = false; | |||
if ((item.material || item.quest || item.quantity) && !item.noStack && !item.uses && !noStack) { | |||
if (isItemStackable(item) && !noStack) { | |||
let existItem = cpnInv.items.find(i => i.name === item.name); | |||
if (existItem) { | |||
exists = true; | |||
@@ -0,0 +1,5 @@ | |||
module.exports = { | |||
isItemStackable: function (item) { | |||
return (item.material || item.quest || item.quantity) && (!item.noStack) && (!item.uses); | |||
} | |||
}; |
@@ -70,6 +70,16 @@ module.exports = { | |||
}, this); | |||
if (!linked) | |||
return; | |||
let passiveResult = { | |||
success: true | |||
}; | |||
this.obj.fireEvent('onBeforePassivesChange', passiveResult, node); | |||
if (!passiveResult.success) | |||
return; | |||
this.obj.instance.eventEmitter.emitNoSticky('onBeforePlayerPassivesChange', passiveResult, this.obj, node); | |||
if (!passiveResult.success) | |||
return; | |||
this.points--; | |||
this.obj.syncer.set(true, 'passives', 'points', this.points); | |||
@@ -87,6 +97,16 @@ module.exports = { | |||
}, | |||
untickNode: function (msg) { | |||
let passiveResult = { | |||
success: true | |||
}; | |||
this.obj.fireEvent('onBeforePassivesChange', passiveResult); | |||
if (!passiveResult.success) | |||
return; | |||
this.obj.instance.eventEmitter.emitNoSticky('onBeforePlayerPassivesChange', passiveResult, this.obj); | |||
if (!passiveResult.success) | |||
return; | |||
let stats = this.obj.stats; | |||
this.selected.forEach(function (s) { | |||
@@ -1,4 +1,5 @@ | |||
const cpnInventory = require('./inventory'); | |||
const { isItemStackable } = require('./inventory/helpers'); | |||
const maxItems = 50; | |||
@@ -29,7 +30,7 @@ module.exports = { | |||
getItem: function (item) { | |||
//Material? | |||
let exists = false; | |||
if (((item.material) || (item.quest) || (item.quantity)) && (!item.noStack) && (!item.uses)) { | |||
if (isItemStackable(item)) { | |||
let existItem = this.items.find(i => i.name === item.name); | |||
if (existItem) { | |||
exists = true; | |||
@@ -66,8 +67,8 @@ module.exports = { | |||
if (!this.active) | |||
return; | |||
else if (this.items.length >= this.maxItems) { | |||
let isMaterial = this.items.some(stashedItem => item.name === stashedItem.name && (item.quantity || item.material)); | |||
if (!isMaterial) { | |||
let isStackable = this.items.some(stashedItem => item.name === stashedItem.name && (isItemStackable(stashedItem))); | |||
if (!isStackable) { | |||
this.obj.instance.syncer.queue('onGetMessages', { | |||
id: this.obj.id, | |||
messages: [{ | |||
@@ -79,7 +80,6 @@ module.exports = { | |||
return; | |||
} | |||
} | |||
this.getItem(item); | |||
this.obj.syncer.setArray(true, 'stash', 'getItems', item); | |||
@@ -2,6 +2,7 @@ const events = require('../misc/events'); | |||
const tos = require('./tos'); | |||
const config = { | |||
logoPath: null, | |||
resourceList: [], | |||
uiList: [], | |||
contextMenuActions: { | |||
@@ -13,6 +14,9 @@ const config = { | |||
module.exports = { | |||
init: function () { | |||
events.emit('onBeforeGetClientConfig', config); | |||
//Deprecated | |||
events.emit('onBeforeGetResourceList', config.resourceList); | |||
events.emit('onBeforeGetUiList', config.uiList); | |||
events.emit('onBeforeGetContextMenuActions', config.contextMenuActions); | |||
@@ -44,7 +44,7 @@ const buildMob = (objects, mobConfig, x, y, mobIndex) => { | |||
cpn: 'dialogue', | |||
method: 'talk', | |||
args: [{ | |||
targetName: 'angler nayla' | |||
targetName: mob.name.toLowerCase() | |||
}] | |||
}, | |||
exit: { | |||
@@ -717,6 +717,7 @@ module.exports = { | |||
material: true, | |||
sprite: [11, 7], | |||
worth: 2, | |||
quality: 0, | |||
infinite: true | |||
}], | |||
level: { | |||
@@ -1,5 +1,5 @@ | |||
module.exports = { | |||
version: '0.4.3', | |||
version: '0.4.4', | |||
port: 4000, | |||
startupMessage: 'Server: ready', | |||
defaultZone: 'fjolarok', | |||
@@ -104,6 +104,7 @@ const reslot = (item, msg) => { | |||
delete item.implicitStats; | |||
delete item.power; | |||
delete item.range; | |||
delete item.requires; | |||
extend(item, newItem); | |||
}; | |||
@@ -1,33 +0,0 @@ | |||
module.exports = { | |||
type: 'pet', | |||
pet: null, | |||
init: function () { | |||
}, | |||
simplify: function () { | |||
return { | |||
type: 'pet', | |||
ttl: this.ttl | |||
}; | |||
}, | |||
destroy: function () { | |||
this.pet.destroyed = true; | |||
this.source.useText = 'summon'; | |||
this.obj.syncer.setArray(true, 'inventory', 'getItems', this.source); | |||
}, | |||
events: { | |||
beforeCastSpell: function (castEvent) { | |||
this.destroyed = true; | |||
}, | |||
beforeTakeDamage: function (dmgEvent) { | |||
this.destroyed = true; | |||
} | |||
} | |||
}; |
@@ -1,78 +0,0 @@ | |||
/* | |||
Example of a pet: | |||
{ | |||
name: 'Red Macaw\'s Cage', | |||
type: 'pet', | |||
quality: 2, | |||
noDrop: true, | |||
noSalvage: true, | |||
cdMax: 10, | |||
sprite: [11, 9], | |||
spritesheet: 'images/questItems.png', | |||
petCell: 42, | |||
petSheet: 'mobs', | |||
petName: 'Red Macaw', | |||
useText: 'summon', | |||
description: 'Vibrant, majestic and bitey.' | |||
} | |||
*/ | |||
module.exports = { | |||
name: 'Feature: Pets', | |||
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 !== 'pet') | |||
return; | |||
let syncer = obj.syncer; | |||
let blueprint = { | |||
x: obj.x + 1, | |||
y: obj.y, | |||
cell: item.petCell, | |||
sheetName: item.petSheet, | |||
name: item.petName, | |||
properties: { | |||
cpnFollower: { | |||
maxDistance: 2 | |||
}, | |||
cpnMob: { | |||
walkDistance: 1 | |||
}, | |||
cpnSyncer: {}, | |||
cpnStats: {} | |||
}, | |||
extraProperties: { | |||
follower: { | |||
master: obj | |||
} | |||
} | |||
}; | |||
//Spawn a mob | |||
let pet = obj.instance.spawners.spawn({ | |||
amountLeft: 1, | |||
blueprint: blueprint | |||
}); | |||
let builtEffect = obj.effects.addEffect({ | |||
type: 'pet', | |||
new: true | |||
}); | |||
builtEffect.source = item; | |||
builtEffect.pet = pet; | |||
item.useText = 'dismiss'; | |||
syncer.setArray(true, 'inventory', 'getItems', item); | |||
}, | |||
onBeforeGetEffect: function (result) { | |||
if (result.type.toLowerCase() === 'pet') | |||
result.url = `${this.relativeFolderName}/effects/effectPet.js`; | |||
} | |||
}; |