@@ -20,13 +20,9 @@ | |||||
text-align: center; | text-align: center; | ||||
color: @white; | color: @white; | ||||
font-size: 18px; | font-size: 18px; | ||||
background-color: fade(@blackD, 10%); | |||||
background-color: fade(@blackD, 15%); | |||||
padding: 8px; | padding: 8px; | ||||
text-shadow: 2px 2px 0 @blackD, | |||||
-2px -2px 0 @blackD, | |||||
2px -2px 0 @blackD, | |||||
-2px 2px 0 @blackD, | |||||
2px 2px 0 @blackD; | |||||
text-shadow: 2px 2px 0 @blackD, -2px -2px 0 @blackD, 2px -2px 0 @blackD, -2px 2px 0 @blackD, 2px 2px 0 @blackD; | |||||
animation: 0.5s ease-in-out infinite bounce; | animation: 0.5s ease-in-out infinite bounce; | ||||
&.success { | &.success { | ||||
@@ -36,12 +32,24 @@ | |||||
&.failure { | &.failure { | ||||
color: @red; | color: @red; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
@keyframes bounce { | @keyframes bounce { | ||||
0% { top: 0px; } | |||||
50% { top: 4px; } | |||||
100% { top: 0px ;} | |||||
} | |||||
0% { | |||||
top: 0px; | |||||
} | |||||
50% { | |||||
top: 4px; | |||||
} | |||||
100% { | |||||
top: 0px; | |||||
} | |||||
} |
@@ -1,11 +1,7 @@ | |||||
const recipes = require('../config/recipes/recipes'); | const recipes = require('../config/recipes/recipes'); | ||||
const generator = require('../items/generator'); | |||||
const { applyItemStats } = require('./equipment/helpers'); | |||||
const buildRecipe = require('./workbench/buildRecipe'); | const buildRecipe = require('./workbench/buildRecipe'); | ||||
const buildMaterials = require('./workbench/buildMaterials'); | |||||
const buildPickedItems = require('./workbench/buildPickedItems'); | |||||
const craft = require('./workbench/craft'); | |||||
module.exports = { | module.exports = { | ||||
type: 'workbench', | type: 'workbench', | ||||
@@ -115,87 +111,10 @@ module.exports = { | |||||
}, | }, | ||||
craft: function (msg) { | craft: function (msg) { | ||||
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; | |||||
const recipe = recipes.getRecipe(craftType, recipeName); | |||||
if (!recipe) | |||||
return; | |||||
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) | |||||
return; | |||||
const result = craft(this, msg); | |||||
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) | |||||
}); | |||||
if (result) | |||||
this.resolveCallback(msg, result); | |||||
}, | }, | ||||
resolveCallback: function (msg, result) { | resolveCallback: function (msg, result) { | ||||
@@ -27,20 +27,12 @@ module.exports = (crafter, recipe, msg) => { | |||||
i.name.includes(nameLike) | i.name.includes(nameLike) | ||||
)); | )); | ||||
const noHaveEnough = ( | |||||
haveMaterial && | |||||
( | |||||
haveMaterial.quantity === 1 || | |||||
haveMaterial.quantity < quantity | |||||
) | |||||
); | |||||
const id = haveMaterial ? haveMaterial.id : null; | const id = haveMaterial ? haveMaterial.id : null; | ||||
const haveQuantity = haveMaterial ? (haveMaterial.quantity || 1) : 0; | const haveQuantity = haveMaterial ? (haveMaterial.quantity || 1) : 0; | ||||
const needQuantity = quantity; | const needQuantity = quantity; | ||||
const noHaveEnough = haveQuantity < needQuantity; | |||||
const material = { | const material = { | ||||
id, | id, | ||||
name, | name, | ||||
@@ -0,0 +1,97 @@ | |||||
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 { 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) | |||||
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) { | |||||
pickedItems.forEach(item => syncer.setArray(true, 'inventory', 'getItems', inventory.simplifyItem(item))); | |||||
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); | |||||
}); | |||||
} | |||||
const result = { | |||||
resultMsg, | |||||
recipe: buildRecipe(craftType, crafter, msg) | |||||
}; | |||||
return result; | |||||
}; |
@@ -17,9 +17,7 @@ module.exports = [{ | |||||
withProps: ['slot'], | withProps: ['slot'], | ||||
withoutProps: ['noAugment'], | withoutProps: ['noAugment'], | ||||
checks: [ | checks: [ | ||||
item => { | |||||
return !item.power || item.power < 3; | |||||
} | |||||
item => !item.power || item.power < 3 | |||||
] | ] | ||||
}] | }] | ||||
}, { | }, { | ||||
@@ -43,9 +41,12 @@ module.exports = [{ | |||||
quantity: 1 | quantity: 1 | ||||
}], | }], | ||||
needItems: [{ | needItems: [{ | ||||
info: 'Pick an item to reroll', | |||||
info: 'Pick the item you wish to ascend', | |||||
withProps: ['slot'], | withProps: ['slot'], | ||||
withoutProps: ['noAugment'] | |||||
withoutProps: ['noAugment'], | |||||
checks: [ | |||||
item => item.level && item.level < consts.maxLevel | |||||
] | |||||
}], | }], | ||||
craftAction: relevel | craftAction: relevel | ||||
}, { | }, { | ||||
@@ -56,7 +57,7 @@ module.exports = [{ | |||||
quantity: 1 | quantity: 1 | ||||
}], | }], | ||||
needItems: [{ | needItems: [{ | ||||
info: 'Pick an item to reroll', | |||||
info: 'Pick an item to reslot', | |||||
withProps: ['slot'], | withProps: ['slot'], | ||||
withoutProps: ['noAugment', 'effects'] | withoutProps: ['noAugment', 'effects'] | ||||
}], | }], | ||||
@@ -69,22 +70,25 @@ module.exports = [{ | |||||
quantity: 1 | quantity: 1 | ||||
}], | }], | ||||
needItems: [{ | needItems: [{ | ||||
info: 'Pick an item to reroll', | |||||
info: 'Pick an item to reforge', | |||||
withProps: ['slot', 'spell'], | withProps: ['slot', 'spell'], | ||||
withoutProps: ['noAugment'] | withoutProps: ['noAugment'] | ||||
}], | }], | ||||
craftAction: reforge | craftAction: reforge | ||||
}, { | }, { | ||||
name: 'Scour', | name: 'Scour', | ||||
description: 'Rerolls a weapon\'s damage range.', | |||||
description: 'Wipe all augments from an item.', | |||||
materials: [{ | materials: [{ | ||||
name: 'Bone Idol', | |||||
name: 'Smoldering Idol', | |||||
quantity: 1 | quantity: 1 | ||||
}], | }], | ||||
needItems: [{ | needItems: [{ | ||||
info: 'Pick an item to reroll', | |||||
info: 'Pick an item to scour', | |||||
withProps: ['slot', 'power'], | withProps: ['slot', 'power'], | ||||
withoutProps: ['noAugment'] | withoutProps: ['noAugment'] | ||||
}], | }], | ||||
craftAction: scour | |||||
craftAction: scour, | |||||
checks: [ | |||||
item => item.power && item.power >= 1 | |||||
] | |||||
}]; | }]; |
@@ -13,5 +13,8 @@ module.exports = (obj, [item]) => { | |||||
}); | }); | ||||
item.spell = extend(oldSpell, item.spell); | item.spell = extend(oldSpell, item.spell); | ||||
return { msg: 'Reforge successful' }; | |||||
const damage = item.spell.values.damage; | |||||
const msg = `Reforged weapon to damage: ${damage}`; | |||||
return { msg }; | |||||
}; | }; |
@@ -14,5 +14,7 @@ module.exports = (obj, [item]) => { | |||||
item.level = Math.min(maxLevel, item.level + offset); | item.level = Math.min(maxLevel, item.level + offset); | ||||
} | } | ||||
return { msg: 'Relevel successful' }; | |||||
const msg = `Relevelled item to level ${item.level}`; | |||||
return { msg }; | |||||
}; | }; |
@@ -30,5 +30,7 @@ module.exports = (obj, [item]) => { | |||||
extend(item, newItem); | extend(item, newItem); | ||||
return { msg: 'Reslot successful' }; | |||||
const msg = `Reslotted item to slot: ${item.slot}`; | |||||
return { msg }; | |||||
}; | }; |