From 05acba14a0ed7f8973885e55bdaa11a00fadb368 Mon Sep 17 00:00:00 2001 From: Shaun Date: Mon, 6 Apr 2020 17:00:32 +0200 Subject: [PATCH] closes #1446 --- src/server/config/maps/fjolarok/dialogues.js | 60 +------ src/server/config/maps/sewer/map.json | 36 +++- src/server/mods/feature-cards/cards.js | 165 +----------------- src/server/mods/feature-cards/config.js | 17 ++ src/server/mods/feature-cards/images/mobs.png | Bin 0 -> 132 bytes .../mods/feature-cards/images/mobs.pyxel | Bin 0 -> 1778 bytes src/server/mods/feature-cards/index.js | 69 +++++--- .../recipes/craftActions/armor.js | 17 ++ .../recipes/craftActions/idol.js | 18 ++ .../recipes/craftActions/rune.js | 14 ++ .../recipes/craftActions/weapon.js | 17 ++ .../mods/feature-cards/recipes/recipes.js | 132 ++++++++++++++ 12 files changed, 294 insertions(+), 251 deletions(-) create mode 100644 src/server/mods/feature-cards/config.js create mode 100644 src/server/mods/feature-cards/images/mobs.png create mode 100644 src/server/mods/feature-cards/images/mobs.pyxel create mode 100644 src/server/mods/feature-cards/recipes/craftActions/armor.js create mode 100644 src/server/mods/feature-cards/recipes/craftActions/idol.js create mode 100644 src/server/mods/feature-cards/recipes/craftActions/rune.js create mode 100644 src/server/mods/feature-cards/recipes/craftActions/weapon.js create mode 100644 src/server/mods/feature-cards/recipes/recipes.js diff --git a/src/server/config/maps/fjolarok/dialogues.js b/src/server/config/maps/fjolarok/dialogues.js index 4a717550..f553ef56 100644 --- a/src/server/config/maps/fjolarok/dialogues.js +++ b/src/server/config/maps/fjolarok/dialogues.js @@ -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' }] } }, diff --git a/src/server/config/maps/sewer/map.json b/src/server/config/maps/sewer/map.json index 80210948..01e50b21 100644 --- a/src/server/config/maps/sewer/map.json +++ b/src/server/config/maps/sewer/map.json @@ -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":[ { diff --git a/src/server/mods/feature-cards/cards.js b/src/server/mods/feature-cards/cards.js index e60df13e..12b83269 100644 --- a/src/server/mods/feature-cards/cards.js +++ b/src/server/mods/feature-cards/cards.js @@ -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] - } - } - }); - } } }; diff --git a/src/server/mods/feature-cards/config.js b/src/server/mods/feature-cards/config.js new file mode 100644 index 00000000..4f6d35ff --- /dev/null +++ b/src/server/mods/feature-cards/config.js @@ -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' } + } + } + } +}; diff --git a/src/server/mods/feature-cards/images/mobs.png b/src/server/mods/feature-cards/images/mobs.png new file mode 100644 index 0000000000000000000000000000000000000000..1837f8bf8b5db98831d296c225fda563168e376c GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-k!3HE}wEkTWq`W;{978H@B_~L*dOQeO`S1Vn z%{&h(4#*@VzyDnC;I!b(EvcNJ4Hgd$JpBBB;^GIFudn}7-V*HbzW(>q@`Du)P4X?~ hZjueoO>y6t7+P{n@2I+UZUP$1;OXk;vd$@?2>>gAH4*>- literal 0 HcmV?d00001 diff --git a/src/server/mods/feature-cards/images/mobs.pyxel b/src/server/mods/feature-cards/images/mobs.pyxel new file mode 100644 index 0000000000000000000000000000000000000000..e2c24886298ac13b3f0e34f3d6decf65bbcfbb0d GIT binary patch literal 1778 zcmWIWW@Zs#VBp|jSen-sAhh=aZw@m9!$)og1|9|mhLrqdm&B4py{zK=yt&hE=glz? zaJc_nTWQ{9E}LzQ`ki9eUe-E**V{G zYL8{yJNtIU)zcpi?hEqTUSDBQQo4QJ4cpr~9sgEm1+|@%K!_o!zNl7fhYKec9feq#gH`6d#D{ zUtITd@q^cV;%;U8?ryxjxFDtYe)FXo3*pzIGx@J19A(@QV;F6qrt|Q%CCi2fDk%pN zkKQ>tO;deiYwuic#*NVWtZAwFycs+J53O2|5v;C2P{;I?sMN zQFTnH=mclFUg_M+GRoOeN@6hrd7+^a>T`~5U#B^%miy4s)e)MRN0qWq`&L9fIPuC! zN!7Oh#IH?vM0_U~7wyX^>f+qKPf4qLipb2!_;cMhs&Qw2InC5q$+3N(&BawJrD=!G z9*?;A^P0FpU(v4hpHrLEOZI(rJ@!>?-`8HjfQh>rzlt(USk@99@6qU4)c4@r_6eI* zzB0aEZNjedmF4y9;s=H&qpnj=h(M!^G}zPtFCzT@a6oS9JV%} z3Z6ZD@K7%P;YU$8F;y=9EGVUp6NYuQgwPTv&lKz zwbson^M|;- zyNqQWvtz!R%v0iDzS)Rr{`~2u&3{(+zb*LDvh4AU*4ic|6KBlX_ABYqp7*PF zhHgAMt1tWe7wG_$Tsg^9Jhugy8$p;0h;tGvQ;Q7r3i8rl^L!|N{&do#q=bYAU%wP^ zGF{?wICJnIn@akYf3f^a_SnYCIBVsps(Wmxvf+sQ`TqaMvo`!%d?!>?_WzH0|6t35 zGrBA1%;y#3=d=0qr~c6+_UY@_{|~w+^ycHff8Q^EY8K`5{iORWZxZi0-@^MdB%+FZ z-mlnIn#Uw{`oYUr&o`aZT*%3Q>Q*tY561(5ZVX0tt056?U19@qt8~kZKilRTD1YR7 zoMhK|iJ9*j4^NHvZPssbb~cPFx(;5xdOme-u#+&Fz21K&T(1S%SqH?NKwOfUlZqpV zWE9Q-L#Y45``2ti>*ne8DT;2NBrKK@*|P4}|No2mHXq$MmA&t7b)LLhP1f04&6AZ} zQgyQa-OLx7yMO(=j1$5Wz4yPr{n9$052l^ngTYi(`dogWAT*29jb0LJ39&h9f{p1_l7qRQZ_z literal 0 HcmV?d00001 diff --git a/src/server/mods/feature-cards/index.js b/src/server/mods/feature-cards/index.js index 0ccfb679..60b1dc11 100644 --- a/src/server/mods/feature-cards/index.js +++ b/src/server/mods/feature-cards/index.js @@ -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)); } }; diff --git a/src/server/mods/feature-cards/recipes/craftActions/armor.js b/src/server/mods/feature-cards/recipes/craftActions/armor.js new file mode 100644 index 00000000..70af0cd6 --- /dev/null +++ b/src/server/mods/feature-cards/recipes/craftActions/armor.js @@ -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 }; +}; diff --git a/src/server/mods/feature-cards/recipes/craftActions/idol.js b/src/server/mods/feature-cards/recipes/craftActions/idol.js new file mode 100644 index 00000000..9916b588 --- /dev/null +++ b/src/server/mods/feature-cards/recipes/craftActions/idol.js @@ -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 }; +}; diff --git a/src/server/mods/feature-cards/recipes/craftActions/rune.js b/src/server/mods/feature-cards/recipes/craftActions/rune.js new file mode 100644 index 00000000..541a2a9a --- /dev/null +++ b/src/server/mods/feature-cards/recipes/craftActions/rune.js @@ -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 }; +}; diff --git a/src/server/mods/feature-cards/recipes/craftActions/weapon.js b/src/server/mods/feature-cards/recipes/craftActions/weapon.js new file mode 100644 index 00000000..df449796 --- /dev/null +++ b/src/server/mods/feature-cards/recipes/craftActions/weapon.js @@ -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 }; +}; diff --git a/src/server/mods/feature-cards/recipes/recipes.js b/src/server/mods/feature-cards/recipes/recipes.js new file mode 100644 index 00000000..844f086a --- /dev/null +++ b/src/server/mods/feature-cards/recipes/recipes.js @@ -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] + } + } + }) +}];