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.
@@ -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
}
}
}
@@ -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
}
}
}
@@ -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."
}
}
}
@@ -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 {
@@ -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)