Resolve "Rebuild enchanting to utilise workbenches" Closes #1445, #1446, and #1440 See merge request Isleward/isleward!467tags/v0.6^2
@@ -179,66 +179,8 @@ module.exports = { | |||
vikar: { | |||
1: { | |||
msg: [{ | |||
msg: 'Is there anything I can help you with today?', | |||
options: [1.1] | |||
}], | |||
options: { | |||
1.1: { | |||
msg: 'I want to hand in some cards.', | |||
prereq: function (obj) { | |||
let fullSet = obj.inventory.items.find(i => ((i.setSize) && (i.setSize <= i.quantity))); | |||
return !!fullSet; | |||
}, | |||
goto: 'tradeCards' | |||
} | |||
} | |||
}, | |||
tradeCards: { | |||
msg: [{ | |||
msg: '', | |||
msg: 'How may I help you today?', | |||
options: [] | |||
}], | |||
method: function (obj) { | |||
let inventory = obj.inventory; | |||
let items = inventory.items; | |||
let sets = items.filter(function (i) { | |||
return ( | |||
(i.type === 'Reward Card') && | |||
(i.quantity >= i.setSize) | |||
); | |||
}); | |||
if (sets.length === 0) | |||
return 'Sorry, you don\'t have any completed sets.'; | |||
sets.forEach(function (s) { | |||
obj.instance.eventEmitter.emit('onGetCardSetReward', s.name, obj); | |||
inventory.destroyItem(s.id, s.setSize); | |||
}); | |||
return 'Thank you.'; | |||
} | |||
}, | |||
tradeBuy: { | |||
cpn: 'trade', | |||
method: 'startBuy', | |||
args: [{ | |||
targetName: 'vikar' | |||
}] | |||
}, | |||
tradeSell: { | |||
cpn: 'trade', | |||
method: 'startSell', | |||
args: [{ | |||
targetName: 'vikar' | |||
}] | |||
}, | |||
tradeBuyback: { | |||
cpn: 'trade', | |||
method: 'startBuyback', | |||
args: [{ | |||
targetName: 'vikar' | |||
}] | |||
} | |||
}, | |||
@@ -1,4 +1,12 @@ | |||
{ "backgroundcolor":"#32222e", | |||
"compressionlevel":-1, | |||
"editorsettings": | |||
{ | |||
"export": | |||
{ | |||
"target":"." | |||
} | |||
}, | |||
"height":120, | |||
"infinite":false, | |||
"layers":[ | |||
@@ -2043,7 +2051,7 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":568, | |||
"x":528, | |||
"y":736 | |||
}, | |||
{ | |||
@@ -2175,8 +2183,8 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":480, | |||
"y":744 | |||
"x":464, | |||
"y":752 | |||
}, | |||
{ | |||
"gid":273, | |||
@@ -2307,7 +2315,7 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":536, | |||
"x":520, | |||
"y":808 | |||
}, | |||
{ | |||
@@ -2319,8 +2327,20 @@ | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":600, | |||
"y":776 | |||
"x":592, | |||
"y":720 | |||
}, | |||
{ | |||
"gid":273, | |||
"height":8, | |||
"id":1291, | |||
"name":"Rat", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":8, | |||
"x":560, | |||
"y":824 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
@@ -2329,7 +2349,7 @@ | |||
"y":0 | |||
}], | |||
"nextlayerid":60, | |||
"nextobjectid":1291, | |||
"nextobjectid":1292, | |||
"orientation":"orthogonal", | |||
"properties":[ | |||
{ | |||
@@ -2338,7 +2358,7 @@ | |||
"value":"[{\"x\":97,\"y\":87}]" | |||
}], | |||
"renderorder":"right-down", | |||
"tiledversion":"1.2.5", | |||
"tiledversion":"1.3.3", | |||
"tileheight":8, | |||
"tilesets":[ | |||
{ | |||
@@ -1,57 +1,37 @@ | |||
let itemGenerator = require('../../items/generator'); | |||
let config = { | |||
'Runecrafter\'s Toil': { | |||
chance: 0.025, | |||
reward: 'Level 10 Rune', | |||
setSize: 3, | |||
mobLevel: [3, 100] | |||
mobLevel: [8, 12] | |||
}, | |||
'Godly Promise': { | |||
chance: 0.01, | |||
reward: 'Level 15 Legendary Weapon', | |||
setSize: 6, | |||
zone: 'sewer' | |||
}, | |||
'The Other Heirloom': { | |||
chance: 0.02, | |||
reward: 'Perfect Level 10 Ring', | |||
setSize: 3, | |||
mobName: 'flamingo' | |||
}, | |||
'Benthic Incantation': { | |||
chance: 0.015, | |||
reward: 'Princess Morgawsa\'s Trident', | |||
setSize: 12, | |||
zone: 'estuary' | |||
}, | |||
'Fangs of Fury': { | |||
chance: 0.05, | |||
reward: 'Steelclaw\'s Bite', | |||
setSize: 20, | |||
mobName: 'stinktooth' | |||
}, | |||
'Tradesman\'s Pride': { | |||
chance: 0.007, | |||
reward: 'Five Random Idols', | |||
setSize: 10 | |||
reward: 'Five Random Idols' | |||
} | |||
}; | |||
module.exports = { | |||
init: function () { | |||
}, | |||
fixCard: function (card) { | |||
let template = config[card.name]; | |||
if (!template) | |||
return; | |||
card.setSize = template.setSize; | |||
}, | |||
getCard: function (looter, mob) { | |||
getCard: function (modFolderPath, looter, mob) { | |||
let pool = []; | |||
let mobLevel = mob.stats.values.level; | |||
@@ -96,147 +76,14 @@ module.exports = { | |||
let builtCard = { | |||
name: pickName, | |||
spritesheet: pick.spritesheet || `${this.folderName}/images/items.png`, | |||
type: 'Reward Card', | |||
description: 'Reward: ' + pick.reward, | |||
spritesheet: pick.spritesheet || `${modFolderPath}/images/items.png`, | |||
type: 'Gambler\'s Card', | |||
noSalvage: true, | |||
sprite: pick.sprite || [0, 0], | |||
quantity: 1, | |||
quality: pick.quality || 1, | |||
setSize: pick.setSize | |||
quality: pick.quality || 1 | |||
}; | |||
return builtCard; | |||
}, | |||
getReward: function (looter, set) { | |||
let configs = extend({}, config); | |||
looter.instance.eventEmitter.emit('onBeforeGetCardsConfig', configs); | |||
let reward = configs[set].reward; | |||
let msg = { | |||
reward: reward, | |||
handler: this.rewards[reward] | |||
}; | |||
looter.instance.eventEmitter.emit('onBeforeGetCardReward', msg); | |||
return msg.handler(looter); | |||
}, | |||
rewards: { | |||
'Level 10 Rune': function () { | |||
return itemGenerator.generate({ | |||
level: 10, | |||
spell: true | |||
}); | |||
}, | |||
'Level 15 Legendary Weapon': function () { | |||
let slot = ['oneHanded', 'twoHanded'][~~(Math.random() * 2)]; | |||
return itemGenerator.generate({ | |||
level: 15, | |||
quality: 4, | |||
noSpell: true, | |||
slot: slot | |||
}); | |||
}, | |||
'Perfect Level 10 Ring': function () { | |||
return itemGenerator.generate({ | |||
level: 10, | |||
noSpell: true, | |||
quality: 1, | |||
perfection: 1, | |||
slot: 'finger' | |||
}); | |||
}, | |||
"Princess Morgawsa's Trident": function () { | |||
return itemGenerator.generate({ | |||
name: 'Princess Morgawsa\'s Trident', | |||
level: [18, 20], | |||
attrRequire: 'int', | |||
quality: 4, | |||
noSpell: true, | |||
slot: 'twoHanded', | |||
sprite: [0, 0], | |||
spritesheet: '../../../images/legendaryItems.png', | |||
type: 'Trident', | |||
description: 'Summoned from the ancient depths of the ocean by the Benthic Incantation.', | |||
stats: ['elementFrostPercent', 'elementFrostPercent', 'elementFrostPercent'], | |||
effects: [{ | |||
type: 'freezeOnHit', | |||
rolls: { | |||
i_chance: [2, 5], | |||
i_duration: [2, 4] | |||
} | |||
}], | |||
spellName: 'projectile', | |||
spellConfig: { | |||
statType: 'int', | |||
statMult: 1, | |||
element: 'arcane', | |||
auto: true, | |||
cdMax: 7, | |||
castTimeMax: 0, | |||
manaCost: 0, | |||
range: 9, | |||
random: { | |||
damage: [1.65, 10.81] | |||
} | |||
} | |||
}); | |||
}, | |||
'Five Random Idols': function () { | |||
let result = []; | |||
for (let i = 0; i < 5; i++) { | |||
result.push(itemGenerator.generate({ | |||
currency: true | |||
})); | |||
} | |||
return result; | |||
}, | |||
"Steelclaw's Bite": function () { | |||
return itemGenerator.generate({ | |||
name: 'Steelclaw\'s Bite', | |||
level: [18, 20], | |||
attrRequire: 'dex', | |||
quality: 4, | |||
noSpell: true, | |||
slot: 'oneHanded', | |||
sprite: [1, 0], | |||
spritesheet: '../../../images/legendaryItems.png', | |||
type: 'Curved Dagger', | |||
description: 'The blade seems to be made of some kind of bone and steel alloy.', | |||
stats: ['dex', 'dex', 'addCritMultiplier', 'addCritMultiplier'], | |||
effects: [{ | |||
type: 'damageSelf', | |||
properties: { | |||
element: 'poison' | |||
}, | |||
rolls: { | |||
i_percentage: [8, 22] | |||
} | |||
}, { | |||
type: 'alwaysCrit', | |||
rolls: {} | |||
}], | |||
spellName: 'melee', | |||
spellConfig: { | |||
statType: 'dex', | |||
statMult: 1, | |||
cdMax: 3, | |||
castTimeMax: 0, | |||
useWeaponRange: true, | |||
random: { | |||
damage: [0.88, 5.79] | |||
} | |||
} | |||
}); | |||
} | |||
} | |||
}; |
@@ -0,0 +1,17 @@ | |||
module.exports = { | |||
dealer: { | |||
zoneName: 'sewer', | |||
pos: { | |||
x: 74, | |||
y: 99 | |||
}, | |||
zoneConfig: { | |||
name: 'Shady Dealer', | |||
cell: 0, | |||
sheetName: '$MODFOLDER$/images/mobs.png', | |||
components: { | |||
cpnWorkbench: { type: 'gambling' } | |||
} | |||
} | |||
} | |||
}; |
@@ -1,18 +1,52 @@ | |||
let cards = require('./cards'); | |||
const cardRecipes = require('./recipes/recipes'); | |||
const cards = require('./cards'); | |||
const { dealer } = require('./config'); | |||
module.exports = { | |||
name: 'Feature: Cards', | |||
extraScripts: [ | |||
'cards' | |||
], | |||
init: function () { | |||
cards.init(); | |||
this.events.on('onBeforeGetClientConfig', this.onBeforeGetClientConfig.bind(this)); | |||
this.events.on('onBeforeDropBag', this.onBeforeDropBag.bind(this)); | |||
this.events.on('onGetCardSetReward', this.onGetCardSetReward.bind(this)); | |||
this.events.on('onBeforeGetItem', this.onBeforeGetItem.bind(this)); | |||
this.events.on('onBeforeGetRecipes', this.onBeforeGetRecipes.bind(this)); | |||
this.events.on('onAfterGetZone', this.onAfterGetZone.bind(this)); | |||
this.events.on('onAfterGetLayerObjects', this.onAfterGetLayerObjects.bind(this)); | |||
}, | |||
onBeforeGetClientConfig: function (config) { | |||
config.textureList.push(`${this.folderName}/images/mobs.png`); | |||
}, | |||
onAfterGetZone: function (zoneName, config) { | |||
const { zoneName: dealerZoneName, zoneConfig } = dealer; | |||
const dealerName = zoneConfig.name.toLowerCase(); | |||
if (zoneName !== dealerZoneName) | |||
return; | |||
zoneConfig.sheetName = zoneConfig.sheetName.replace('$MODFOLDER$', this.folderName); | |||
config.objects[dealerName] = zoneConfig; | |||
}, | |||
onAfterGetLayerObjects: function ({ map, layer, objects, mapScale }) { | |||
const { zoneName: dealerZoneName, pos: { x, y }, zoneConfig: { name } } = dealer; | |||
if (map !== dealerZoneName || layer !== 'objects') | |||
return; | |||
objects.push({ | |||
name, | |||
x: x * mapScale, | |||
y: y * mapScale, | |||
height: 8, | |||
width: 8, | |||
visible: true | |||
}); | |||
}, | |||
onBeforeGetRecipes: function (recipes) { | |||
recipes.gambling = cardRecipes; | |||
}, | |||
onBeforeDropBag: function (dropper, items, looter) { | |||
@@ -27,25 +61,10 @@ module.exports = { | |||
if (Math.random() >= dropEvent.chanceMultiplier) | |||
return; | |||
let res = cards.getCard(looter, dropper); | |||
let res = cards.getCard(this.folderName, looter, dropper); | |||
if (!res) | |||
return; | |||
items.push(res); | |||
}, | |||
onBeforeGetItem: function (item, obj) { | |||
if ((!obj.player) && (item.type !== 'Reward Card')) | |||
return; | |||
cards.fixCard(item); | |||
}, | |||
onGetCardSetReward: function (set, obj) { | |||
let reward = cards.getReward(obj, set); | |||
if (!reward.push) | |||
reward = [reward]; | |||
reward.forEach(r => obj.inventory.getItem(r, false, false, false, true)); | |||
} | |||
}; |
@@ -0,0 +1,17 @@ | |||
let itemGenerator = require('../../../../items/generator'); | |||
module.exports = ({ level, quality, slot, perfection }, crafter) => { | |||
const result = itemGenerator.generate({ | |||
level, | |||
noSpell: true, | |||
quality, | |||
perfection, | |||
slot | |||
}); | |||
crafter.inventory.getItem(result, false, false, false, true); | |||
const msg = `You received: ${result.name}`; | |||
return { msg }; | |||
}; |
@@ -0,0 +1,18 @@ | |||
let itemGenerator = require('../../../../items/generator'); | |||
module.exports = ({ rolls, quantity = 1 }, crafter) => { | |||
let quantityReceived = rolls * quantity; | |||
for (let i = 0; i < rolls; i++) { | |||
const idol = itemGenerator.generate({ | |||
currency: true, | |||
quantity | |||
}); | |||
crafter.inventory.getItem(idol, false, false, false, true); | |||
} | |||
const msg = `You received ${quantityReceived} idols`; | |||
return { msg }; | |||
}; |
@@ -0,0 +1,14 @@ | |||
let itemGenerator = require('../../../../items/generator'); | |||
module.exports = ({ level }, crafter) => { | |||
const result = itemGenerator.generate({ | |||
level, | |||
spell: true | |||
}); | |||
crafter.inventory.getItem(result, false, false, false, true); | |||
const msg = `You received: ${result.name}`; | |||
return { msg }; | |||
}; |
@@ -0,0 +1,17 @@ | |||
let itemGenerator = require('../../../../items/generator'); | |||
module.exports = (config, crafter) => { | |||
const slot = config.slot || ['oneHanded', 'twoHanded'][~~(Math.random() * 2)]; | |||
const result = itemGenerator.generate({ | |||
noSpell: true, | |||
slot, | |||
...config | |||
}); | |||
crafter.inventory.getItem(result, false, false, false, true); | |||
const msg = `You received: ${result.name}`; | |||
return { msg }; | |||
}; |
@@ -0,0 +1,132 @@ | |||
const rune = require('./craftActions/rune'); | |||
const weapon = require('./craftActions/weapon'); | |||
const armor = require('./craftActions/armor'); | |||
const idol = require('./craftActions/idol'); | |||
module.exports = [{ | |||
name: 'Level 10 Rune', | |||
description: '', | |||
materials: [{ | |||
name: 'Runecrafter\'s Toil', | |||
quantity: 3 | |||
}], | |||
craftAction: rune.bind(null, { | |||
level: 10 | |||
}) | |||
}, { | |||
name: 'Legendary Level 15 Weapon', | |||
description: '', | |||
materials: [{ | |||
name: 'Godly Promise', | |||
quantity: 6 | |||
}], | |||
craftAction: weapon.bind(null, { | |||
level: 15, | |||
quality: 4 | |||
}) | |||
}, { | |||
name: 'Perfect Level 10 Ring', | |||
description: '', | |||
materials: [{ | |||
name: 'The Other Heirloom', | |||
quantity: 3 | |||
}], | |||
craftAction: armor.bind(null, { | |||
level: 10, | |||
slot: 'finger', | |||
perfection: 1, | |||
quality: 1 | |||
}) | |||
}, { | |||
name: '5 Random Idols', | |||
description: '', | |||
materials: [{ | |||
name: 'Tradesman\'s Pride', | |||
quantity: 10 | |||
}], | |||
craftAction: idol.bind(null, { | |||
rolls: 5 | |||
}) | |||
}, { | |||
name: 'Princess Morgawsa\'s Trident', | |||
description: '', | |||
materials: [{ | |||
name: 'Benthic Incantation', | |||
quantity: 12 | |||
}], | |||
craftAction: weapon.bind(null, { | |||
name: 'Princess Morgawsa\'s Trident', | |||
level: [18, 20], | |||
attrRequire: 'int', | |||
quality: 4, | |||
slot: 'twoHanded', | |||
sprite: [0, 0], | |||
spritesheet: '../../../images/legendaryItems.png', | |||
type: 'Trident', | |||
description: 'Summoned from the ancient depths of the ocean by the Benthic Incantation.', | |||
stats: ['elementFrostPercent', 'elementFrostPercent', 'elementFrostPercent'], | |||
effects: [{ | |||
type: 'freezeOnHit', | |||
rolls: { | |||
i_chance: [2, 5], | |||
i_duration: [2, 4] | |||
} | |||
}], | |||
spellName: 'projectile', | |||
spellConfig: { | |||
statType: 'int', | |||
statMult: 1, | |||
element: 'arcane', | |||
auto: true, | |||
cdMax: 7, | |||
castTimeMax: 0, | |||
manaCost: 0, | |||
range: 9, | |||
random: { | |||
damage: [1.65, 10.81] | |||
} | |||
} | |||
}) | |||
}, { | |||
name: 'Steelclaw\'s Bite', | |||
description: '', | |||
materials: [{ | |||
name: 'Fangs of Fury', | |||
quantity: 20 | |||
}], | |||
craftAction: weapon.bind(null, { | |||
name: 'Steelclaw\'s Bite', | |||
level: [18, 20], | |||
attrRequire: 'dex', | |||
quality: 4, | |||
slot: 'oneHanded', | |||
sprite: [1, 0], | |||
spritesheet: '../../../images/legendaryItems.png', | |||
type: 'Curved Dagger', | |||
description: 'The blade seems to be made of some kind of bone and steel alloy.', | |||
stats: ['dex', 'dex', 'addCritMultiplier', 'addCritMultiplier'], | |||
effects: [{ | |||
type: 'damageSelf', | |||
properties: { | |||
element: 'poison' | |||
}, | |||
rolls: { | |||
i_percentage: [8, 22] | |||
} | |||
}, { | |||
type: 'alwaysCrit', | |||
rolls: {} | |||
}], | |||
spellName: 'melee', | |||
spellConfig: { | |||
statType: 'dex', | |||
statMult: 1, | |||
cdMax: 3, | |||
castTimeMax: 0, | |||
useWeaponRange: true, | |||
random: { | |||
damage: [0.88, 5.79] | |||
} | |||
} | |||
}) | |||
}]; |
@@ -261,7 +261,8 @@ module.exports = { | |||
let info = { | |||
map: this.name, | |||
layer: layerName, | |||
objects: data | |||
objects: data, | |||
mapScale | |||
}; | |||
events.emit('onAfterGetLayerObjects', info); | |||
} | |||
@@ -376,8 +377,8 @@ module.exports = { | |||
let blueprint = { | |||
clientObj: clientObj, | |||
sheetName: cellInfo.sheetName, | |||
cell: cellInfo.cell - 1, | |||
sheetName: cell.has('sheetName') ? cell.sheetName : cellInfo.sheetName, | |||
cell: cell.has('cell') ? cell.cell : cellInfo.cell - 1, | |||
x: cell.x / mapScale, | |||
y: (cell.y / mapScale) - 1, | |||
name: name, | |||