Fixed farming bug, redid canoe stations entirely into new listener system

This commit is contained in:
Ceikry
2021-03-15 15:49:57 -05:00
parent 8992e81581
commit df40fbb32d
11 changed files with 298 additions and 772 deletions
@@ -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.
*/
@@ -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 <code>CanoeExtension</code>
*/
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;
}
}
@@ -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 <b>Canoe</b> 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 <b>CanoeStation</b> by the <b>GameObject</b>.
* @param object the object.
* @return the <code>CanoeStation</code>.
*/
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;
}
}
@@ -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<Object> 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;
}
}
@@ -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<Object> 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);
}
}
}
}
@@ -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.