mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -07:00
Rewrote grappling, fixes Yanille south shortcut, Catherby skill check and requirements text getting cut off
This commit is contained in:
parent
24b314426e
commit
50eb295fda
15 changed files with 788 additions and 651 deletions
|
|
@ -1,114 +0,0 @@
|
||||||
package content.global.skill.agility.shortcuts
|
|
||||||
|
|
||||||
import core.api.*
|
|
||||||
import core.game.node.entity.player.Player
|
|
||||||
import core.game.node.entity.skill.Skills
|
|
||||||
import core.game.system.task.Pulse
|
|
||||||
import core.game.world.map.Location
|
|
||||||
import core.game.world.update.flag.context.Animation
|
|
||||||
import org.rs09.consts.Items
|
|
||||||
import org.rs09.consts.Scenery
|
|
||||||
import core.game.interaction.IntType
|
|
||||||
import core.game.interaction.InteractionListener
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the Catherby to Taverley grapple shortcut
|
|
||||||
* @author Byte
|
|
||||||
*/
|
|
||||||
class CatherbyGrappleShortcut : InteractionListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val START_LOCATION: Location = Location.create(2866, 3429, 0)
|
|
||||||
private val END_LOCATION: Location = Location.create(2869,3430,0)
|
|
||||||
|
|
||||||
private val REQUIREMENTS = hashMapOf(
|
|
||||||
Skills.AGILITY to 32,
|
|
||||||
Skills.RANGE to 35,
|
|
||||||
Skills.STRENGTH to 35
|
|
||||||
)
|
|
||||||
|
|
||||||
private val VALID_CROSSBOWS = intArrayOf(
|
|
||||||
Items.MITH_CROSSBOW_9181,
|
|
||||||
Items.ADAMANT_CROSSBOW_9183,
|
|
||||||
Items.RUNE_CROSSBOW_9185,
|
|
||||||
Items.DORGESHUUN_CBOW_8880
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var rocks = getScenery(Location.create(2869,3429, 0))
|
|
||||||
|
|
||||||
override fun defineListeners() {
|
|
||||||
flagInstant() // execute listeners instantly without determining path
|
|
||||||
|
|
||||||
on(Scenery.ROCKS_17042, IntType.SCENERY, "grapple") { player, _ ->
|
|
||||||
if (isPlayerInRangeToGrapple(player)) {
|
|
||||||
forceWalk(player, START_LOCATION, "smart")
|
|
||||||
} else {
|
|
||||||
sendMessage(player, "Nothing interesting happens.")
|
|
||||||
return@on true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!doesPlayerHaveRequiredItemsEquipped(player)) {
|
|
||||||
sendDialogue(player, "You need a Mithril crossbow and a Mithril grapple in order to do this.")
|
|
||||||
return@on true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!doesPlayerHaveRequiredLevels(player)) {
|
|
||||||
sendDialogueLines(player,
|
|
||||||
"You need at least " +
|
|
||||||
REQUIREMENTS[Skills.AGILITY] + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", " +
|
|
||||||
REQUIREMENTS[Skills.RANGE] + " " + Skills.SKILL_NAME[Skills.RANGE] + ", ",
|
|
||||||
"and " +
|
|
||||||
REQUIREMENTS[Skills.STRENGTH] + " " + Skills.SKILL_NAME[Skills.STRENGTH] + " to use this shortcut."
|
|
||||||
)
|
|
||||||
return@on true
|
|
||||||
}
|
|
||||||
|
|
||||||
lock(player, 15)
|
|
||||||
submitWorldPulse(object : Pulse(2) {
|
|
||||||
var counter = 0
|
|
||||||
override fun pulse() : Boolean {
|
|
||||||
when (counter++) {
|
|
||||||
1 -> {
|
|
||||||
face(player, END_LOCATION)
|
|
||||||
// Audit: shows player climbing (probably a wall), need a cliff climb animation
|
|
||||||
animate(player, Animation(4455))
|
|
||||||
}
|
|
||||||
3 -> {
|
|
||||||
// Audit: shows grapple on rocks, but there is no rope
|
|
||||||
replaceScenery(rocks!!, rocks!!.id + 1, 10)
|
|
||||||
}
|
|
||||||
8 -> {
|
|
||||||
teleport(player, END_LOCATION)
|
|
||||||
}
|
|
||||||
9 -> {
|
|
||||||
sendMessage(player, "You successfully grapple the rock and climb the cliffside.")
|
|
||||||
unlock(player)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return@on true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doesPlayerHaveRequiredItemsEquipped(player: Player): Boolean {
|
|
||||||
return inEquipment(player, Items.MITH_GRAPPLE_9419) && anyInEquipment(player, *VALID_CROSSBOWS)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doesPlayerHaveRequiredLevels(player: Player): Boolean {
|
|
||||||
for ((skill, requiredLevel) in REQUIREMENTS) {
|
|
||||||
if (!hasLevelDyn(player, skill, requiredLevel)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isPlayerInRangeToGrapple(player: Player): Boolean {
|
|
||||||
return inBorders(player, START_LOCATION.x - 2, START_LOCATION.y - 2, START_LOCATION.x, START_LOCATION.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
package content.global.skill.agility.shortcuts;
|
|
||||||
|
|
||||||
import core.cache.def.impl.SceneryDefinition;
|
|
||||||
import core.game.component.Component;
|
|
||||||
import org.rs09.consts.Items;
|
|
||||||
import core.game.interaction.OptionHandler;
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.impl.ForceMovement;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.entity.player.link.diary.DiaryType;
|
|
||||||
import core.game.node.item.Item;
|
|
||||||
import core.game.system.task.Pulse;
|
|
||||||
import core.game.world.GameWorld;
|
|
||||||
import core.game.world.map.Location;
|
|
||||||
import core.game.world.update.flag.context.Animation;
|
|
||||||
import core.game.world.update.flag.context.Graphics;
|
|
||||||
import core.net.packet.PacketRepository;
|
|
||||||
import core.net.packet.context.MinimapStateContext;
|
|
||||||
import core.net.packet.out.MinimapState;
|
|
||||||
import core.plugin.Initializable;
|
|
||||||
import core.plugin.Plugin;
|
|
||||||
import core.game.node.entity.skill.Skills;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the plugin used to handle the grappling of the falador wall.
|
|
||||||
*
|
|
||||||
* @author 'Vexia
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
@Initializable
|
|
||||||
public final class FaladorGrapplePlugin extends OptionHandler {
|
|
||||||
private static final HashMap<Integer, Integer> REQUIREMENTS = new HashMap<>();
|
|
||||||
private static String requirementsString;
|
|
||||||
|
|
||||||
static {
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.AGILITY, 11);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.RANGE, 19);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.STRENGTH, 37);
|
|
||||||
|
|
||||||
requirementsString = "You need at least "
|
|
||||||
+ REQUIREMENTS.get(Skills.AGILITY) + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", "
|
|
||||||
+ REQUIREMENTS.get(Skills.RANGE) + " " + Skills.SKILL_NAME[Skills.RANGE] + ", and "
|
|
||||||
+ REQUIREMENTS.get(Skills.STRENGTH) + " " + Skills.SKILL_NAME[Skills.STRENGTH]
|
|
||||||
+ " to use this shortcut.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int[] CBOWS = new int[]{
|
|
||||||
Items.MITH_CROSSBOW_9181,
|
|
||||||
Items.ADAMANT_CROSSBOW_9183,
|
|
||||||
Items.RUNE_CROSSBOW_9185,
|
|
||||||
Items.DORGESHUUN_CBOW_8880
|
|
||||||
};
|
|
||||||
private static final Item MITH_GRAPPLE = new Item(9419);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
|
||||||
SceneryDefinition.forId(17049).getHandlers().put("option:grapple", this);
|
|
||||||
SceneryDefinition.forId(17050).getHandlers().put("option:grapple", this);
|
|
||||||
SceneryDefinition.forId(17051).getHandlers().put("option:jump", this);
|
|
||||||
SceneryDefinition.forId(17052).getHandlers().put("option:jump", this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handle(final Player player, final Node node, String option) {
|
|
||||||
Location destination;
|
|
||||||
Location current = player.getLocation();
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case "jump":
|
|
||||||
ForceMovement.run(player,
|
|
||||||
current,
|
|
||||||
node.asScenery().getId() == 17051
|
|
||||||
? Location.create(3033, 3390, 0)
|
|
||||||
: Location.create(3032, 3388, 0),
|
|
||||||
new Animation(7268),
|
|
||||||
10);
|
|
||||||
break;
|
|
||||||
case "grapple":
|
|
||||||
destination = node.asScenery().getId() == 17049
|
|
||||||
? Location.create(3033, 3389, 1)
|
|
||||||
: Location.create(3032, 3391, 1);
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, Integer> e : REQUIREMENTS.entrySet()) {
|
|
||||||
if (player.getSkills().getLevel(e.getKey()) < e.getValue()) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue(requirementsString);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getEquipment().containsAtLeastOneItem(CBOWS) || !player.getEquipment().containsItem(MITH_GRAPPLE)) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue("You need a Mithril crossbow and a Mithril grapple in order to do this.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.lock();
|
|
||||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
|
||||||
int counter = 1;
|
|
||||||
Component tab;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pulse() {
|
|
||||||
switch (counter++) {
|
|
||||||
case 1:
|
|
||||||
player.faceLocation(destination);
|
|
||||||
player.visualize(new Animation(4455), new Graphics(760, 100));
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
tab = player.getInterfaceManager().getSingleTab();
|
|
||||||
player.getInterfaceManager().openOverlay(new Component(115));
|
|
||||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2));
|
|
||||||
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12);
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
player.getProperties().setTeleportLocation(destination);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
player.getInterfaceManager().restoreTabs();
|
|
||||||
if (tab != null) {
|
|
||||||
player.getInterfaceManager().openTab(tab);
|
|
||||||
}
|
|
||||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
|
|
||||||
player.getInterfaceManager().closeOverlay();
|
|
||||||
player.getInterfaceManager().close();
|
|
||||||
player.unlock();
|
|
||||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.FALADOR, 1, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getDestination(final Node moving, final Node destination) {
|
|
||||||
return destination.asScenery().getId() == 17050 ? Location.create(3032, 3388, 0) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
package content.global.skill.agility.shortcuts;
|
|
||||||
|
|
||||||
import core.cache.def.impl.SceneryDefinition;
|
|
||||||
import core.game.component.Component;
|
|
||||||
import org.rs09.consts.Items;
|
|
||||||
import core.game.interaction.OptionHandler;
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.entity.player.link.diary.DiaryType;
|
|
||||||
import core.game.node.item.Item;
|
|
||||||
import core.game.node.scenery.Scenery;
|
|
||||||
import core.game.system.task.Pulse;
|
|
||||||
import core.game.world.GameWorld;
|
|
||||||
import core.game.world.map.Direction;
|
|
||||||
import core.game.world.map.Location;
|
|
||||||
import core.game.world.map.RegionManager;
|
|
||||||
import core.game.world.update.flag.context.Animation;
|
|
||||||
import core.plugin.Initializable;
|
|
||||||
import core.plugin.Plugin;
|
|
||||||
import core.game.node.entity.skill.Skills;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Initializable
|
|
||||||
public class KaramjaGrapple extends OptionHandler {
|
|
||||||
private static final HashMap<Integer, Integer> REQUIREMENTS = new HashMap<>();
|
|
||||||
private static final String requirementsString;
|
|
||||||
|
|
||||||
static {
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.AGILITY, 53);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.RANGE, 42);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.STRENGTH, 21);
|
|
||||||
|
|
||||||
requirementsString = "You need at least "
|
|
||||||
+ REQUIREMENTS.get(Skills.AGILITY) + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", "
|
|
||||||
+ REQUIREMENTS.get(Skills.RANGE) + " " + Skills.SKILL_NAME[Skills.RANGE] + ", and "
|
|
||||||
+ REQUIREMENTS.get(Skills.STRENGTH) + " " + Skills.SKILL_NAME[Skills.STRENGTH]
|
|
||||||
+ " to use this shortcut.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int[] CBOWS = new int[]{
|
|
||||||
Items.MITH_CROSSBOW_9181,
|
|
||||||
Items.ADAMANT_CROSSBOW_9183,
|
|
||||||
Items.RUNE_CROSSBOW_9185,
|
|
||||||
Items.DORGESHUUN_CBOW_8880
|
|
||||||
};
|
|
||||||
private static final Item MITH_GRAPPLE = new Item(9419);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
|
||||||
SceneryDefinition.forId(17074).getHandlers().put("option:grapple", this);
|
|
||||||
// island tree 17074 +1 rope loop, +2 grappled one way, +3 grappled other way
|
|
||||||
// north tree 17056 +1 rope loop, +2 grappled
|
|
||||||
// south tree 17059 +1 rope loop, +2 grappled
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handle(Player player, Node node, String option) {
|
|
||||||
Location destination;
|
|
||||||
Location current = player.getLocation();
|
|
||||||
Scenery startTree, endTree;
|
|
||||||
Direction direction;
|
|
||||||
if (current.getY() > 3134) { // starting at north side
|
|
||||||
startTree = RegionManager.getObject(Location.create(2874, 3144, 0));
|
|
||||||
endTree = RegionManager.getObject(Location.create(2873, 3125, 0));
|
|
||||||
destination = Location.create(2874, 3127, 0);
|
|
||||||
direction = Direction.SOUTH;
|
|
||||||
} else {
|
|
||||||
startTree = RegionManager.getObject(Location.create(2873, 3125, 0));
|
|
||||||
endTree = RegionManager.getObject(Location.create(2874, 3144, 0));
|
|
||||||
destination = Location.create(2874, 3142, 0);
|
|
||||||
direction = Direction.NORTH;
|
|
||||||
}
|
|
||||||
Scenery islandTree = RegionManager.getObject(Location.create(2873, 3134, 0));
|
|
||||||
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case "grapple":
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, Integer> e : REQUIREMENTS.entrySet()) {
|
|
||||||
if (player.getSkills().getLevel(e.getKey()) < e.getValue()) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue(requirementsString);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getEquipment().containsAtLeastOneItem(CBOWS) || !player.getEquipment().containsItem(MITH_GRAPPLE)) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue("You need a Mithril crossbow and a Mithril grapple in order to do this.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.lock();
|
|
||||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
|
||||||
int counter = 1;
|
|
||||||
Component tab;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pulse() {
|
|
||||||
switch (counter++) {
|
|
||||||
// TODO animations not implemented.
|
|
||||||
// See ~11min in https://www.youtube.com/watch?v=qpB53rzYqrA
|
|
||||||
// don't know how to get ropes to show up. The tree objects have grapples and stuff but don't look like the video and aren't the right directions
|
|
||||||
// splash gfx are 68 and 69, not sure why there are two
|
|
||||||
// not sure what swimming animation is, could be 4464 thru 4468
|
|
||||||
case 1:
|
|
||||||
player.faceLocation(player.getLocation().transform(direction));
|
|
||||||
player.animate(new Animation(4230));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
//player.getPacketDispatch().sendPositionedGraphic(67, 10, 0, player.getLocation().transform(direction, 5)); //
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
//ObjectBuilder.replace(startTree, startTree.transform(startTree.getId() + 1), 10);
|
|
||||||
//ObjectBuilder.replace(islandTree, islandTree.transform(islandTree.getId() + 1), 10);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
player.getProperties().setTeleportLocation(destination);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
player.unlock();
|
|
||||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 2, 6);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getDestination(final Node moving, final Node destination) {
|
|
||||||
// Run between tree and water before firing grapple
|
|
||||||
if (moving.getLocation().getY() > 3134) { // starting at north side
|
|
||||||
return Location.create(2874, 3142, 0);
|
|
||||||
} else {
|
|
||||||
return Location.create(2874, 3127, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
package content.global.skill.agility.shortcuts;
|
|
||||||
|
|
||||||
import core.cache.def.impl.SceneryDefinition;
|
|
||||||
import core.game.component.Component;
|
|
||||||
import org.rs09.consts.Items;
|
|
||||||
import core.game.interaction.OptionHandler;
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.entity.player.link.diary.DiaryType;
|
|
||||||
import core.game.node.item.Item;
|
|
||||||
import core.game.node.scenery.Scenery;
|
|
||||||
import core.game.node.scenery.SceneryBuilder;
|
|
||||||
import core.game.system.task.Pulse;
|
|
||||||
import core.game.world.GameWorld;
|
|
||||||
import core.game.world.map.Location;
|
|
||||||
import core.game.world.map.RegionManager;
|
|
||||||
import core.game.world.update.flag.context.Animation;
|
|
||||||
import core.plugin.Initializable;
|
|
||||||
import core.plugin.Plugin;
|
|
||||||
import core.game.node.entity.skill.Skills;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Initializable
|
|
||||||
public class WaterOrbGrapple extends OptionHandler {
|
|
||||||
private static final HashMap<Integer, Integer> REQUIREMENTS = new HashMap<>();
|
|
||||||
private static final String requirementsString;
|
|
||||||
|
|
||||||
static {
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.AGILITY, 36);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.RANGE, 39);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.STRENGTH, 22);
|
|
||||||
|
|
||||||
requirementsString = "You need at least "
|
|
||||||
+ REQUIREMENTS.get(Skills.AGILITY) + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", "
|
|
||||||
+ REQUIREMENTS.get(Skills.RANGE) + " " + Skills.SKILL_NAME[Skills.RANGE] + ", and "
|
|
||||||
+ REQUIREMENTS.get(Skills.STRENGTH) + " " + Skills.SKILL_NAME[Skills.STRENGTH]
|
|
||||||
+ " to use this shortcut.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int[] CBOWS = new int[]{
|
|
||||||
Items.MITH_CROSSBOW_9181,
|
|
||||||
Items.ADAMANT_CROSSBOW_9183,
|
|
||||||
Items.RUNE_CROSSBOW_9185,
|
|
||||||
Items.DORGESHUUN_CBOW_8880
|
|
||||||
};
|
|
||||||
private static final Item MITH_GRAPPLE = new Item(9419);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
|
||||||
SceneryDefinition.forId(17062).getHandlers().put("option:grapple", this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handle(Player player, Node node, String option) {
|
|
||||||
Location destination;
|
|
||||||
Location current = player.getLocation();
|
|
||||||
Scenery rock = RegionManager.getObject(Location.create(2841, 3426, 0));
|
|
||||||
Scenery tree = RegionManager.getObject(Location.create(2841, 3434, 0));
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case "grapple":
|
|
||||||
destination = Location.create(2841, 3433, 0);
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, Integer> e : REQUIREMENTS.entrySet()) {
|
|
||||||
if (player.getSkills().getLevel(e.getKey()) < e.getValue()) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue(requirementsString);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getEquipment().containsAtLeastOneItem(CBOWS) || !player.getEquipment().containsItem(MITH_GRAPPLE)) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue("You need a Mithril crossbow and a Mithril grapple in order to do this.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.lock();
|
|
||||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
|
||||||
int counter = 1;
|
|
||||||
Component tab;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pulse() {
|
|
||||||
switch (counter++) {
|
|
||||||
// TODO this animation sequence is wrong. sendPositionedGraphic doesn't work correctly, and rest of water crossing not well implemented
|
|
||||||
// See 4:24 in https://www.youtube.com/watch?v=O90y-N_vwTc
|
|
||||||
// rope gfx is 67
|
|
||||||
// splash gfx are 68 and 69, not sure why there are two
|
|
||||||
// not sure what swimming animation is, could be 4464 thru 4468
|
|
||||||
case 1:
|
|
||||||
player.faceLocation(destination);
|
|
||||||
player.animate(new Animation(4230));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
player.getPacketDispatch().sendPositionedGraphic(67, 10, 0, Location.create(2840,3427,0)); //
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
SceneryBuilder.replace(rock, rock.transform(rock.getId() + 1), 10);
|
|
||||||
SceneryBuilder.replace(tree, tree.transform(tree.getId() + 1), 10);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
player.getProperties().setTeleportLocation(destination);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
player.unlock();
|
|
||||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 2, 10);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getDestination(final Node moving, final Node destination) {
|
|
||||||
// Run between rock and stream before firing grapple
|
|
||||||
return Location.create(2841, 3427, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
package content.global.skill.agility.shortcuts;
|
|
||||||
|
|
||||||
import core.cache.def.impl.SceneryDefinition;
|
|
||||||
import core.game.component.Component;
|
|
||||||
import core.game.interaction.OptionHandler;
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.impl.ForceMovement;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.item.Item;
|
|
||||||
import core.game.system.task.Pulse;
|
|
||||||
import core.game.world.GameWorld;
|
|
||||||
import core.game.world.map.Location;
|
|
||||||
import core.game.world.update.flag.context.Animation;
|
|
||||||
import core.game.world.update.flag.context.Graphics;
|
|
||||||
import core.net.packet.PacketRepository;
|
|
||||||
import core.net.packet.context.MinimapStateContext;
|
|
||||||
import core.net.packet.out.MinimapState;
|
|
||||||
import core.plugin.Initializable;
|
|
||||||
import core.plugin.Plugin;
|
|
||||||
import core.game.node.entity.skill.Skills;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Initializable
|
|
||||||
public class YanilleGrapple extends OptionHandler {
|
|
||||||
private static final HashMap<Integer, Integer> REQUIREMENTS = new HashMap<>();
|
|
||||||
private static String requirementsString;
|
|
||||||
|
|
||||||
static {
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.AGILITY, 39);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.RANGE, 21);
|
|
||||||
REQUIREMENTS.putIfAbsent(Skills.STRENGTH, 38);
|
|
||||||
|
|
||||||
requirementsString = "You need at least "
|
|
||||||
+ REQUIREMENTS.get(Skills.AGILITY) + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", "
|
|
||||||
+ REQUIREMENTS.get(Skills.RANGE) + " " + Skills.SKILL_NAME[Skills.RANGE] + ", and "
|
|
||||||
+ REQUIREMENTS.get(Skills.STRENGTH) + " " + Skills.SKILL_NAME[Skills.STRENGTH]
|
|
||||||
+ " to use this shortcut.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Item MITH_CBOW = new Item(9181);
|
|
||||||
private static final Item MITH_GRAPPLE = new Item(9419);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
|
||||||
SceneryDefinition.forId(17047).getHandlers().put("option:grapple", this);
|
|
||||||
SceneryDefinition.forId(17048).getHandlers().put("option:jump", this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handle(Player player, Node node, String option) {
|
|
||||||
Location destination;
|
|
||||||
Location current = player.getLocation();
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case "jump":
|
|
||||||
ForceMovement.run(player,
|
|
||||||
current,
|
|
||||||
current.getY() < 3074 ? Location.create(2556,3072,0) : Location.create(2556,3075,0),
|
|
||||||
new Animation(7268),
|
|
||||||
10);
|
|
||||||
break;
|
|
||||||
case "grapple":
|
|
||||||
destination = current.getY() < 3073
|
|
||||||
? Location.create(2556, 3073, 1)
|
|
||||||
: Location.create(2556, 3074, 1);
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, Integer> e : REQUIREMENTS.entrySet()) {
|
|
||||||
if (player.getSkills().getLevel(e.getKey()) < e.getValue()) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue(requirementsString);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getEquipment().containsItem(MITH_CBOW) || !player.getEquipment().containsItem(MITH_GRAPPLE)) {
|
|
||||||
player.getDialogueInterpreter().sendDialogue("You need a Mithril crossbow and a Mithril grapple in order to do this.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.lock();
|
|
||||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
|
||||||
int counter = 1;
|
|
||||||
Component tab;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pulse() {
|
|
||||||
switch (counter++) {
|
|
||||||
case 1:
|
|
||||||
player.faceLocation(destination);
|
|
||||||
player.visualize(new Animation(4455), new Graphics(760, 100));
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
tab = player.getInterfaceManager().getSingleTab();
|
|
||||||
player.getInterfaceManager().openOverlay(new Component(115));
|
|
||||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2));
|
|
||||||
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12);
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
player.getProperties().setTeleportLocation(destination);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
player.getInterfaceManager().restoreTabs();
|
|
||||||
if (tab != null) {
|
|
||||||
player.getInterfaceManager().openTab(tab);
|
|
||||||
}
|
|
||||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
|
|
||||||
player.getInterfaceManager().closeOverlay();
|
|
||||||
player.getInterfaceManager().close();
|
|
||||||
player.unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.interaction.InteractionListener
|
||||||
|
import core.game.interaction.QueueStrength
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.node.scenery.Scenery
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import org.rs09.consts.Items
|
||||||
|
|
||||||
|
abstract class AbstractGrappleShortcut : InteractionListener {
|
||||||
|
/**
|
||||||
|
* Make sure that you have flagInstant in your listeners.
|
||||||
|
* If you do not the player will run and try to touch the grapple point
|
||||||
|
*/
|
||||||
|
private val VALID_CROSSBOWS = intArrayOf(
|
||||||
|
Items.MITH_CROSSBOW_9181,
|
||||||
|
Items.ADAMANT_CROSSBOW_9183,
|
||||||
|
Items.RUNE_CROSSBOW_9185,
|
||||||
|
Items.DORGESHUUN_CBOW_8880
|
||||||
|
)
|
||||||
|
|
||||||
|
protected abstract val REQUIREMENTS: HashMap<Int, Int>
|
||||||
|
|
||||||
|
protected abstract val grappleStartLocation: Location
|
||||||
|
protected abstract val grappleEndLocation: Location
|
||||||
|
|
||||||
|
// use lazy so that the skill requirements can be populated after the child builds them
|
||||||
|
private val requirementString1: String by lazy {
|
||||||
|
"You need at least " +
|
||||||
|
REQUIREMENTS[Skills.AGILITY] + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", " +
|
||||||
|
REQUIREMENTS[Skills.RANGE] + " " + Skills.SKILL_NAME[Skills.RANGE] + ","
|
||||||
|
}
|
||||||
|
private val requirementString2: String by lazy {
|
||||||
|
"and " +
|
||||||
|
REQUIREMENTS[Skills.STRENGTH] + " " + Skills.SKILL_NAME[Skills.STRENGTH] + " to use this shortcut."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// What needs to have its model changed during a grapple
|
||||||
|
protected abstract val grappleScenery: List<Scenery?>
|
||||||
|
|
||||||
|
// What animation to use when getting the player across
|
||||||
|
protected abstract val animation: Animation
|
||||||
|
// How long should the animation last (in ticks)
|
||||||
|
protected abstract val animationDuration: Int
|
||||||
|
|
||||||
|
protected abstract fun animation(animationStage: Int, player: Player): Boolean
|
||||||
|
|
||||||
|
|
||||||
|
// The message that can appear if there should be one after grappling
|
||||||
|
protected val message: String? = null
|
||||||
|
|
||||||
|
private fun getRequirementString(): Array<String> {
|
||||||
|
val requirementString = arrayOf(requirementString1, requirementString2)
|
||||||
|
return requirementString
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doesPlayerHaveRequiredItemsEquipped(player: Player): Boolean {
|
||||||
|
return inEquipment(player, Items.MITH_GRAPPLE_9419) && anyInEquipment(player, *VALID_CROSSBOWS)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doesPlayerHaveRequiredLevels(player: Player): Boolean {
|
||||||
|
for ((skill, requiredLevel) in REQUIREMENTS) {
|
||||||
|
if (!hasLevelDyn(player, skill, requiredLevel)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun isPlayerInRangeToGrapple(player: Player, startLoc: Location, range: Int): Boolean {
|
||||||
|
return inBorders(player, startLoc.x - range, startLoc.y - range,
|
||||||
|
startLoc.x + range, startLoc.y + range)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See if the [player] is close enough to the [startLoc] (based on [range] to
|
||||||
|
* try and grapple. This will return false if the [player] is too far away,
|
||||||
|
* if the player does not have the right levels or if the player does not have
|
||||||
|
* the correct gear equipped.
|
||||||
|
*/
|
||||||
|
protected fun canGrapple(player: Player, startLoc: Location, range: Int): Boolean {
|
||||||
|
if (isPlayerInRangeToGrapple(player, startLoc, range)) {
|
||||||
|
forceWalk(player, startLoc, "smart")
|
||||||
|
} else {
|
||||||
|
// todo should this be "you are too far away" or something like that?
|
||||||
|
sendMessage(player, "Nothing interesting happens.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doesPlayerHaveRequiredItemsEquipped(player)) {
|
||||||
|
sendDialogue(player, "You need a Mithril crossbow and a Mithril grapple in order to do this.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doesPlayerHaveRequiredLevels(player)) {
|
||||||
|
sendDialogueLines(player,
|
||||||
|
*getRequirementString()
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun grapple(player: Player, message: String?): Boolean {
|
||||||
|
|
||||||
|
lock(player, animationDuration)
|
||||||
|
// TODO is this right? should we force the player to cross?
|
||||||
|
queueScript(player, strength = QueueStrength.SOFT) { stage: Int ->
|
||||||
|
if (animation(stage, player)){
|
||||||
|
// We're done with the animation
|
||||||
|
return@queueScript stopExecuting(player)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return@queueScript delayScript(player, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message?.let{
|
||||||
|
player.sendMessage(message)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If an achievement diary can be updated it should be done here
|
||||||
|
*/
|
||||||
|
protected open fun updateDiary(player: Player): Boolean{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
|
||||||
|
abstract class AbstractOneWayGrapple : AbstractGrappleShortcut() {
|
||||||
|
|
||||||
|
|
||||||
|
override fun animation(animationStage: Int, player: Player): Boolean {
|
||||||
|
when (animationStage) {
|
||||||
|
1 -> {
|
||||||
|
// Point towards the grapple landing zone
|
||||||
|
face(player, grappleEndLocation)
|
||||||
|
// Start the grapple animation
|
||||||
|
animate(player, animation)
|
||||||
|
}
|
||||||
|
|
||||||
|
5 -> {
|
||||||
|
for (tgt in grappleScenery) {
|
||||||
|
// Add grapple effects to all scenery (for 10 ticks)
|
||||||
|
replaceScenery(tgt!!, tgt.id + 1, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
5 + animationDuration -> {
|
||||||
|
// After the animation is done teleport to the landing zone
|
||||||
|
teleport(player, grappleEndLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
5 + animationDuration + 1 -> {
|
||||||
|
// free the player
|
||||||
|
unlock(player)
|
||||||
|
updateDiary(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.world.map.Direction
|
||||||
|
import core.game.world.map.Location
|
||||||
|
|
||||||
|
abstract class AbstractTwoWayGrapple : AbstractGrappleShortcut(){
|
||||||
|
|
||||||
|
abstract var direction: Direction?
|
||||||
|
|
||||||
|
abstract var startLoc: Location?
|
||||||
|
abstract var endLoc: Location?
|
||||||
|
|
||||||
|
protected abstract fun setStartEndSide(player: Player, margin: Int = 5)
|
||||||
|
protected abstract fun getGrappleScenery(direction: Direction): List<core.game.node.scenery.Scenery?>
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.world.map.Direction
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
|
||||||
|
class AlKharidGrapple : AbstractTwoWayGrapple(){
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 8, Skills.RANGE to 37, Skills.STRENGTH to 19)
|
||||||
|
|
||||||
|
// Lumbridge
|
||||||
|
override val grappleStartLocation: Location = Location(3246, 3179, 0)
|
||||||
|
|
||||||
|
// Al Kharid
|
||||||
|
override val grappleEndLocation: Location = Location(3259, 3179, 0)
|
||||||
|
|
||||||
|
override var direction: Direction? = null
|
||||||
|
override var startLoc: Location? = null
|
||||||
|
override var endLoc: Location? = null
|
||||||
|
|
||||||
|
override var grappleScenery: List<core.game.node.scenery.Scenery?> = listOf()
|
||||||
|
|
||||||
|
override val animation: Animation = Animation(4230)
|
||||||
|
override val animationDuration: Int = 9
|
||||||
|
override fun animation(animationStage: Int, player: Player): Boolean {
|
||||||
|
when (animationStage) {
|
||||||
|
1 -> {
|
||||||
|
face(player, endLoc!!)
|
||||||
|
animate(player, animation)
|
||||||
|
}
|
||||||
|
|
||||||
|
5 -> {
|
||||||
|
for (tgt in grappleScenery) {
|
||||||
|
if ((tgt!!.id == 17068)) {
|
||||||
|
// This is the raft
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
replaceScenery(tgt, tgt.id + 1, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
5 + animationDuration -> {
|
||||||
|
teleport(player, endLoc!!)
|
||||||
|
}
|
||||||
|
5 + animationDuration + 1 -> {
|
||||||
|
unlock(player)
|
||||||
|
updateDiary(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant() // execute listeners instantly without determining path
|
||||||
|
|
||||||
|
on(Scenery.BROKEN_RAFT_17068, IntType.SCENERY, "grapple") { player, target ->
|
||||||
|
// Check if we are on the east or the west of the broken raft
|
||||||
|
// East = Lum
|
||||||
|
setStartEndSide(player)
|
||||||
|
if (!canGrapple(player, startLoc!!, 2)){
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player,message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun setStartEndSide(player: Player, margin: Int) {
|
||||||
|
if (player.location.x < grappleStartLocation.x + margin){
|
||||||
|
// We're on the west side
|
||||||
|
direction = Direction.EAST // got to jump east
|
||||||
|
startLoc = grappleStartLocation
|
||||||
|
endLoc = grappleEndLocation
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we're on the east side
|
||||||
|
direction = Direction.WEST // got to jump west
|
||||||
|
startLoc = grappleEndLocation
|
||||||
|
endLoc = grappleStartLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
grappleScenery = getGrappleScenery(direction!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGrappleScenery(direction: Direction): List<core.game.node.scenery.Scenery?> {
|
||||||
|
val lumbridgeTree = getScenery(Location(3244, 3179, 0))
|
||||||
|
val alKharidTree = getScenery(Location(3260, 3178, 0))
|
||||||
|
val startTree : core.game.node.scenery.Scenery?
|
||||||
|
val endTree : core.game.node.scenery.Scenery?
|
||||||
|
val raft = getScenery(Location(3252, 3179, 0))
|
||||||
|
if (direction == Direction.EAST){
|
||||||
|
startTree = lumbridgeTree
|
||||||
|
endTree = alKharidTree
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
startTree = alKharidTree
|
||||||
|
endTree = lumbridgeTree
|
||||||
|
}
|
||||||
|
return listOf(startTree,endTree, raft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.plugin.Initializable
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
|
|
||||||
|
@Initializable
|
||||||
|
class CatherbyGrappleShortcut : AbstractOneWayGrapple(){
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 32, Skills.RANGE to 35, Skills.STRENGTH to 35)
|
||||||
|
|
||||||
|
override val grappleStartLocation: Location = Location.create(2866, 3429, 0)
|
||||||
|
|
||||||
|
override val grappleEndLocation: Location = Location.create(2869,3430,0)
|
||||||
|
|
||||||
|
// todo this is the wrong animation
|
||||||
|
override val animation: Animation = Animation(4455)
|
||||||
|
|
||||||
|
override val animationDuration: Int = 9
|
||||||
|
|
||||||
|
override val grappleScenery: List<core.game.node.scenery.Scenery?> = listOf(
|
||||||
|
getScenery(Location.create(2869,3429, 0)) // rocks
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant()
|
||||||
|
|
||||||
|
on(Scenery.ROCKS_17042, IntType.SCENERY, "grapple"){ player, _ ->
|
||||||
|
if (!canGrapple(player, grappleStartLocation, 1)) {
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.player.link.diary.DiaryType
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import core.game.world.update.flag.context.Graphics
|
||||||
|
import core.plugin.Initializable
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
|
||||||
|
abstract class AbstractFaladorGrapple(private var wallGrappleInterface: WallGrappleInterface = WallGrappleInterfaceImpl()): AbstractOneWayGrapple() {
|
||||||
|
|
||||||
|
override val animation: Animation = Animation(4455)
|
||||||
|
|
||||||
|
override val animationDuration: Int = 14
|
||||||
|
|
||||||
|
// There are no scenery items to hook so don't let children override this
|
||||||
|
final override val grappleScenery: List<core.game.node.scenery.Scenery?> = listOf()
|
||||||
|
|
||||||
|
protected fun jump(player: Player, destination: Location): Boolean {
|
||||||
|
return wallGrappleInterface.jump(player, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun animation(animationStage: Int, player: Player): Boolean {
|
||||||
|
when (animationStage) {
|
||||||
|
1 -> {
|
||||||
|
player.faceLocation(grappleEndLocation)
|
||||||
|
visualize(player, animation, Graphics(760, 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
8 -> {
|
||||||
|
wallGrappleInterface.fadeToBlack(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
13 -> teleport(player, grappleEndLocation)
|
||||||
|
14 -> {
|
||||||
|
wallGrappleInterface.showGame(player)
|
||||||
|
unlock(player)
|
||||||
|
updateDiary(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@Initializable
|
||||||
|
class FaladorGrappleNorth : AbstractFaladorGrapple() {
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 11, Skills.RANGE to 19, Skills.STRENGTH to 37)
|
||||||
|
|
||||||
|
override val grappleStartLocation: Location = Location.create(3033, 3390, 0)
|
||||||
|
|
||||||
|
|
||||||
|
override val grappleEndLocation: Location = Location.create(3033, 3389, 1)
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant()
|
||||||
|
on(Scenery.WALL_17049, IntType.SCENERY, "grapple") { player, _ ->
|
||||||
|
if(!canGrapple(player, grappleStartLocation, 4)) {
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
|
||||||
|
on(Scenery.WALL_17051, IntType.SCENERY, "jump"){ player, _ ->
|
||||||
|
jump(player, grappleStartLocation)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPlayerInRangeToGrapple(player: Player, startLoc: Location, range: Int): Boolean {
|
||||||
|
// Do not let the player grapple from the other side of the wall
|
||||||
|
return inBorders(player, startLoc.x - range, startLoc.y,
|
||||||
|
startLoc.x + range, startLoc.y + 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDiary(player: Player): Boolean {
|
||||||
|
player.achievementDiaryManager.finishTask(player, DiaryType.FALADOR, 1, 2)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Initializable
|
||||||
|
class FaladorGrappleSouth : AbstractFaladorGrapple() {
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 11, Skills.RANGE to 19, Skills.STRENGTH to 37)
|
||||||
|
|
||||||
|
override val grappleStartLocation: Location = Location.create(3032, 3388, 0)
|
||||||
|
|
||||||
|
override val grappleEndLocation: Location = Location.create(3032, 3389, 1)
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant()
|
||||||
|
on(Scenery.WALL_17050, IntType.SCENERY, "grapple") { player, _ ->
|
||||||
|
if(!canGrapple(player, grappleStartLocation, 4)) {
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
|
||||||
|
on(Scenery.WALL_17052, IntType.SCENERY, "jump"){ player, _ ->
|
||||||
|
jump(player, grappleStartLocation)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPlayerInRangeToGrapple(player: Player, startLoc: Location, range: Int): Boolean {
|
||||||
|
// Do not let the player grapple from the other side of the wall
|
||||||
|
return inBorders(player, startLoc.x - range, startLoc.y,
|
||||||
|
startLoc.x + range, startLoc.y - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDiary(player: Player): Boolean {
|
||||||
|
player.achievementDiaryManager.finishTask(player, DiaryType.FALADOR, 1, 2)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.player.link.diary.DiaryType
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.world.map.Direction
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import core.plugin.Initializable
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
|
||||||
|
@Initializable
|
||||||
|
class KaramjaGrapple : AbstractTwoWayGrapple(){
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 53, Skills.RANGE to 42, Skills.STRENGTH to 21)
|
||||||
|
|
||||||
|
// South
|
||||||
|
override val grappleStartLocation: Location = Location.create(2874, 3127, 0)
|
||||||
|
|
||||||
|
|
||||||
|
// North
|
||||||
|
override val grappleEndLocation: Location = Location.create(2874,3142,0)
|
||||||
|
|
||||||
|
override var direction: Direction? = null
|
||||||
|
override var startLoc: Location? = null
|
||||||
|
override var endLoc: Location? = null
|
||||||
|
|
||||||
|
override var grappleScenery: List<core.game.node.scenery.Scenery?> = listOf()
|
||||||
|
|
||||||
|
override val animation: Animation = Animation(4230)
|
||||||
|
override val animationDuration: Int = 9
|
||||||
|
|
||||||
|
override fun animation(animationStage: Int, player: Player): Boolean {
|
||||||
|
when (animationStage) {
|
||||||
|
1 -> {
|
||||||
|
face(player, endLoc!!)
|
||||||
|
animate(player, animation)
|
||||||
|
}
|
||||||
|
|
||||||
|
5 -> {
|
||||||
|
for (tgt in grappleScenery) {
|
||||||
|
replaceScenery(tgt!!, tgt.id + 1, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
5 + animationDuration -> {
|
||||||
|
teleport(player, endLoc!!)
|
||||||
|
}
|
||||||
|
5 + animationDuration + 1 -> {
|
||||||
|
unlock(player)
|
||||||
|
updateDiary(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant()
|
||||||
|
|
||||||
|
on(Scenery.STRONG_TREE_17074, IntType.SCENERY, "grapple"){ player, _ ->
|
||||||
|
setStartEndSide(player)
|
||||||
|
if(!canGrapple(player, startLoc!!, 1)){
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStartEndSide(player: Player, margin: Int) {
|
||||||
|
if (player.location.y > grappleEndLocation.y - margin){ // we're on the north side
|
||||||
|
direction = Direction.SOUTH // got to jump south
|
||||||
|
startLoc = grappleEndLocation
|
||||||
|
endLoc = grappleStartLocation
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
direction = Direction.NORTH // got to jump north
|
||||||
|
startLoc = grappleStartLocation
|
||||||
|
endLoc = grappleEndLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
grappleScenery = getGrappleScenery(direction!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGrappleScenery(direction: Direction): List<core.game.node.scenery.Scenery?> {
|
||||||
|
val startTree : core.game.node.scenery.Scenery?
|
||||||
|
val endTree : core.game.node.scenery.Scenery?
|
||||||
|
val islandTree = getScenery(Location(2873, 3134, 0))
|
||||||
|
if (direction == Direction.NORTH){
|
||||||
|
startTree = getScenery(Location(2874, 3144, 0))
|
||||||
|
endTree = getScenery(Location(2873, 3125, 0))
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
startTree = getScenery(Location(2874, 3144, 0))
|
||||||
|
endTree = getScenery(Location(2873, 3125, 0))
|
||||||
|
}
|
||||||
|
return listOf(startTree,endTree, islandTree)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDiary(player: Player): Boolean {
|
||||||
|
player.achievementDiaryManager.finishTask(player, DiaryType.KARAMJA, 2, 6)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.game.component.Component
|
||||||
|
import core.game.interaction.QueueStrength
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.world.map.Location
|
||||||
|
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
|
||||||
|
|
||||||
|
interface WallGrappleInterface {
|
||||||
|
var tab: Component?
|
||||||
|
fun jump(player: Player, destination: Location): Boolean
|
||||||
|
fun fadeToBlack(player: Player): Component
|
||||||
|
fun showGame(player: Player): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WallGrappleInterfaceImpl: WallGrappleInterface{
|
||||||
|
override var tab: Component? = null
|
||||||
|
|
||||||
|
override fun jump(player: Player, destination: Location): Boolean {
|
||||||
|
// todo this doesn't look great compared to what it used to look like
|
||||||
|
forceWalk(player, destination,"smart" )
|
||||||
|
face(player, destination)
|
||||||
|
// We're teleporting if we are animating so make the strength SOFT
|
||||||
|
queueScript(player, strength = QueueStrength.SOFT){ stage: Int ->
|
||||||
|
when (stage){
|
||||||
|
1 -> animate(player, Animation(7268))
|
||||||
|
2 ->{
|
||||||
|
teleport(player, destination)
|
||||||
|
return@queueScript stopExecuting(player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@queueScript delayScript(player, 1)
|
||||||
|
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun fadeToBlack(player: Player): Component {
|
||||||
|
// todo make this work. Right now the tab is always null
|
||||||
|
tab = player.interfaceManager.singleTab
|
||||||
|
player.interfaceManager.openOverlay(Component(115))
|
||||||
|
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||||
|
player.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12)
|
||||||
|
if (tab == null){
|
||||||
|
println("Panic")
|
||||||
|
return Component(1)
|
||||||
|
}
|
||||||
|
return tab!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showGame(player: Player): Boolean {
|
||||||
|
player.interfaceManager.restoreTabs()
|
||||||
|
if (tab != null) {
|
||||||
|
player.interfaceManager.openTab(tab)
|
||||||
|
}
|
||||||
|
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||||
|
closeOverlay(player)
|
||||||
|
closeInterface(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.getScenery
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.player.link.diary.DiaryType
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import core.plugin.Initializable
|
||||||
|
|
||||||
|
@Initializable
|
||||||
|
class WaterOrbGrapple : AbstractOneWayGrapple(){
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 36, Skills.RANGE to 39, Skills.STRENGTH to 22)
|
||||||
|
|
||||||
|
override val grappleStartLocation: Location = Location.create(2841, 3427, 0)
|
||||||
|
|
||||||
|
override val grappleEndLocation: Location = Location.create(2841, 3433, 0)
|
||||||
|
|
||||||
|
override val animation: Animation = Animation(4230)
|
||||||
|
|
||||||
|
override val animationDuration: Int = 9
|
||||||
|
|
||||||
|
override val grappleScenery: List<core.game.node.scenery.Scenery?> = listOf(
|
||||||
|
getScenery(Location.create(2841, 3426, 0)), // rock
|
||||||
|
getScenery(Location.create(2841, 3434, 0)) // tree
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
flagInstant()
|
||||||
|
|
||||||
|
on(Scenery.CROSSBOW_TREE_17062, IntType.SCENERY, "grapple"){ player, _ ->
|
||||||
|
if (!canGrapple(player, grappleStartLocation, 1)) {
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDiary(player: Player): Boolean {
|
||||||
|
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 2, 10)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package content.global.skill.agility.shortcuts.grapple
|
||||||
|
|
||||||
|
import core.api.inBorders
|
||||||
|
import core.api.teleport
|
||||||
|
import core.api.unlock
|
||||||
|
import core.api.visualize
|
||||||
|
import core.game.interaction.IntType
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.world.map.Direction
|
||||||
|
import core.game.world.map.Location
|
||||||
|
import core.game.world.update.flag.context.Animation
|
||||||
|
import core.game.world.update.flag.context.Graphics
|
||||||
|
import core.plugin.Initializable
|
||||||
|
import org.rs09.consts.Scenery
|
||||||
|
|
||||||
|
@Initializable
|
||||||
|
class YanilleGrapple(private var wallGrappleInterface: WallGrappleInterface = WallGrappleInterfaceImpl()): AbstractTwoWayGrapple() {
|
||||||
|
|
||||||
|
override val REQUIREMENTS: HashMap<Int, Int> = hashMapOf(Skills.AGILITY to 11, Skills.RANGE to 19, Skills.STRENGTH to 37)
|
||||||
|
|
||||||
|
override val grappleStartLocation: Location = Location.create(2556, 3072, 0)
|
||||||
|
|
||||||
|
override val grappleEndLocation: Location = Location.create(2556, 3073, 1)
|
||||||
|
|
||||||
|
override var direction: Direction? = null
|
||||||
|
override var startLoc: Location? = null
|
||||||
|
override var endLoc: Location? = null
|
||||||
|
override fun setStartEndSide(player: Player, margin: Int) {
|
||||||
|
// Start location is where you end after jumping in the opposite way
|
||||||
|
if (player.location.y > 3073 ){
|
||||||
|
// We are north of the middle of the wall
|
||||||
|
startLoc = Location.create(2556, 3075, 0) // This is where you grapple from/land after jumping
|
||||||
|
endLoc = Location.create(2556, 3074, 1) //
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We are south of the middle of the wall
|
||||||
|
startLoc = Location.create(2556, 3072, 0)
|
||||||
|
endLoc = Location.create(2556, 3073, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGrappleScenery(direction: Direction): List<core.game.node.scenery.Scenery?> {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override var grappleScenery: List<core.game.node.scenery.Scenery?> = listOf()
|
||||||
|
|
||||||
|
override val animation: Animation = Animation(4455)
|
||||||
|
override val animationDuration: Int = 9
|
||||||
|
override fun animation(animationStage: Int, player: Player): Boolean {
|
||||||
|
when (animationStage) {
|
||||||
|
1 -> {
|
||||||
|
player.faceLocation(endLoc)
|
||||||
|
visualize(player, animation, Graphics(760, 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
8 -> {
|
||||||
|
wallGrappleInterface.fadeToBlack(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
13 -> teleport(player, endLoc!!)
|
||||||
|
14 -> {
|
||||||
|
wallGrappleInterface.showGame(player)
|
||||||
|
unlock(player)
|
||||||
|
updateDiary(player)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
// Do not use flagListeners here
|
||||||
|
// The player needs to be able to touch the target
|
||||||
|
on(Scenery.WALL_17047, IntType.SCENERY, "grapple") { player, _ ->
|
||||||
|
setStartEndSide(player, 0)
|
||||||
|
if(!canGrapple(player, startLoc!!, 4)){
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
grapple(player, message)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
|
||||||
|
on(Scenery.WALL_17048, IntType.SCENERY, "jump") { player, _ ->
|
||||||
|
setStartEndSide(player, 0)
|
||||||
|
wallGrappleInterface.jump(player, startLoc!!)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPlayerInRangeToGrapple(player: Player, startLoc: Location, range: Int): Boolean {
|
||||||
|
// Do not let the player grapple from the other side of the wall
|
||||||
|
return inBorders(
|
||||||
|
player, startLoc.x - range, startLoc.y,
|
||||||
|
startLoc.x + range, startLoc.y - 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue