@@ -245,4 +245,87 @@ body { | |||||
} | } | ||||
.color-tealB { | .color-tealB { | ||||
color: @tealB !important;} | |||||
color: @tealB !important; | |||||
} | |||||
[class^="ui"] .renderItem { | |||||
width: 72px; | |||||
height: 72px; | |||||
float: left; | |||||
position: relative; | |||||
cursor: pointer; | |||||
box-sizing: border-box; | |||||
margin: 4px; | |||||
background-color: @blackD; | |||||
&.hover { | |||||
background-color: fade(@blueA, 10%); | |||||
} | |||||
&.dragging { | |||||
position: absolute; | |||||
opacity: 0.5; | |||||
pointer-events: none; | |||||
background-color: transparent; | |||||
.icon { | |||||
filter: brightness(100%) | |||||
drop-shadow(0px -4px 0px @blackD) | |||||
drop-shadow(0px 4px 0px @blackD) | |||||
drop-shadow(4px 0px 0px @blackD) | |||||
drop-shadow(-4px 0px 0px @blackD); | |||||
-moz-filter: brightness(100%) | |||||
drop-shadow(0px -4px 0px @blackD) | |||||
drop-shadow(0px 4px 0px @blackD) | |||||
drop-shadow(4px 0px 0px @blackD) | |||||
drop-shadow(-4px 0px 0px @blackD); | |||||
} | |||||
} | |||||
.quantity { | |||||
left: 6px; | |||||
bottom: 3px; | |||||
position: absolute; | |||||
color: @white; | |||||
filter: drop-shadow(0px -2px 0px @blackD) | |||||
drop-shadow(0px 2px 0px @blackD) | |||||
drop-shadow(2px 0px 0px @blackD) | |||||
drop-shadow(-2px 0px 0px @blackD); | |||||
-moz-filter: drop-shadow(0px -2px 0px @blackD) | |||||
drop-shadow(0px 2px 0px @blackD) | |||||
drop-shadow(2px 0px 0px @blackD) | |||||
drop-shadow(-2px 0px 0px @blackD); | |||||
} | |||||
.icon { | |||||
width: 64px; | |||||
height: 64px; | |||||
position: absolute; | |||||
left: 4px; | |||||
top: 4px; | |||||
} | |||||
&.eq { | |||||
.quantity { | |||||
color: @yellow; | |||||
} | |||||
} | |||||
&.new { | |||||
.quantity { | |||||
color: @green; | |||||
} | |||||
} | |||||
&:hover { | |||||
.icon { | |||||
filter: brightness(160%); | |||||
-moz-filter: brightness(160%); | |||||
} | |||||
} | |||||
} |
@@ -32,7 +32,6 @@ define([ | |||||
'events', | 'events', | ||||
'progressBar', | 'progressBar', | ||||
'stash', | 'stash', | ||||
'smithing', | |||||
'talk', | 'talk', | ||||
'trade', | 'trade', | ||||
'overlay', | 'overlay', | ||||
@@ -151,7 +150,6 @@ define([ | |||||
'passives', | 'passives', | ||||
'quests', | 'quests', | ||||
'reputation', | 'reputation', | ||||
'smithing', | |||||
'stash' | 'stash' | ||||
].map(m => 'ui/templates/' + m + '/' + m), this.afterPreload.bind(this)); | ].map(m => 'ui/templates/' + m + '/' + m), this.afterPreload.bind(this)); | ||||
}, | }, | ||||
@@ -1,5 +1,5 @@ | |||||
const tplItem = ` | const tplItem = ` | ||||
<div class="item"> | |||||
<div class="renderItem item"> | |||||
<div class="icon"></div> | <div class="icon"></div> | ||||
<div class="quantity"></div> | <div class="quantity"></div> | ||||
</div> | </div> | ||||
@@ -155,31 +155,18 @@ define([ | |||||
}); | }); | ||||
}, | }, | ||||
openAugmentUi: function (item) { | |||||
events.emit('onSetSmithItem', { | |||||
item: item | |||||
}); | |||||
}, | |||||
showContext: function (item, e) { | showContext: function (item, e) { | ||||
let menuItems = { | let menuItems = { | ||||
unequip: { | unequip: { | ||||
text: 'unequip', | text: 'unequip', | ||||
callback: this.unequipItem.bind(this, item) | callback: this.unequipItem.bind(this, item) | ||||
}, | |||||
augment: { | |||||
text: 'craft', | |||||
callback: this.openAugmentUi.bind(this, item) | |||||
} | |||||
} | |||||
}; | }; | ||||
let config = []; | let config = []; | ||||
config.push(menuItems.unequip); | config.push(menuItems.unequip); | ||||
if (item.slot) | |||||
config.push(menuItems.augment); | |||||
events.emit('onContextMenu', config, e); | events.emit('onContextMenu', config, e); | ||||
e.preventDefault(); | e.preventDefault(); | ||||
@@ -293,10 +293,6 @@ define([ | |||||
text: 'equip', | text: 'equip', | ||||
callback: this.performItemAction.bind(this, item, 'equip') | callback: this.performItemAction.bind(this, item, 'equip') | ||||
}, | }, | ||||
augment: { | |||||
text: 'craft', | |||||
callback: this.openAugmentUi.bind(this, item) | |||||
}, | |||||
mail: { | mail: { | ||||
text: 'mail', | text: 'mail', | ||||
callback: this.openMailUi.bind(this, item) | callback: this.openMailUi.bind(this, item) | ||||
@@ -336,11 +332,6 @@ define([ | |||||
ctxConfig.push(menuItems.equip); | ctxConfig.push(menuItems.equip); | ||||
if (!item.eq) | if (!item.eq) | ||||
ctxConfig.push(menuItems.divider); | ctxConfig.push(menuItems.divider); | ||||
if (!item.eq) { | |||||
ctxConfig.push(menuItems.augment); | |||||
ctxConfig.push(menuItems.divider); | |||||
} | |||||
} | } | ||||
if ((!item.eq) && (!item.active)) { | if ((!item.eq) && (!item.active)) { | ||||
@@ -354,9 +345,6 @@ define([ | |||||
if ((!item.material) && (!item.noSalvage)) | if ((!item.material) && (!item.noSalvage)) | ||||
ctxConfig.push(menuItems.salvage); | ctxConfig.push(menuItems.salvage); | ||||
} | } | ||||
if (!item.noDestroy) | |||||
ctxConfig.push(menuItems.destroy); | |||||
} | } | ||||
if (item.quantity > 1 && !item.quest) | if (item.quantity > 1 && !item.quest) | ||||
@@ -367,6 +355,11 @@ define([ | |||||
ctxConfig.push(menuItems.link); | ctxConfig.push(menuItems.link); | ||||
if (!item.eq && !item.active && !item.noDestroy) { | |||||
ctxConfig.push(menuItems.divider); | |||||
ctxConfig.push(menuItems.destroy); | |||||
} | |||||
if (isMobile) | if (isMobile) | ||||
this.hideTooltip(null, this.hoverItem); | this.hideTooltip(null, this.hoverItem); | ||||
@@ -568,12 +561,6 @@ define([ | |||||
}); | }); | ||||
}, | }, | ||||
openAugmentUi: function (item) { | |||||
events.emit('onSetSmithItem', { | |||||
item: item | |||||
}); | |||||
}, | |||||
openMailUi: function (item) { | openMailUi: function (item) { | ||||
events.emit('onSetMailItem', { | events.emit('onSetMailItem', { | ||||
item: item | item: item | ||||
@@ -1,343 +0,0 @@ | |||||
define([ | |||||
'js/system/events', | |||||
'js/system/client', | |||||
'html!ui/templates/smithing/template', | |||||
'css!ui/templates/smithing/styles', | |||||
'html!/ui/templates/smithing/templateItem', | |||||
'js/misc/statTranslations' | |||||
], function ( | |||||
events, | |||||
client, | |||||
template, | |||||
styles, | |||||
templateItem, | |||||
statTranslations | |||||
) { | |||||
return { | |||||
tpl: template, | |||||
centered: true, | |||||
modal: true, | |||||
hasClose: true, | |||||
eventCloseInv: null, | |||||
eventClickInv: null, | |||||
hoverItem: null, | |||||
item: null, | |||||
waiting: false, | |||||
action: 'augment', | |||||
postRender: function () { | |||||
this.onEvent('onShowSmithing', this.toggle.bind(this)); | |||||
this.onEvent('onKeyDown', this.onKey.bind(this, true)); | |||||
this.onEvent('onKeyUp', this.onKey.bind(this, false)); | |||||
this.find('.item-picker').on('click', this.openInventory.bind(this)); | |||||
this.find('.actionButton').on('click', this.smith.bind(this)); | |||||
//If we don't listen to these events, they'll be queued | |||||
this.onEvent('onHideInventory', () => {}); | |||||
this.onEvent('beforeInventoryClickItem', () => {}); | |||||
this.onEvent('onGetItems', this.onGetItems.bind(this)); | |||||
this.onEvent('onSetSmithItem', this.onHideInventory.bind(this)); | |||||
this.find('.col-btn').on('click', this.clickAction.bind(this)); | |||||
}, | |||||
clickAction: function (e) { | |||||
let el = $(e.target); | |||||
this.find('.col-btn').removeClass('selected'); | |||||
let action = el.attr('action'); | |||||
let changed = (action !== this.action); | |||||
this.action = action; | |||||
el.addClass('selected'); | |||||
if (this.item && changed) | |||||
this.getMaterials(this.item); | |||||
}, | |||||
smith: function () { | |||||
this.setDisabled(true); | |||||
client.request({ | |||||
cpn: 'player', | |||||
method: 'performAction', | |||||
data: { | |||||
cpn: 'inventory', | |||||
method: 'enchantItem', | |||||
data: { | |||||
itemId: this.item.id, | |||||
action: this.action | |||||
} | |||||
}, | |||||
callback: this.onSmith.bind(this, this.item) | |||||
}); | |||||
}, | |||||
onSmith: function (item, result) { | |||||
this.setDisabled(false); | |||||
let msg = { | |||||
msg: 'Item Enhancement Succeeded', | |||||
type: 'success', | |||||
zIndex: 9999999, | |||||
top: 100 | |||||
}; | |||||
if (this.action === 'reroll') | |||||
msg.msg = 'Item Reroll Succeeded'; | |||||
else if (this.action === 'relevel') | |||||
msg.msg = 'Item Relevel Succeeded'; | |||||
else if (this.action === 'reslot') | |||||
msg.msg = 'Item Reslot Succeeded'; | |||||
result.addStatMsgs.forEach(a => { | |||||
let statName = statTranslations.translate(a.stat); | |||||
msg.msg += `<br />${(a.value > 0) ? '+' : ''}${a.value} ${statName}`; | |||||
}); | |||||
events.emit('onGetAnnouncement', msg); | |||||
if (result.item) | |||||
this.item = result.item; | |||||
this.getMaterials(this.item); | |||||
let augment = this.find('[action="augment"]').addClass('disabled'); | |||||
if ((result.item.power || 0) < 3) | |||||
augment.removeClass('disabled'); | |||||
else if (this.action === 'augment') | |||||
this.find('[action="reroll"]').click(); | |||||
}, | |||||
openInventory: function () { | |||||
this.waiting = true; | |||||
this.eventCloseInv = this.onEvent('onHideInventory', this.onHideInventory.bind(this)); | |||||
this.eventClickInv = this.onEvent('beforeInventoryClickItem', this.onHideInventory.bind(this)); | |||||
events.emit('onShowInventory'); | |||||
}, | |||||
onHideInventory: function (msg) { | |||||
if (msg) | |||||
msg.success = false; | |||||
this.waiting = false; | |||||
if (!msg || !msg.item) { | |||||
this.offEvent(this.eventCloseInv); | |||||
this.offEvent(this.eventClickInv); | |||||
return; | |||||
} else if (!msg.item.slot || msg.item.noAugment) { | |||||
let resultMsg = { | |||||
msg: 'Incorrect Item Type', | |||||
type: 'failure', | |||||
zIndex: 9999999, | |||||
top: 180 | |||||
}; | |||||
events.emit('onGetAnnouncement', resultMsg); | |||||
return; | |||||
} | |||||
this.find('.selected').removeClass('selected'); | |||||
this.find('[action="augment"]').addClass('selected'); | |||||
this.action = 'augment'; | |||||
let augment = this.find('[action="augment"]').addClass('disabled'); | |||||
if ((msg.item.power || 0) < 3) | |||||
augment.removeClass('disabled'); | |||||
let reforge = this.find('[action="reforge"]').addClass('disabled'); | |||||
if (msg.item.spell) | |||||
reforge.removeClass('disabled'); | |||||
let reslot = this.find('[action="reslot"]').addClass('disabled'); | |||||
if (!msg.item.effects && msg.item.slot !== 'tool') | |||||
reslot.removeClass('disabled'); | |||||
let relevel = this.find('[action="relevel"]').addClass('disabled'); | |||||
if (msg.item.slot !== 'tool') | |||||
relevel.removeClass('disabled'); | |||||
this.offEvent(this.eventClickInv); | |||||
$('.uiInventory').data('ui').hide(); | |||||
this.show(); | |||||
this.el.show(); | |||||
this.shown = true; | |||||
msg.success = false; | |||||
if (!msg || !msg.item || !msg.item.slot) | |||||
return; | |||||
this.item = msg.item; | |||||
this.getMaterials(msg.item); | |||||
}, | |||||
getMaterials: function (item) { | |||||
this.setDisabled(true); | |||||
client.request({ | |||||
cpn: 'player', | |||||
method: 'performAction', | |||||
data: { | |||||
cpn: 'inventory', | |||||
method: 'getEnchantMaterials', | |||||
data: { | |||||
itemId: item.id, | |||||
action: this.action | |||||
} | |||||
}, | |||||
callback: this.onGetMaterials.bind(this, item) | |||||
}); | |||||
}, | |||||
onGetMaterials: function (item, result) { | |||||
this.find('.item').remove(); | |||||
this.drawItem(this.find('.item-picker'), item); | |||||
this.find('.actionButton').removeClass('disabled').addClass('disabled'); | |||||
if (result.materials) { | |||||
let material = result.materials[0]; | |||||
if (material) { | |||||
let hasMaterials = window.player.inventory.items.find(i => i.name === material.name); | |||||
if (hasMaterials) { | |||||
material.quantityText = hasMaterials.quantity + '/' + material.quantity; | |||||
hasMaterials = hasMaterials.quantity >= material.quantity; | |||||
} else { | |||||
if (!material.quantityText) | |||||
material.quantityText = ''; | |||||
material.quantityText += '0/' + material.quantity; | |||||
} | |||||
if (hasMaterials) | |||||
this.find('.actionButton').removeClass('disabled'); | |||||
this.drawItem(this.find('.material'), material, !hasMaterials); | |||||
} | |||||
} | |||||
this.setDisabled(false); | |||||
}, | |||||
onGetItems: function (items) { | |||||
let elMaterial = this.find('.material .item'); | |||||
if (!elMaterial.length) | |||||
return; | |||||
let itemMaterial = elMaterial.data('item'); | |||||
let elQuantity = elMaterial.find('.quantity'); | |||||
let invMaterial = items.find(i => i.name === itemMaterial.name) || { quantity: 0 }; | |||||
let currentText = elQuantity.html().split('/'); | |||||
let newText = invMaterial.quantity + '/' + currentText[1]; | |||||
elQuantity.html(newText); | |||||
let elButton = this.find('.actionButton').removeClass('disabled'); | |||||
if (invMaterial.quantity < currentText[1]) { | |||||
elButton.addClass('disabled'); | |||||
elQuantity.addClass('red'); | |||||
} else { | |||||
elButton.removeClass('disabled'); | |||||
elQuantity.removeClass('red'); | |||||
} | |||||
}, | |||||
drawItem: function (container, item, redQuantity) { | |||||
container.find('.icon').hide(); | |||||
let imgX = -item.sprite[0] * 64; | |||||
let imgY = -item.sprite[1] * 64; | |||||
let spritesheet = item.spritesheet || '../../../images/items.png'; | |||||
if (item.material) | |||||
spritesheet = '../../../images/materials.png'; | |||||
else if (item.quest) | |||||
spritesheet = '../../../images/questItems.png'; | |||||
else if (item.type === 'consumable') | |||||
spritesheet = '../../../images/consumables.png'; | |||||
let el = $(templateItem) | |||||
.appendTo(container); | |||||
el | |||||
.data('item', item) | |||||
.on('mousemove', this.onHover.bind(this, el, item)) | |||||
.on('mouseleave', this.hideTooltip.bind(this, el, item)) | |||||
.find('.icon') | |||||
.css('background', 'url(' + spritesheet + ') ' + imgX + 'px ' + imgY + 'px'); | |||||
if (item.quantity) { | |||||
let quantityText = item.quantityText; | |||||
el.find('.quantity').html(quantityText); | |||||
if (redQuantity) | |||||
el.find('.quantity').addClass('red'); | |||||
} | |||||
}, | |||||
onHover: function (el, item, e) { | |||||
if (item) | |||||
this.hoverItem = item; | |||||
else | |||||
item = this.hoverItem; | |||||
let ttPos = null; | |||||
if (el) { | |||||
ttPos = { | |||||
x: ~~(e.clientX + 32), | |||||
y: ~~(e.clientY) | |||||
}; | |||||
} | |||||
events.emit('onShowItemTooltip', item, ttPos, true); | |||||
}, | |||||
hideTooltip: function (el, item, e) { | |||||
events.emit('onHideItemTooltip', this.hoverItem); | |||||
this.hoverItem = null; | |||||
}, | |||||
beforeHide: function () { | |||||
if (this.waiting) | |||||
return; | |||||
this.item = null; | |||||
this.offEvent(this.eventCloseInv); | |||||
this.offEvent(this.eventClickInv); | |||||
}, | |||||
toggle: function () { | |||||
this.shown = !this.el.is(':visible'); | |||||
if (this.shown) { | |||||
this.find('.item').remove(); | |||||
this.find('.icon').show(); | |||||
this.find('.actionButton').removeClass('disabled').addClass('disabled'); | |||||
this.show(); | |||||
} else | |||||
this.hide(); | |||||
}, | |||||
onKey: function (isDown, key) { | |||||
if (isDown && key === 'm') | |||||
this.toggle(); | |||||
else if (key === 'shift' && this.hoverItem) | |||||
this.onHover(); | |||||
} | |||||
}; | |||||
}); |
@@ -1,186 +0,0 @@ | |||||
@import "../../../css/colors.less"; | |||||
.uiSmithing { | |||||
display: none; | |||||
background-color: @blackB; | |||||
border: 5px solid @blackB; | |||||
text-align: center; | |||||
> .heading { | |||||
color: @blueA; | |||||
width: 100%; | |||||
height: 36px; | |||||
background-color: @blackB; | |||||
.heading-text { | |||||
padding-top: 8px; | |||||
margin: auto; | |||||
} | |||||
} | |||||
.bottom { | |||||
height: 170px; | |||||
background-color: @blackC; | |||||
padding: 10px; | |||||
} | |||||
.col { | |||||
float: left; | |||||
margin-right: 10px; | |||||
&:last-child { | |||||
margin-right: 0px; | |||||
} | |||||
.heading { | |||||
width: 80px; | |||||
height: 16px; | |||||
color: @white; | |||||
text-align: center; | |||||
margin-bottom: 10px; | |||||
} | |||||
.content { | |||||
width: 80px; | |||||
height: 80px; | |||||
background-color: @blackD; | |||||
&.chance { | |||||
padding-top: 32px; | |||||
color: @white; | |||||
text-align: center; | |||||
} | |||||
&.item-picker, | |||||
&.actionButton { | |||||
cursor: pointer; | |||||
&:hover { | |||||
background-color: @blackC; | |||||
} | |||||
} | |||||
&.item-picker { | |||||
> .icon { | |||||
margin: 8px; | |||||
display: inline-block; | |||||
width: 64px; | |||||
height: 64px; | |||||
background: url('../../../images/uiIcons.png') -256px -64px; | |||||
} | |||||
} | |||||
&.actionButton { | |||||
padding: 8px; | |||||
.icon { | |||||
width: 64px; | |||||
height: 64px; | |||||
background: url('../../../images/uiIcons.png') -192px -64px; | |||||
} | |||||
} | |||||
.item { | |||||
width: 100%; | |||||
height: 100%; | |||||
float: left; | |||||
position: relative; | |||||
cursor: pointer; | |||||
box-sizing: border-box; | |||||
.quantity { | |||||
left: 6px; | |||||
bottom: 3px; | |||||
position: absolute; | |||||
color: @white; | |||||
filter: drop-shadow(0px -2px 0px @blackD) | |||||
drop-shadow(0px 2px 0px @blackD) | |||||
drop-shadow(2px 0px 0px @blackD) | |||||
drop-shadow(-2px 0px 0px @blackD); | |||||
-moz-filter: drop-shadow(0px -2px 0px @blackD) | |||||
drop-shadow(0px 2px 0px @blackD) | |||||
drop-shadow(2px 0px 0px @blackD) | |||||
drop-shadow(-2px 0px 0px @blackD); | |||||
&.red { | |||||
color: @red; | |||||
} | |||||
} | |||||
.icon { | |||||
width: 64px; | |||||
height: 64px; | |||||
position: absolute; | |||||
left: 8px; | |||||
top: 8px; | |||||
filter: brightness(100%) | |||||
drop-shadow(0px -4px 0px @blackD) | |||||
drop-shadow(0px 4px 0px @blackD) | |||||
drop-shadow(4px 0px 0px @blackD) | |||||
drop-shadow(-4px 0px 0px @blackD); | |||||
-moz-filter: brightness(100%) | |||||
drop-shadow(0px -4px 0px @blackD) | |||||
drop-shadow(0px 4px 0px @blackD) | |||||
drop-shadow(4px 0px 0px @blackD) | |||||
drop-shadow(-4px 0px 0px @blackD); | |||||
} | |||||
} | |||||
} | |||||
&:first-child { | |||||
.heading { | |||||
width: 190px; | |||||
} | |||||
.content { | |||||
width: 190px; | |||||
background-color: transparent; | |||||
.col-btn { | |||||
height: calc((100% - 10px) / 2); | |||||
width: 100%; | |||||
color: #f2f5f5; | |||||
text-align: center; | |||||
padding-top: 10px; | |||||
background-color: @blackB; | |||||
margin-bottom: 10px; | |||||
cursor: pointer; | |||||
&.selected { | |||||
color: @orangeA; | |||||
} | |||||
&:hover { | |||||
background-color: @blackA; | |||||
} | |||||
&.col-half { | |||||
width: calc((100% - 10px) / 2); | |||||
float: left; | |||||
&:nth-child(2n + 1) { | |||||
margin-right: 10px; | |||||
} | |||||
} | |||||
&:not(.col-half) { | |||||
clear: both; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,34 +0,0 @@ | |||||
<div class="uiSmithing"> | |||||
<div class="heading"> | |||||
<div class="heading-text">craft item</div> | |||||
</div> | |||||
<div class="bottom"> | |||||
<div class="col"> | |||||
<div class="heading">action</div> | |||||
<div class="content"> | |||||
<div class="col-btn col-half selected" action="augment">augment</div> | |||||
<div class="col-btn col-half" action="scour">scour</div> | |||||
<div class="col-btn col-half" action="reroll">reroll</div> | |||||
<div class="col-btn col-half" action="relevel">relevel</div> | |||||
<div class="col-btn col-half" action="reslot">reslot</div> | |||||
<div class="col-btn col-half" action="reforge">reforge</div> | |||||
</div> | |||||
</div> | |||||
<div class="col"> | |||||
<div class="heading">item</div> | |||||
<div class="content item-picker"> | |||||
<div class="icon"></div> | |||||
</div> | |||||
</div> | |||||
<div class="col"> | |||||
<div class="heading">material</div> | |||||
<div class="content material"></div> | |||||
</div> | |||||
<div class="col"> | |||||
<div class="heading"></div> | |||||
<div class="content actionButton disabled"> | |||||
<div class="icon"></div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> |
@@ -1,4 +0,0 @@ | |||||
<div class="item"> | |||||
<div class="icon"></div> | |||||
<div class="quantity"></div> | |||||
</div> |
@@ -2,17 +2,20 @@ | |||||
.uiWorkbench { | .uiWorkbench { | ||||
display: none; | display: none; | ||||
width: 720px; | |||||
height: 385px; | |||||
border: 5px solid fade(@blackB, 90%); | |||||
text-align: center; | |||||
width: 827px; | |||||
height: 447px; | |||||
border: 5px solid @blackB; | |||||
color: @white; | color: @white; | ||||
position: relative; | |||||
z-index: 2; | |||||
> .heading { | |||||
color: @blueA; | |||||
> .heading, | |||||
> .itemPicker > .heading { | |||||
color: @orangeA; | |||||
width: 100%; | width: 100%; | ||||
height: 36px; | height: 36px; | ||||
background-color: fade(@blackB, 90%); | |||||
background-color: @blackB; | |||||
text-align: center; | |||||
.heading-text { | .heading-text { | ||||
padding-top: 8px; | padding-top: 8px; | ||||
@@ -21,14 +24,15 @@ | |||||
} | } | ||||
.bottom { | |||||
background-color: fade(@blackC, 90%); | |||||
> .bottom { | |||||
background-color: @blackC; | |||||
height: calc(100% - 36px); | height: calc(100% - 36px); | ||||
width: 100%; | width: 100%; | ||||
.heading { | .heading { | ||||
color: @blueB; | color: @blueB; | ||||
margin-bottom: 10px; | margin-bottom: 10px; | ||||
text-align: center; | |||||
} | } | ||||
.left, | .left, | ||||
@@ -44,14 +48,18 @@ | |||||
.list { | .list { | ||||
height: calc(100% - 25px); | height: calc(100% - 25px); | ||||
overflow-y: auto; | overflow-y: auto; | ||||
display: flex; | |||||
flex-direction: column; | |||||
.item { | .item { | ||||
width: 100%; | width: 100%; | ||||
padding: 5px 0px; | |||||
padding: 5px 10px; | |||||
cursor: pointer; | cursor: pointer; | ||||
color: @grayB; | |||||
&.selected { | &.selected { | ||||
background-color: @blackB; | background-color: @blackB; | ||||
color: @white; | |||||
} | } | ||||
&:hover { | &:hover { | ||||
@@ -66,6 +74,9 @@ | |||||
.right { | .right { | ||||
width: calc(100% - 300px); | width: calc(100% - 300px); | ||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: space-between; | |||||
> * { | > * { | ||||
width: 100%; | width: 100%; | ||||
@@ -73,17 +84,24 @@ | |||||
.info { | .info { | ||||
height: calc(100% - 100px - 35px); | height: calc(100% - 100px - 35px); | ||||
flex: 1; | |||||
.title { | .title { | ||||
color: @orangeA; | |||||
color: @blueB; | |||||
padding-bottom: 10px; | padding-bottom: 10px; | ||||
text-align: center; | |||||
} | |||||
.description { | |||||
color: @grayB; | |||||
text-align: justify; | |||||
} | } | ||||
} | } | ||||
.materialList { | .materialList { | ||||
height: 100px; | |||||
visibility: hidden; | visibility: hidden; | ||||
margin-bottom: 20px; | |||||
.material { | .material { | ||||
&.need { | &.need { | ||||
@@ -94,6 +112,24 @@ | |||||
} | } | ||||
.needItems { | |||||
display: none; | |||||
margin-bottom: 20px; | |||||
flex-direction: column; | |||||
.title { | |||||
color: @blueB; | |||||
padding-bottom: 10px; | |||||
text-align: center; | |||||
} | |||||
.list { | |||||
display: flex; | |||||
justify-content: space-around; | |||||
} | |||||
} | |||||
.buttons { | .buttons { | ||||
height: 40px; | height: 40px; | ||||
@@ -123,6 +159,24 @@ | |||||
} | } | ||||
> .itemPicker { | |||||
display: none; | |||||
position: absolute; | |||||
left: 0px; | |||||
top: 0px; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: @blackC; | |||||
flex-direction: column; | |||||
.list { | |||||
display: flex; | |||||
flex-wrap: wrap; | |||||
overflow-y: auto; | |||||
} | |||||
} | |||||
} | } | ||||
.mobile .uiWorkbench { | .mobile .uiWorkbench { | ||||
@@ -1,6 +1,6 @@ | |||||
<div class="uiWorkbench"> | <div class="uiWorkbench"> | ||||
<div class="heading"> | <div class="heading"> | ||||
<div class="heading-text">Workbench</div> | |||||
<div class="mainHeading heading-text">Workbench</div> | |||||
</div> | </div> | ||||
<div class="bottom"> | <div class="bottom"> | ||||
<div class="left"> | <div class="left"> | ||||
@@ -15,6 +15,10 @@ | |||||
<div class="title"></div> | <div class="title"></div> | ||||
<div class="description"></div> | <div class="description"></div> | ||||
</div> | </div> | ||||
<div class="needItems"> | |||||
<div class="title">Pick Items</div> | |||||
<div class="list"></div> | |||||
</div> | |||||
<div class="materialList"> | <div class="materialList"> | ||||
<div class="heading">Requires:</div> | <div class="heading">Requires:</div> | ||||
</div> | </div> | ||||
@@ -24,4 +28,12 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="itemPicker"> | |||||
<div class="heading"> | |||||
<div class="heading-text"></div> | |||||
</div> | |||||
<div class="list"> | |||||
</div> | |||||
</div> | |||||
</div> | </div> |
@@ -2,12 +2,16 @@ define([ | |||||
'js/system/events', | 'js/system/events', | ||||
'js/system/client', | 'js/system/client', | ||||
'html!ui/templates/workbench/template', | 'html!ui/templates/workbench/template', | ||||
'css!ui/templates/workbench/styles' | |||||
'css!ui/templates/workbench/styles', | |||||
'ui/shared/renderItem', | |||||
'js/misc/statTranslations' | |||||
], function ( | ], function ( | ||||
events, | events, | ||||
client, | client, | ||||
template, | template, | ||||
styles | |||||
styles, | |||||
renderItem, | |||||
statTranslations | |||||
) { | ) { | ||||
return { | return { | ||||
tpl: template, | tpl: template, | ||||
@@ -22,9 +26,18 @@ define([ | |||||
recipes: null, | recipes: null, | ||||
currentRecipe: null, | currentRecipe: null, | ||||
selectedNeedItems: null, | |||||
hoverItem: null, | |||||
hoverEl: null, | |||||
postRender: function () { | postRender: function () { | ||||
this.onEvent('onOpenWorkbench', this.onOpenWorkbench.bind(this)); | this.onEvent('onOpenWorkbench', this.onOpenWorkbench.bind(this)); | ||||
this.onEvent('onCloseWorkbench', this.hide.bind(this)); | this.onEvent('onCloseWorkbench', this.hide.bind(this)); | ||||
this.onEvent('onGetItems', this.onGetItems.bind(this)); | |||||
this.onEvent('onKeyDown', this.onKeyDown.bind(this)); | |||||
this.onEvent('onKeyUp', this.onKeyUp.bind(this)); | |||||
this.on('.btnCraft', 'click', this.craft.bind(this)); | this.on('.btnCraft', 'click', this.craft.bind(this)); | ||||
this.on('.btnCancel', 'click', this.hide.bind(this)); | this.on('.btnCancel', 'click', this.hide.bind(this)); | ||||
@@ -32,17 +45,29 @@ define([ | |||||
onOpenWorkbench: function (msg) { | onOpenWorkbench: function (msg) { | ||||
this.workbenchId = msg.workbenchId; | this.workbenchId = msg.workbenchId; | ||||
this.find('.heading-text').html(msg.name); | |||||
this.find('.mainHeading').html(msg.name); | |||||
this.find('.itemPicker').hide(); | |||||
this.find('.needItems').hide(); | |||||
this.renderRecipes(msg.recipes); | this.renderRecipes(msg.recipes); | ||||
this.show(); | this.show(); | ||||
}, | }, | ||||
//Redraw items if they change | |||||
onGetItems: function (items) { | |||||
if (!this.currentRecipe) | |||||
return; | |||||
const { currentRecipe: { needItems } } = this; | |||||
this.buildNeedItemBoxes(needItems, true); | |||||
}, | |||||
renderRecipes: function (recipes) { | renderRecipes: function (recipes) { | ||||
this.recipes = recipes; | this.recipes = recipes; | ||||
let container = this.find('.list').empty(); | |||||
let container = this.find('.left .list').empty(); | |||||
recipes.forEach(function (r) { | recipes.forEach(function (r) { | ||||
let el = $('<div class="item">' + r + '</div>') | let el = $('<div class="item">' + r + '</div>') | ||||
@@ -64,18 +89,20 @@ define([ | |||||
cpn: 'workbench', | cpn: 'workbench', | ||||
method: 'getRecipe', | method: 'getRecipe', | ||||
data: { | data: { | ||||
name: recipeName | |||||
name: recipeName | |||||
} | } | ||||
}, | }, | ||||
callback: this.onGetRecipe.bind(this) | |||||
callback: this.onGetRecipe.bind(this, false) | |||||
}); | }); | ||||
}, | }, | ||||
onGetRecipe: function (recipe) { | |||||
onGetRecipe: function (persistNeedItems, recipe) { | |||||
const { name: recipeName, description, materials, needItems } = recipe; | |||||
this.currentRecipe = recipe; | this.currentRecipe = recipe; | ||||
this.find('.title').html(recipe.name); | |||||
this.find('.description').html(recipe.description); | |||||
this.find('.info .title').html(recipeName); | |||||
this.find('.description').html(description); | |||||
this.find('.materialList .material').remove(); | this.find('.materialList .material').remove(); | ||||
@@ -84,13 +111,16 @@ define([ | |||||
visibility: 'visible' | visibility: 'visible' | ||||
}); | }); | ||||
let canCraft = true; | |||||
let canCraft = !!materials.length; | |||||
materials.forEach(m => { | |||||
const { needQuantity, nameLike, name: materialName, haveQuantity, noHaveEnough } = m; | |||||
recipe.materials.forEach(function (m) { | |||||
let el = $('<div class="material">' + m.quantity + 'x ' + (m.nameLike || m.name) + '</div>') | |||||
const materialText = `${needQuantity}x ${(nameLike || materialName)} (${haveQuantity})`; | |||||
let el = $(`<div class="material">${materialText}</div>`) | |||||
.appendTo(container); | .appendTo(container); | ||||
if (m.need) { | |||||
if (noHaveEnough) { | |||||
canCraft = false; | canCraft = false; | ||||
el.addClass('need'); | el.addClass('need'); | ||||
} | } | ||||
@@ -103,10 +133,138 @@ define([ | |||||
this.find('.btnCraft') | this.find('.btnCraft') | ||||
.addClass('disabled'); | .addClass('disabled'); | ||||
} | } | ||||
//If there are no materials, the selected items aren't valid | |||||
this.find('.materialList').show(); | |||||
if (!materials.length) { | |||||
this.find('.materialList').hide(); | |||||
persistNeedItems = false; | |||||
} | |||||
this.buildNeedItemBoxes(needItems, persistNeedItems); | |||||
}, | |||||
buildNeedItemBoxes: function (needItems = [], persistNeedItems) { | |||||
if (!persistNeedItems) { | |||||
this.selectedNeedItems = new Array(needItems.length); | |||||
this.selectedNeedItems.fill(null); | |||||
} | |||||
const container = this.find('.needItems').hide(); | |||||
const list = container.find('.list').empty(); | |||||
if (!needItems.length) | |||||
return; | |||||
container.css({ display: 'flex' }); | |||||
needItems.forEach((n, i) => this.buildNeedItemBox(list, n, i)); | |||||
}, | |||||
buildNeedItemBox: function (container, needItem, needItemIndex) { | |||||
const item = this.selectedNeedItems[needItemIndex]; | |||||
const el = renderItem(container, item); | |||||
el | |||||
.on('mousemove', this.toggleTooltip.bind(this, true, el, needItem, item)) | |||||
.on('mouseleave', this.toggleTooltip.bind(this, false, el, needItem, item)) | |||||
.on('click', this.toggleItemPicker.bind(this, true, needItem, needItemIndex)); | |||||
}, | |||||
toggleItemPicker: function (show, needItem, needItemIndex) { | |||||
const container = this.find('.itemPicker').hide(); | |||||
if (!show) | |||||
return; | |||||
const { allowedItemIds } = needItem; | |||||
container | |||||
.css({ display: 'flex' }) | |||||
.find('.heading-text').html(needItem.info); | |||||
const list = container.find('.list').empty(); | |||||
const items = window.player.inventory.items | |||||
.filter(item => { | |||||
const isValidItem = allowedItemIds.find(f => f === item.id); | |||||
return isValidItem; | |||||
}); | |||||
items.forEach(item => { | |||||
const el = renderItem(list, item); | |||||
el | |||||
.on('click', this.onSelectItem.bind(this, item, needItemIndex)) | |||||
.on('mousemove', this.toggleTooltip.bind(this, true, el, null, item)) | |||||
.on('mouseleave', this.toggleTooltip.bind(this, false, el, null, item)); | |||||
}); | |||||
}, | |||||
onSelectItem: function (item, needItemIndex) { | |||||
this.selectedNeedItems[needItemIndex] = item; | |||||
const { currentRecipe: { needItems } } = this; | |||||
this.buildNeedItemBoxes(needItems, true); | |||||
const allItemsSelected = this.selectedNeedItems.every(i => !!i); | |||||
if (allItemsSelected && this.currentRecipe.dynamicMaterials) { | |||||
const pickedItemIds = this.selectedNeedItems.map(i => i.id); | |||||
client.request({ | |||||
cpn: 'player', | |||||
method: 'performAction', | |||||
data: { | |||||
targetId: this.workbenchId, | |||||
cpn: 'workbench', | |||||
method: 'getRecipe', | |||||
data: { | |||||
name: this.currentRecipe.name, | |||||
pickedItemIds | |||||
} | |||||
}, | |||||
callback: this.onGetRecipe.bind(this, true) | |||||
}); | |||||
} | |||||
this.find('.itemPicker').hide(); | |||||
}, | |||||
toggleTooltip: function (show, el, needItem, item, e) { | |||||
if (item) { | |||||
this.hoverItem = show ? item : null; | |||||
this.hoverEl = show ? el : null; | |||||
} | |||||
let pos = null; | |||||
if (e) { | |||||
const { clientX, clientY } = e; | |||||
pos = { | |||||
x: clientX + 25, | |||||
y: clientY | |||||
}; | |||||
} | |||||
if (item) { | |||||
if (show) | |||||
events.emit('onShowItemTooltip', item, pos, true); | |||||
else | |||||
events.emit('onHideItemTooltip', item); | |||||
return; | |||||
} | |||||
if (show) | |||||
events.emit('onShowTooltip', needItem.info, el[0], pos); | |||||
else | |||||
events.emit('onHideTooltip', el[0]); | |||||
}, | }, | ||||
craft: function () { | craft: function () { | ||||
let selectedRecipe = this.find('.list .item.selected').html(); | |||||
const selectedRecipe = this.find('.left .list .item.selected').html(); | |||||
const pickedItemIds = this.selectedNeedItems | |||||
.map(item => item.id); | |||||
client.request({ | client.request({ | ||||
cpn: 'player', | cpn: 'player', | ||||
@@ -116,15 +274,32 @@ define([ | |||||
cpn: 'workbench', | cpn: 'workbench', | ||||
method: 'craft', | method: 'craft', | ||||
data: { | data: { | ||||
name: selectedRecipe | |||||
name: selectedRecipe, | |||||
pickedItemIds | |||||
} | } | ||||
}, | }, | ||||
callback: this.onCraft.bind(this) | callback: this.onCraft.bind(this) | ||||
}); | }); | ||||
}, | }, | ||||
onCraft: function (recipe) { | |||||
this.onGetRecipe(recipe); | |||||
onCraft: function ({ recipe, resultMsg }) { | |||||
this.onGetRecipe(true, recipe); | |||||
if (resultMsg) { | |||||
const { msg: baseMsg, addStatMsgs = [] } = resultMsg; | |||||
let msg = baseMsg; | |||||
addStatMsgs.forEach(a => { | |||||
const statName = statTranslations.translate(a.stat); | |||||
msg += `<br />${(a.value > 0) ? '+' : ''}${a.value} ${statName}`; | |||||
}); | |||||
events.emit('onGetAnnouncement', { | |||||
msg, | |||||
top: 150 | |||||
}); | |||||
} | |||||
}, | }, | ||||
onAfterShow: function () { | onAfterShow: function () { | ||||
@@ -133,7 +308,7 @@ define([ | |||||
clear: function () { | clear: function () { | ||||
this.find('.left .list .selected').removeClass('selected'); | this.find('.left .list .selected').removeClass('selected'); | ||||
this.find('.title').html(''); | |||||
this.find('.info .title').html(''); | |||||
this.find('.description').html(''); | this.find('.description').html(''); | ||||
this.find('.materialList .material').remove(); | this.find('.materialList .material').remove(); | ||||
this.find('.materialList') | this.find('.materialList') | ||||
@@ -141,6 +316,16 @@ define([ | |||||
visibility: 'hidden' | visibility: 'hidden' | ||||
}); | }); | ||||
this.find('.btnCraft').addClass('disabled'); | this.find('.btnCraft').addClass('disabled'); | ||||
}, | |||||
onKeyDown: function (key) { | |||||
if (key === 'shift' && this.hoverItem) | |||||
this.toggleTooltip(true, this.hoverEl, null, this.hoverItem); | |||||
}, | |||||
onKeyUp: function (key) { | |||||
if (key === 'shift' && this.hoverItem) | |||||
this.toggleTooltip(true, this.hoverEl, null, this.hoverItem); | |||||
} | } | ||||
}; | }; | ||||
}); | }); |
@@ -1,6 +1,5 @@ | |||||
let generator = require('../items/generator'); | let generator = require('../items/generator'); | ||||
let salvager = require('../items/salvager'); | let salvager = require('../items/salvager'); | ||||
let enchanter = require('../items/enchanter'); | |||||
let classes = require('../config/spirits'); | let classes = require('../config/spirits'); | ||||
let mtx = require('../mtx/mtx'); | let mtx = require('../mtx/mtx'); | ||||
let factions = require('../config/factions'); | let factions = require('../config/factions'); | ||||
@@ -10,8 +9,6 @@ const events = require('../misc/events'); | |||||
const { isItemStackable } = require('./inventory/helpers'); | const { isItemStackable } = require('./inventory/helpers'); | ||||
const transactions = require('../security/transactions'); | const transactions = require('../security/transactions'); | ||||
const { applyItemStats } = require('./equipment/helpers'); | |||||
const getItem = require('./inventory/getItem'); | const getItem = require('./inventory/getItem'); | ||||
const dropBag = require('./inventory/dropBag'); | const dropBag = require('./inventory/dropBag'); | ||||
const useItem = require('./inventory/useItem'); | const useItem = require('./inventory/useItem'); | ||||
@@ -151,45 +148,6 @@ module.exports = { | |||||
} | } | ||||
}, | }, | ||||
enchantItem: function (msg) { | |||||
const { itemId, action } = msg; | |||||
const item = this.findItem(itemId); | |||||
if (!item) | |||||
return; | |||||
const { eq, slot, power, noAugment } = item; | |||||
if (!slot || noAugment || (action === 'scour' && !power)) { | |||||
this.resolveCallback(msg); | |||||
return; | |||||
} | |||||
const obj = this.obj; | |||||
if (eq) { | |||||
applyItemStats(obj, item, false); | |||||
enchanter.enchant(obj, item, msg); | |||||
applyItemStats(obj, item, true); | |||||
if (item.slot !== slot) | |||||
obj.equipment.unequip(itemId); | |||||
else | |||||
obj.spellbook.calcDps(); | |||||
} else | |||||
enchanter.enchant(obj, item, msg); | |||||
obj.equipment.unequipAttrRqrGear(); | |||||
}, | |||||
getEnchantMaterials: function (msg) { | |||||
let result = []; | |||||
let item = this.findItem(msg.itemId); | |||||
if ((item) && (item.slot)) | |||||
result = enchanter.getEnchantMaterials(item, msg.action); | |||||
this.resolveCallback(msg, result); | |||||
}, | |||||
learnAbility: function (itemId, runeSlot) { | learnAbility: function (itemId, runeSlot) { | ||||
if (itemId.has('itemId')) { | if (itemId.has('itemId')) { | ||||
let msg = itemId; | let msg = itemId; | ||||
@@ -1,6 +1,12 @@ | |||||
const recipes = require('../config/recipes/recipes'); | const recipes = require('../config/recipes/recipes'); | ||||
const generator = require('../items/generator'); | const generator = require('../items/generator'); | ||||
const { applyItemStats } = require('./equipment/helpers'); | |||||
const buildRecipe = require('./workbench/buildRecipe'); | |||||
const buildMaterials = require('./workbench/buildMaterials'); | |||||
const buildPickedItems = require('./workbench/buildPickedItems'); | |||||
module.exports = { | module.exports = { | ||||
type: 'workbench', | type: 'workbench', | ||||
@@ -98,93 +104,98 @@ module.exports = { | |||||
}, [obj.serverId]); | }, [obj.serverId]); | ||||
}, | }, | ||||
buildRecipe: function (crafter, recipeName) { | |||||
let recipe = recipes.getRecipe(this.craftType, recipeName); | |||||
if (!recipe) | |||||
return; | |||||
const items = crafter.inventory.items; | |||||
let sendRecipe = extend({}, recipe); | |||||
(sendRecipe.materials || []).forEach(function (m) { | |||||
m.need = !items.some(i => ( | |||||
( | |||||
i.name === m.name || | |||||
i.name.indexOf(m.nameLike) > -1 | |||||
) && | |||||
( | |||||
m.quantity === 1 || | |||||
i.quantity >= m.quantity | |||||
) | |||||
)); | |||||
}); | |||||
return sendRecipe; | |||||
}, | |||||
getRecipe: function (msg) { | getRecipe: function (msg) { | ||||
let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId); | let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId); | ||||
if ((!obj) || (!obj.player)) | if ((!obj) || (!obj.player)) | ||||
return; | return; | ||||
const sendRecipe = this.buildRecipe(obj, msg.name); | |||||
const sendRecipe = buildRecipe(this.craftType, obj, msg); | |||||
this.resolveCallback(msg, sendRecipe); | this.resolveCallback(msg, sendRecipe); | ||||
}, | }, | ||||
craft: function (msg) { | craft: function (msg) { | ||||
let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId); | |||||
if ((!obj) || (!obj.player)) | |||||
const { craftType, obj: { instance: { objects: { objects } } } } = this; | |||||
const { name: recipeName, sourceId } = msg; | |||||
const crafter = objects.find(o => o.serverId === sourceId); | |||||
if (!crafter || !crafter.player) | |||||
return; | return; | ||||
let recipe = recipes.getRecipe(this.craftType, msg.name); | |||||
const recipe = recipes.getRecipe(craftType, recipeName); | |||||
if (!recipe) | if (!recipe) | ||||
return; | return; | ||||
const items = obj.inventory.items; | |||||
let canCraft = recipe.materials.every(m => (items.some(i => ( | |||||
( | |||||
i.name === m.name || | |||||
i.name.indexOf(m.nameLike) > -1 | |||||
) && | |||||
( | |||||
m.quantity === 1 || | |||||
i.quantity >= m.quantity | |||||
) | |||||
)))); | |||||
const { needItems } = recipe; | |||||
const { syncer, inventory, equipment, spellbook } = crafter; | |||||
const materials = buildMaterials(crafter, recipe, msg); | |||||
const pickedItems = buildPickedItems(crafter, recipe, msg); | |||||
const canCraft = ( | |||||
!materials.some(m => m.noHaveEnough) && | |||||
pickedItems.length === needItems.length && | |||||
!pickedItems.some(i => !i) | |||||
); | |||||
if (!canCraft) | if (!canCraft) | ||||
return; | return; | ||||
recipe.materials.forEach(m => { | |||||
let findItem = obj.inventory.items.find(f => ( | |||||
f.name === m.name || | |||||
f.name.indexOf(m.nameLike) > -1 | |||||
)); | |||||
obj.inventory.destroyItem(findItem.id, m.quantity); | |||||
}); | |||||
let outputItems = recipe.item ? [ recipe.item ] : recipe.items; | |||||
outputItems.forEach(itemBpt => { | |||||
let item = null; | |||||
if (itemBpt.generate) | |||||
item = generator.generate(itemBpt); | |||||
else | |||||
item = extend({}, itemBpt); | |||||
if (item.description) | |||||
item.description += `<br /><br />(Crafted by ${obj.name})`; | |||||
else | |||||
item.description = `<br /><br />(Crafted by ${obj.name})`; | |||||
const quantity = item.quantity; | |||||
if (quantity && quantity.push) | |||||
item.quantity = quantity[0] + ~~(Math.random() * (quantity[1] - quantity[0])); | |||||
obj.inventory.getItem(item); | |||||
materials.forEach(m => inventory.destroyItem(m.id, m.needQuantity)); | |||||
let resultMsg = null; | |||||
if (recipe.craftAction) { | |||||
pickedItems.forEach(p => { | |||||
if (p.eq) | |||||
applyItemStats(crafter, p, false); | |||||
}); | |||||
const oldSlots = pickedItems.map(p => p.slot); | |||||
resultMsg = recipe.craftAction(crafter, pickedItems); | |||||
pickedItems.forEach((p, i) => { | |||||
if (!p.eq) | |||||
return; | |||||
applyItemStats(crafter, p, true); | |||||
if (p.slot !== oldSlots[i]) | |||||
equipment.unequip(p.id); | |||||
spellbook.calcDps(); | |||||
pickedItems.forEach(item => syncer.setArray(true, 'inventory', 'getItems', inventory.simplifyItem(item))); | |||||
}); | |||||
equipment.unequipAttrRqrGear(); | |||||
} | |||||
if (recipe.item || recipe.items) { | |||||
const outputItems = recipe.item ? [ recipe.item ] : recipe.items; | |||||
outputItems.forEach(itemBpt => { | |||||
let item = null; | |||||
if (itemBpt.generate) | |||||
item = generator.generate(itemBpt); | |||||
else | |||||
item = extend({}, itemBpt); | |||||
if (item.description) | |||||
item.description += `<br /><br />(Crafted by ${crafter.name})`; | |||||
else | |||||
item.description = `<br /><br />(Crafted by ${crafter.name})`; | |||||
const quantity = item.quantity; | |||||
if (quantity && quantity.push) | |||||
item.quantity = quantity[0] + ~~(Math.random() * (quantity[1] - quantity[0])); | |||||
crafter.inventory.getItem(item); | |||||
}); | |||||
} | |||||
this.resolveCallback(msg, { | |||||
resultMsg, | |||||
recipe: buildRecipe(craftType, crafter, msg) | |||||
}); | }); | ||||
this.resolveCallback(msg, this.buildRecipe(obj, msg.name)); | |||||
}, | }, | ||||
resolveCallback: function (msg, result) { | resolveCallback: function (msg, result) { | ||||
@@ -0,0 +1,57 @@ | |||||
const buildPickedItems = require('./buildPickedItems'); | |||||
module.exports = (crafter, recipe, msg) => { | |||||
const { inventory: { items } } = crafter; | |||||
const { materialGenerator, materials, needItems = [] } = recipe; | |||||
const { pickedItemIds = [] } = msg; | |||||
const pickedItems = buildPickedItems(crafter, recipe, msg); | |||||
const allPickedItemsSet = ( | |||||
pickedItemIds.length === needItems.length && | |||||
!pickedItems.some(i => !i) | |||||
); | |||||
if (!allPickedItemsSet) | |||||
return []; | |||||
let useMaterials = materials; | |||||
if (materialGenerator) | |||||
useMaterials = materialGenerator(crafter, pickedItems); | |||||
const result = useMaterials.map(m => { | |||||
const { name, nameLike, quantity } = m; | |||||
const haveMaterial = items.find(i => ( | |||||
i.name === name || | |||||
i.name.includes(nameLike) | |||||
)); | |||||
const noHaveEnough = ( | |||||
haveMaterial && | |||||
( | |||||
haveMaterial.quantity === 1 || | |||||
haveMaterial.quantity < quantity | |||||
) | |||||
); | |||||
const id = haveMaterial ? haveMaterial.id : null; | |||||
const haveQuantity = haveMaterial ? (haveMaterial.quantity || 1) : 0; | |||||
const needQuantity = quantity; | |||||
const material = { | |||||
id, | |||||
name, | |||||
nameLike, | |||||
haveQuantity, | |||||
needQuantity, | |||||
noHaveEnough | |||||
}; | |||||
return material; | |||||
}); | |||||
return result; | |||||
}; |
@@ -0,0 +1,29 @@ | |||||
module.exports = ({ inventory: { items } }, { needItems }) => { | |||||
if (!needItems) | |||||
return null; | |||||
const result = needItems.map(n => { | |||||
const { info, withProps = [], withoutProps = [], checks = [] } = n; | |||||
const allowedItemIds = items | |||||
.filter(item => { | |||||
const isValidItem = ( | |||||
withProps.every(p => item.has(p)) && | |||||
withoutProps.every(p => !item.has(p)) && | |||||
checks.every(c => c(item)) | |||||
); | |||||
return isValidItem; | |||||
}) | |||||
.map(item => item.id); | |||||
const needItem = { | |||||
info, | |||||
allowedItemIds | |||||
}; | |||||
return needItem; | |||||
}); | |||||
return result; | |||||
}; |
@@ -0,0 +1,19 @@ | |||||
const buildNeedItems = require('./buildNeedItems'); | |||||
module.exports = (crafter, recipe, { pickedItemIds = [] }) => { | |||||
const needItems = buildNeedItems(crafter, recipe); | |||||
const { inventory: { items } } = crafter; | |||||
const result = pickedItemIds.map((pickedId, i) => { | |||||
const item = items.find(f => f.id === pickedId); | |||||
const isItemValid = needItems[i].allowedItemIds.includes(item.id); | |||||
if (!isItemValid) | |||||
return null; | |||||
return item; | |||||
}); | |||||
return result; | |||||
}; |
@@ -0,0 +1,30 @@ | |||||
const recipes = require('../../config/recipes/recipes'); | |||||
const buildMaterials = require('./buildMaterials'); | |||||
const buildNeedItems = require('./buildNeedItems'); | |||||
const buildBase = (crafter, { name, description }) => { | |||||
return { | |||||
name, | |||||
description | |||||
}; | |||||
}; | |||||
module.exports = (craftType, crafter, msg) => { | |||||
const recipe = recipes.getRecipe(craftType, msg.name); | |||||
if (!recipe) | |||||
return; | |||||
const result = buildBase(crafter, recipe); | |||||
const needItems = buildNeedItems(crafter, recipe); | |||||
if (needItems) | |||||
result.needItems = needItems; | |||||
if (recipe.materialGenerator || recipe.needItems) | |||||
result.dynamicMaterials = true; | |||||
result.materials = buildMaterials(crafter, recipe, msg); | |||||
return result; | |||||
}; |
@@ -18,14 +18,6 @@ module.exports = { | |||||
type: 'fish', | type: 'fish', | ||||
quantity: [6, 12] | quantity: [6, 12] | ||||
}, | }, | ||||
vikardoor: { | |||||
properties: { | |||||
cpnDoor: { | |||||
locked: true, | |||||
key: 'vikar' | |||||
} | |||||
} | |||||
}, | |||||
shopestrid: { | shopestrid: { | ||||
properties: { | properties: { | ||||
cpnNotice: { | cpnNotice: { | ||||
@@ -523,6 +515,61 @@ module.exports = { | |||||
type: 'cooking' | type: 'cooking' | ||||
} | } | ||||
} | } | ||||
}, | |||||
'enchanting shrine': { | |||||
components: { | |||||
cpnParticles: { | |||||
simplify: function () { | |||||
return { | |||||
type: 'particles', | |||||
blueprint: { | |||||
color: { | |||||
start: ['48edff', 'fc66f7'], | |||||
end: ['393268', '42548d'] | |||||
}, | |||||
scale: { | |||||
start: { | |||||
min: 2, | |||||
max: 10 | |||||
}, | |||||
end: { | |||||
min: 0, | |||||
max: 2 | |||||
} | |||||
}, | |||||
speed: { | |||||
start: { | |||||
min: 4, | |||||
max: 16 | |||||
}, | |||||
end: { | |||||
min: 2, | |||||
max: 8 | |||||
} | |||||
}, | |||||
lifetime: { | |||||
min: 1, | |||||
max: 4 | |||||
}, | |||||
randomScale: true, | |||||
randomSpeed: true, | |||||
chance: 0.2, | |||||
randomColor: true, | |||||
spawnType: 'rect', | |||||
spawnRect: { | |||||
x: -15, | |||||
y: -28, | |||||
w: 30, | |||||
h: 8 | |||||
} | |||||
} | |||||
}; | |||||
} | |||||
}, | |||||
cpnWorkbench: { | |||||
type: 'enchanting' | |||||
} | |||||
} | |||||
} | } | ||||
}, | }, | ||||
mobs: { | mobs: { | ||||
@@ -0,0 +1,90 @@ | |||||
const calculateAugmentMaterials = require('./enchanting/calculateAugmentMaterials'); | |||||
const reroll = require('./enchanting/craftActions/reroll'); | |||||
const relevel = require('./enchanting/craftActions/relevel'); | |||||
const augment = require('./enchanting/craftActions/augment'); | |||||
const reslot = require('./enchanting/craftActions/reslot'); | |||||
const reforge = require('./enchanting/craftActions/reforge'); | |||||
const scour = require('./enchanting/craftActions/scour'); | |||||
module.exports = [{ | |||||
name: 'Augment', | |||||
description: 'Adds a random stat to an item. Items can hold a maximum of three augments.', | |||||
materialGenerator: calculateAugmentMaterials, | |||||
craftAction: augment, | |||||
needItems: [{ | |||||
info: 'Pick an item to augment', | |||||
withProps: ['slot'], | |||||
withoutProps: ['noAugment'], | |||||
checks: [ | |||||
item => { | |||||
return !item.power || item.power < 3; | |||||
} | |||||
] | |||||
}] | |||||
}, { | |||||
name: 'Reroll', | |||||
description: 'Rerolls an item\'s implicit and explicit stats. Augmentations are not affected.', | |||||
materials: [{ | |||||
name: 'Unstable Idol', | |||||
quantity: 1 | |||||
}], | |||||
needItems: [{ | |||||
info: 'Pick an item to reroll', | |||||
withProps: ['slot'], | |||||
withoutProps: ['noAugment'] | |||||
}], | |||||
craftAction: reroll | |||||
}, { | |||||
name: 'Increase Level', | |||||
description: 'Adds [1 - 3] to an item\'s required level. Items with higher levels yield better stats when rerolled.', | |||||
materials: [{ | |||||
name: 'Ascendant Idol', | |||||
quantity: 1 | |||||
}], | |||||
needItems: [{ | |||||
info: 'Pick an item to reroll', | |||||
withProps: ['slot'], | |||||
withoutProps: ['noAugment'] | |||||
}], | |||||
craftAction: relevel | |||||
}, { | |||||
name: 'Reslot', | |||||
description: 'Reforms the item into a random new item that retains the source item\'s quality and stat types.', | |||||
materials: [{ | |||||
name: 'Dragon-Glass Idol', | |||||
quantity: 1 | |||||
}], | |||||
needItems: [{ | |||||
info: 'Pick an item to reroll', | |||||
withProps: ['slot'], | |||||
withoutProps: ['noAugment', 'effects'] | |||||
}], | |||||
craftAction: reslot | |||||
}, { | |||||
name: 'Reforge Weapon', | |||||
description: 'Rerolls a weapon\'s damage range.', | |||||
materials: [{ | |||||
name: 'Bone Idol', | |||||
quantity: 1 | |||||
}], | |||||
needItems: [{ | |||||
info: 'Pick an item to reroll', | |||||
withProps: ['slot', 'spell'], | |||||
withoutProps: ['noAugment'] | |||||
}], | |||||
craftAction: reforge | |||||
}, { | |||||
name: 'Scour', | |||||
description: 'Rerolls a weapon\'s damage range.', | |||||
materials: [{ | |||||
name: 'Bone Idol', | |||||
quantity: 1 | |||||
}], | |||||
needItems: [{ | |||||
info: 'Pick an item to reroll', | |||||
withProps: ['slot', 'power'], | |||||
withoutProps: ['noAugment'] | |||||
}], | |||||
craftAction: scour | |||||
}]; |
@@ -0,0 +1,17 @@ | |||||
const salvager = require('../../../items/salvager'); | |||||
module.exports = (obj, [item]) => { | |||||
let powerLevel = item.power || 0; | |||||
let mult = null; | |||||
if (powerLevel < 3) | |||||
mult = [5, 10, 20][powerLevel]; | |||||
else | |||||
return; | |||||
const result = salvager.salvage(item, true); | |||||
result.forEach(r => { | |||||
r.quantity = Math.max(1, ~~(r.quantity * mult)); | |||||
}); | |||||
return result; | |||||
}; |
@@ -0,0 +1,17 @@ | |||||
let generatorStats = require('../../../../items/generators/stats'); | |||||
module.exports = (obj, [item]) => { | |||||
let newPower = (item.power || 0) + 1; | |||||
if (newPower > 3) | |||||
return; | |||||
item.power = newPower; | |||||
const result = { msg: 'Augment successful', addStatMsgs: [] }; | |||||
generatorStats.generate(item, { | |||||
statCount: 1 | |||||
}, result); | |||||
return result; | |||||
}; |
@@ -0,0 +1,17 @@ | |||||
let generatorSpells = require('../../../../items/generators/spellbook'); | |||||
module.exports = (obj, [item]) => { | |||||
if (!item.spell) | |||||
return; | |||||
let spellName = item.spell.name.toLowerCase(); | |||||
let oldSpell = item.spell; | |||||
delete item.spell; | |||||
generatorSpells.generate(item, { | |||||
spellName: spellName | |||||
}); | |||||
item.spell = extend(oldSpell, item.spell); | |||||
return { msg: 'Reforge successful' }; | |||||
}; |
@@ -0,0 +1,18 @@ | |||||
module.exports = (obj, [item]) => { | |||||
if (item.slot === 'tool') | |||||
return; | |||||
let offset = 1 + ~~(Math.random() * 2); | |||||
const maxLevel = consts.maxLevel; | |||||
if (!item.originalLevel) | |||||
item.level = Math.min(maxLevel, item.level + offset); | |||||
else { | |||||
offset = Math.min(maxLevel - item.originalLevel, offset); | |||||
item.originalLevel = Math.min(maxLevel, item.originalLevel + offset); | |||||
item.level = Math.min(maxLevel, item.level + offset); | |||||
} | |||||
return { msg: 'Relevel successful' }; | |||||
}; |
@@ -0,0 +1,58 @@ | |||||
let generatorStats = require('../../../../items/generators/stats'); | |||||
let generatorSlots = require('../../../../items/generators/slots'); | |||||
let generatorTypes = require('../../../../items/generators/types'); | |||||
module.exports = (obj, [item]) => { | |||||
const enchantedStats = item.enchantedStats; | |||||
const implicitStats = item.implicitStats; | |||||
delete item.enchantedStats; | |||||
delete item.implicitStats; | |||||
if ((item.stats) && (item.stats.lvlRequire)) { | |||||
item.level = Math.min(consts.maxLevel, item.level + item.stats.lvlRequire); | |||||
delete item.originalLevel; | |||||
} | |||||
item.stats = {}; | |||||
let bpt = { | |||||
slot: item.slot, | |||||
type: item.type, | |||||
sprite: item.sprite, | |||||
spritesheet: item.spritesheet | |||||
}; | |||||
generatorSlots.generate(item, bpt); | |||||
generatorTypes.generate(item, bpt); | |||||
generatorStats.generate(item, bpt); | |||||
for (let p in enchantedStats) { | |||||
if (!item.stats[p]) | |||||
item.stats[p] = 0; | |||||
item.stats[p] += enchantedStats[p]; | |||||
if (p === 'lvlRequire') { | |||||
if (!item.originalLevel) | |||||
item.originalLevel = item.level; | |||||
item.level -= enchantedStats[p]; | |||||
if (item.level < 1) | |||||
item.level = 1; | |||||
} | |||||
} | |||||
item.enchantedStats = enchantedStats || null; | |||||
//Some items have special implicits (different stats than their types imply) | |||||
// We add the old one back in if this is the case. Ideally we'd like to reroll | |||||
// these but that'd be a pretty big hack. We'll solve this one day | |||||
if ( | |||||
item.implicitStats && | |||||
implicitStats && | |||||
item.implicitStats[0] && | |||||
implicitStats[0] && | |||||
item.implicitStats[0].stat !== implicitStats[0].stat | |||||
) | |||||
item.implicitStats = implicitStats; | |||||
return { msg: 'Reroll successful' }; | |||||
}; |
@@ -0,0 +1,34 @@ | |||||
let configSlots = require('../../../../items/config/slots'); | |||||
let generator = require('../../../../items/generator'); | |||||
module.exports = (obj, [item]) => { | |||||
if (item.effects || item.slot === 'tool') | |||||
return; | |||||
if (item.originalLevel) | |||||
item.level = item.originalLevel; | |||||
delete item.enchantedStats; | |||||
let possibleStats = Object.keys(item.stats || {}); | |||||
let newItem = generator.generate({ | |||||
slot: configSlots.getRandomSlot(item.slot), | |||||
level: item.level, | |||||
quality: item.quality, | |||||
stats: possibleStats, | |||||
limitSlotStats: true | |||||
}); | |||||
delete item.spritesheet; | |||||
delete item.stats; | |||||
delete item.spell; | |||||
delete item.implicitStats; | |||||
delete item.power; | |||||
delete item.range; | |||||
delete item.requires; | |||||
extend(item, newItem); | |||||
return { msg: 'Reslot successful' }; | |||||
}; |
@@ -0,0 +1,31 @@ | |||||
module.exports = (obj, [item]) => { | |||||
if (!item.power) | |||||
return; | |||||
const result = { msg: 'Scour successful', addStatMsgs: [] }; | |||||
for (let p in item.enchantedStats) { | |||||
let value = item.enchantedStats[p]; | |||||
if (item.stats[p]) { | |||||
result.addStatMsgs.push({ | |||||
stat: p, | |||||
value: -value | |||||
}); | |||||
item.stats[p] -= value; | |||||
if (item.stats[p] <= 0) | |||||
delete item.stats[p]; | |||||
if (p === 'lvlRequire') { | |||||
item.level = Math.min(consts.maxLevel, item.level + value); | |||||
delete item.originalLevel; | |||||
} | |||||
} | |||||
} | |||||
delete item.enchantedStats; | |||||
delete item.power; | |||||
return result; | |||||
}; |
@@ -3,17 +3,13 @@ let events = require('../../misc/events'); | |||||
const recipesAlchemy = require('./alchemy'); | const recipesAlchemy = require('./alchemy'); | ||||
const recipesCooking = require('./cooking'); | const recipesCooking = require('./cooking'); | ||||
const recipesEtching = require('./etching'); | const recipesEtching = require('./etching'); | ||||
const recipesEnchanting = require('./enchanting'); | |||||
let recipes = { | let recipes = { | ||||
alchemy: [ | |||||
...recipesAlchemy | |||||
], | |||||
cooking: [ | |||||
...recipesCooking | |||||
], | |||||
etching: [ | |||||
...recipesEtching | |||||
] | |||||
alchemy: [ ...recipesAlchemy ], | |||||
cooking: [ ...recipesCooking ], | |||||
etching: [ ...recipesEtching ], | |||||
enchanting: [ ...recipesEnchanting ] | |||||
}; | }; | ||||
module.exports = { | module.exports = { | ||||
@@ -22,7 +18,11 @@ module.exports = { | |||||
}, | }, | ||||
getList: function (type, unlocked) { | getList: function (type, unlocked) { | ||||
return (recipes[type] || []) | |||||
const useRecipes = recipes[type]; | |||||
if (!useRecipes) | |||||
return []; | |||||
return useRecipes | |||||
.filter(r => { | .filter(r => { | ||||
let hasUnlocked = (r.default !== false); | let hasUnlocked = (r.default !== false); | ||||
if (!hasUnlocked) | if (!hasUnlocked) | ||||
@@ -1,245 +0,0 @@ | |||||
let generatorStats = require('./generators/stats'); | |||||
let generatorSlots = require('./generators/slots'); | |||||
let generatorTypes = require('./generators/types'); | |||||
let generatorSpells = require('./generators/spellbook'); | |||||
let salvager = require('./salvager'); | |||||
let configCurrencies = require('./config/currencies'); | |||||
let configSlots = require('./config/slots'); | |||||
let generator = require('./generator'); | |||||
const reroll = (item, msg) => { | |||||
const enchantedStats = item.enchantedStats; | |||||
const implicitStats = item.implicitStats; | |||||
delete item.enchantedStats; | |||||
delete item.implicitStats; | |||||
delete msg.addStatMsgs; | |||||
if ((item.stats) && (item.stats.lvlRequire)) { | |||||
item.level = Math.min(consts.maxLevel, item.level + item.stats.lvlRequire); | |||||
delete item.originalLevel; | |||||
} | |||||
item.stats = {}; | |||||
let bpt = { | |||||
slot: item.slot, | |||||
type: item.type, | |||||
sprite: item.sprite, | |||||
spritesheet: item.spritesheet | |||||
}; | |||||
generatorSlots.generate(item, bpt); | |||||
generatorTypes.generate(item, bpt); | |||||
generatorStats.generate(item, bpt); | |||||
for (let p in enchantedStats) { | |||||
if (!item.stats[p]) | |||||
item.stats[p] = 0; | |||||
item.stats[p] += enchantedStats[p]; | |||||
if (p === 'lvlRequire') { | |||||
if (!item.originalLevel) | |||||
item.originalLevel = item.level; | |||||
item.level -= enchantedStats[p]; | |||||
if (item.level < 1) | |||||
item.level = 1; | |||||
} | |||||
} | |||||
item.enchantedStats = enchantedStats || null; | |||||
//Some items have special implicits (different stats than their types imply) | |||||
// We add the old one back in if this is the case. Ideally we'd like to reroll | |||||
// these but that'd be a pretty big hack. We'll solve this one day | |||||
if ( | |||||
item.implicitStats && | |||||
implicitStats && | |||||
item.implicitStats[0] && | |||||
implicitStats[0] && | |||||
item.implicitStats[0].stat !== implicitStats[0].stat | |||||
) | |||||
item.implicitStats = implicitStats; | |||||
}; | |||||
const relevel = item => { | |||||
if (item.slot === 'tool') | |||||
return; | |||||
let offset = 1 + ~~(Math.random() * 2); | |||||
const maxLevel = consts.maxLevel; | |||||
if (!item.originalLevel) | |||||
item.level = Math.min(maxLevel, item.level + offset); | |||||
else { | |||||
offset = Math.min(maxLevel - item.originalLevel, offset); | |||||
item.originalLevel = Math.min(maxLevel, item.originalLevel + offset); | |||||
item.level = Math.min(maxLevel, item.level + offset); | |||||
} | |||||
}; | |||||
const reslot = (item, msg) => { | |||||
if (item.effects || item.slot === 'tool') | |||||
return; | |||||
if (item.originalLevel) | |||||
item.level = item.originalLevel; | |||||
delete item.enchantedStats; | |||||
delete msg.addStatMsgs; | |||||
let possibleStats = Object.keys(item.stats || {}); | |||||
let newItem = generator.generate({ | |||||
slot: configSlots.getRandomSlot(item.slot), | |||||
level: item.level, | |||||
quality: item.quality, | |||||
stats: possibleStats, | |||||
limitSlotStats: true | |||||
}); | |||||
delete item.spritesheet; | |||||
delete item.stats; | |||||
delete item.spell; | |||||
delete item.implicitStats; | |||||
delete item.power; | |||||
delete item.range; | |||||
delete item.requires; | |||||
extend(item, newItem); | |||||
}; | |||||
const reforge = item => { | |||||
if (!item.spell) | |||||
return; | |||||
let spellName = item.spell.name.toLowerCase(); | |||||
let oldSpell = item.spell; | |||||
delete item.spell; | |||||
generatorSpells.generate(item, { | |||||
spellName: spellName | |||||
}); | |||||
item.spell = extend(oldSpell, item.spell); | |||||
}; | |||||
const scour = (item, result) => { | |||||
if (!item.power) | |||||
return; | |||||
for (let p in item.enchantedStats) { | |||||
let value = item.enchantedStats[p]; | |||||
if (item.stats[p]) { | |||||
result.addStatMsgs.push({ | |||||
stat: p, | |||||
value: -value | |||||
}); | |||||
item.stats[p] -= value; | |||||
if (item.stats[p] <= 0) | |||||
delete item.stats[p]; | |||||
if (p === 'lvlRequire') { | |||||
item.level = Math.min(consts.maxLevel, item.level + value); | |||||
delete item.originalLevel; | |||||
} | |||||
} | |||||
} | |||||
delete item.enchantedStats; | |||||
delete item.power; | |||||
}; | |||||
const augment = (item, inventory, result, msg) => { | |||||
let newPower = (item.power || 0) + 1; | |||||
if (newPower > 3) { | |||||
inventory.resolveCallback(msg); | |||||
return; | |||||
} | |||||
item.power = newPower; | |||||
generatorStats.generate(item, { | |||||
statCount: 1 | |||||
}, result); | |||||
}; | |||||
module.exports = { | |||||
enchant: function (obj, item, msg) { | |||||
let inventory = obj.inventory; | |||||
let config = this.getEnchantMaterials(item, msg.action); | |||||
let success = true; | |||||
config.materials.forEach(function (m) { | |||||
let hasMaterial = inventory.items.find(i => i.name === m.name); | |||||
if (hasMaterial) | |||||
hasMaterial = hasMaterial.quantity >= m.quantity; | |||||
if (!hasMaterial) | |||||
success = false; | |||||
}); | |||||
if (!success) { | |||||
inventory.resolveCallback(msg); | |||||
return; | |||||
} | |||||
let result = { | |||||
item: item, | |||||
addStatMsgs: [] | |||||
}; | |||||
config.materials.forEach(function (m) { | |||||
let invMaterial = inventory.items.find(i => i.name === m.name); | |||||
inventory.destroyItem(invMaterial.id, m.quantity); | |||||
}); | |||||
if (msg.action === 'reroll') | |||||
reroll(item, msg); | |||||
else if (msg.action === 'relevel') | |||||
relevel(item); | |||||
else if (msg.action === 'reslot') | |||||
reslot(item, msg); | |||||
else if (msg.action === 'reforge') | |||||
reforge(item); | |||||
else if (msg.action === 'scour') | |||||
scour(item, result); | |||||
else | |||||
augment(item, inventory, result, msg); | |||||
obj.syncer.setArray(true, 'inventory', 'getItems', inventory.simplifyItem(item)); | |||||
inventory.resolveCallback(msg, result); | |||||
}, | |||||
getEnchantMaterials: function (item, action) { | |||||
let result = null; | |||||
if (action === 'reroll') | |||||
result = [configCurrencies.getCurrencyFromAction('reroll')]; | |||||
else if (action === 'relevel') | |||||
result = [configCurrencies.getCurrencyFromAction('relevel')]; | |||||
else if (action === 'reslot') | |||||
result = [configCurrencies.getCurrencyFromAction('reslot')]; | |||||
else if (action === 'reforge') | |||||
result = [configCurrencies.getCurrencyFromAction('reforge')]; | |||||
else if (action === 'scour') | |||||
result = [configCurrencies.getCurrencyFromAction('scour')]; | |||||
else { | |||||
let powerLevel = item.power || 0; | |||||
let mult = null; | |||||
if (powerLevel < 3) | |||||
mult = [5, 10, 20][powerLevel]; | |||||
else | |||||
return; | |||||
result = salvager.salvage(item, true); | |||||
result.forEach(r => { | |||||
r.quantity = Math.max(1, ~~(r.quantity * mult)); | |||||
}); | |||||
} | |||||
return { | |||||
materials: result | |||||
}; | |||||
} | |||||
}; |
@@ -10,7 +10,7 @@ const routerConfig = { | |||||
dialogue: ['talk'], | dialogue: ['talk'], | ||||
gatherer: ['gather'], | gatherer: ['gather'], | ||||
quests: ['complete'], | quests: ['complete'], | ||||
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'enchantItem', 'getEnchantMaterials', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'], | |||||
inventory: ['combineStacks', 'splitStack', 'activateMtx', 'useItem', 'moveItem', 'learnAbility', 'unlearnAbility', 'dropItem', 'destroyItem', 'salvageItem', 'stashItem', 'mailItem', 'sortInventory'], | |||||
equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'], | equipment: ['equip', 'unequip', 'setQuickSlot', 'useQuickSlot', 'inspect'], | ||||
stash: ['withdraw', 'open'], | stash: ['withdraw', 'open'], | ||||
trade: ['buySell'], | trade: ['buySell'], | ||||