From 79bf670d5134b3964b7de46c20cef08fb7f30c2e Mon Sep 17 00:00:00 2001 From: Ceikry Date: Mon, 9 Mar 2020 22:09:33 -0500 Subject: [PATCH 1/3] Reworked Pyramid Plunder NPCs --- .../PyramidPlunderMummyNPC.java | 53 +++++ .../pyramidplunder/PyramidPlunderNPC.java | 188 ++++++++++++++++++ .../pyramidplunder/PyramidPlunderOptions.java | 35 +++- .../PyramidPlunderSwarmNPC.java | 53 +++++ 4 files changed, 319 insertions(+), 10 deletions(-) create mode 100644 Server/src/plugin/activity/pyramidplunder/PyramidPlunderMummyNPC.java create mode 100644 Server/src/plugin/activity/pyramidplunder/PyramidPlunderNPC.java create mode 100644 Server/src/plugin/activity/pyramidplunder/PyramidPlunderSwarmNPC.java diff --git a/Server/src/plugin/activity/pyramidplunder/PyramidPlunderMummyNPC.java b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderMummyNPC.java new file mode 100644 index 000000000..366453c46 --- /dev/null +++ b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderMummyNPC.java @@ -0,0 +1,53 @@ +package plugin.activity.pyramidplunder; +import org.crandor.game.node.entity.Entity; +import org.crandor.game.node.entity.player.Player; +import org.crandor.game.world.map.Location; +import org.crandor.tools.RandomFunction; + +/** + * Handles the mummy NPC in pyramid plunder + * @author ceik + */ +public final class PyramidPlunderMummyNPC extends PyramidPlunderNPC { + + /** + * The swarm id. + */ + private static final int[] IDS = new int[] { 1958 }; + + public PyramidPlunderMummyNPC(int id, Location location, Player player) { + super(id, location, player); + } + + @Override + public void init() { + super.init(); + setRespawn(false); + getProperties().getCombatPulse().attack(player); + sendChat("How dare you disturb my rest!"); + } + + @Override + public void handleTickActions() { + super.handleTickActions(); + if (!getProperties().getCombatPulse().isAttacking()) { + getProperties().getCombatPulse().attack(player); + } + if (getProperties().getCombatPulse().isAttacking()) { + if (RandomFunction.random(40) < 2) { + sendChat("Leave this place!"); + } + } + } + + @Override + public boolean isIgnoreMultiBoundaries(Entity victim) { + return victim == player; + } + + @Override + public int[] getIds() { + return IDS; + } + +} diff --git a/Server/src/plugin/activity/pyramidplunder/PyramidPlunderNPC.java b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderNPC.java new file mode 100644 index 000000000..b6dddafe8 --- /dev/null +++ b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderNPC.java @@ -0,0 +1,188 @@ +package plugin.activity.pyramidplunder; + +import org.crandor.game.interaction.MovementPulse; +import org.crandor.game.node.entity.Entity; +import org.crandor.game.node.entity.combat.CombatStyle; +import org.crandor.game.node.entity.npc.AbstractNPC; +import org.crandor.game.node.entity.player.Player; +import org.crandor.game.world.GameWorld; +import org.crandor.game.world.map.Location; +import org.crandor.game.world.map.RegionManager; +import org.crandor.game.world.map.path.Pathfinder; +import org.crandor.plugin.Plugin; + +/** + * Handles a Pyramid Plunder enemy, adapted from AntiMacroNPC.java by ceikry + * @author Vexia + */ +public abstract class PyramidPlunderNPC extends AbstractNPC { + + /** + * The player. + */ + protected final Player player; + + /** + * The quotes the npc will say(null if none) + */ + private String[] quotes; + + /** + * The counter representing speech cycles. + */ + private int count; + + /** + * The time until the next speech. + */ + private int nextSpeech; + + /** + * If the players time is up. + */ + protected boolean timeUp; + + /** + * The end time. + */ + private int endTime; + + /** + * Constructs a new {@code AntiMacroNPC} {@code Object}. + * @param id the id. + * @param location the location. + * @param player the player. + */ + public PyramidPlunderNPC(int id, Location location, Player player) { + super(id, location); + this.player = player; + this.quotes = quotes; + this.endTime = (int) (GameWorld.getTicks() + (1000 / 0.6)); + } + + @Override + public void init() { + location = RegionManager.getSpawnLocation(player, this); + if (location == null) { + clear(); + return; + } + super.init(); + startFollowing(); + } + + @Override + public void handleTickActions() { + if (GameWorld.getTicks() > endTime) { + clear(); + } + if (!getLocks().isMovementLocked()) { + if (dialoguePlayer == null || !dialoguePlayer.isActive() || !dialoguePlayer.getInterfaceManager().hasChatbox()) { + dialoguePlayer = null; + } + } + if (!player.isActive() || !getLocation().withinDistance(player.getLocation(), 10)) { + handlePlayerLeave(); + } + if (!getPulseManager().hasPulseRunning()) { + startFollowing(); + } + if (quotes != null) { + if (nextSpeech < GameWorld.getTicks() && this.getDialoguePlayer() == null && !this.getLocks().isMovementLocked()) { + if (count > quotes.length - 1) { + return; + } + nextSpeech = (int) (GameWorld.getTicks() + (20 / 0.5)); + if (++count >= quotes.length) { + setTimeUp(true); + handleTimeUp(); + return; + } + } + } + } + + /** + * Called when the player is gone. + */ + public void handlePlayerLeave() { + clear(); + } + + /** + * Called when the quotes are finished. + */ + public void handleTimeUp() { + } + + @Override + public boolean isAttackable(Entity entity, CombatStyle style) { + if (entity instanceof Player && entity != player) { + ((Player) entity).getPacketDispatch().sendMessage("It's not after you."); + return false; + } + return super.isAttackable(entity, style); + } + + @Override + public void onRegionInactivity() { + super.onRegionInactivity(); + clear(); + } + + @Override + public void clear() { + super.clear(); + } + + @Override + public AbstractNPC construct(int id, Location location, Object... objects) { + return null; + } + + + + /** + * Starts following the player. + */ + public void startFollowing() { + getPulseManager().run(new MovementPulse(this, player, Pathfinder.DUMB) { + @Override + public boolean pulse() { + return false; + } + }, "movement"); + face(player); + } + + @Override + public Plugin newInstance(Object arg) throws Throwable { + return super.newInstance(arg); + } + + /** + * Gets the player. + * @return The player. + */ + public Player getPlayer() { + return player; + } + + + /** + * Gets the timeUp. + * @return The timeUp. + */ + public boolean isTimeUp() { + return timeUp; + } + + /** + * Sets the timeUp. + * @param timeUp The timeUp to set. + */ + public void setTimeUp(boolean timeUp) { + this.timeUp = timeUp; + } + +} diff --git a/Server/src/plugin/activity/pyramidplunder/PyramidPlunderOptions.java b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderOptions.java index ad6986ba3..a0fd44473 100644 --- a/Server/src/plugin/activity/pyramidplunder/PyramidPlunderOptions.java +++ b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderOptions.java @@ -5,18 +5,16 @@ import org.crandor.game.content.global.action.ClimbActionHandler; import org.crandor.game.content.skill.Skills; import org.crandor.game.interaction.OptionHandler; import org.crandor.game.node.Node; -import org.crandor.game.node.entity.Entity; import org.crandor.game.node.entity.combat.ImpactHandler; import org.crandor.game.node.entity.npc.NPC; import org.crandor.game.node.entity.player.Player; import org.crandor.game.node.item.Item; import org.crandor.game.node.object.GameObject; -import org.crandor.game.world.map.Direction; +import org.crandor.game.world.GameWorld; import org.crandor.game.world.map.Location; import org.crandor.game.world.update.flag.context.Animation; import org.crandor.plugin.InitializablePlugin; import org.crandor.plugin.Plugin; -import org.crandor.plugin.PluginManager; import org.crandor.tools.RandomFunction; import java.util.Random; @@ -43,8 +41,14 @@ public final class PyramidPlunderOptions extends OptionHandler { return this; } public void rollSceptre(Player player){ - if(RandomFunction.random(1000) == 4){ - player.getInventory().add(new Item(9050)); + if(RandomFunction.random(1000) == 451){ + if(!player.getInventory().isFull()) { + player.getInventory().add(new Item(9044)); + player.getPacketDispatch().sendMessage("You find a strange object."); + } else { + player.getBank().add(new Item(9044)); + player.getPacketDispatch().sendMessage("You sense that something has appeared in your bank."); + } } } public final boolean success(final Player player, final int skill) { @@ -59,6 +63,7 @@ public final class PyramidPlunderOptions extends OptionHandler { } @Override public boolean handle(Player player, Node node, String option) { + int NPCDeathTime = GameWorld.getTicks() + (1000 / 6); Location room_entrance[] = {new Location(1927,4477), new Location(1927,4453), new Location(1943,4421), new Location(1954,4477), new Location(1974,4420), new Location(1977,4471), new Location(1927, 4424)}; int currentX = player.getLocation().getX(); int currentY = player.getLocation().getY(); @@ -151,6 +156,7 @@ public final class PyramidPlunderOptions extends OptionHandler { break; case 16473: if(option.equals("search") || option.equals("Search")) { + boolean willSpawnSwarm = (RandomFunction.random(1,20) == 10); if (reqLevel > level){ player.getPacketDispatch().sendMessage("You need to be at least level " + reqLevel + " thieving."); break; @@ -158,10 +164,18 @@ public final class PyramidPlunderOptions extends OptionHandler { player.getPacketDispatch().sendMessage("You search the chest..."); player.animate(animations[1]); player.lock(2); - player.getInventory().add(ARTIFACTS[RandomFunction.random(1,3)][RandomFunction.random(3)]); - rollSceptre(player); - player.getPacketDispatch().sendMessage("And you find an artifact!"); - player.getSkills().addExperience(Skills.THIEVING,40 + (room * 20)); + if(willSpawnSwarm) { + player.getPacketDispatch().sendMessage("A swarm flies out!"); + PyramidPlunderSwarmNPC swarm = new PyramidPlunderSwarmNPC(2001,player.getLocation(),player); + swarm.setRespawn(false); + swarm.setAggressive(true); + swarm.init(); + } else { + player.getInventory().add(ARTIFACTS[RandomFunction.random(1, 3)][RandomFunction.random(3)]); + rollSceptre(player); + player.getPacketDispatch().sendMessage("And you find an artifact!"); + player.getSkills().addExperience(Skills.THIEVING, 40 + (room * 20)); + } } break; case 16495: @@ -175,7 +189,7 @@ public final class PyramidPlunderOptions extends OptionHandler { player.getPacketDispatch().sendMessage("You open the sarcophagus and...."); if(willSpawnMummy) { player.getPacketDispatch().sendMessage("A mummy crawls out!"); - NPC mummy = NPC.create(1958, player.getLocation()); + PyramidPlunderMummyNPC mummy = new PyramidPlunderMummyNPC(1958, player.getLocation(),player); mummy.setRespawn(false); mummy.setAggressive(true); mummy.init(); @@ -199,6 +213,7 @@ public final class PyramidPlunderOptions extends OptionHandler { if (doesOpen) { player.getPacketDispatch().sendMessage("The door opens!"); player.getProperties().setTeleportLocation(room_entrance[room]); + player.getPacketDispatch().sendMessage("Room: " + (room + 1) + " Level required: " + (reqLevel + 10)); } else { player.getPacketDispatch().sendMessage("You fail to unlock the door."); } diff --git a/Server/src/plugin/activity/pyramidplunder/PyramidPlunderSwarmNPC.java b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderSwarmNPC.java new file mode 100644 index 000000000..97e267d40 --- /dev/null +++ b/Server/src/plugin/activity/pyramidplunder/PyramidPlunderSwarmNPC.java @@ -0,0 +1,53 @@ +package plugin.activity.pyramidplunder; +import org.crandor.game.node.entity.Entity; +import org.crandor.game.node.entity.player.Player; +import org.crandor.game.world.map.Location; +import org.crandor.tools.RandomFunction; + +/** + * Handles the swarm NPC in pyramid plunder + * @author ceik + */ +public final class PyramidPlunderSwarmNPC extends PyramidPlunderNPC { + + /** + * The swarm id. + */ + private static final int[] IDS = new int[] { 2001 }; + + public PyramidPlunderSwarmNPC(int id, Location location, Player player) { + super(id, location, player); + } + + @Override + public void init() { + super.init(); + setRespawn(false); + getProperties().getCombatPulse().attack(player); + sendChat("bzzzzz"); + } + + @Override + public void handleTickActions() { + super.handleTickActions(); + if (!getProperties().getCombatPulse().isAttacking()) { + getProperties().getCombatPulse().attack(player); + } + if (getProperties().getCombatPulse().isAttacking()) { + if (RandomFunction.random(40) < 2) { + sendChat("bzzzzz"); + } + } + } + + @Override + public boolean isIgnoreMultiBoundaries(Entity victim) { + return victim == player; + } + + @Override + public int[] getIds() { + return IDS; + } + +} From f8dfc4fe413a2c8b809ba604dcd3fab5e86215fe Mon Sep 17 00:00:00 2001 From: Ceikry Date: Mon, 9 Mar 2020 22:26:18 -0500 Subject: [PATCH 2/3] Tweaked dialogue a little --- Server/src/plugin/dialogue/SimonTempleton.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Server/src/plugin/dialogue/SimonTempleton.java b/Server/src/plugin/dialogue/SimonTempleton.java index 833775c0b..65f6d4204 100644 --- a/Server/src/plugin/dialogue/SimonTempleton.java +++ b/Server/src/plugin/dialogue/SimonTempleton.java @@ -102,6 +102,7 @@ public final class SimonTempleton extends DialoguePlugin{ case 20: switch(buttonId){ case 1: + end(); for(int j = 0; j < 28; j++){ switch(player.getInventory().getId(j)){ case 9032: @@ -121,6 +122,7 @@ public final class SimonTempleton extends DialoguePlugin{ stage = 999; break; case 2: + end(); for(int j = 0; j < 28; j++){ switch(player.getInventory().getId(j)){ case 9042: @@ -140,6 +142,7 @@ public final class SimonTempleton extends DialoguePlugin{ stage = 999; break; case 3: + end(); for(int j = 0; j < 28; j++){ switch(player.getInventory().getId(j)){ case 9040: @@ -159,6 +162,7 @@ public final class SimonTempleton extends DialoguePlugin{ stage = 999; break; case 4: + end(); for(int j = 0; j < 28; j++){ switch(player.getInventory().getId(j)){ case 9040: @@ -202,6 +206,7 @@ public final class SimonTempleton extends DialoguePlugin{ stage = 999; break; } + break; case 30: player("What! This is a genuine pharaoh's scepter - made out of"," solid gold and finely jewelled with precious gems"," by the finest craftsmen in the area."); stage = 31; From d8fb088e281ea13e29cd0d121d8646dc4feb0b7b Mon Sep 17 00:00:00 2001 From: Ceikry Date: Tue, 10 Mar 2020 15:33:54 -0500 Subject: [PATCH 3/3] Added more dialogue to the Guardian Mummy --- .../pyramidplunder/GuardMummyDialogue.java | 82 ++++++++++++++++--- .../pyramidplunder/PyramidOptionHandler.java | 28 ++++++- 2 files changed, 95 insertions(+), 15 deletions(-) diff --git a/Server/src/plugin/activity/pyramidplunder/GuardMummyDialogue.java b/Server/src/plugin/activity/pyramidplunder/GuardMummyDialogue.java index 74cc0efd4..b823f261f 100644 --- a/Server/src/plugin/activity/pyramidplunder/GuardMummyDialogue.java +++ b/Server/src/plugin/activity/pyramidplunder/GuardMummyDialogue.java @@ -7,26 +7,22 @@ import org.crandor.game.node.entity.player.Player; /** * Handles Guardian mummy dialogue. - * @author Emperor + * @author Originally Emperor, completely redone by Ceikry. */ public final class GuardMummyDialogue extends DialoguePlugin { /** * If the player successfully caught the evil twin. + * Will remain unused until the quest is implemented. (if ever) */ - private int type; + //private int type; - /** - * Constructs a new {@code GuardMummyDialogue} {@code Object}. - */ - public GuardMummyDialogue() { - super(); - } /** * Constructs a new {@code GuardMummyDialogue} {@code Object}. * @param player The player. */ + public GuardMummyDialogue() {super();} public GuardMummyDialogue(Player player) { super(player); } @@ -39,18 +35,78 @@ public final class GuardMummyDialogue extends DialoguePlugin { @Override public boolean open(Object... args) { npc = (NPC) args[0]; - type = args.length == 1 ? 0 : (Integer) args[1]; + if(args.length > 1){ + switch((int) args[1]){ + case 0: + npc("You! How did you get into this place?"); + stage = 50; + break; + case 1: + player("I know what I'm doing - let's get on with it."); + stage = 10; + break; + } + } else { + npc("Errr"); + } + /*type = args.length == 1 ? 0 : (Integer) args[1]; if (type == 1) { player("I know what I'm doing - let's get on with it."); } else { - System.out.println("TODO:1"); - } + npc("You! How did you get in?"); + }*/ return true; } @Override public boolean handle(int interfaceId, int buttonId) { - switch (stage++) { + switch(stage){ + case 10: + npc("Fine, I'll take you to the first room now..."); + stage = 60; + break; + case 50: + player("I could ask you the same thing."); + stage = 51; + break; + case 51: + npc("Nevermind that. I suppose since you're here I can tell", "you how to play."); + stage = 52; + break; + case 52: + npc("In each room there are urns, a chest, and a sarcophagus."); + stage = 53; + break; + case 53: + npc("The urns contain artifacts based on the room that you are","currently in. The chest contains valuable artifacts but is","sometimes trapped. The sarcophagus has one of my","brothers in it. And lots of artifacts."); + stage = 54; + break; + case 54: + player("Anything else I should know?"); + stage = 55; + break; + case 55: + npc("Yes, each room requires more thieving knowledge than the"," last. And be careful not to die."); + stage = 56; + break; + case 56: + player("Oh, yes, dying. Not good. Well I suppose that covers it?"); + stage = 57; + break; + case 57: + npc("Yep."); + stage = 58; + break; + case 58: + end(); + break; + case 60: + end(); + ActivityManager.start(player, "Pyramid plunder", false); + break; + + } + /*switch (stage++) { case 0: if (type == 1) { npc("Fine, I'll take you to the first room now..."); @@ -66,7 +122,7 @@ public final class GuardMummyDialogue extends DialoguePlugin { System.out.println("TODO:3"); } return true; - } + }*/ return false; } diff --git a/Server/src/plugin/activity/pyramidplunder/PyramidOptionHandler.java b/Server/src/plugin/activity/pyramidplunder/PyramidOptionHandler.java index 41cf7b846..fe9eda57b 100644 --- a/Server/src/plugin/activity/pyramidplunder/PyramidOptionHandler.java +++ b/Server/src/plugin/activity/pyramidplunder/PyramidOptionHandler.java @@ -8,7 +8,10 @@ import org.crandor.game.node.Node; import org.crandor.game.node.entity.npc.NPC; import org.crandor.game.node.entity.player.Player; import org.crandor.game.node.object.GameObject; +import org.crandor.game.system.task.Pulse; +import org.crandor.game.world.GameWorld; import org.crandor.game.world.map.Location; +import org.crandor.game.world.update.flag.context.Animation; import org.crandor.plugin.Plugin; import org.crandor.tools.RandomFunction; @@ -51,6 +54,7 @@ public final class PyramidOptionHandler extends OptionHandler { ObjectDefinition.forId(16458).getConfigurations().put("option:leave tomb", this); ObjectDefinition.forId(16459).getConfigurations().put("option:leave tomb", this); NPCDefinition.forId(4476).getConfigurations().put("option:start-minigame", this); + NPCDefinition.forId(4476).getConfigurations().put("option:talk-to",this); return null; } @@ -59,6 +63,7 @@ public final class PyramidOptionHandler extends OptionHandler { if (node instanceof GameObject) { Location destination = EMPTY_ROOM; GameObject object = (GameObject) node; + boolean willBePushed = (RandomFunction.random(10) > 3); if (object.getId() == 16458 || object.getId() == 16459) { ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location.create(3288, 2801, 0)); return true; @@ -75,9 +80,28 @@ public final class PyramidOptionHandler extends OptionHandler { } player.getConfigManager().set(704, value); player.getPacketDispatch().sendMessage("You use your thieving skills to search the stone panel."); - ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, destination, "You find a door! You open it."); + if(entrance == currentEntrance && willBePushed){ + player.lock(); + player.animate(new Animation(7299)); + player.getImpactHandler().setDisabledTicks(4); + GameWorld.submit(new Pulse(4, player) { + @Override + public boolean pulse() { + player.unlock(); + player.getAnimator().reset(); + return true; + } + }); + } else { + ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, destination, "You find a door! You open it."); + } + //ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, destination, "You find a door! You open it."); } else if (node instanceof NPC) { - player.getDialogueInterpreter().open(node.getId(), node, 1); + if (option.equals("talk-to")) { + player.getDialogueInterpreter().open(node.getId(), node, 0); + } else { + player.getDialogueInterpreter().open(node.getId(), node, 1); + } } return true; }