package net.scapeemulator.game.content.alkharid; import net.scapeemulator.game.dialogue.Dialogue; import net.scapeemulator.game.dialogue.DialogueContext; import net.scapeemulator.game.dialogue.DialogueOption; import net.scapeemulator.game.dialogue.HeadAnimation; import net.scapeemulator.game.dispatcher.npc.NPCDispatcher; import net.scapeemulator.game.dispatcher.npc.NPCHandler; import net.scapeemulator.game.dispatcher.object.ObjectDispatcher; import net.scapeemulator.game.dispatcher.object.ObjectHandler; import net.scapeemulator.game.model.Option; import net.scapeemulator.game.model.Position; import net.scapeemulator.game.model.World; import net.scapeemulator.game.model.mob.Direction; import net.scapeemulator.game.model.npc.NPC; import net.scapeemulator.game.model.npc.stateful.impl.NormalNPC; import net.scapeemulator.game.model.object.GroundObjectList.GroundObject; import net.scapeemulator.game.model.object.GroundObjectListenerAdapter; import net.scapeemulator.game.model.player.Item; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.model.player.action.BlockedAction; import net.scapeemulator.game.model.player.action.ReachObjectAction; import net.scapeemulator.game.task.Task; import net.scapeemulator.game.util.HandlerContext; /** * @author David Insley */ public class TollGate { private static final Dialogue<Integer> GATE_DIALOGUE = new GateDialogue(); private static final int GUARD_TYPE = 925; private static final Item TOLL = new Item(995, 10); public static void init() { ObjectDispatcher.getInstance().bind(new ObjectHandler(Option.ONE) { @Override public void handle(Player player, GroundObject object, String optionName, HandlerContext context) { if (object != GateObjects.closedLeft && object != GateObjects.closedRight) { return; } player.startAction(new WalkToGate(player, object, false)); } }); ObjectDispatcher.getInstance().bind(new ObjectHandler(Option.FOUR) { @Override public void handle(Player player, GroundObject object, String optionName, HandlerContext context) { if (object != GateObjects.closedLeft && object != GateObjects.closedRight) { return; } player.startAction(new WalkToGate(player, object, true)); } }); NPCDispatcher.getInstance().bind(new NPCHandler(Option.ONE) { @Override public void handle(Player player, NPC npc, String option, HandlerContext context) { if (npc.getType() == GUARD_TYPE) { context.stop(); player.sendMessage("He don't seem very interested in talking."); } } }); World.getWorld().getGroundObjects().addListener(new GateObjects()); NPC npc = new NormalNPC(GUARD_TYPE); npc.setPosition(new Position(3267, 3226, 0)); npc.setDirections(Direction.NORTH, Direction.NONE); World.getWorld().addNpc(npc); npc = new NormalNPC(GUARD_TYPE); npc.setPosition(new Position(3268, 3226, 0)); npc.setDirections(Direction.NORTH, Direction.NONE); World.getWorld().addNpc(npc); } private static class WalkToGate extends ReachObjectAction { private final boolean quickPay; public WalkToGate(Player player, GroundObject gate, boolean quickPay) { super(1, true, player, gate, 1, true); this.quickPay = quickPay; } @Override public void executeAction() { if (!mob.notWalking()) { return; } if (quickPay) { if (!mob.getInventory().contains(TOLL)) { mob.sendMessage("You don't have enough coins to pay the toll!"); stop(); } else { mob.getInventory().remove(TOLL); mob.sendMessage("You pay the guard and he opens the gate."); mob.startAction(new WalkThroughGate(mob)); } } else { GATE_DIALOGUE.displayTo(mob); stop(); } } } private static class WalkThroughGate extends BlockedAction { private final Position dest; private boolean started; private boolean wasRunning = false; public WalkThroughGate(Player player) { super(player, 1, true); dest = new Position(player.getPosition().getX() >= 3268 ? 3266 : 3269, mob.getPosition().getY()); } @Override public void executeAction() { if (!started) { GateObjects.open(); World.getWorld().getTaskScheduler().schedule(new Task(4, false) { @Override public void execute() { GateObjects.close(); stop(); } }); mob.setClipped(false); if (mob.isRunning()) { wasRunning = true; mob.getSettings().setRunning(false); } // TODO change to force walking update block when added maybe? mob.getWalkingQueue().addFirstStep(dest); started = true; } if (mob.getPosition().equals(dest)) { stop(); } } public void stop() { mob.setClipped(true); if (wasRunning) { mob.getSettings().setRunning(true); } super.stop(); } } private static class GateObjects extends GroundObjectListenerAdapter { private static final int CLOSED_LEFT_ID = 35549; private static final int CLOSED_RIGHT_ID = 35551; private static GroundObject closedLeft; private static GroundObject closedRight; private static GroundObject openLeft; private static GroundObject openRight; @Override public void groundObjectAdded(GroundObject object) { if (closedLeft == null && object.getId() == CLOSED_LEFT_ID) { closedLeft = object; openLeft = World.getWorld().getGroundObjects().put(object.getPosition().copy(-1, 0), 35550, 3, object.getType()); openLeft.hide(); } if (closedRight == null && object.getId() == CLOSED_RIGHT_ID) { closedRight = object; openRight = World.getWorld().getGroundObjects().put(object.getPosition().copy(-1, 0), 35552, 1, object.getType()); openRight.hide(); } if (closedRight != null && closedLeft != null) { World.getWorld().getGroundObjects().removeListener(this); } } private static void open() { /* * We use setId(0) instead of hide() because it keeps the path * clipped */ closedRight.setId(0); openRight.reveal(); closedLeft.setId(0); openLeft.reveal(); } private static void close() { closedRight.setId(CLOSED_RIGHT_ID); openRight.hide(); closedLeft.setId(CLOSED_LEFT_ID); openLeft.hide(); } } /* private static Dialogue createDialogue() { ContinueNode willPay = new PlayerDialogueNode("Fine. I'll pay that.", HeadAnimation.SAD, true) { @Override public void handleOption(DialogueContext ctx, DialogueOption option) { Player player = ctx.getPlayer(); if (!player.getInventory().contains(TOLL)) { ctx.setNode(new NPCDialogueNode("Bah, you don't even have enough coins! Go away!", GUARD_TYPE, HeadAnimation.ANGRY, true)); } else { ctx.stop(); player.getInventory().remove(TOLL); player.sendMessage("You pay the guard and he opens the gate."); player.startAction(new WalkThroughGate(player)); } } }; ContinueNode goAway = new NPCDialogueNode("Then go away!", GUARD_TYPE, HeadAnimation.ANGRY, true); ContinueNode root = new NPCDialogueNode("Halt! Anyone wishing to enter Al Kharid must pay the toll.", GUARD_TYPE, HeadAnimation.STERN, true); root.setNext(new PlayerDialogueNode("And how much is that?", HeadAnimation.CALMLY_TALKING, true).setNext( new NPCDialogueNode("10 gold pieces.", GUARD_TYPE, HeadAnimation.PLEASED, true)).setNext( new BranchNode(). addBranch("10 whole pieces?! That's ridiculous! I'm not paying that", new PlayerDialogueNode("10 whole pieces?! That's ridiculous! I'm not paying that", HeadAnimation.ANGRY, true).setNext( goAway)). addBranch("Fine. I'll pay that.", willPay) ) ); return new Dialogue(root); }*/ private static class GateDialogue extends Dialogue<Integer> { @Override public void initialize(DialogueContext<Integer> ctx) { ctx.openNpcConversationDialogue("Halt! Anyone wishing to enter Al Kharid must pay the toll.", GUARD_TYPE, HeadAnimation.STERN, true); ctx.setStage(1); } @Override public void handleOption(DialogueContext<Integer> ctx, DialogueOption opt) { switch (ctx.getStage()) { case -1: ctx.stop(); break; case 1: ctx.openPlayerConversationDialogue("And how much is that?", HeadAnimation.CALMLY_TALKING, true); ctx.setStage(2); break; case 2: ctx.openNpcConversationDialogue("10 gold pieces.", GUARD_TYPE, HeadAnimation.PLEASED, true); ctx.setStage(ctx.getPlayer().getInventory().contains(TOLL) ? 31 : 32); break; case 31: ctx.openOptionDialogue("10 whole pieces?! That's ridiculous! I'm not paying that.", "Fine. I'll pay that."); ctx.setStage(41); break; case 41: if (opt == DialogueOption.OPTION_1) { ctx.openPlayerConversationDialogue("10 whole pieces?! That's ridiculous! I'm not paying that.", HeadAnimation.ANGRY, true); ctx.setStage(511); } else { ctx.openPlayerConversationDialogue("Fine. I'll pay that.", HeadAnimation.SAD, true); ctx.setStage(512); } break; case 512: Player player = ctx.getPlayer(); if (!player.getInventory().contains(TOLL)) { // Really shouldn't happen because we checked already... but // just in case. ctx.openNpcConversationDialogue("Bah, you don't even have enough coins! Go away!", GUARD_TYPE, HeadAnimation.ANGRY, true); ctx.setStage(-1); } else { ctx.stop(); player.getInventory().remove(TOLL); player.sendMessage("You pay the guard and he opens the gate."); player.startAction(new WalkThroughGate(player)); } break; case 32: ctx.openPlayerConversationDialogue("But I don't have 10 gold pieces...", HeadAnimation.SAD, true); ctx.setStage(42); break; case 42: case 511: ctx.openNpcConversationDialogue("Then go away!", GUARD_TYPE, HeadAnimation.ANGRY, true); ctx.setStage(-1); break; } } } }