From df40fbb32d07208d5d104e4922b30f24cf98612d Mon Sep 17 00:00:00 2001 From: Ceikry Date: Mon, 15 Mar 2021 15:49:57 -0500 Subject: [PATCH] Fixed farming bug, redid canoe stations entirely into new listener system --- .../content/global/travel/canoe/Canoe.java | 17 +- .../global/travel/canoe/CanoeExtension.java | 456 ------------------ .../global/travel/canoe/CanoeStation.java | 153 ------ .../inter/CanoeInterfacePlugin.java | 53 -- .../interaction/object/CanoeOptionPlugin.java | 102 ---- .../core/game/node/entity/impl/Animator.java | 4 + .../canoestation/CanoeInterfaceListeners.kt | 127 +++++ .../canoestation/CanoeStationListener.kt | 88 ++++ .../object/canoestation/CanoeUtils.kt | 62 +++ .../game/node/entity/skill/farming/Patch.kt | 3 +- .../state/newsys/states/FarmingState.kt | 5 +- 11 files changed, 298 insertions(+), 772 deletions(-) delete mode 100644 Server/src/main/java/core/game/content/global/travel/canoe/CanoeExtension.java delete mode 100644 Server/src/main/java/core/game/content/global/travel/canoe/CanoeStation.java delete mode 100644 Server/src/main/java/core/game/interaction/inter/CanoeInterfacePlugin.java delete mode 100644 Server/src/main/java/core/game/interaction/object/CanoeOptionPlugin.java create mode 100644 Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeInterfaceListeners.kt create mode 100644 Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeStationListener.kt create mode 100644 Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeUtils.kt diff --git a/Server/src/main/java/core/game/content/global/travel/canoe/Canoe.java b/Server/src/main/java/core/game/content/global/travel/canoe/Canoe.java index 5d900cb66..3ee0e6a22 100644 --- a/Server/src/main/java/core/game/content/global/travel/canoe/Canoe.java +++ b/Server/src/main/java/core/game/content/global/travel/canoe/Canoe.java @@ -6,10 +6,10 @@ package core.game.content.global.travel.canoe; * @date 09/11/2013 */ public enum Canoe { - LOG(12, 30, 30), - DUGOUT(27, 60, 31), - STABLE_DUGOUT(42, 90, 32), - WAKA(57, 150, 33); + LOG(12, 30, 30,0,0), + DUGOUT(27, 60, 31,9,3), + STABLE_DUGOUT(42, 90, 32,10,2), + WAKA(57, 150, 33,8,5); /** * Constructs a new {@code Canoe.java} {@code Object}. @@ -17,12 +17,19 @@ public enum Canoe { * @param experience the experience. * @param child the child. */ - Canoe(final int level, final double experience, final int child) { + Canoe(final int level, final double experience, final int child, final int silhouetteChild, final int textChild) { this.level = level; this.experience = experience; this.child = child; + this.silhouetteChild = silhouetteChild; + this.textChild = textChild; + this.maxDist = ordinal() + 1; } + public int silhouetteChild; + public int textChild; + public int maxDist; + /** * Represents the woodcutting level requirement to craft the canoe. */ diff --git a/Server/src/main/java/core/game/content/global/travel/canoe/CanoeExtension.java b/Server/src/main/java/core/game/content/global/travel/canoe/CanoeExtension.java deleted file mode 100644 index 774c8bbd1..000000000 --- a/Server/src/main/java/core/game/content/global/travel/canoe/CanoeExtension.java +++ /dev/null @@ -1,456 +0,0 @@ -package core.game.content.global.travel.canoe; - -import core.game.component.Component; -import core.game.node.entity.skill.Skills; -import core.game.node.entity.skill.gather.SkillingTool; -import core.game.node.entity.impl.Animator.Priority; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.diary.DiaryType; -import core.game.node.object.GameObject; -import core.game.system.task.Pulse; -import rs09.game.world.GameWorld; -import core.game.world.update.flag.context.Animation; -import core.net.packet.PacketRepository; -import core.net.packet.context.MinimapStateContext; -import core.net.packet.out.MinimapState; -import core.tools.RandomFunction; - -/** - * Represents a class that i used to hold relative information of the states of a canoe for a player. - * @author Vexia - * - */ -public final class CanoeExtension { - - /** - * Represents the canoe shaping component. - */ - private static final Component shape = new Component(52); - - /** - * Represents the destination selection interface component. - */ - private static final Component destinationSelector = new Component(53); - - /** - * Represents the animation of pushing a canoe. - */ - private static final Animation PUSH = new Animation(3301); - - /** - * Represents the animation of rowing a canoe. - */ - @SuppressWarnings("unused") - private static final Animation ROW = new Animation(3302); - - /** - * Represents the animation of falling over. - */ - private static final Animation FALL = new Animation(3303); - - /** - * Represents the animation of a floating canoe. - */ - private static final Animation FLOAT = new Animation(3304); - - /** - * Represents the animation of a sinking canoe. - */ - @SuppressWarnings("unused") - private static final Animation SINK = new Animation(3305); - - /** - * Represents multiple config base ids of different states of canoes. - */ - private static final int[] CONFIGS = new int[] { 9, 10, 1, 5, 11 }; - - /** - * Represents the shaping configs. - */ - private static final int[][] shapeConfigs = new int[][] {{ 9, 3 }, {10, 2 }, { 8, 5 }}; - - /** - * Represents the boat childs (indexes) - */ - private static final int[] boatChilds = new int[] { 47, 48, 3, 6, 49 }; - - /** - * Represents the location childs (indexes) - */ - private static final int[] locationChilds = new int[] { 50, 47, 44, 36 }; - - /** - * Represents the maximum distances that every canoe type can travel (indexes) - */ - private static final int[] maxDistances = new int[] { 1, 2, 3, 4 }; - - /** - * Represents the player instance. - */ - private final Player player; - - /** - * Represents the stage the player is at with crafting a canoe.(1=fallen, - * 2=crafted,3=floating) - */ - private int stage; - - /** - * Represents the current canoe station the {@link #player} is at. - */ - private CanoeStation currentStation; - - /** - * Represents the current canoe. - */ - private Canoe canoe; - - /** - * Constructs a new {@code CanoeExtension} {@code Object}. - * @param player the player. - */ - public CanoeExtension(final Player player) { - this.player = player; - } - - /** - * Method used to get the extension of this class, if its already there we - * return it if not we create a new instance which is added to the player. - * @param player the player. - * @return the CanoeExtension - */ - public static CanoeExtension extension(final Player player) { - CanoeExtension extension = player.getExtension(CanoeExtension.class); - if (extension == null) { - extension = new CanoeExtension(player); - player.addExtension(CanoeExtension.class, extension); - } - player.varpManager.get(674).setSave(false); - return extension; - } - - /** - * Method used to chop down a tree. - * @param object the object. - */ - public final void chopTree(final GameObject object) { - final CanoeStation station = CanoeStation.getStationByObject(object); - final SkillingTool axe = getTool(); - if (axe == null) { - player.getPacketDispatch().sendMessage("You do not have an axe which you have the woodcutting level to use."); - return; - } - if (player.getSkills().getLevel(Skills.WOODCUTTING) < 12) { - player.getPacketDispatch().sendMessage("You need a woodcutting level of at least 12 to chop down this tree."); - return; - } - player.lock(3); - player.animate(axe.getAnimation()); - player.varpManager.get(675).setVarbit(17, station.ordinal() + 1).send(player); - player.varpManager.get(674).setVarbit(station.ordinal() * 8,9).send(player); - GameWorld.getPulser().submit(new Pulse(4, player) { - @Override - public boolean pulse() { - player.animate(new Animation(-1, Priority.HIGH)); - player.varpManager.get(674).setVarbit(station.ordinal() * 8, 10).send(player); - player.getPacketDispatch().sendObjectAnimation(object.getChild(player), FALL, false); - setCurrentStation(station); - setStage(1); - return true; - } - }); - } - - /** - * Method used to shape a canoe. - */ - public final void shapeCanoe() { - player.getInterfaceManager().open(shape); - for (int i = 0; i < shapeConfigs.length; i++) { - if (player.getSkills().getLevel(Skills.WOODCUTTING) < Canoe.values()[i].getRequiredLevel()) { - continue; - } - player.getPacketDispatch().sendInterfaceConfig(52, shapeConfigs[i][0], true); - player.getPacketDispatch().sendInterfaceConfig(52, shapeConfigs[i][1], false); - } - } - - /** - * Method used to craft a canoe. - * @param canoe the canoe. - */ - public final void craftCanoe(final Canoe canoe) { - if (player.getSkills().getLevel(Skills.WOODCUTTING) < canoe.getRequiredLevel()) { - player.getPacketDispatch().sendMessage("You need a woodcutting level of at least " + canoe.getRequiredLevel() + " to make this canoe."); - return; - } - player.getInterfaceManager().close(); - final SkillingTool axe = getTool(); - if (axe == null) { - player.getPacketDispatch().sendMessage("You do not have an axe which you have the woodcutting level to use."); - return; - } - player.lock(20); - player.animate(getAnimation(axe)); - player.getPulseManager().run(new Pulse(3) { - @Override - public boolean pulse() { - if (RandomFunction.random(canoe == Canoe.WAKA ? 8 : 6) == 1) { - if (currentStation == CanoeStation.EDGEVILLE && canoe == Canoe.WAKA) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 2, 10); - } - player.varpManager.get(674) - .setVarbit(currentStation.ordinal() * 8, currentStation.getCraftConfig(canoe,false)) - .send(player); - player.varpManager.get(675).setVarbit(17, currentStation.ordinal() + 1).send(player); - player.getSkills().addExperience(Skills.WOODCUTTING, canoe.getExperience()); - setCanoe(canoe); - setStage(2); - player.unlock(); - return true; - } - player.animate(getAnimation(axe)); - return false; - } - - @Override - public void stop() { - super.stop(); - player.animate(new Animation(-1, Priority.HIGH)); - player.unlock(); - } - }); - } - - /** - * Method used to set afloat the canoe. - * @param object the object. - */ - public final void setAfloat(final GameObject object) { - player.animate(PUSH); - player.varpManager.get(674) - .setVarbit(currentStation.ordinal() * 8, currentStation.getCraftConfig(canoe,true)) - .send(player); - GameWorld.getPulser().submit(new Pulse(1) { - int counter = 0; - - @Override - public boolean pulse() { - if (counter == 1) { - player.getPacketDispatch().sendObjectAnimation(object, FLOAT, false); - player.varpManager.get(674) - .setVarbit(currentStation.ordinal() * 8, currentStation.getCraftConfig(canoe,true)) - .send(player); - setStage(3); - } - counter += 1; - return false; - } - }); - } - - /** - * Method used to travel to a canoe station. - * @param destinationStation the station to travel to. - */ - public final void travel(final CanoeStation destinationStation) { - player.getInterfaceManager().close(); - if (player.getFamiliarManager().hasFamiliar()) { - player.getPacketDispatch().sendMessage("You can't take a follower on a canoe."); - return; - } - player.lock(18); - GameWorld.getPulser().submit(new Pulse(1) { - int count = 0; - - @Override - public boolean pulse() { - switch (count++) { - case 1: - player.getInterfaceManager().openOverlay(new Component(115)); - break; - case 3: - PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2)); - player.getInterfaceManager().hideTabs(0, 1, 2, 3, 4, 5, 6, 11, 12); - break; - case 16: - player.getProperties().setTeleportLocation(destinationStation.getDestination()); - break; - case 17: - - player.getInterfaceManager().close(); - player.getInterfaceManager().restoreTabs(); - PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0)); - player.getPacketDispatch().sendMessage("You arrive " + (destinationStation != CanoeStation.WILDERNESS ? "at " + destinationStation.getName() + "." : "in the wilderness. There are no trees suitable to make a canoe.")); - player.getPacketDispatch().sendMessage(destinationStation != CanoeStation.WILDERNESS ? "Your canoe sinks into the water after the hard journey." : "Your canoe sinks into the water after the hard journey. Looks like you're"); - if (destinationStation == CanoeStation.WILDERNESS) { - player.getPacketDispatch().sendMessage("walking back."); - } - setCanoe(null); - player.varpManager.get(674).setVarbit(currentStation.ordinal() * 8,0).send(player); - setCurrentStation(null); - setStage(0); - player.unlock(); - player.getInterfaceManager().closeOverlay(); - return true; - } - return false; - } - - }); - } - - /** - * Method used to select the destination. - */ - public final void selectDestination() { - player.getInterfaceManager().open(destinationSelector); - int stationIndex = currentStation.ordinal(); - player.getPacketDispatch().sendInterfaceConfig(53, boatChilds[stationIndex], true); - player.getPacketDispatch().sendInterfaceConfig(53, locationChilds[stationIndex], false); - int maxDistance = maxDistances[canoe.ordinal()]; - for (int i = 0; i < CanoeStation.values().length; i++) { - if (Math.abs(currentStation.ordinal() - i) > maxDistance) { - player.getPacketDispatch().sendInterfaceConfig(53, boatChilds[i], true); - } - } - if (canoe != Canoe.WAKA) { - player.getPacketDispatch().sendInterfaceConfig(53, 49, true); - } - } - - /** - * Method used to get the axe to use. - */ - private SkillingTool getTool() { - SkillingTool tool = null; - if (checkTool(SkillingTool.DRAGON_AXE)) { - tool = SkillingTool.DRAGON_AXE; - } else if (checkTool(SkillingTool.RUNE_AXE)) { - tool = SkillingTool.RUNE_AXE; - } else if (checkTool(SkillingTool.ADAMANT_AXE)) { - tool = SkillingTool.ADAMANT_AXE; - } else if (checkTool(SkillingTool.MITHRIL_AXE)) { - tool = SkillingTool.MITHRIL_AXE; - } else if (checkTool(SkillingTool.BLACK_AXE)) { - tool = SkillingTool.BLACK_AXE; - } else if (checkTool(SkillingTool.STEEL_AXE)) { - tool = SkillingTool.STEEL_AXE; - } else if (checkTool(SkillingTool.IRON_AXE)) { - tool = SkillingTool.IRON_AXE; - } else if (checkTool(SkillingTool.BRONZE_AXE)) { - tool = SkillingTool.BRONZE_AXE; - } - return tool; - } - - /** - * Checks if the player has a tool and if he can use it. - * @param tool The tool. - * @return {@code True} if the tool is usable. - */ - private boolean checkTool(SkillingTool tool) { - if (player.getSkills().getStaticLevel(Skills.WOODCUTTING) < tool.getLevel()) { - return false; - } - if (player.getEquipment().getNew(3).getId() == tool.getId()) { - return true; - } - return player.getInventory().contains(tool.getId(), 1); - } - - /** - * Method used to get the shaping animation of a tool. - * @param tool the tool. - * @return the animation. - */ - private Animation getAnimation(final SkillingTool tool) { - Animation animation = null; - switch (tool) { - case BRONZE_AXE: - animation = Animation.create(3291); - break; - case IRON_AXE: - animation = Animation.create(3290); - break; - case STEEL_AXE: - animation = Animation.create(3289); - break; - case BLACK_AXE: - animation = Animation.create(3288); - break; - case MITHRIL_AXE: - animation = Animation.create(3287); - break; - case ADAMANT_AXE: - animation = Animation.create(3286); - break; - case RUNE_AXE: - animation = Animation.create(3285); - break; - case DRAGON_AXE: - animation = Animation.create(3292); - break; - default: - break; - } - return animation; - } - - /** - * Gets the station. - * @return The station. - */ - public CanoeStation getCurrentStation() { - return currentStation; - } - - /** - * Sets the station. - * @param currentStation The station to set. - */ - public void setCurrentStation(CanoeStation currentStation) { - this.currentStation = currentStation; - } - - /** - * Gets the canoe. - * @return The canoe. - */ - public Canoe getCanoe() { - return canoe; - } - - /** - * Sets the canoe. - * @param canoe The canoe to set. - */ - public void setCanoe(Canoe canoe) { - this.canoe = canoe; - } - - /** - * Gets the player. - * @return The player. - */ - public Player getPlayer() { - return player; - } - - /** - * Gets the stage. - * @return The stage. - */ - public int getStage() { - return stage; - } - - /** - * Sets the stage. - * @param stage The stage to set. - */ - public void setStage(int stage) { - this.stage = stage; - } - -} diff --git a/Server/src/main/java/core/game/content/global/travel/canoe/CanoeStation.java b/Server/src/main/java/core/game/content/global/travel/canoe/CanoeStation.java deleted file mode 100644 index eac1632a1..000000000 --- a/Server/src/main/java/core/game/content/global/travel/canoe/CanoeStation.java +++ /dev/null @@ -1,153 +0,0 @@ -package core.game.content.global.travel.canoe; - -import core.game.node.object.GameObject; -import core.game.world.map.Location; -import core.tools.StringUtils; - -/** - * Represents a Canoe location. - * @author 'Vexia - * @date 09/11/2013 - */ -public enum CanoeStation { - LUMBRIDGE(12163, 47, Location.create(3240, 3242, 0), new Location(3241, 3235, 0)), - CHAMPIONS_GUILD(12164, 48, Location.create(3199, 3344, 0), new Location(3200, 3341, 0)), - BARBARIAN_VILLAGE(12165, 3, Location.create(3109, 3415, 0), new Location(3110, 3409, 0)), - EDGEVILLE(12166, 6, Location.create(3132, 3510, 0), new Location(3130, 3508, 0)), - WILDERNESS(-1, 49, Location.create(3139, 3796, 0), null); - - /** - * Constructs a new {@code CanoeStation} {@code Object}. - * @param objectId the object id of the station. - * @param button the button representing the station. - * @param location the location of the station. - * @param destination the location to end at when the station is the destination. - */ - CanoeStation(final int objectId, final int button, final Location destination, final Location location) { - this.object = objectId; - this.button = button; - this.destination = destination; - this.objLocation = location; - } - - /** - * Represents the object id of this station. - */ - private final int object; - - /** - * Represents the button. - */ - private final int button; - - /** - * Represents the location to end at when the station is the destination. - */ - private final Location destination; - - /** - * Represents the location of the canoe station object. - */ - private final Location objLocation; - - /** - * Gets the object id of the station. - * @return The object. - */ - public int getObject() { - return object; - } - - /** - * Method used to get the formatted name of the station. - * @return the name. - */ - public String getName() { - return (this == BARBARIAN_VILLAGE || this == CHAMPIONS_GUILD ? "the " : "") + StringUtils.formatDisplayName(name()); - } - - /** - * Method used to get the CanoeStation by the GameObject. - * @param object the object. - * @return the CanoeStation. - */ - public static CanoeStation getStationByObject(final GameObject object) { - CanoeStation[] stations = values(); - for (CanoeStation station : stations) { - if (station.getObjLocation() != null && station.getObjLocation().equals(object.getLocation())) { - return station; - } - } - return null; - } - - /** - * Method used to get the config for a floating canoe. - * @param canoe the canoe. - * @return the config. - */ - public int getFloatConfig(final Canoe canoe) { - int value = 0; - switch (this) { - case BARBARIAN_VILLAGE: - return (canoe != Canoe.LOG ? 65536 * canoe.ordinal() : 0); - case CHAMPIONS_GUILD: - return (canoe != Canoe.LOG ? 256 * canoe.ordinal() : 0); - case EDGEVILLE: - return (canoe != Canoe.LOG ? 16777216 * canoe.ordinal() : 0); - case LUMBRIDGE: - return (canoe != Canoe.LOG ? canoe.ordinal() : 0); - default: - break; - } - return value; - } - - /** - * Method used to get the config for a crafted canoe. - * @param canoe the canoe. - * @return the config. - */ - public int getCraftConfig(final Canoe canoe, boolean floating) { - return 1 + (canoe.ordinal() + (floating? 10 : 0)); - } - - /** - * Method used to get the canoe station from the button. - * @param button the button. - * @return the station. - */ - public static CanoeStation getStationFromButton(final int button) { - CanoeStation[] stations = values(); - for (CanoeStation station : stations) { - if (station.button == button) { - return station; - } - } - return null; - } - - /** - * Gets the buttons. - * @return the buttons. - */ - public int getButton() { - return button; - } - - /** - * Gets the destination. - * @return The destination. - */ - public Location getDestination() { - return destination; - } - - /** - * Gets the objLocation. - * @return The objLocation. - */ - public Location getObjLocation() { - return objLocation; - } -} diff --git a/Server/src/main/java/core/game/interaction/inter/CanoeInterfacePlugin.java b/Server/src/main/java/core/game/interaction/inter/CanoeInterfacePlugin.java deleted file mode 100644 index 6d0a21852..000000000 --- a/Server/src/main/java/core/game/interaction/inter/CanoeInterfacePlugin.java +++ /dev/null @@ -1,53 +0,0 @@ -package core.game.interaction.inter; - -import core.game.component.Component; -import core.game.component.ComponentDefinition; -import core.game.component.ComponentPlugin; -import core.game.content.global.travel.canoe.Canoe; -import core.game.content.global.travel.canoe.CanoeExtension; -import core.game.content.global.travel.canoe.CanoeStation; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the canoe interface plugins. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class CanoeInterfacePlugin extends ComponentPlugin { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - ComponentDefinition.put(52, this); - ComponentDefinition.put(53, this); - return this; - } - - @Override - public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { - final CanoeExtension extension = CanoeExtension.extension(player); - switch (component.getId()) { - case 52: - final Canoe canoe = Canoe.getCanoeFromChild(button); - if (canoe == null) { - return true; - } - extension.craftCanoe(canoe); - break; - case 53: - final CanoeStation station = CanoeStation.getStationFromButton(button); - if (station == null) { - return true; - } - if (extension.getStage() < 3) { - return true; - } - extension.travel(station); - break; - } - return true; - } - -} \ No newline at end of file diff --git a/Server/src/main/java/core/game/interaction/object/CanoeOptionPlugin.java b/Server/src/main/java/core/game/interaction/object/CanoeOptionPlugin.java deleted file mode 100644 index 6d257f416..000000000 --- a/Server/src/main/java/core/game/interaction/object/CanoeOptionPlugin.java +++ /dev/null @@ -1,102 +0,0 @@ -package core.game.interaction.object; - -import core.cache.def.impl.ObjectDefinition; -import core.game.content.global.travel.canoe.CanoeExtension; -import core.game.content.global.travel.canoe.CanoeStation; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.object.GameObject; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Represents the option handler plugin that will handle all node interactions - * related to canoes. - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class CanoeOptionPlugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - final String[] options = new String[] { "chop-down", "shape-canoe", "float canoe", "paddle canoe", "float log", "float waka", "paddle log" }; - for (CanoeStation station : CanoeStation.values()) { - if (station == CanoeStation.WILDERNESS) { - continue; - } - int ids[] = new int[] { 12140, 12141, 12142, 12143, 12145, 12146, 12147, 12148, 12151, 12152, 12153, 12154, 12155, 12156, 12157, 12158, 12144, 12146, 12149, 12150, 12157 }; - for (String option : options) { - for (int i : ids) { - ObjectDefinition.forId(i).getHandlers().put("option:" + option, this); - } - } - } - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - final GameObject object = ((GameObject) node); - final CanoeExtension extension = CanoeExtension.extension(player); - if (extension.getStage() != 0 && extension.getCurrentStation() != null && extension.getCurrentStation() != CanoeStation.getStationByObject(object)) { - extension.setStage(0); - } - if (extension.getStage() != 0) { - player.faceLocation(player.getLocation().transform(object.getId() == 12163 ? -4 : object.getId() == 12164 ? 0 : object.getId() == 12165 ? -1 : -1, object.getId() == 12163 ? 0 : object.getId() == 12164 ? -1 : object.getId() == 12165 ? 0 : 0, 0)); - } - if (extension.getStage() == 0) { - player.faceLocation(player.getLocation().transform(-1, 0, 0)); - } - switch (extension.getStage()) { - case 0: - extension.chopTree(object); - break; - case 1: - extension.shapeCanoe(); - break; - case 2: - extension.setAfloat(object); - break; - case 3: - extension.selectDestination(); - break; - } - return true; - } - - @Override - public Location getDestination(Node node, Node n) { - final Player p = ((Player) node); - final GameObject object = ((GameObject) n); - final CanoeExtension extension = CanoeExtension.extension(p); - if (object.getLocation().equals(new Location(3110, 3409, 0))) { - if (extension.getStage() == 0) { - return Location.create(3112, 3409, 0); - } else { - return Location.create(3112, 3411, 0); - } - } else if (object.getLocation().equals(new Location(3130, 3508, 0))) { - if (extension.getStage() == 0) { - return Location.create(3132, 3508, 0); - } else { - return Location.create(3132, 3510, 0); - } - } else if (object.getLocation().equals(new Location(3200, 3341, 0))) {// champions - // guild - if (extension.getStage() == 0) { - return Location.create(3204, 3343, 0); - } else { - return Location.create(3202, 3343, 0); - } - } else { - if (extension.getStage() == 0) { - return Location.create(3243, 3235, 0); - } else { - return Location.create(3243, 3237, 0); - } - } - } -} diff --git a/Server/src/main/java/core/game/node/entity/impl/Animator.java b/Server/src/main/java/core/game/node/entity/impl/Animator.java index 843464524..8bc30f93f 100644 --- a/Server/src/main/java/core/game/node/entity/impl/Animator.java +++ b/Server/src/main/java/core/game/node/entity/impl/Animator.java @@ -132,6 +132,10 @@ public final class Animator { return true; } + public void stop(){ + animate(RESET_A); + } + /** * Forces an animation. * @param animation The animation to display. diff --git a/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeInterfaceListeners.kt b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeInterfaceListeners.kt new file mode 100644 index 000000000..c5970e469 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeInterfaceListeners.kt @@ -0,0 +1,127 @@ +package rs09.game.interaction.`object`.canoestation + +import core.cache.def.impl.VarbitDefinition +import core.game.component.Component +import core.game.content.global.travel.canoe.Canoe +import core.game.node.entity.player.link.diary.DiaryType +import core.game.node.entity.skill.Skills +import core.game.node.entity.skill.gather.SkillingTool +import core.game.system.task.Pulse +import core.net.packet.PacketRepository +import core.net.packet.context.MinimapStateContext +import core.net.packet.out.MinimapState +import core.tools.RandomFunction +import org.rs09.consts.Components +import rs09.game.interaction.InterfaceListener + +class CanoeInterfaceListeners : InterfaceListener() { + + val SHAPE_INTERFACE = Components.CANOE_52 + val DESTINATION_INTERFACE = Components.CANOE_STATIONS_MAP_53 + val EDGEVILLE_REGION = 12342 + private val boatChilds = intArrayOf(47, 48, 3, 6, 49) + private val locationChilds = intArrayOf(50, 47, 44, 36) + + + override fun defineListeners() { + + onOpen(SHAPE_INTERFACE){player, _ -> + CanoeUtils.checkCanoe(player,Canoe.DUGOUT) + CanoeUtils.checkCanoe(player,Canoe.STABLE_DUGOUT) + CanoeUtils.checkCanoe(player,Canoe.WAKA) + return@onOpen true + } + + on(SHAPE_INTERFACE) { player, _, _, buttonID, _, _ -> + player.interfaceManager.close() + val canoe = Canoe.getCanoeFromChild(buttonID) + val varbit = player.getAttribute("canoe-varbit", VarbitDefinition.forObjectID(0)) + + val axe: SkillingTool? = SkillingTool.getHatchet(player) + if (axe == null) { + player.packetDispatch.sendMessage("You do not have an axe which you have the woodcutting level to use.") + return@on true + } + + player.lock() + player.animate(axe.animation) + player.pulseManager.run(object : Pulse(3) { + override fun pulse(): Boolean { + if (RandomFunction.random(if (canoe == Canoe.WAKA) 8 else 6) == 1) { + if (player.location.regionId == EDGEVILLE_REGION && canoe == Canoe.WAKA) { + player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 2, 10) + } + player.varpManager.setVarbit(varbit,CanoeUtils.getCraftValue(canoe,false)) + player.skills.addExperience(Skills.WOODCUTTING, canoe.experience) + player.unlock() + return true + } + player.animate(axe.animation) + return false + } + }) + return@on true + } + + onOpen(DESTINATION_INTERFACE){player, component -> + val varbit = player.getAttribute("canoe-varbit",VarbitDefinition.forObjectID(0)) + val canoe = CanoeUtils.getCanoeFromVarbit(player,varbit) + val stationIndex = CanoeUtils.getStationIndex(player.location) + val maxDistance = canoe.maxDist + player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,boatChilds[stationIndex],true) + player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,locationChilds[stationIndex],false) + if(canoe != Canoe.WAKA){ + player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,49,true) + for(i in 0..3){ + if(i == stationIndex) continue + if(Math.abs(i - stationIndex) > maxDistance){ + player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,boatChilds[i],true) + player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,locationChilds[i],true) + } + } + } + return@onOpen true + } + + on(DESTINATION_INTERFACE){player, _, _, buttonID, _, _ -> + val dest = CanoeUtils.getDestinationFromButtonID(buttonID) + val destIndex = CanoeUtils.getStationIndex(dest) + val arrivalMessage = CanoeUtils.getNameByIndex(destIndex) + val varbit = player.getAttribute("canoe-varbit",VarbitDefinition.forObjectID(0)) + if (player.familiarManager.hasFamiliar()) { + player.sendMessage("You can't take a follower on a canoe.") + return@on true + } + player.lock() + player.interfaceManager.close() + player.pulseManager.run(object : Pulse(){ + var counter = 0 + override fun pulse(): Boolean { + when(counter++){ + 0 -> player.interfaceManager.openOverlay(Component(Components.FADE_TO_BLACK_120)) + 2 -> { + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2)) + player.interfaceManager.hideTabs(0, 1, 2, 3, 4, 5, 6, 11, 12) + } + 15 -> player.properties.teleportLocation = dest + 16 -> {player.interfaceManager.closeOverlay(); player.interfaceManager.openOverlay(Component(Components.FADE_FROM_BLACK_170))} + 18 -> { + player.unlock() + player.interfaceManager.restoreTabs() + PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0)) + player.sendMessage("You arrive at $arrivalMessage.") + player.sendMessage("Your canoe sinks from the long journey.") + if(destIndex == 4){ + player.sendMessage("There are no trees nearby to make a new canoe. Guess you're walking.") + } + player.varpManager.setVarbit(varbit,0) + return true + } + } + return false + } + }) + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeStationListener.kt b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeStationListener.kt new file mode 100644 index 000000000..75e96dbe4 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeStationListener.kt @@ -0,0 +1,88 @@ +package rs09.game.interaction.`object`.canoestation + +import core.game.component.Component +import core.game.node.entity.skill.Skills +import core.game.node.entity.skill.gather.SkillingTool +import core.game.system.task.Pulse +import core.game.world.update.flag.context.Animation +import org.rs09.consts.Components +import rs09.game.interaction.InteractionListener + +class CanoeStationListener : InteractionListener() { + + val STATION_IDs = intArrayOf(12140, 12141, 12142, 12143, 12145, 12146, 12147, 12148, 12151, 12152, 12153, 12154, 12155, 12156, 12157, 12158, 12144, 12146, 12149, 12150, 12157) + val CHOP_STATION = intArrayOf(12144) + val STAGE_TREE_NONINTERACTABLE = 9 + val STAGE_LOG_CHOPPED = 10 + private val SHAPING_INTERFACE = Components.CANOE_52 + private val PUSH = Animation(3301) + private val ROW = Animation(3302) + private val FALL = Animation(3303) + private val FLOAT = Animation(3304) + private val SINK = Animation(3305) + + override fun defineListeners() { + on(CHOP_STATION,OBJECT,"chop-down"){player, node -> + val axe: SkillingTool? = SkillingTool.getHatchet(player) + val varbit = node.asObject().definition.configFile + + if(varbit.getValue(player) != 0){ + player.varpManager.setVarbit(varbit,0) + } + + if (axe == null) { + player.packetDispatch.sendMessage("You do not have an axe which you have the woodcutting level to use.") + return@on true + } + if (player.skills.getLevel(Skills.WOODCUTTING) < 12) { + player.packetDispatch.sendMessage("You need a woodcutting level of at least 12 to chop down this tree.") + return@on true + } + player.lock() + player.animate(axe.animation) + player.varpManager.setVarbit(varbit,STAGE_TREE_NONINTERACTABLE) + player.pulseManager.run(object : Pulse(4){ + override fun pulse(): Boolean { + player.animator.stop() + player.varpManager.setVarbit(varbit,STAGE_LOG_CHOPPED) + player.packetDispatch.sendObjectAnimation(node.asObject().getChild(player), FALL, false) + player.unlock() + return true + } + }) + return@on true + } + + on(STATION_IDs,OBJECT,"shape-canoe"){player, node -> + val varbit = node.asObject().definition.configFile + if(varbit.getValue(player) != STAGE_LOG_CHOPPED){ + player.varpManager.setVarbit(varbit,0) + return@on true + } + player.interfaceManager.open(Component(SHAPING_INTERFACE)) + player.setAttribute("canoe-varbit",varbit) + return@on true + } + + on(STATION_IDs,OBJECT,"float canoe","float log","float waka"){player, node -> + val varbit = node.asObject().definition.configFile + val canoe = CanoeUtils.getCanoeFromVarbit(player,varbit) + player.animator.animate(PUSH) + player.lock() + player.pulseManager.run(object : Pulse(){ + override fun pulse(): Boolean { + player.varpManager.setVarbit(varbit,CanoeUtils.getCraftValue(canoe,true)) + player.packetDispatch.sendObjectAnimation(node.asObject(), FLOAT, false) + player.unlock() + return true + } + }) + return@on true + } + + on(STATION_IDs,OBJECT,"paddle log","paddle canoe"){player, node -> + player.interfaceManager.open(Component(Components.CANOE_STATIONS_MAP_53)) + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeUtils.kt b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeUtils.kt new file mode 100644 index 000000000..6dc726245 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/object/canoestation/CanoeUtils.kt @@ -0,0 +1,62 @@ +package rs09.game.interaction.`object`.canoestation + +import core.cache.def.impl.VarbitDefinition +import core.game.content.global.travel.canoe.Canoe +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import org.rs09.consts.Components + +object CanoeUtils { + val SHAPE_INTERFACE = Components.CANOE_52 + + fun checkCanoe(player: Player, canoe: Canoe){ + if(player.skills.getLevel(Skills.WOODCUTTING) < canoe.requiredLevel) return + player.packetDispatch.sendInterfaceConfig(SHAPE_INTERFACE,canoe.silhouetteChild,true) + player.packetDispatch.sendInterfaceConfig(SHAPE_INTERFACE,canoe.textChild,false) + } + + fun getCanoeFromVarbit(player: Player, varbit: VarbitDefinition): Canoe{ + var bit = varbit.getValue(player) + if(bit > 10) bit -= 10 + return Canoe.values()[bit - 1] + } + + fun getCraftValue(canoe: Canoe, floating: Boolean): Int{ + return 1 + (canoe.ordinal + if (floating) 10 else 0) + } + + fun getStationIndex(location: Location): Int{ + return when(location.regionId){ + 12850 -> 0 + 12852,12596 -> 1 + 12341 -> 2 + 12342 -> 3 + 12603 -> 4 + else -> 0 + } + } + + fun getDestinationFromButtonID(buttonID: Int): Location { + return when(buttonID){ + 47 -> Location.create(3240, 3242, 0) + 48 -> Location.create(3199, 3344, 0) + 3 -> Location.create(3109, 3415, 0) + 6 -> Location.create(3132, 3510, 0) + 49 -> Location.create(3139, 3796, 0) + else -> Location.create(3240, 3242, 0) + } + } + + fun getNameByIndex(index: Int): String{ + return when(index){ + 0 -> "Lumbridge" + 1 -> "the Champion's Guild." + 2 -> "Barbarian Village" + 3 -> "Edgeville" + 4 -> "the Wilderness Pond" + else -> "Uhhh report this." + } + } + +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt index 57c0cb074..c953e44e1 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Patch.kt @@ -1,8 +1,8 @@ package rs09.game.node.entity.skill.farming import core.game.node.entity.player.Player -import rs09.game.system.SystemLogger import core.tools.RandomFunction +import rs09.game.system.SystemLogger import java.util.concurrent.TimeUnit class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantable?, var currentGrowthStage: Int, var isDiseased: Boolean, var isDead: Boolean, var isWatered: Boolean, var nextGrowth: Long, var harvestAmt: Int, var isCheckHealth: Boolean) { @@ -180,6 +180,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl currentGrowthStage = 3 setCurrentState(3) compost = CompostType.NONE + protectionPaid = false } fun getFruitOrBerryCount() : Int { diff --git a/Server/src/main/kotlin/rs09/game/node/entity/state/newsys/states/FarmingState.kt b/Server/src/main/kotlin/rs09/game/node/entity/state/newsys/states/FarmingState.kt index 5551ae44c..2297a85aa 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/state/newsys/states/FarmingState.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/state/newsys/states/FarmingState.kt @@ -97,7 +97,8 @@ class FarmingState(player: Player? = null) : State(player) { patch.compost = CompostType.values()[compostOrdinal] patch.protectionPaid = protectionPaid - if(patch.currentGrowthStage < patch.plantable?.stages ?: 0 && !patch.isWeedy()){ + patch.setCurrentState(savedState) + if((patch.currentGrowthStage < patch.plantable?.stages ?: 0) && !patch.isWeedy()){ val startTime = (patch.nextGrowth - TimeUnit.MINUTES.toMillis(patch.patch.type.stageGrowthTime * (patch.currentGrowthStage + 1).toLong())) var expectedStage = Math.floor((System.currentTimeMillis() - startTime.toDouble()) / TimeUnit.MINUTES.toMillis(patch.patch.type.stageGrowthTime.toLong())).toInt() SystemLogger.logErr("$expectedStage $startTime ${System.currentTimeMillis()}") @@ -112,7 +113,7 @@ class FarmingState(player: Player? = null) : State(player) { } } - if(savedState > patch.plantable?.value ?: 0 + patch.currentGrowthStage){ + if((savedState - (patch?.plantable?.value ?: 0)) > patch.plantable?.value ?: 0 + patch.currentGrowthStage){ patch.setCurrentState(savedState) } else { patch.setCurrentState((patch.plantable?.value ?: 0) + patch.currentGrowthStage)