From 8cbe357c6dc7f7374caab0c9c5186844a5c78598 Mon Sep 17 00:00:00 2001 From: James Monger Date: Sun, 12 Feb 2023 03:26:34 +0000 Subject: [PATCH 1/6] smelting conversion --- src/plugins/skills/smithing/forging-task.ts | 63 +++++++++ src/plugins/skills/smithing/forging.plugin.ts | 90 +++--------- src/plugins/skills/smithing/smelting-task.ts | 76 ++++++++++ .../skills/smithing/smelting.plugin.ts | 130 +++++------------- 4 files changed, 191 insertions(+), 168 deletions(-) create mode 100644 src/plugins/skills/smithing/forging-task.ts create mode 100644 src/plugins/skills/smithing/smelting-task.ts diff --git a/src/plugins/skills/smithing/forging-task.ts b/src/plugins/skills/smithing/forging-task.ts new file mode 100644 index 000000000..4c35ad6f2 --- /dev/null +++ b/src/plugins/skills/smithing/forging-task.ts @@ -0,0 +1,63 @@ +import { ActorTask } from "@engine/task/impl"; +import { widgets } from '@engine/config/config-handler'; +import { Player, Skill } from "@engine/world/actor"; +import { Smithable } from "./forging-types"; + +/** + * A task that handles the forging of an item. + * + * Operates repeatedly every 4 ticks, and stops when the player has forged the amount they wanted. + */ +export class ForgingTask extends ActorTask { + private elapsedTicks = 0; + private amountForged = 0; + + constructor(player: Player, private readonly smithable: Smithable, private readonly amount: number) { + super(player); + } + + public execute(): void { + const taskIteration = this.elapsedTicks++; + + // completed the task if we've forged the amount we wanted + if (this.amountForged >= this.amount) { + this.stop(); + return; + } + + // TODO (Jameskmonger) remove magic number + this.actor.playAnimation(898); + + // only do something every 4 ticks + if (taskIteration % 4 !== 0) { + return; + } + + // can't continue + if (!this.hasMaterials()) { + this.stop(); + // TODO (Jameskmonger) send message + return; + } + + // Remove ingredients + for (let i = 0; i < this.smithable.ingredient.amount; i++) { + this.actor.inventory.removeFirst(this.smithable.ingredient.itemId); + } + + // Add item to inventory + this.actor.inventory.add({ + itemId: this.smithable.item.itemId, + amount: this.smithable.item.amount + }); + + this.actor.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.actor.inventory); + this.actor.skills.addExp(Skill.SMITHING, this.smithable.experience); + + this.amountForged++; + } + + private hasMaterials() { + return this.smithable.ingredient.amount <= this.actor.inventory.findAll(this.smithable.ingredient.itemId).length + } +} diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index 527f4e977..ec362e82b 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -1,5 +1,5 @@ import { - itemOnObjectActionHandler, ItemOnObjectActionHook, ItemInteractionAction, ItemInteractionActionHook, TaskExecutor + itemOnObjectActionHandler, ItemOnObjectActionHook, ItemInteractionActionHook } from '@engine/action'; import { widgets } from '@engine/config/config-handler'; import { Skill } from '@engine/world/actor/skills'; @@ -9,16 +9,7 @@ import { Smithable } from '@plugins/skills/smithing/forging-types'; import { Player } from '@engine/world/actor/player/player'; import { findItem } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; - -/** - * The amount of items the player wants to forge. - */ -let wantedAmount = 0; - -/** - * The amount of items already forged. - */ -let forgedAmount = 0; +import { ForgingTask } from './forging-task'; const mapWidgetItemsToFlatArray = (input) => { const result = []; @@ -44,7 +35,7 @@ const mapToFlatArray = (input) => { * Lookup a smithable from just an item id. * @param itemId */ -const findSmithableByItemId = (itemId) : Smithable => { +const findSmithableByItemId = (itemId): Smithable => { return mapToFlatArray(smithables).find((smithable) => { return smithable.item.itemId === itemId; }); @@ -54,11 +45,7 @@ const findSmithableByItemId = (itemId) : Smithable => { * Check if the player is able to perform the action. * @param task */ -const canActivate = (task: TaskExecutor): boolean => { - const { actor, player, actionData } = task.getDetails(); - const itemId = actionData.itemId; - const smithable = findSmithableByItemId(itemId); - +const canForge = (player: Player, smithable: Smithable): boolean => { // In case the smithable doesn't exist. if (!smithable) { return false; @@ -83,56 +70,6 @@ const canActivate = (task: TaskExecutor): boolean => { return true; }; -/** - * The actual forging loop. - * @param task - * @param taskIteration - */ -const activate = (task: TaskExecutor, taskIteration: number): boolean => { - const { player, actionData } = task.getDetails(); - const itemId = actionData.itemId; - const smithable = findSmithableByItemId(itemId); - - // How many? Quick and dirty. - switch (actionData.option) { - case 'make' : wantedAmount = 1; break; - case 'make-5' : wantedAmount = 5; break; - case 'make-10' : wantedAmount = 10; break; - } - - for(let m=0; m { + const smithable = findSmithableByItemId(itemId); + let wantedAmount = 0; + + switch (option) { + case 'make': wantedAmount = 1; break; + case 'make-5': wantedAmount = 5; break; + case 'make-10': wantedAmount = 10; break; + } + + if (!canForge(player, smithable)) { + return; + } + + player.enqueueTask(ForgingTask, [smithable, wantedAmount]); } } as ItemInteractionActionHook ] diff --git a/src/plugins/skills/smithing/smelting-task.ts b/src/plugins/skills/smithing/smelting-task.ts new file mode 100644 index 000000000..7fc1c0ad9 --- /dev/null +++ b/src/plugins/skills/smithing/smelting-task.ts @@ -0,0 +1,76 @@ +import { ActorTask } from "@engine/task/impl"; +import { findItem } from '@engine/config/config-handler'; +import { Player, Skill } from "@engine/world/actor"; +import { Smeltable } from "./smelting-types"; +import { animationIds, soundIds } from "@engine/world/config"; + +/** + * A task that handles the smelting of an item. + * + * Operates repeatedly every 3 ticks, and stops when the player has smelted the amount they wanted. + */ +export class SmeltingTask extends ActorTask { + private elapsedTicks = 0; + private amountSmelted = 0 + + constructor(player: Player, private readonly smeltable: Smeltable, private readonly amount: number) { + super(player); + } + + public execute(): void { + const taskIteration = this.elapsedTicks++; + + // completed the task if we've smelted the amount we wanted + if (this.amountSmelted >= this.amount) { + this.stop(); + return; + } + + const bar = this.smeltable.bar; + + if (!this.hasMaterials()) { + this.actor.sendMessage(`You don't have enough ${findItem(bar.barId).name.toLowerCase()}.`, true); + this.stop(); + return; + } + + if (!this.hasLevel()) { + this.actor.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${findItem(bar.barId).name.toLowerCase()}s.`, true); + return; + } + + // Smelting takes 3 ticks for each item + if (taskIteration % 3 !== 0) { + return; + } + + bar.ingredients.forEach((item) => { + for (let i = 0; i < item.amount; i++) { + this.actor.removeFirstItem(item.itemId); + } + }); + + this.actor.giveItem(bar.barId); + this.actor.skills.addExp(Skill.SMITHING, bar.experience); + this.amountSmelted++; + + this.actor.playAnimation(animationIds.smelting); + this.actor.outgoingPackets.playSound(soundIds.smelting, 5); + + } + + private hasMaterials() { + return this.smeltable.bar.ingredients.every((item) => { + const itemIndex = this.actor.inventory.findIndex(item); + if (itemIndex === -1 || this.actor.inventory.amountInStack(itemIndex) < item.amount) { + return false; + } + + return true; + }); + } + + private hasLevel() { + return this.actor.skills.hasLevel(Skill.SMITHING, this.smeltable.bar.requiredLevel); + } +} diff --git a/src/plugins/skills/smithing/smelting.plugin.ts b/src/plugins/skills/smithing/smelting.plugin.ts index c4ab4b118..841ecbbb3 100644 --- a/src/plugins/skills/smithing/smelting.plugin.ts +++ b/src/plugins/skills/smithing/smelting.plugin.ts @@ -1,17 +1,12 @@ -import { Item } from '@engine/world/items/item'; -import { ItemContainer } from '@engine/world/items/item-container'; import { objectIds } from '@engine/world/config/object-ids'; -import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action'; -import { buttonActionHandler, ButtonAction } from '@engine/action'; +import { objectInteractionActionHandler, ObjectInteractionAction, ButtonActionHook, ObjectInteractionActionHook } from '@engine/action'; +import { buttonActionHandler } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; import { colors } from '@engine/util/colors'; -import { findItem, widgets } from '@engine/config/config-handler'; +import { widgets } from '@engine/config/config-handler'; import { PlayerQuest } from '@engine/config/quest-config'; import { widgetButtonIds, widgetItems } from '@plugins/skills/smithing/smelting-constants'; -import { Bar } from '@plugins/skills/smithing/smelting-types'; -import { loopingEvent } from '@engine/plugins'; +import { SmeltingTask } from './smelting-task'; export const openSmeltingInterface: objectInteractionActionHandler = (details) => { @@ -23,7 +18,7 @@ export const openSmeltingInterface: objectInteractionActionHandler = (details) = // We need to tell the widget what the bars actually look like. const loadSmeltingInterface = (details: ObjectInteractionAction) => { - const theKnightsSwordQuest : PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); + const theKnightsSwordQuest: PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); // Send the items to the widget. widgetItems.forEach((item) => { details.player.outgoingPackets.setItemOnWidget(widgets.furnace.widgetId, item.slot.modelId, item.bar.barId, 125); @@ -39,101 +34,42 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { }); }; -/** - * Check whether the player has the needed ingredients. - */ -const hasIngredients = (details: ButtonAction, ingredients: Item[], inventory: ItemContainer, loop) => { - ingredients.forEach((item: Item) => { - const itemIndex = inventory.findIndex(item); - if (itemIndex === -1 || inventory.amountInStack(itemIndex) < item.amount) { - details.player.sendMessage(`You don't have enough ${findItem(item.itemId).name.toLowerCase()}.`, true); - loop.cancel(); - return; - } - }); -}; - -const canSmelt = (details: ButtonAction, bar: Bar): boolean => { - return details.player.skills.hasLevel(Skill.SMITHING, bar.requiredLevel); -}; - -const smeltProduct = (details: ButtonAction, bar: Bar, count: number) => { - - const theKnightsSwordQuest : PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); - if (bar.quest !== undefined && (theKnightsSwordQuest == undefined || theKnightsSwordQuest.complete)) { - details.player.sendMessage(`You need to complete The Knight's Sword quest first.`, true); - return; - } - - // Check if the player has the required smithing level. - if (!canSmelt(details, bar)) { - details.player.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${findItem(bar.barId).name.toLowerCase()}s.`, true); +export const buttonClicked: buttonActionHandler = (details) => { + // Check if player might be spawning widget clientside + // TODO - this should be handled by the engine + if (!details.player.interfaceState.findWidget(widgets.furnace.widgetId)) { return; } - let elapsedTicks = 0; - let smelted = 0; - const loop = loopingEvent({ player: details.player }); - - // Check if the player is missing some or all ingredients. - hasIngredients(details, bar.ingredients, details.player.inventory, loop); - - // Start the loop for smelting ores into bars. - loop.event.subscribe(() => { - if (smelted === count) { - loop.cancel(); - return; - } - - // Check if the player still has the ingredients needed. - hasIngredients(details, bar.ingredients, details.player.inventory, loop); - - // Smelting takes 3 ticks for each item - if (elapsedTicks % 3 === 0) { - bar.ingredients.forEach((item) => { - for (let i = 0; i < item.amount; i++) { - details.player.removeFirstItem(item.itemId); - } - }); - details.player.giveItem(bar.barId); - details.player.skills.addExp(Skill.SMITHING, bar.experience); - smelted++; - - details.player.playAnimation(animationIds.smelting); - details.player.outgoingPackets.playSound(soundIds.smelting, 5); - } + const smeltable = widgetButtonIds.get(details.buttonId); - elapsedTicks++; - }); -}; + // TODO (Jameskmonger) check for quest-specific items, e.g. the knights sword + // const theKnightsSwordQuest: PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); + // if (bar.quest !== undefined && (theKnightsSwordQuest == undefined || theKnightsSwordQuest.complete)) { + // details.player.sendMessage(`You need to complete The Knight's Sword quest first.`, true); + // return; + // } -export const buttonClicked : buttonActionHandler = (details) => { + details.player.interfaceState.closeAllSlots(); - // Check if player might be spawning widget clientside - if (!details.player.interfaceState.findWidget(widgets.furnace.widgetId)) { + if (!smeltable.takesInput) { + details.player.enqueueTask(SmeltingTask, [smeltable, smeltable.count]); return; } - const product = widgetButtonIds.get(details.buttonId); - - details.player.interfaceState.closeAllSlots(); + const numericInputSpinSubscription = details.player.numericInputEvent.subscribe((number) => { + actionCancelledSpinSubscription?.unsubscribe(); + numericInputSpinSubscription?.unsubscribe(); - if (!product.takesInput) { - smeltProduct(details, product.bar, product.count); - } else { - const numericInputSpinSubscription = details.player.numericInputEvent.subscribe((number) => { - actionCancelledSpinSubscription?.unsubscribe(); - numericInputSpinSubscription?.unsubscribe(); - smeltProduct(details, product.bar, number); - }); + details.player.enqueueTask(SmeltingTask, [smeltable, number]); + }); - const actionCancelledSpinSubscription = details.player.actionsCancelled.subscribe(() => { - actionCancelledSpinSubscription?.unsubscribe(); - numericInputSpinSubscription?.unsubscribe(); - }); + const actionCancelledSpinSubscription = details.player.actionsCancelled.subscribe(() => { + actionCancelledSpinSubscription?.unsubscribe(); + numericInputSpinSubscription?.unsubscribe(); + }); - details.player.outgoingPackets.showNumberInputDialogue(); - } + details.player.outgoingPackets.showNumberInputDialogue(); }; export default { @@ -141,16 +77,16 @@ export default { hooks: [ { type: 'object_interaction', - objectIds: [ objectIds.furnace, 11666 ], - options: [ 'smelt' ], + objectIds: [objectIds.furnace, 11666], + options: ['smelt'], walkTo: true, handler: openSmeltingInterface - }, + } as ObjectInteractionActionHook, { type: 'button', widgetId: widgets.furnace.widgetId, buttonIds: Array.from(widgetButtonIds.keys()), handler: buttonClicked - } + } as ButtonActionHook ] }; From 0ea272129b9a46489dc4db011f7e5e51ba2817e8 Mon Sep 17 00:00:00 2001 From: James Monger Date: Sun, 12 Feb 2023 18:33:07 +0000 Subject: [PATCH 2/6] refactor: lint fixes --- src/plugins/skills/smithing/forging-task.ts | 6 +++--- src/plugins/skills/smithing/smelting-task.ts | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/skills/smithing/forging-task.ts b/src/plugins/skills/smithing/forging-task.ts index 4c35ad6f2..a8f5cc7c6 100644 --- a/src/plugins/skills/smithing/forging-task.ts +++ b/src/plugins/skills/smithing/forging-task.ts @@ -1,7 +1,7 @@ -import { ActorTask } from "@engine/task/impl"; +import { ActorTask } from '@engine/task/impl'; import { widgets } from '@engine/config/config-handler'; -import { Player, Skill } from "@engine/world/actor"; -import { Smithable } from "./forging-types"; +import { Player, Skill } from '@engine/world/actor'; +import { Smithable } from './forging-types'; /** * A task that handles the forging of an item. diff --git a/src/plugins/skills/smithing/smelting-task.ts b/src/plugins/skills/smithing/smelting-task.ts index 7fc1c0ad9..e0637bb01 100644 --- a/src/plugins/skills/smithing/smelting-task.ts +++ b/src/plugins/skills/smithing/smelting-task.ts @@ -1,8 +1,8 @@ -import { ActorTask } from "@engine/task/impl"; +import { ActorTask } from '@engine/task/impl'; import { findItem } from '@engine/config/config-handler'; -import { Player, Skill } from "@engine/world/actor"; -import { Smeltable } from "./smelting-types"; -import { animationIds, soundIds } from "@engine/world/config"; +import { Player, Skill } from '@engine/world/actor'; +import { Smeltable } from './smelting-types'; +import { animationIds, soundIds } from '@engine/world/config'; /** * A task that handles the smelting of an item. From 7e3e9c330054aa8fc1e408da94a976a19b046c98 Mon Sep 17 00:00:00 2001 From: James Monger Date: Sun, 12 Feb 2023 18:34:53 +0000 Subject: [PATCH 3/6] refactor: null checks --- src/plugins/skills/smithing/forging.plugin.ts | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index ec362e82b..f5de1c79f 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -10,6 +10,7 @@ import { Player } from '@engine/world/actor/player/player'; import { findItem } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; import { ForgingTask } from './forging-task'; +import { logger } from '@runejs/common'; const mapWidgetItemsToFlatArray = (input) => { const result = []; @@ -54,14 +55,26 @@ const canForge = (player: Player, smithable: Smithable): boolean => { // Check if the player has the level required. if (smithable.level > player.skills.getLevel(Skill.SMITHING)) { const item = findItem(smithable.item.itemId); + + if (!item) { + logger.error(`Could not find smithable item with id ${smithable.item.itemId}`); + return false; + } + player.sendMessage(`You have to be at least level ${smithable.level} to smith ${item.name}s.`, true); return false; } // Check if the player has sufficient materials. if (!hasMaterials(player, smithable)) { - const bar = findItem(smithable.ingredient.itemId); - player.sendMessage(`You don't have enough ${bar.name}s.`, true); + const ingredient = findItem(smithable.ingredient.itemId); + + if (!ingredient) { + logger.error(`Could not find smithable ingredient with id ${smithable.ingredient.itemId}`); + return false; + } + + player.sendMessage(`You don't have enough ${ingredient.name}s.`, true); return false; } @@ -97,6 +110,12 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => { const barLevel = bars.get(item.itemId); const bar = findItem(item.itemId); + + if (barLevel === undefined || !bar) { + logger.error(`Could not find bar with id ${item.itemId}`); + return; + } + if (barLevel > player.skills.getLevel(Skill.SMITHING)) { player.sendMessage(`You have to be at least level ${barLevel} to smith ${bar.name}s.`, true); return; From d756cf44f111ac473248c612b72fa91f08c59f02 Mon Sep 17 00:00:00 2001 From: James Monger Date: Sun, 12 Feb 2023 22:04:03 +0000 Subject: [PATCH 4/6] docs --- src/plugins/skills/smithing/forging-task.ts | 6 ++++++ src/plugins/skills/smithing/forging.plugin.ts | 3 +-- src/plugins/skills/smithing/smelting-task.ts | 11 ++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/plugins/skills/smithing/forging-task.ts b/src/plugins/skills/smithing/forging-task.ts index a8f5cc7c6..16046a1c8 100644 --- a/src/plugins/skills/smithing/forging-task.ts +++ b/src/plugins/skills/smithing/forging-task.ts @@ -7,6 +7,8 @@ import { Smithable } from './forging-types'; * A task that handles the forging of an item. * * Operates repeatedly every 4 ticks, and stops when the player has forged the amount they wanted. + * + * @author jameskmonger */ export class ForgingTask extends ActorTask { private elapsedTicks = 0; @@ -57,6 +59,10 @@ export class ForgingTask extends ActorTask { this.amountForged++; } + /** + * Whether the player has the required materials to forge the item. + * @returns {boolean} True if the player has the required materials, false otherwise. + */ private hasMaterials() { return this.smithable.ingredient.amount <= this.actor.inventory.findAll(this.smithable.ingredient.itemId).length } diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index f5de1c79f..986cd0c5a 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -43,8 +43,7 @@ const findSmithableByItemId = (itemId): Smithable => { }; /** - * Check if the player is able to perform the action. - * @param task + * Check if the player is able to forge an item. */ const canForge = (player: Player, smithable: Smithable): boolean => { // In case the smithable doesn't exist. diff --git a/src/plugins/skills/smithing/smelting-task.ts b/src/plugins/skills/smithing/smelting-task.ts index e0637bb01..7e035b940 100644 --- a/src/plugins/skills/smithing/smelting-task.ts +++ b/src/plugins/skills/smithing/smelting-task.ts @@ -8,6 +8,8 @@ import { animationIds, soundIds } from '@engine/world/config'; * A task that handles the smelting of an item. * * Operates repeatedly every 3 ticks, and stops when the player has smelted the amount they wanted. + * + * @author jameskmonger */ export class SmeltingTask extends ActorTask { private elapsedTicks = 0; @@ -56,9 +58,12 @@ export class SmeltingTask extends ActorTask { this.actor.playAnimation(animationIds.smelting); this.actor.outgoingPackets.playSound(soundIds.smelting, 5); - } + /** + * Whether the player has the required materials to smelt the item. + * @returns {boolean} True if the player has the required materials, false otherwise. + */ private hasMaterials() { return this.smeltable.bar.ingredients.every((item) => { const itemIndex = this.actor.inventory.findIndex(item); @@ -70,6 +75,10 @@ export class SmeltingTask extends ActorTask { }); } + /** + * Whether the player has the required level to smelt the item. + * @returns {boolean} True if the player has the required level, false otherwise. + */ private hasLevel() { return this.actor.skills.hasLevel(Skill.SMITHING, this.smeltable.bar.requiredLevel); } From 49239beba1add40d3761c4b30606615ea06a5bbf Mon Sep 17 00:00:00 2001 From: James Monger Date: Thu, 9 Mar 2023 13:09:53 +0000 Subject: [PATCH 5/6] Update forging.plugin.ts --- src/plugins/skills/smithing/forging.plugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index 92390bf5d..8326508ad 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -55,7 +55,6 @@ const mapSmithablesToFlatArray = (input: Map>) => * Lookup a smithable from just an item id. * @param itemId */ -const findSmithableByItemId = (itemId): Smithable => { const findSmithableByItemId = (itemId: number) : Smithable | null => { return mapSmithablesToFlatArray(smithables).find((smithable) => { return smithable.item.itemId === itemId; From 8ca145dd55b7acd987e60a6b93b330be75de2601 Mon Sep 17 00:00:00 2001 From: James Monger Date: Tue, 11 Jul 2023 23:53:56 +0100 Subject: [PATCH 6/6] fix typecheck --- src/plugins/skills/smithing/forging.plugin.ts | 7 +++++++ src/plugins/skills/smithing/smelting-task.ts | 11 +++++++++-- src/plugins/skills/smithing/smelting.plugin.ts | 9 +++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index 8326508ad..5ad019e0e 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -187,6 +187,13 @@ export default { cancelOtherActions: true, handler: ({ player, itemId, option }) => { const smithable = findSmithableByItemId(itemId); + + if (!smithable) { + logger.error(`Could not find smithable with item id ${itemId}`); + player.sendMessage('Could not find smithable, please tell a dev.'); + return; + } + let wantedAmount = 0; switch (option) { diff --git a/src/plugins/skills/smithing/smelting-task.ts b/src/plugins/skills/smithing/smelting-task.ts index 7e035b940..d05abbc51 100644 --- a/src/plugins/skills/smithing/smelting-task.ts +++ b/src/plugins/skills/smithing/smelting-task.ts @@ -29,15 +29,22 @@ export class SmeltingTask extends ActorTask { } const bar = this.smeltable.bar; + const barItem = findItem(bar.barId); + + if (!barItem) { + this.actor.sendMessage(`Could not find item with id ${bar.barId}. Please tell a dev.`); + this.stop(); + return; + } if (!this.hasMaterials()) { - this.actor.sendMessage(`You don't have enough ${findItem(bar.barId).name.toLowerCase()}.`, true); + this.actor.sendMessage(`You don't have enough ${barItem.name.toLowerCase()}.`, true); this.stop(); return; } if (!this.hasLevel()) { - this.actor.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${findItem(bar.barId).name.toLowerCase()}s.`, true); + this.actor.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${barItem.name.toLowerCase()}s.`, true); return; } diff --git a/src/plugins/skills/smithing/smelting.plugin.ts b/src/plugins/skills/smithing/smelting.plugin.ts index 978a04158..a1e4ae30d 100644 --- a/src/plugins/skills/smithing/smelting.plugin.ts +++ b/src/plugins/skills/smithing/smelting.plugin.ts @@ -20,7 +20,7 @@ export const openSmeltingInterface: objectInteractionActionHandler = (details) = // We need to tell the widget what the bars actually look like. const loadSmeltingInterface = (details: ObjectInteractionAction) => { - const theKnightsSwordQuest: PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); + const theKnightsSwordQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); // Send the items to the widget. widgetItems.forEach((item) => { @@ -34,7 +34,7 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { // TODO (Jameskmonger) I don't think that this logic is correct.. it targets all items, not just those related to the quest. // Check if the player has completed 'The Knight's Sword' quest, even if the level is okay. - if (item.bar.quest !== undefined && (theKnightsSwordQuest == undefined || theKnightsSwordQuest.complete)) { + if (Boolean(item.bar.quest) && (!theKnightsSwordQuest || theKnightsSwordQuest.complete)) { details.player.modifyWidget(widgets.furnace.widgetId, { childId: item.slot.titleId, textColor: colors.red }); } }); @@ -56,6 +56,11 @@ export const buttonClicked: buttonActionHandler = (details) => { // return; // } + if (!smeltable) { + details.player.sendMessage(`Could not find smeltable for button id ${details.buttonId}. Please tell a dev.`); + return; + } + details.player.interfaceState.closeAllSlots(); if (!smeltable.takesInput) {