From ec1450cec1abcd4b570514e11fbd227e8bf4d4e5 Mon Sep 17 00:00:00 2001 From: P0nk Date: Wed, 29 Mar 2023 19:54:59 +0200 Subject: [PATCH] Rewrite Mo NPC script to be GMS-like --- scripts/npc/9201099.js | 88 +++++++++++++++++-- .../scripting/AbstractPlayerInteraction.java | 9 +- .../scripting/npc/NPCConversationManager.java | 13 +++ 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/scripts/npc/9201099.js b/scripts/npc/9201099.js index c22922ed9f..8973e0b2b8 100644 --- a/scripts/npc/9201099.js +++ b/scripts/npc/9201099.js @@ -1,14 +1,88 @@ /** - *9201098 - Mo - *@author Ronan + * 9201098 - Mo + * @author Ronan + * @author Ponk */ +let status = 0; +let selectedItem = undefined; + +/* +References: +- https://www.youtube.com/watch?v=g6y2zmCGglI +- https://www.youtube.com/watch?v=CttmlVWLJKM +*/ function start() { - if (cm.getQuestStatus(8224) == 2) { - cm.openShopNPC(9201099); - } else { - cm.sendOk("Hm, at who do you think you are looking at?"); + if (cm.getQuestStatus(8224) !== 2) { + cm.sendDefault(); + cm.dispose(); + return; } - cm.dispose(); + cm.sendSimple("Name's Mo. I've got Mo' items for Mo' mesos. What business do you bring me?\r\n#L0##bI'd like to buy some items#k"); +} + +function action(action, type, selection) { + if (!action) { + cm.dispose(); + return; + } + + if (status === 0) { + let index = 0; + const selections = "#e" + shopItems() + .map(i => { + const mesoText = i.quantity === 1 ? "meso" : `meso per ${i.quantity} arrows`; + return `\r\n#L${index++}##i${i.itemId}# #z${i.itemId}# #b${i.cost} ${mesoText}#k`; + }) + .join(""); + cm.sendSimple("An ally of the Raven Ninja Clan is welcome to buy from me!" + selections); + status++; + } else if (status === 1 && selection !== -1) { + selectedItem = shopItems()[selection]; + cm.sendAcceptDecline("Are you sure you want to buy it?"); + status++; + } else if (status === 2) { + if (!selectedItem) { + cm.dispose(); + return; + } + if (!cm.hasMeso(selectedItem.cost)) { + cm.sendOk("You don't have enough mesos."); + cm.dispose(); + return; + } + if (!cm.canHold(selectedItem.itemId, selectedItem.quantity)) { + cm.sendOk("There's no room in your inventory."); + cm.dispose(); + return; + } + + cm.loseMeso(selectedItem.cost); + cm.gainItem(selectedItem.itemId, selectedItem.quantity); + cm.dispose(); + } +} + +function shopItems() { + return [ + {itemId: 2050004, quantity: 1, cost: 400}, // All-Cure Potion + {itemId: 2050000, quantity: 1, cost: 200}, // Antidote + {itemId: 2020012, quantity: 1, cost: 4500}, // Melting Cheese + {itemId: 2020013, quantity: 1, cost: 5000}, // Reindeer Milk + {itemId: 2020014, quantity: 1, cost: 8100}, // Sunrise Dew + {itemId: 2020015, quantity: 1, cost: 9690}, // Sunset Dew + {itemId: 2050001, quantity: 1, cost: 200}, // Eyedrop + {itemId: 2050002, quantity: 1, cost: 300}, // Tonic + {itemId: 2050003, quantity: 1, cost: 500}, // Holy Water + {itemId: 2022000, quantity: 1, cost: 1650}, // Pure Water + {itemId: 2002017, quantity: 1, cost: 5000}, // Warrior Elixir + {itemId: 2060004, quantity: 2000, cost: 40_000}, // Diamond Arrow for Bow + {itemId: 2061004, quantity: 2000, cost: 40_000}, // Diamond Arrow for Crossbow + {itemId: 2070010, quantity: 1, cost: 2000}, // Icicle + {itemId: 2022003, quantity: 1, cost: 1100}, // Unagi + {itemId: 2000006, quantity: 1, cost: 620}, // Mana Elixir + {itemId: 2022002, quantity: 1, cost: 1000}, // Cider + {itemId: 2030020, quantity: 1, cost: 400}, // Return to New Leaf City Scroll + ] } diff --git a/src/main/java/scripting/AbstractPlayerInteraction.java b/src/main/java/scripting/AbstractPlayerInteraction.java index 3f8cd0626b..15dc90ce70 100644 --- a/src/main/java/scripting/AbstractPlayerInteraction.java +++ b/src/main/java/scripting/AbstractPlayerInteraction.java @@ -36,6 +36,8 @@ import net.server.Server; import net.server.guild.Guild; import net.server.world.Party; import net.server.world.PartyCharacter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import scripting.event.EventInstanceManager; import scripting.event.EventManager; import scripting.npc.NPCScriptManager; @@ -61,6 +63,7 @@ import java.util.*; import static java.util.concurrent.TimeUnit.DAYS; public class AbstractPlayerInteraction { + private static final Logger log = LoggerFactory.getLogger(AbstractPlayerInteraction.class); public Client c; @@ -68,6 +71,10 @@ public class AbstractPlayerInteraction { this.c = c; } + public void log(String message) { + log.info(message); + } + public Client getClient() { return c; } @@ -1207,4 +1214,4 @@ public class AbstractPlayerInteraction { private void sendBlueNotice(MapleMap map, String message) { map.dropMessage(6, message); } -} \ No newline at end of file +} diff --git a/src/main/java/scripting/npc/NPCConversationManager.java b/src/main/java/scripting/npc/NPCConversationManager.java index 328d0f4640..23d80acfe1 100644 --- a/src/main/java/scripting/npc/NPCConversationManager.java +++ b/src/main/java/scripting/npc/NPCConversationManager.java @@ -272,10 +272,23 @@ public class NPCConversationManager extends AbstractPlayerInteraction { return getPlayer().getMeso(); } + // TODO: refactor scripts to use this instead of "getMeso() < amount" + public boolean hasMeso(int amount) { + return getMeso() >= amount; + } + public void gainMeso(int gain) { getPlayer().gainMeso(gain); } + // TODO: refactor scripts to use this instead of "gainMeso(-amount)" + public void loseMeso(int loss) { + if (loss < 0) { + throw new IllegalArgumentException("Can only lose positive amount of mesos"); + } + gainMeso(-loss); + } + public void gainExp(int gain) { getPlayer().gainExp(gain, true, true); }