@@ -41,7 +41,6 @@ define([ | |||||
'mail', | 'mail', | ||||
'wardrobe', | 'wardrobe', | ||||
'passives', | 'passives', | ||||
'workbench', | |||||
'middleHud', | 'middleHud', | ||||
'options' | 'options' | ||||
]; | ]; | ||||
@@ -1,184 +0,0 @@ | |||||
@import "../../../css/colors.less"; | |||||
.uiWorkbench { | |||||
display: none; | |||||
width: 827px; | |||||
height: 447px; | |||||
border: 5px solid @blackB; | |||||
color: @white; | |||||
position: relative; | |||||
z-index: 2; | |||||
> .heading, | |||||
> .itemPicker > .heading { | |||||
color: @orangeA; | |||||
width: 100%; | |||||
height: 36px; | |||||
background-color: @blackB; | |||||
text-align: center; | |||||
.heading-text { | |||||
padding-top: 8px; | |||||
margin: auto; | |||||
} | |||||
} | |||||
> .bottom { | |||||
background-color: @blackC; | |||||
height: calc(100% - 36px); | |||||
width: 100%; | |||||
.heading { | |||||
color: @blueB; | |||||
margin-bottom: 10px; | |||||
text-align: center; | |||||
} | |||||
.left, | |||||
.right { | |||||
float: left; | |||||
height: 100%; | |||||
padding: 10px; | |||||
} | |||||
.left { | |||||
width: 300px; | |||||
.list { | |||||
height: calc(100% - 25px); | |||||
overflow-y: auto; | |||||
display: flex; | |||||
flex-direction: column; | |||||
.item { | |||||
width: 100%; | |||||
padding: 5px 10px; | |||||
cursor: pointer; | |||||
color: @grayB; | |||||
&.selected { | |||||
background-color: @blackB; | |||||
color: @white; | |||||
} | |||||
&:hover { | |||||
background-color: @blackB; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.right { | |||||
width: calc(100% - 300px); | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: space-between; | |||||
> * { | |||||
width: 100%; | |||||
} | |||||
.info { | |||||
height: calc(100% - 100px - 35px); | |||||
flex: 1; | |||||
.title { | |||||
color: @blueB; | |||||
padding-bottom: 10px; | |||||
text-align: center; | |||||
} | |||||
.description { | |||||
color: @grayB; | |||||
text-align: justify; | |||||
} | |||||
} | |||||
.materialList { | |||||
visibility: hidden; | |||||
margin-bottom: 20px; | |||||
.material { | |||||
&.need { | |||||
color: @redB; | |||||
} | |||||
} | |||||
} | |||||
.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 { | |||||
height: 40px; | |||||
> .btn { | |||||
height: 35px; | |||||
width: 100px; | |||||
color: @white; | |||||
text-align: center; | |||||
padding-top: 10px; | |||||
background-color: @blackB; | |||||
cursor: pointer; | |||||
float: left; | |||||
&:last-child { | |||||
float: right; | |||||
} | |||||
&:hover { | |||||
background-color: @blackA; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
> .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 { | |||||
z-index: 2; | |||||
} |
@@ -1,39 +0,0 @@ | |||||
<div class="uiWorkbench"> | |||||
<div class="heading"> | |||||
<div class="mainHeading heading-text">Workbench</div> | |||||
</div> | |||||
<div class="bottom"> | |||||
<div class="left"> | |||||
<div class="heading">Recipes</div> | |||||
<div class="list"> | |||||
</div> | |||||
</div> | |||||
<div class="right"> | |||||
<div class="info"> | |||||
<div class="icon"></div> | |||||
<div class="title"></div> | |||||
<div class="description"></div> | |||||
</div> | |||||
<div class="needItems"> | |||||
<div class="title">Pick Items</div> | |||||
<div class="list"></div> | |||||
</div> | |||||
<div class="materialList"> | |||||
<div class="heading">Requires:</div> | |||||
</div> | |||||
<div class="buttons"> | |||||
<div class="btn btnCancel">Cancel</div> | |||||
<div class="btn btnCraft disabled">Craft</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="itemPicker"> | |||||
<div class="heading"> | |||||
<div class="heading-text"></div> | |||||
</div> | |||||
<div class="list"> | |||||
</div> | |||||
</div> | |||||
</div> |
@@ -1,331 +0,0 @@ | |||||
define([ | |||||
'js/system/events', | |||||
'js/system/client', | |||||
'html!ui/templates/workbench/template', | |||||
'css!ui/templates/workbench/styles', | |||||
'ui/shared/renderItem', | |||||
'js/misc/statTranslations' | |||||
], function ( | |||||
events, | |||||
client, | |||||
template, | |||||
styles, | |||||
renderItem, | |||||
statTranslations | |||||
) { | |||||
return { | |||||
tpl: template, | |||||
centered: true, | |||||
modal: true, | |||||
hasClose: true, | |||||
workbenchId: null, | |||||
recipes: null, | |||||
currentRecipe: null, | |||||
selectedNeedItems: null, | |||||
hoverItem: null, | |||||
hoverEl: null, | |||||
postRender: function () { | |||||
this.onEvent('onOpenWorkbench', this.onOpenWorkbench.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('.btnCancel', 'click', this.hide.bind(this)); | |||||
}, | |||||
onOpenWorkbench: function (msg) { | |||||
this.workbenchId = msg.workbenchId; | |||||
this.find('.mainHeading').html(msg.name); | |||||
this.find('.itemPicker').hide(); | |||||
this.find('.needItems').hide(); | |||||
this.renderRecipes(msg.recipes); | |||||
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) { | |||||
this.recipes = recipes; | |||||
let container = this.find('.left .list').empty(); | |||||
recipes.forEach(function (r) { | |||||
let el = $('<div class="item">' + r + '</div>') | |||||
.appendTo(container); | |||||
el.on('click', this.onSelectRecipe.bind(this, el, r)); | |||||
}, this); | |||||
}, | |||||
onSelectRecipe: function (el, recipeName) { | |||||
el.parent().find('.selected').removeClass('selected'); | |||||
el.addClass('selected'); | |||||
client.request({ | |||||
cpn: 'player', | |||||
method: 'performAction', | |||||
data: { | |||||
targetId: this.workbenchId, | |||||
cpn: 'workbench', | |||||
method: 'getRecipe', | |||||
data: { | |||||
name: recipeName | |||||
} | |||||
}, | |||||
callback: this.onGetRecipe.bind(this, false) | |||||
}); | |||||
}, | |||||
onGetRecipe: function (persistNeedItems, recipe) { | |||||
const { name: recipeName, description, materials, needItems } = recipe; | |||||
this.currentRecipe = recipe; | |||||
this.find('.info .title').html(recipeName); | |||||
this.find('.description').html(description); | |||||
this.find('.materialList .material').remove(); | |||||
let container = this.find('.materialList') | |||||
.css({ | |||||
visibility: 'visible' | |||||
}); | |||||
let canCraft = !!materials.length; | |||||
materials.forEach(m => { | |||||
const { needQuantity, nameLike, name: materialName, haveQuantity, noHaveEnough } = m; | |||||
const materialText = `${needQuantity}x ${(nameLike || materialName)} (${haveQuantity})`; | |||||
let el = $(`<div class="material">${materialText}</div>`) | |||||
.appendTo(container); | |||||
if (noHaveEnough) { | |||||
canCraft = false; | |||||
el.addClass('need'); | |||||
} | |||||
}); | |||||
this.find('.btnCraft') | |||||
.removeClass('disabled'); | |||||
if (!canCraft) { | |||||
this.find('.btnCraft') | |||||
.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 () { | |||||
const selectedRecipe = this.find('.left .list .item.selected').html(); | |||||
const pickedItemIds = this.selectedNeedItems | |||||
.map(item => item.id); | |||||
client.request({ | |||||
cpn: 'player', | |||||
method: 'performAction', | |||||
data: { | |||||
targetId: this.workbenchId, | |||||
cpn: 'workbench', | |||||
method: 'craft', | |||||
data: { | |||||
name: selectedRecipe, | |||||
pickedItemIds | |||||
} | |||||
}, | |||||
callback: this.onCraft.bind(this) | |||||
}); | |||||
}, | |||||
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 () { | |||||
this.clear(); | |||||
}, | |||||
clear: function () { | |||||
this.find('.left .list .selected').removeClass('selected'); | |||||
this.find('.info .title').html(''); | |||||
this.find('.description').html(''); | |||||
this.find('.materialList .material').remove(); | |||||
this.find('.materialList') | |||||
.css({ | |||||
visibility: 'hidden' | |||||
}); | |||||
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,139 +0,0 @@ | |||||
const recipes = require('../config/recipes/recipes'); | |||||
const buildRecipe = require('./workbench/buildRecipe'); | |||||
const craft = require('./workbench/craft'); | |||||
module.exports = { | |||||
type: 'workbench', | |||||
craftType: null, | |||||
noticeMessage: null, | |||||
init: function (blueprint) { | |||||
this.craftType = blueprint.type; | |||||
this.noticeMessage = blueprint.noticeMessage; | |||||
this.obj.instance.objects.buildObjects([{ | |||||
properties: { | |||||
x: this.obj.x - 1, | |||||
y: this.obj.y - 1, | |||||
width: 3, | |||||
height: 3, | |||||
cpnNotice: { | |||||
actions: { | |||||
enter: { | |||||
cpn: 'workbench', | |||||
method: 'enterArea', | |||||
targetId: this.obj.id, | |||||
args: [] | |||||
}, | |||||
exit: { | |||||
cpn: 'workbench', | |||||
method: 'exitArea', | |||||
targetId: this.obj.id, | |||||
args: [] | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}]); | |||||
}, | |||||
exitArea: function (obj) { | |||||
if (!obj.player) | |||||
return; | |||||
obj.syncer.setArray(true, 'serverActions', 'removeActions', { | |||||
key: 'u', | |||||
action: { | |||||
targetId: this.obj.id, | |||||
cpn: 'workbench', | |||||
method: 'access' | |||||
} | |||||
}); | |||||
this.obj.instance.syncer.queue('onCloseWorkbench', null, [obj.serverId]); | |||||
}, | |||||
enterArea: function (obj) { | |||||
if (!obj.player) | |||||
return; | |||||
let msg = `Press U to ${this.noticeMessage || `access the ${this.obj.name}`}`; | |||||
obj.syncer.setArray(true, 'serverActions', 'addActions', { | |||||
key: 'u', | |||||
name: 'access workbench', | |||||
action: { | |||||
targetId: this.obj.id, | |||||
cpn: 'workbench', | |||||
method: 'open' | |||||
} | |||||
}); | |||||
this.obj.instance.syncer.queue('onGetAnnouncement', { | |||||
src: this.obj.id, | |||||
msg: msg | |||||
}, [obj.serverId]); | |||||
}, | |||||
open: async function (msg) { | |||||
if (!msg.has('sourceId')) | |||||
return; | |||||
let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId); | |||||
if ((!obj) || (!obj.player)) | |||||
return; | |||||
let thisObj = this.obj; | |||||
if ((Math.abs(thisObj.x - obj.x) > 1) || (Math.abs(thisObj.y - obj.y) > 1)) | |||||
return; | |||||
const unlocked = await io.getAsync({ | |||||
key: obj.name, | |||||
table: 'recipes', | |||||
isArray: true | |||||
}); | |||||
this.obj.instance.syncer.queue('onOpenWorkbench', { | |||||
workbenchId: this.obj.id, | |||||
name: this.obj.name, | |||||
recipes: recipes.getList(this.craftType, unlocked) | |||||
}, [obj.serverId]); | |||||
}, | |||||
getRecipe: function (msg) { | |||||
let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId); | |||||
if ((!obj) || (!obj.player)) | |||||
return; | |||||
const sendRecipe = buildRecipe(this.craftType, obj, msg); | |||||
this.resolveCallback(msg, sendRecipe); | |||||
}, | |||||
craft: function (msg) { | |||||
const result = craft(this, msg); | |||||
if (result) | |||||
this.resolveCallback(msg, result); | |||||
}, | |||||
resolveCallback: function (msg, result) { | |||||
let callbackId = (msg.has('callbackId')) ? msg.callbackId : msg; | |||||
result = result || []; | |||||
if (!callbackId) | |||||
return; | |||||
process.send({ | |||||
module: 'atlas', | |||||
method: 'resolveCallback', | |||||
msg: { | |||||
id: callbackId, | |||||
result: result | |||||
} | |||||
}); | |||||
} | |||||
}; |
@@ -1,49 +0,0 @@ | |||||
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 id = haveMaterial ? haveMaterial.id : null; | |||||
const haveQuantity = haveMaterial ? (haveMaterial.quantity || 1) : 0; | |||||
const needQuantity = quantity; | |||||
const noHaveEnough = haveQuantity < needQuantity; | |||||
const material = { | |||||
id, | |||||
name, | |||||
nameLike, | |||||
haveQuantity, | |||||
needQuantity, | |||||
noHaveEnough | |||||
}; | |||||
return material; | |||||
}); | |||||
return result; | |||||
}; |
@@ -1,29 +0,0 @@ | |||||
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; | |||||
}; |
@@ -1,22 +0,0 @@ | |||||
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); | |||||
if (!item) | |||||
return null; | |||||
const isItemValid = needItems[i].allowedItemIds.includes(item.id); | |||||
if (!isItemValid) | |||||
return null; | |||||
return item; | |||||
}); | |||||
return result; | |||||
}; |
@@ -1,30 +0,0 @@ | |||||
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; | |||||
}; |
@@ -1,94 +0,0 @@ | |||||
const recipes = require('../../config/recipes/recipes'); | |||||
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 = (cpnWorkbench, msg) => { | |||||
const { craftType, obj: { instance: { objects: { objects } } } } = cpnWorkbench; | |||||
const { name: recipeName, sourceId } = msg; | |||||
const crafter = objects.find(o => o.serverId === sourceId); | |||||
if (!crafter || !crafter.player) | |||||
return null; | |||||
const recipe = recipes.getRecipe(craftType, recipeName); | |||||
if (!recipe) | |||||
return null; | |||||
const { needItems = [] } = recipe; | |||||
const { 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) | |||||
return null; | |||||
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(); | |||||
}); | |||||
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])); | |||||
console.log(item); | |||||
crafter.inventory.getItem(item); | |||||
}); | |||||
} | |||||
const result = { | |||||
resultMsg, | |||||
recipe: buildRecipe(craftType, crafter, msg) | |||||
}; | |||||
return result; | |||||
}; |
@@ -1,61 +0,0 @@ | |||||
module.exports = [{ | |||||
name: 'Minor Healing Potion', | |||||
description: 'Does not affect emotional scars.', | |||||
item: { | |||||
name: 'Minor Healing Potion', | |||||
type: 'consumable', | |||||
sprite: [0, 1], | |||||
description: 'Does not affect emotional scars.', | |||||
worth: 0, | |||||
noSalvage: true, | |||||
noAugment: true, | |||||
uses: 1, | |||||
cdMax: 85, | |||||
effects: [{ | |||||
type: 'gainStat', | |||||
rolls: { | |||||
stat: 'hp', | |||||
amount: '50%' | |||||
} | |||||
}] | |||||
}, | |||||
materials: [{ | |||||
name: 'Skyblossom', | |||||
quantity: 3 | |||||
}, { | |||||
name: 'Empty Vial', | |||||
quantity: 1 | |||||
}] | |||||
}, { | |||||
id: 'noxiousOil', | |||||
name: 'Noxious Oil', | |||||
description: 'Makes your weapon both stinkier, and hurtier.', | |||||
default: false, | |||||
item: { | |||||
name: 'Noxious Oil', | |||||
type: 'consumable', | |||||
sprite: [0, 1], | |||||
description: 'Makes your weapon both stinkier, and hurtier.', | |||||
worth: 0, | |||||
noSalvage: true, | |||||
noAugment: true, | |||||
uses: 1, | |||||
cdMax: 85, | |||||
effects: [{ | |||||
type: 'augmentWeapon', | |||||
rolls: { | |||||
duration: 500 | |||||
} | |||||
}] | |||||
}, | |||||
materials: [{ | |||||
name: 'Mudfish', | |||||
quantity: 3 | |||||
}, { | |||||
name: 'Stinkcap', | |||||
quantity: 3 | |||||
}, { | |||||
name: 'Empty Vial', | |||||
quantity: 1 | |||||
}] | |||||
}]; |
@@ -1,53 +0,0 @@ | |||||
const baseRecipes = { | |||||
carp: { | |||||
description: 'It\'s a fish on a stick, what more do you want to know?', | |||||
item: { | |||||
name: 'Carp on a Stick', | |||||
type: 'consumable', | |||||
sprite: [0, 9], | |||||
description: 'It\'s a fish on a stick, what more do you want to know?', | |||||
worth: 0, | |||||
noSalvage: true, | |||||
noAugment: true, | |||||
uses: 1, | |||||
effects: [{ | |||||
type: 'gainStat', | |||||
rolls: { | |||||
stat: 'hp' | |||||
} | |||||
}] | |||||
}, | |||||
materials: [{ | |||||
quantity: 1 | |||||
}, { | |||||
name: 'Skewering Stick', | |||||
quantity: 1 | |||||
}] | |||||
} | |||||
}; | |||||
const buildRecipe = function (recipeName, itemName, effectAmount, materialName, quantity) { | |||||
return extend({}, baseRecipes[recipeName], { | |||||
name: itemName, | |||||
item: { | |||||
name: itemName, | |||||
quantity: quantity, | |||||
effects: [{ | |||||
rolls: { | |||||
amount: effectAmount | |||||
} | |||||
}] | |||||
}, | |||||
materials: [{ | |||||
name: materialName | |||||
}] | |||||
}); | |||||
}; | |||||
module.exports = [ | |||||
buildRecipe('carp', 'Carp on a Stick', 50, 'Sun Carp', 1), | |||||
buildRecipe('carp', 'Big Carp on a Stick', 50, 'Big Sun Carp', 2), | |||||
buildRecipe('carp', 'Giant Carp on a Stick', 150, 'Giant Sun Carp', 1), | |||||
buildRecipe('carp', 'Trophy Carp on a Stick', 150, 'Trophy Sun Carp', 2), | |||||
buildRecipe('carp', 'Fabled Carp on a Stick', 200, 'Fabled Sun Carp', [3, 5]) | |||||
]; |
@@ -1,37 +0,0 @@ | |||||
module.exports = [{ | |||||
id: 'runeWhirlwind', | |||||
name: 'Rune of Whirlwind', | |||||
default: false, | |||||
description: 'You furiously spin in a circle, striking all foes around you.', | |||||
item: { | |||||
name: 'Rune of Whirlwind', | |||||
generate: true, | |||||
spell: true, | |||||
spellName: 'whirlwind' | |||||
}, | |||||
materials: [{ | |||||
name: 'Muddy Runestone', | |||||
quantity: 1 | |||||
}, { | |||||
name: 'Eagle Feather', | |||||
quantity: 1 | |||||
}] | |||||
}, { | |||||
id: 'runeAmbush', | |||||
name: 'Rune of Ambush', | |||||
default: false, | |||||
description: 'Step into the shadows and reappear behind your target before delivering a concussing blow.', | |||||
item: { | |||||
name: 'Rune of Ambush', | |||||
generate: true, | |||||
spell: true, | |||||
spellName: 'ambush' | |||||
}, | |||||
materials: [{ | |||||
name: 'Muddy Runestone', | |||||
quantity: 1 | |||||
}, { | |||||
name: 'Rat Claw', | |||||
quantity: 1 | |||||
}] | |||||
}]; |
@@ -1,38 +0,0 @@ | |||||
let events = require('../../misc/events'); | |||||
const recipesAlchemy = require('./alchemy'); | |||||
const recipesCooking = require('./cooking'); | |||||
const recipesEtching = require('./etching'); | |||||
let recipes = { | |||||
alchemy: [ ...recipesAlchemy ], | |||||
cooking: [ ...recipesCooking ], | |||||
etching: [ ...recipesEtching ] | |||||
}; | |||||
module.exports = { | |||||
init: function () { | |||||
events.emit('onBeforeGetRecipes', recipes); | |||||
}, | |||||
getList: function (type, unlocked) { | |||||
const useRecipes = recipes[type]; | |||||
if (!useRecipes) | |||||
return []; | |||||
return useRecipes | |||||
.filter(r => { | |||||
let hasUnlocked = (r.default !== false); | |||||
if (!hasUnlocked) | |||||
hasUnlocked = unlocked.some(u => u.profession === type && u.teaches === r.id); | |||||
return hasUnlocked; | |||||
}) | |||||
.map(r => r.name); | |||||
}, | |||||
getRecipe: function (type, name) { | |||||
let recipe = (recipes[type] || []).find(r => r.name === name); | |||||
return recipe; | |||||
} | |||||
}; |
@@ -10,7 +10,6 @@ let classes = require('./config/spirits'); | |||||
let spellsConfig = require('./config/spellsConfig'); | let spellsConfig = require('./config/spellsConfig'); | ||||
let spells = require('./config/spells'); | let spells = require('./config/spells'); | ||||
let itemTypes = require('./items/config/types'); | let itemTypes = require('./items/config/types'); | ||||
let recipes = require('./config/recipes/recipes'); | |||||
let mapList = require('./config/maps/mapList'); | let mapList = require('./config/maps/mapList'); | ||||
let sheets = require('./security/sheets'); | let sheets = require('./security/sheets'); | ||||
let fixes = require('./fixes/fixes'); | let fixes = require('./fixes/fixes'); | ||||
@@ -37,7 +36,6 @@ let startup = { | |||||
classes.init(); | classes.init(); | ||||
spellsConfig.init(); | spellsConfig.init(); | ||||
spells.init(); | spells.init(); | ||||
recipes.init(); | |||||
itemTypes.init(); | itemTypes.init(); | ||||
profanities.init(); | profanities.init(); | ||||
mapList.init(); | mapList.init(); | ||||
@@ -17,8 +17,7 @@ const routerConfig = { | |||||
door: ['lock', 'unlock'], | door: ['lock', 'unlock'], | ||||
wardrobe: ['open', 'apply'], | wardrobe: ['open', 'apply'], | ||||
stats: ['respawn'], | stats: ['respawn'], | ||||
passives: ['tickNode', 'untickNode'], | |||||
workbench: ['open', 'craft', 'getRecipe'] | |||||
passives: ['tickNode', 'untickNode'] | |||||
}, | }, | ||||
globalAllowed: { | globalAllowed: { | ||||
clientConfig: ['getClientConfig'], | clientConfig: ['getClientConfig'], | ||||
@@ -14,7 +14,6 @@ let factions = require('../config/factions'); | |||||
let classes = require('../config/spirits'); | let classes = require('../config/spirits'); | ||||
let spellsConfig = require('../config/spellsConfig'); | let spellsConfig = require('../config/spellsConfig'); | ||||
let spells = require('../config/spells'); | let spells = require('../config/spells'); | ||||
let recipes = require('../config/recipes/recipes'); | |||||
let itemTypes = require('../items/config/types'); | let itemTypes = require('../items/config/types'); | ||||
let mapList = require('../config/maps/mapList'); | let mapList = require('../config/maps/mapList'); | ||||
let sheets = require('../security/sheets'); | let sheets = require('../security/sheets'); | ||||
@@ -30,7 +29,6 @@ let onCpnsReady = function () { | |||||
spells.init(); | spells.init(); | ||||
itemTypes.init(); | itemTypes.init(); | ||||
mapList.init(); | mapList.init(); | ||||
recipes.init(); | |||||
sheets.init(); | sheets.init(); | ||||
itemEffects.init(); | itemEffects.init(); | ||||