From 18dadc54c8069499f34d67fd6bb2d293033a359d Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 8 Feb 2026 12:55:20 +0000 Subject: [PATCH] Refactored Spirit Graahk Added the effect of Spirit Graahk's scroll, Goad Added Spirit Graahk's dialogue Added Spirit Graahk's Baroo!-isms --- .../familiar/SpiritGraahkDialogue.java | 81 ------------ .../familiar/SpiritGraahkDialogue.kt | 115 ++++++++++++++++++ .../summoning/familiar/SpiritGraahkNPC.java | 52 -------- .../summoning/familiar/SpiritGraahkNPC.kt | 51 ++++++++ .../familiar/SpiritGraahkOptionPlugin.java | 29 ----- .../familiar/SpiritGraahkOptionPlugin.kt | 27 ++++ .../core/game/dialogue/FacialExpression.java | 8 +- 7 files changed, 200 insertions(+), 163 deletions(-) delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.java create mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.kt delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.java create mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.kt delete mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.java create mode 100644 Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.kt diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.java deleted file mode 100644 index 98721c62f..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.java +++ /dev/null @@ -1,81 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.game.dialogue.DialoguePlugin; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.TeleportManager.TeleportType; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.game.world.map.zone.impl.WildernessZone; - -/** - * Represents the spirit graahk's dialogue - * @author Splinter - * @version 1.0 - */ -@Initializable -public final class SpiritGraahkDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code GertrudesCatDialogue} {@code Object}. - */ - public SpiritGraahkDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code GertrudesCatDialogue} {@code Object}. - * @param player the player. - */ - public SpiritGraahkDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new SpiritGraahkDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - if (!(npc instanceof Familiar)) { - return false; - } - final Familiar fam = (Familiar) npc; - if (fam.getOwner() != player) { - player.getPacketDispatch().sendMessage("This is not your familiar."); - return true; - } else { - interpreter.sendOptions("Select an Option", "Chat", "Teleport"); - } - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (buttonId) { - case 1: - player.sendMessage("The Graahk does not feel like talking now."); - end(); - break; - case 2: - if (!WildernessZone.checkTeleport(player, 20)) { - player.sendMessage("You cannot teleport with the Graahk above level 20 wilderness."); - end(); - } else { - player.getTeleporter().send(new Location(2786, 3002), TeleportType.NORMAL); - end(); - } - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 7353, 7364 }; - } -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.kt b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.kt new file mode 100644 index 000000000..4a0c23c9e --- /dev/null +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkDialogue.kt @@ -0,0 +1,115 @@ +package content.global.skill.summoning.familiar + +import core.api.openDialogue +import core.game.dialogue.ChatAnim +import core.game.dialogue.DialogueLabeller +import core.game.dialogue.DialoguePlugin +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager.TeleportType +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import core.game.world.map.zone.impl.WildernessZone +import core.plugin.Initializable +import core.tools.RandomFunction +import org.rs09.consts.NPCs + +/** + * Represents the spirit graahk's dialogue + * @author Splinter & Bishop + * @version 2.0 + */ +@Initializable +class SpiritGraahkDialogue : DialoguePlugin { + constructor() + constructor(player: Player?) : super(player) + + override fun newInstance(player: Player?): DialoguePlugin { + return SpiritGraahkDialogue(player) + } + + override fun open(vararg args: Any?): Boolean { + npc = args[0] as NPC? + if (npc !is Familiar) { + return false + } + val fam = npc as Familiar + if (fam.getOwner() !== player) { + player.packetDispatch.sendMessage("This is not your familiar.") + return true + } else { + interpreter.sendOptions("Select an Option", "Chat", "Teleport") + } + return true + } + + override fun handle(interfaceId: Int, buttonId: Int): Boolean { + when (buttonId) { + 1 -> if (player.skills.getStaticLevel(Skills.SUMMONING) >= 67) { + openDialogue(player, SpiritGraahkDialogueFile(), npc) + } else { + player.sendMessage("The Graahk does not feel like talking now.") //This message is likely inauthentic, but I cannot source the correct one so I'm keeping the default here -Bishop + end() + } + + 2 -> if (!WildernessZone.checkTeleport(player, 20)) { + player.sendMessage("You cannot teleport with the Graahk above level 20 wilderness.") + end() + } else { + player.teleporter.send(Location(2786, 3002), TeleportType.NORMAL) + end() + } + } + return true + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.SPIRIT_GRAAHK_7363, NPCs.SPIRIT_GRAAHK_7364) + } +} + +class SpiritGraahkDialogueFile : DialogueLabeller() { + override fun addConversation() { + exec { player, npc -> + val spiritGraahkRandomConversation = RandomFunction.random(4) + when (spiritGraahkRandomConversation) { + 0 -> loadLabel(player, "spiky spikes") + 1 -> loadLabel(player, "pet the spikes") + 2 -> loadLabel(player, "therapeutic spikes") + 3 -> loadLabel(player, "inspect the spikes") + } + } + + label("spiky spikes") + player(ChatAnim.NEUTRAL, "Your spikes are looking particularly spiky today.") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Graaaaahk raaaawr?", "(Really, you think so?)") + player(ChatAnim.HAPPY, "Yes. Most pointy, indeed.") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Raaaawr...", "(That's really kind of you to say. I was going to spike", "you but I won't now...)") + player(ChatAnim.HAPPY, "Thanks?") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "...Grrrrr ark.", "(...I'll do it later instead.)") + player(ChatAnim.HAPPY, "*Sigh!*") + + label("pet the spikes") + npc(ChatAnim.GHRAAK_SHAKE_MILD, "Graahk grrrrowl?", "(My spikes hurt, could you pet them for me?)") + player(ChatAnim.HAPPY, "Aww, of course I can I'll just... Oww! I think you drew", "blood that time.") + + label("therapeutic spikes") + npc(ChatAnim.GHRAAK_SHAKE_MILD, "Graahk!", "(Hi!)") //? + player(ChatAnim.SUSPICIOUS, "Hello. Are you going to spike me again?") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Grar rawr howl!", "(No, I got a present to apologise for last time.)") + player(ChatAnim.HAPPY, "That's really sweet, thank you.") + npc(ChatAnim.GRAAHK_NOD, "Howl graaahk rawr.", "(Here you go, it's a special cushion to make you", "comfortable.)") + player(ChatAnim.ANGRY, "It's made of spikes!") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Howl graaahk rawr.", "(Yes, but they're therapeutic spikes.)") + player(ChatAnim.ANGRY, "...") + + label("inspect the spikes") + player(ChatAnim.HAPPY, "How's your day going?") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Graaahk. Grak grak!", "(It's great! Actually I've got something to show you!)") + player(ChatAnim.HALF_ASKING, "Oh? What's that?") + npc(ChatAnim.GRAAHK_NOD, "Grrrrrk hiss graaaaa!", "(You'll need to get closer!)") + player(ChatAnim.HALF_ASKING, "I can't see anything...") + npc(ChatAnim.GHRAAK_SHAKE_VIGOROUS, "Grah grr aaaaahk grahk.", "(It's really small - even closer.)") + player(ChatAnim.ANGRY, "Oww! I'm going to have your spikes trimmed!") + } +} \ No newline at end of file diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.java deleted file mode 100644 index dd6b48975..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.java +++ /dev/null @@ -1,52 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.game.node.entity.skill.SkillBonus; -import core.game.node.entity.skill.Skills; -import core.game.node.entity.combat.equipment.WeaponInterface; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; - -/** - * Represents the Spirit Graahk familiar. - * @author Aero - */ -@Initializable -public class SpiritGraahkNPC extends Familiar { - - /** - * Constructs a new {@code SpiritGraahkNPC} {@code Object}. - */ - public SpiritGraahkNPC() { - this(null, 7363); - } - - /** - * Constructs a new {@code SpiritGraahkNPC} {@code Object}. - * @param owner The owner. - * @param id The id. - */ - public SpiritGraahkNPC(Player owner, int id) { - super(owner, id, 4900, 12810, 3, WeaponInterface.STYLE_AGGRESSIVE); - boosts.add(new SkillBonus(Skills.HUNTER, 5)); - } - - @Override - public Familiar construct(Player owner, int id) { - return new SpiritGraahkNPC(owner, id); - } - - @Override - protected boolean specialMove(FamiliarSpecial special) { - if (!super.isOwnerAttackable()) { - return false; - } - call(); - return true; - } - - @Override - public int[] getIds() { - return new int[] { 7363, 7364 }; - } - -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.kt b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.kt new file mode 100644 index 000000000..af84870d7 --- /dev/null +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkNPC.kt @@ -0,0 +1,51 @@ +package content.global.skill.summoning.familiar + +import core.game.node.entity.Entity +import core.game.node.entity.combat.equipment.WeaponInterface +import core.game.node.entity.player.Player +import core.game.node.entity.skill.SkillBonus +import core.game.node.entity.skill.Skills +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.plugin.Initializable +import core.tools.RandomFunction +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +/** + * Represents the Spirit Graahk familiar. + * @author Aero & Bishop + */ +@Initializable +class SpiritGraahkNPC @JvmOverloads constructor(owner: Player? = null, id: Int = NPCs.SPIRIT_GRAAHK_7363) : + Familiar(owner, id, 4900, Items.SPIRIT_GRAAHK_POUCH_12810, 3, WeaponInterface.STYLE_AGGRESSIVE) { + + init { + boosts.add(SkillBonus(Skills.HUNTER, 5.0)) + } + + override fun construct(owner: Player?, id: Int): Familiar { + return SpiritGraahkNPC(owner, id) + } + + override fun specialMove(special: FamiliarSpecial): Boolean { + val target: Entity = special.target ?: return false + if (!canCombatSpecial(target)) { + return false + } + properties.combatPulse.attack(target) + return true + } + + override fun visualizeSpecialMove() { + owner.visualize(Animation.create(7660), Graphics.create(1316)) + } + + override fun getIds(): IntArray { + return intArrayOf(NPCs.SPIRIT_GRAAHK_7363, NPCs.SPIRIT_GRAAHK_7364) + } + + override fun getText(): String { + return if (RandomFunction.random(2) == 0) "Howl!" else "Rowr!" + } +} diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.java deleted file mode 100644 index 44c4678a9..000000000 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.java +++ /dev/null @@ -1,29 +0,0 @@ -package content.global.skill.summoning.familiar; - -import core.cache.def.impl.NPCDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the plugin used to handle the spirit graahk familiar - * @author Splinter - */ -@Initializable -public final class SpiritGraahkOptionPlugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - NPCDefinition.forId(7363).getHandlers().put("option:interact", this); - return this; - } - - @Override - public boolean handle(final Player player, Node node, String option) { - player.getDialogueInterpreter().open(7353, node.asNpc()); - return true; - } - -} diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.kt b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.kt new file mode 100644 index 000000000..d3b3b1e97 --- /dev/null +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritGraahkOptionPlugin.kt @@ -0,0 +1,27 @@ +package content.global.skill.summoning.familiar + +import core.cache.def.impl.NPCDefinition +import core.game.interaction.OptionHandler +import core.game.node.Node +import core.game.node.entity.player.Player +import core.plugin.Initializable +import core.plugin.Plugin +import org.rs09.consts.NPCs; + +/** + * Represents the plugin used to handle the spirit graahk familiar + * @author Splinter + */ +@Initializable +class SpiritGraahkOptionPlugin : OptionHandler() { + @Throws(Throwable::class) + override fun newInstance(arg: Any?): Plugin { + NPCDefinition.forId(NPCs.SPIRIT_GRAAHK_7363).getHandlers()["option:interact"] = this + return this + } + + override fun handle(player: Player, node: Node, option: String?): Boolean { + player.dialogueInterpreter.open(NPCs.SPIRIT_GRAAHK_7364, node.asNpc()) + return true + } +} diff --git a/Server/src/main/core/game/dialogue/FacialExpression.java b/Server/src/main/core/game/dialogue/FacialExpression.java index 6d415cf0f..8b4f2eb8c 100644 --- a/Server/src/main/core/game/dialogue/FacialExpression.java +++ b/Server/src/main/core/game/dialogue/FacialExpression.java @@ -104,13 +104,19 @@ public enum FacialExpression { CHILD_SUSPICIOUS(7179), CHILD_SURPRISED(7180), + //Familiar Chatheads + GRAAHK_NOD(6551), + GHRAAK_SHAKE_MILD(6553), + GHRAAK_SHAKE_VIGOROUS(6555), + + ; //TODO: More? /* * From some sources: here's a potential list of chatheads. * // 667 * Chat animation group: 1540; linked animations: [7, 8, 9, 6824] - * Chat animation group: 1489; linked animations: [225, 6550, 6551, 6552, 6553, 6555, 8372, 8373, 8374, 8375, 8581, 8582, 9178, 9179, 9180, 9181, 9183, 9187, 9189, 9190, 9192, 9202] + * Chat animation group: 1489; potentially all familiars; linked animations: [225, 6550, 6551, 6552, 6553, 6555, 8372, 8373, 8374, 8375, 8581, 8582, 9178, 9179, 9180, 9181, 9183, 9187, 9189, 9190, 9192, 9202] * Chat animation group: 82; linked animations: [554, 555, 556, 557, 562, 563, 564, 565, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 610, 611, 612, 613, 614, 615, 616, 617] * Chat animation group: 84; linked animations: [558, 559, 560, 561] * Chat animation group: 80; linked animations: [584, 585, 586, 587]