Repository reorganisation

Unified kotlin and java into just src/main
Unified the rs09 and core packages
Took all content out of the core package, and placed it into the new content package
Reorganised all source code relating to content to be easier to find and explore
This commit is contained in:
Ceikry
2023-01-26 13:59:28 +00:00
committed by Ryan
parent e4b799c44a
commit a100affda2
3156 changed files with 24205 additions and 30585 deletions
@@ -0,0 +1,240 @@
package content.global.skill.thieving;
import core.cache.def.impl.SceneryDefinition;
import core.game.global.action.DoorActionHandler;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.ImpactHandler;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.plugin.Plugin;
import core.tools.RandomFunction;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a pickable door.
* @author Vexia
*/
@Initializable
public class PickableDoorHandler extends OptionHandler {
/**
* The lock pick item.
*/
private static final Item LOCK_PICK = new Item(1523);
private static final List<PickableDoor> pickableDoors = new ArrayList<>(20);
private static final int[] DOORS = new int[]{42028, 2550, 2551, 2554, 2555, 2556, 2557, 2558, 2559, 5501, 7246, 9565, 13314, 13317, 13320, 13323, 13326, 13344, 13345, 13346, 13347, 13348, 13349, 15759, 34005, 34805, 34806, 34812};
PickableDoor door;
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int i : DOORS) {
SceneryDefinition.forId(i).getHandlers().put("option:pick-lock", this);
SceneryDefinition.forId(i).getHandlers().put("option:open", this);
}
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2672, 3308, 0)}, 1, 3.8));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2672, 3301, 0)}, 14, 15));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2610, 3316, 0)}, 15, 15));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(3190, 3957, 0)}, 32, 25, true));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2565, 3356, 0)}, 46, 37.5));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2579, 3286, 1)}, 61, 50));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2579, 3307, 1)}, 61, 50));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(3018, 3187, 0)}, 1, 0.0));
pickableDoors.add(new PickableDoor(new Location[]{Location.create(2601, 9482, 0)}, 82, 0.0, true));
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
door = forDoor(node.getLocation());
if (option.equals("open")) {
if (door == null) {
player.getPacketDispatch().sendMessage("The door is locked.");
return true;
}
door.open(player, (Scenery) node);
return true;
}
if (option.equals("pick-lock")) {
door.pickLock(player, (Scenery) node);
return true;
}
System.out.println("Unhandled door: " + node.getId());
return false;
}
@Override
public Location getDestination(Node node, Node n) {
if (n instanceof Scenery) {
Scenery object = (Scenery) n;
if (object.getDefinition().hasAction("pick-lock")) {
return DoorActionHandler.getDestination((Entity) node, object);
}
}
return null;
}
private PickableDoor forDoor(Location location) {
for (PickableDoor door : pickableDoors) {
for (Location l : door.getLocations()) {
if (l.equals(location)) {
return door;
}
}
}
return null;
}
public class PickableDoor{
/**
* The locations of the door.
*/
private final Location[] locations;
/**
* The level.
*/
private final int level;
/**
* The experience required.
*/
private final double experience;
/**
* If it requires a lockpick.
*/
private final boolean lockpick;
/**
* Constructs a new {@code PickableDoor} {@code Object}.
* @param locations the locations.
* @param level the level.
* @param experience the experience.
* @param lockpick the lock pick.
*/
public PickableDoor(final Location[] locations, int level, double experience, boolean lockpick) {
this.locations = locations;
this.level = level;
this.experience = experience;
this.lockpick = lockpick;
}
/**
* Constructs a new {@code PickableDoor} {@code Object}.
* @param level the level.
* @param experience the experience.
*/
public PickableDoor(Location[] locations, int level, double experience) {
this(locations, level, experience, false);
}
/**
* Gets the location.
* @return The location.
*/
public Location[] getLocations() {
return locations;
}
/**
* Opens a pickable door.
* @param player the player.
* @param object the object.
*/
public void open(Player player, Scenery object) {
if (isInside(player, object)) {
DoorActionHandler.handleAutowalkDoor(player, object);
player.getPacketDispatch().sendMessage("You go through the door.");
} else {
player.getPacketDispatch().sendMessage("The door is locked.");
}
}
/**
* Picks a lock on a door.
* @param player the player.
* @param object the object.
*/
public void pickLock(Player player, Scenery object) {
boolean success = RandomFunction.random(12) >= 4;
if (isInside(player, object)) {
player.getPacketDispatch().sendMessage("The door is already unlocked.");
return;
}
if (player.getSkills().getLevel(Skills.THIEVING) < level) {
player.sendMessage("You attempt to pick the lock.");
boolean hit = RandomFunction.random(10) < 5;
player.getImpactHandler().manualHit(player, RandomFunction.random(1, 3), ImpactHandler.HitsplatType.NORMAL);
player.sendMessage(hit ? "You have activated a trap on the lock." : "You fail to pick the lock.");
return;
}
if (lockpick && !player.getInventory().containsItem(LOCK_PICK)) {
player.sendMessage("You need a lockpick in order to pick this lock.");
return;
}
if (success) {
player.getSkills().addExperience(Skills.THIEVING, experience, true);
DoorActionHandler.handleAutowalkDoor(player, object);
}
player.getPacketDispatch().sendMessage("You attempt to pick the lock.");
player.getPacketDispatch().sendMessage("You " + (success ? "manage" : "fail") + " to pick the lock.");
}
/**
* Checks if we're behind the door/inside the building.
* @param player the player.
* @param object the object.
* @return {@code True} if so.
*/
private boolean isInside(Player player, Scenery object) {
boolean inside = false;
Direction dir = Direction.getLogicalDirection(player.getLocation(), object.getLocation());
Direction direction = object.getDirection();
if (direction == Direction.SOUTH && dir == Direction.WEST) {
inside = true;
} else if (direction == Direction.EAST && dir == Direction.SOUTH) {
inside = true;
} else if (direction == Direction.NORTH && dir == Direction.EAST) {
inside = true;
}
return inside;
}
/**
* Gets the level.
* @return The level.
*/
public int getLevel() {
return level;
}
/**
* Gets the experience.
* @return The experience.
*/
public double getExperience() {
return experience;
}
/**
* Gets the lockpick.
* @return The lockpick.
*/
public boolean isLockpick() {
return lockpick;
}
}
}
@@ -0,0 +1,203 @@
package content.global.skill.thieving
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import core.api.utils.WeightBasedTable
import core.api.utils.WeightedItem
import java.util.stream.IntStream
enum class Pickpockets(val ids: IntArray, val requiredLevel: Int, val low: Double, val high: Double, val experience: Double, val stunDamageMin: Int, val stunDamageMax: Int, val stunTime: Int, val table: WeightBasedTable) {
MAN(intArrayOf(1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 3224, 3915, 3226, 3227, 5924, 5923), 1, 180.0, 240.0, 8.0, 1, 1,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,3,3,1.0,true)
)),
FARMER(intArrayOf(7, 1757, 1758), 10, 180.0, 240.0, 14.5, 1,1,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,9,9,1.0,true),
WeightedItem(Items.POTATO_SEED_5318,1,1,1.0,true)
)),
MALE_HAM_MEMBER(intArrayOf(1714), 20, 117.0, 240.0, 22.5, 1,3,4, WeightBasedTable.create(
WeightedItem(Items.COINS_995,1,21,5.5),
WeightedItem(Items.TINDERBOX_590,1,1,5.0),
WeightedItem(Items.LOGS_1511,1,1,7.0),
WeightedItem(Items.UNCUT_JADE_1627,1,1,2.5),
WeightedItem(Items.UNCUT_OPAL_1625,1,1,2.5),
WeightedItem(Items.RAW_ANCHOVIES_321,1,1,7.0),
WeightedItem(Items.RAW_CHICKEN_2138,1,1,3.5),
WeightedItem(Items.HAM_CLOAK_4304,1,1,0.25),
WeightedItem(Items.HAM_HOOD_4302,1,1,0.25),
WeightedItem(Items.HAM_LOGO_4306,1,1,0.25),
WeightedItem(Items.HAM_ROBE_4300,1,1,0.25),
WeightedItem(Items.HAM_SHIRT_4298,1,1,0.25),
WeightedItem(Items.BOOTS_4310,1,1,1.0),
WeightedItem(Items.GLOVES_4308,1,1,1.0),
WeightedItem(Items.BRONZE_PICKAXE_1265,1,1,5.0),
WeightedItem(Items.IRON_PICKAXE_1267,1,1,5.0),
WeightedItem(Items.STEEL_PICKAXE_1269,1,1,2.5),
WeightedItem(Items.GRIMY_GUAM_199,1,1,2.0),
WeightedItem(Items.GRIMY_HARRALANDER_205,1,1,2.0),
WeightedItem(Items.GRIMY_KWUARM_213,1,1,2.0),
WeightedItem(Items.GRIMY_MARRENTILL_201,1,1,1.5),
WeightedItem(Items.RUSTY_SWORD_686,1,1,3.5),
WeightedItem(Items.BROKEN_ARMOUR_698,1,1,3.5),
WeightedItem(Items.BROKEN_STAFF_689,1,1,3.2),
WeightedItem(Items.BROKEN_ARROW_687,1,1,3.1),
WeightedItem(Items.BUTTONS_688,1,1,3.0)
).insertEasyClue(1.0)),
FEMALE_HAM_MEMBER(intArrayOf(1715), 15, 135.0, 240.0, 18.5, 1,3,4, WeightBasedTable.create(
WeightedItem(Items.COINS_995,1,21,5.5),
WeightedItem(Items.TINDERBOX_590,1,1,5.0),
WeightedItem(Items.LOGS_1511,1,1,7.0),
WeightedItem(Items.UNCUT_JADE_1627,1,1,2.5),
WeightedItem(Items.UNCUT_OPAL_1625,1,1,2.5),
WeightedItem(Items.RAW_ANCHOVIES_321,1,1,7.0),
WeightedItem(Items.RAW_CHICKEN_2138,1,1,3.5),
WeightedItem(Items.HAM_CLOAK_4304,1,1,0.25),
WeightedItem(Items.HAM_HOOD_4302,1,1,0.25),
WeightedItem(Items.HAM_LOGO_4306,1,1,0.25),
WeightedItem(Items.HAM_SHIRT_4298,1,1,0.25),
WeightedItem(Items.HAM_ROBE_4300,1,1,0.25),
WeightedItem(Items.BOOTS_4310,1,1,1.0),
WeightedItem(Items.GLOVES_4308,1,1,1.0),
WeightedItem(Items.BRONZE_PICKAXE_1265,1,1,5.0),
WeightedItem(Items.IRON_PICKAXE_1267,1,1,5.0),
WeightedItem(Items.STEEL_PICKAXE_1269,1,1,2.5),
WeightedItem(Items.GRIMY_GUAM_199,1,1,2.0),
WeightedItem(Items.GRIMY_HARRALANDER_205,1,1,2.0),
WeightedItem(Items.GRIMY_KWUARM_213,1,1,2.0),
WeightedItem(Items.GRIMY_MARRENTILL_201,1,1,1.5),
WeightedItem(Items.RUSTY_SWORD_686,1,1,3.5),
WeightedItem(Items.BROKEN_ARMOUR_698,1,1,3.5),
WeightedItem(Items.BROKEN_STAFF_689,1,1,3.2),
WeightedItem(Items.BROKEN_ARROW_687,1,1,3.1),
WeightedItem(Items.BUTTONS_688,1,1,3.0)
).insertEasyClue(1.0)),
WARRIOR(intArrayOf(15, 18), 25, 84.0, 240.0, 26.0, 2, 2, 5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,18,18,1.0,true)
)),
ROGUE(intArrayOf(187, 2267, 2268, 2269, 8122), 32, 74.0, 240.0,35.5, 2, 2, 5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,25,40,5.0,true),
WeightedItem(Items.JUG_OF_WINE_1993,1,1,6.0),
WeightedItem(Items.AIR_RUNE_556,8,8,8.0),
WeightedItem(Items.LOCKPICK_1523,1,1,5.0),
WeightedItem(Items.IRON_DAGGERP_1219,1,1,1.0)
)),
CAVE_GOBLIN(IntStream.rangeClosed(5752, 5768).toArray(), 36, 72.0, 240.0, 40.0, 1,1,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,30,30,6.5),
WeightedItem(Items.OIL_LAMP_4522,1,1,0.5),
WeightedItem(Items.BULLSEYE_LANTERN_4544,1,1,0.5),
WeightedItem(Items.UNLIT_TORCH_596,1,1,0.5),
WeightedItem(Items.TINDERBOX_590,1,1,0.5),
WeightedItem(Items.SWAMP_TAR_1939,1,1,0.5),
WeightedItem(Items.IRON_ORE_441,1,4,0.25)
)),
MASTER_FARMER(intArrayOf(2234, 2235, NPCs.MARTIN_THE_MASTER_GARDENER_3299), 38, 90.0, 240.0, 43.0, 3, 3, 5, WeightBasedTable.create(
WeightedItem(Items.POTATO_SEED_5318,1,3,50.0),
WeightedItem(Items.ONION_SEED_5319,1,3,50.0),
WeightedItem(Items.CABBAGE_SEED_5324,1,3,50.0),
WeightedItem(Items.TOMATO_SEED_5322,1,2,50.0),
WeightedItem(Items.SWEETCORN_SEED_5320,1,2,50.0),
WeightedItem(Items.STRAWBERRY_SEED_5323,1,1,25.0),
WeightedItem(Items.WATERMELON_SEED_5321,1,1,8.0),
WeightedItem(Items.BARLEY_SEED_5305,1,4,50.0),
WeightedItem(Items.HAMMERSTONE_SEED_5307,1,3,50.0),
WeightedItem(Items.ASGARNIAN_SEED_5308,1,3,50.0),
WeightedItem(Items.JUTE_SEED_5306,1,3,50.0),
WeightedItem(Items.YANILLIAN_SEED_5309,1,2,25.0),
WeightedItem(Items.KRANDORIAN_SEED_5310,1,2,25.0),
WeightedItem(Items.WILDBLOOD_SEED_5311,1,1,8.0),
WeightedItem(Items.MARIGOLD_SEED_5096,1,1,50.0),
WeightedItem(Items.NASTURTIUM_SEED_5098,1,1,50.0),
WeightedItem(Items.ROSEMARY_SEED_5097,1,1,50.0),
WeightedItem(Items.WOAD_SEED_5099,1,1,50.0),
WeightedItem(Items.LIMPWURT_SEED_5100,1,1,25.0),
WeightedItem(Items.REDBERRY_SEED_5101,1,1,50.0),
WeightedItem(Items.CADAVABERRY_SEED_5102,1,1,50.0),
WeightedItem(Items.DWELLBERRY_SEED_5103,1,1,25.0),
WeightedItem(Items.JANGERBERRY_SEED_5104,1,1,25.0),
WeightedItem(Items.WHITEBERRY_SEED_5105,1,1,25.0),
WeightedItem(Items.GUAM_SEED_5291,1,1,50.0),
WeightedItem(Items.MARRENTILL_SEED_5292,1,1,50.0),
WeightedItem(Items.TARROMIN_SEED_5293,1,1,50.0),
WeightedItem(Items.HARRALANDER_SEED_5294,1,1,25.0),
WeightedItem(Items.RANARR_SEED_5295,1,1,8.0),
WeightedItem(Items.TOADFLAX_SEED_5296,1,1,8.0),
WeightedItem(Items.IRIT_SEED_5297,1,1,8.0),
WeightedItem(Items.AVANTOE_SEED_5298,1,1,8.0),
WeightedItem(Items.KWUARM_SEED_5299,1,1,8.0),
WeightedItem(Items.SNAPDRAGON_SEED_5300,1,1,5.0),
WeightedItem(Items.CADANTINE_SEED_5301,1,1,8.0),
WeightedItem(Items.LANTADYME_SEED_5302,1,1,5.0),
WeightedItem(Items.DWARF_WEED_SEED_5303,1,1,5.0),
WeightedItem(Items.TORSTOL_SEED_5304,1,1,5.0)
)),
GUARD(intArrayOf(9, 32, 206, 296, 297, 298, 299, 344, 345, 346, 368, 678, 812, 9, 32, 296, 297, 298, 299, 2699, 2700, 2701, 2702, 2703, 3228, 3229, 3230, 3231, 3232, 3233, 3241, 3407, 3408, 4307, 4308, 4309, 4310, 4311, 5919, 5920), 40, 50.0, 240.0, 46.5, 2,2,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,30,30,1.0,true)
)),
FREMENNIK_CITIZEN(intArrayOf(2462), 45, 65.0, 240.0, 65.0, 2, 2, 5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,40,40,1.0,true)
)),
BEARDED_BANDIT(intArrayOf(1880, 1881, 6174), 45, 50.0, 240.0, 65.0, 5,5,5, WeightBasedTable.create(
WeightedItem(Items.ANTIPOISON4_2446,1,1,1.0),
WeightedItem(Items.LOCKPICK_1523,1,1,2.0),
WeightedItem(Items.COINS_995,1,1,4.0)
)),
DESERT_BANDIT(intArrayOf(1926, 1921), 53, 50.0, 240.0, 79.5, 3,3,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,50,1,3.0),
WeightedItem(Items.ANTIPOISON4_2446,1,1,1.0),
WeightedItem(Items.LOCKPICK_1523,1,1,1.0)
)),
KNIGHT_OF_ADROUGNE(intArrayOf(23, 26), 55, 50.0, 240.0, 84.3, 3,3,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,50,50,1.0,true)
)),
YANILLE_WATCHMAN(intArrayOf(34), 65, 50.0, 240.0, 137.5, 3,3,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,60,60,1.0,true),
WeightedItem(Items.BREAD_2309,1,1,1.0,true)
)),
MENAPHITE_THUG(intArrayOf(1905), 65, 50.0, 240.0, 137.5, 5,5,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,60,60,1.0,true)
)),
PALADIN(intArrayOf(20, 2256), 70, 50.0, 150.0,151.75, 3,3,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,80,80,1.0,true),
WeightedItem(Items.CHAOS_RUNE_562,2,2,1.0,true)
)),
GNOME(intArrayOf(66, 67, 68, 168, 169, 2249, 2250, 2251, 2371, 2649, 2650, 6002, 6004), 75, 8.0, 120.0, 198.5, 1,1,5, WeightBasedTable.create(
WeightedItem(Items.COINS_995,300,300,2.5),
WeightedItem(Items.EARTH_RUNE_557,1,1,3.5),
WeightedItem(Items.GOLD_ORE_445,1,1,1.0),
WeightedItem(Items.FIRE_ORB_569,1,1,5.0),
WeightedItem(Items.SWAMP_TOAD_2150,1,1,8.0),
WeightedItem(Items.KING_WORM_2162,1,1,9.0)
)),
HERO(intArrayOf(21), 80, 6.0, 100.0,273.3, 6,6,4, WeightBasedTable.create(
WeightedItem(Items.COINS_995,200,300,1.5),
WeightedItem(Items.DEATH_RUNE_560,2,2,1.0),
WeightedItem(Items.BLOOD_RUNE_565,1,1,0.5),
WeightedItem(Items.FIRE_ORB_569,1,1,2.5),
WeightedItem(Items.DIAMOND_1601,1,1,2.0),
WeightedItem(Items.GOLD_ORE_444,1,1,1.5),
WeightedItem(Items.JUG_OF_WINE_1993,1,1,3.0)
));
companion object {
val idMap = HashMap<Int,Pickpockets>(values().size * 5)
init {
values().forEach {
it.ids.forEach { id -> idMap[id] = it }
}
}
@JvmStatic
fun forID(id: Int): Pickpockets? {
return idMap[id]
}
}
fun getSuccessChance(player: Player): Double{
return RandomFunction.getSkillSuccessChance(low,high,player.skills.getLevel(Skills.THIEVING))
}
}
@@ -0,0 +1,93 @@
package content.global.skill.thieving;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.tools.RandomFunction;
import java.util.*;
/**
* Represents a thieving stall.
* @author Ceikry, Woahscam
*/
public enum Stall {
VEGETABLE_STALL(new Integer[]{4706, 4708}, new Integer[] { 634 }, 2, new Item[]{new Item(1957, 1), new Item(1965, 1), new Item(1942, 1), new Item(1982, 1), new Item(1550, 1)}, 10, 4,"vegetables"),
BAKER_STALL(new Integer[]{2561, 6163, 34384}, new Integer[] { 634, 6984, 34381 }, 5, new Item[]{new Item(1891, 1), new Item(2309, 1), new Item(1901, 1)}, 16, 4,"pastries"),
CRAFTING_STALL(new Integer[]{4874, 6166}, new Integer[] { 4797, 6984 }, 5, new Item[]{new Item(1592, 1), new Item(1597, 1), new Item(1755, 1)}, 16, 12,"crafting supplies"),
TEA_STALL(new Integer[]{635, 6574}, new Integer[] { 634, 6573 }, 5, new Item[]{new Item(712, 1)}, 16, 12,"tea"),
SILK_STALL(new Integer[]{34383, 2560}, new Integer[] { 34381, 634 }, 20, new Item[]{new Item(950, 1)}, 24, 13,"silk"),
WINE_STALL(new Integer[]{2046}, new Integer[] { 634 }, 22, new Item[]{new Item(1935, 1), new Item(1937, 1), new Item(1993, 1), new Item(7919, 1)}, 27, 27,"wine"), //OBJECT MISSING IN CACHE
MARKET_SEED_STALL(new Integer[]{7053}, new Integer[] { 634 }, 27, new Item[]{new Item(5096, 1), new Item(5097, 1), new Item(5101, 1), new Item(5318, 1), new Item(5319, 1), new Item(5324, 1)}, 10, 19,"seeds"),
FUR_STALL(new Integer[]{ 34387, 2563, 4278}, new Integer[] { 34381, 634, 634 }, 35, new Item[]{new Item(6814, 1), new Item(958, 1)}, 36, 25,"fur"),
FISH_STALL(new Integer[]{ 4277, 4705, 4707 }, new Integer[] { 634, 634, 634 }, 42, new Item[]{new Item(331, 1), new Item(359, 1), new Item(377, 1)}, 42, 27,"fish"),
CROSSBOW_STALL(new Integer[]{17031}, new Integer[] { 6984 }, 49, new Item[]{new Item(877, 3), new Item(9420, 1), new Item(9440, 1)}, 52, 19,"equipment"),
SILVER_STALL(new Integer[]{2565, 6164, 34382}, new Integer[] { 634, 6984, 34381}, 50, new Item[]{new Item(442, 1)}, 54, 50,"jewellery"),
SPICE_STALL(new Integer[]{34386, 6166}, new Integer[] { 34381, 6984 }, 65, new Item[]{new Item(2007, 1)}, 81, 134,"spices"),
GEM_STALL(new Integer[]{2562, 6162, 34385}, new Integer[] { 634, 6984, 34381 }, 75, new Item[]{new Item(1623, 1), new Item(1605, 1), new Item(1603, 1), new Item(1601, 1)}, 160, 300,"gems"),
//Ape Atoll Stalls
SCIMITAR_STALL(new Integer[]{4878}, new Integer[] { 4797 }, 65, new Item[]{new Item(1323, 1)}, 100, 134,"equipment"),
MAGIC_STALL(new Integer[]{4877}, new Integer[] { 4797 }, 65, new Item[]{new Item(556, 1), new Item(557, 1), new Item(554, 1), new Item(555, 1), new Item(563, 1)}, 100, 134,"equipment"),
GENERAL_STALL(new Integer[]{4876}, new Integer[] { 4797 }, 5, new Item[]{new Item(1931, 1), new Item(2347, 1), new Item(590, 1)}, 16, 12,"goods"),
FOOD_STALL(new Integer[]{4875}, new Integer[] { 4797 }, 5, new Item[]{new Item(1963, 1)}, 16, 12,"food");
//CRAFTING_STALL (Ape Atoll) shares same drops/exp as regular crafting stall
//Quest Stalls Rocking Out
//CUSTOMS_EVIDENCE_FILES(new Integer[]{FIND OBJ ID}, FIND OBJ EMPTY ID, 63, new Item[]{new Item(1333, 1), new Item(1617, 1), new Item(1619, 1), new Item(1623, 1), new Item(385, 1), new Item(2359, 1), new Item(2357, 1), new Item(2351, 1), new Item(7114, 1), new Item(7134, 1), new Item(1025, 1), new Item(1281, 1), new Item(1325, 1), new Item(1323, 1), new Item(1321, 1), new Item(995, 300)}, 75, 100);
public static HashMap<Integer,Stall> idMap = new HashMap<>();
static{
Arrays.stream(Stall.values()).forEach(entry -> entry.full_ids.stream().forEach(id -> idMap.putIfAbsent(id, entry)));
}
List<Integer> full_ids;
List<Integer> empty_ids;
int level, delay;
Item[] rewards;
double experience;
String msgItem;
Stall(Integer[] full_ids, Integer[] empty_ids, int level, Item[] rewards, double experience, int delay, String msgItem) {
this.full_ids = new ArrayList<Integer>(Arrays.asList(full_ids));
this.empty_ids = new ArrayList<Integer>(Arrays.asList(empty_ids));
this.level = level;
this.delay = delay;
this.rewards = rewards;
this.experience = experience;
this.msgItem = msgItem;
}
public List<Integer> getFullIDs() {
return full_ids;
}
public int getLevel() {
return level;
}
public Item[] getRewards() {
return rewards;
}
public double getExperience() {
return experience;
}
public int getEmpty(int id) {
int fullIndex = full_ids.indexOf(id);
return this.empty_ids.get(fullIndex);
}
public int getDelay() {
return delay;
}
public Item getRandomLoot() {
return rewards[RandomFunction.random(rewards.length)];
}
public static Stall forObject(final Scenery object) {
return idMap.get(object.getId());
}
}
@@ -0,0 +1,153 @@
package content.global.skill.thieving;
import core.game.node.entity.skill.SkillPulse;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.world.GameWorld;
import core.game.world.map.RegionManager;
import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction;
import core.tools.StringUtils;
import static core.api.ContentAPIKt.*;
/**
* Represents the pulse used to thieve a stall.
* @author 'Vexia
*/
public final class StallThiefPulse extends SkillPulse<Scenery> {
/**
* Represents the stealing animation.
*/
private static final Animation ANIMATION = new Animation(832);
/**
* Represents the stall being thieved.
*/
private final Stall stall;
/**
* Represents the ticks passed.
*/
private int ticks;
/**
* Constructs a new {@code StallThiefPulse} {@code Object}.
* @param player the player.
* @param node the node.
* @param stall the stall.
*/
public StallThiefPulse(Player player, Scenery node, final Stall stall) {
super(player, node);
this.stall = stall;
}
@Override
public void start() {
player.setAttribute("thieveDelay", GameWorld.getTicks());
super.start();
}
@Override
public boolean checkRequirements() {
if (stall == null) {
return false;
}
if (player.inCombat()) {
player.getPacketDispatch().sendMessage("You cant steal from the market stall during combat!");
return false;
}
if (player.getSkills().getLevel(Skills.THIEVING) < stall.getLevel()) {
player.getPacketDispatch().sendMessage("You need to be level " + stall.getLevel() + " to steal from the " + node.getName().toLowerCase() + ".");
return false;
}
if (player.getInventory().freeSlots() == 0) {
player.getPacketDispatch().sendMessage("You don't have enough inventory space.");
return false;
}
if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, "Fremennik Trials") && stall.full_ids.contains(4278)) {
sendDialogue(player, "The fur trader is staring at you suspiciously. You cannot steal from his stall while he distrusts you.");
return false;
}
if (player.getLocation().isInRegion(10553) && !isQuestComplete(player, "Fremennik Trials") && stall.full_ids.contains(4277)) {
sendDialogue(player, "The fishmonger is staring at you suspiciously. You cannot steal from his stall while he distrusts you.");
return false;
}
return true;
}
@Override
public boolean hasInactiveNode() {
if (player.getAttribute("thieveDelay", 0) <= GameWorld.getTicks()) {
return false;
}
return super.hasInactiveNode();
}
@Override
public void animate() {
}
@Override
public boolean reward() {
if (ticks == 0) {
player.animate(ANIMATION);
player.getLocks().lockInteractions(2);
}
if (++ticks % 3 != 0) {
return false;
}
final boolean success = success();
if (success) {
if (stall == Stall.SILK_STALL) {
player.getSavedData().getGlobalData().setSilkSteal(System.currentTimeMillis() + 1800000);
}
if (node.isActive()) {
SceneryBuilder.replace(node, node.transform(stall.getEmpty(node.getId())), stall.getDelay());
}
final Item item = stall.getRandomLoot();
player.getInventory().add(item);
player.getSkills().addExperience(Skills.THIEVING, stall.getExperience(), true);
if (item.getId() == 1987) {
player.getPacketDispatch().sendMessage("You steal grapes from the grape stall.");
return true;
}
player.getPacketDispatch().sendMessage("You steal " + (StringUtils.isPlusN(item.getName()) ? "an" : "a") + " " + item.getName().toLowerCase() + " from the " + stall.name().toLowerCase().replace('_',' ') + ".");
}
return true;
}
@Override
public void message(int type) {
switch (type) {
case 0:
player.getPacketDispatch().sendMessage("You attempt to steal some " + stall.msgItem + " from the " + stall.name().toLowerCase().replace('_',' '));
break;
}
}
/**
* Checks if the thief is successful.
* @return {@code True} if so.
*/
private boolean success() {
int mod = 0;
if (RandomFunction.random(15 + mod) < 4) {
for (NPC npc : RegionManager.getLocalNpcs(player.getLocation(), 8)) {
if (!npc.getProperties().getCombatPulse().isAttacking() && (npc.getId() == 32 || npc.getId() == 2236)) {
npc.sendChat("Hey! Get your hands off there!");
npc.getProperties().getCombatPulse().attack(player);
return false;
}
}
}
return true;
}
}
@@ -0,0 +1,280 @@
package content.global.skill.thieving;
import core.cache.def.impl.SceneryDefinition;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.player.Player;
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.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Handles the thieving of chests.
* @author Vexia
*/
@Initializable
public final class ThievableChestPlugin extends OptionHandler {
/**
* The lock pick item.
*/
private static final Item LOCK_PICK = new Item(1523);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (Chest chest : Chest.values()) {
for (int id : chest.getObjectIds()) {
SceneryDefinition def = SceneryDefinition.forId(id);
def.getHandlers().put("option:open", this);
def.getHandlers().put("option:search for traps", this);
}
}
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final Chest chest = Chest.forId(node.getId());
switch (option) {
case "open":
if (chest != null) {
chest.open(player, (Scenery) node);
return true;
}
return true;
case "search for traps":
chest.searchTraps(player, (Scenery) node);
return true;
}
return true;
}
/**
* Represents a thievable chest.
* @author Vexia
*/
public static enum Chest {
TEN_COIN(2566, 13, 7.8, new Item[] { new Item(995, 10) }, 7), NATURE_RUNE(2567, 28, 25, new Item[] { new Item(995, 3), new Item(561, 1) }, 8), FIFTY_COIN(2568, 43, 125, new Item[] { new Item(995, 50) }, 55), STEEL_ARROWHEADS(2573, 47, 150, new Item[] { new Item(41, 5) }, 210), BLOOD_RUNES(2569, 59, 250, new Item[] { new Item(995, 500), new Item(565, 2) }, 135), PALADIN(2570, 72, 500, new Item[] { new Item(995, 1000), new Item(383, 1), new Item(449, 1), new Item(1623, 1) }, 120);
/**
* The object id.
*/
private final int[] objectIds;
/**
* The level required.
*/
private final int level;
/**
* The experience gained.
*/
private final double experience;
/**
* The rewards.
*/
private final Item[] rewards;
/**
* The respawn time.
*/
private final int respawn;
/**
* The current respawn time.
*/
private int currentRespawn;
/**
* Constructs a new {@code Chest} {@code Object}.
* @param level the level.
* @param experience the experience.
* @param rewards the rewards.
* @param respawn the respawn time.
*/
private Chest(int[] objectIds, int level, double experience, Item[] rewards, int respawn) {
this.objectIds = objectIds;
this.level = level;
this.experience = experience;
this.rewards = rewards;
this.respawn = respawn;
}
/**
* Constructs a new {@code Chest} {@code Object}.
* @param objectId the object id.
* @param level the level.
* @param experience the experience.
* @param rewards the rewards.
* @param respawn the respawn time.
*/
private Chest(int objectId, int level, double experience, Item[] rewards, int respawn) {
this(new int[] { objectId }, level, experience, rewards, respawn);
}
/**
* Opens the chest for a reward.
* @param player the player.
* @param object the object.
*/
private void open(final Player player, final Scenery object) {
if (isRespawning()) {
player.sendMessage("It looks like this chest has already been looted.");
return;
}
player.lock(2);
player.sendMessage("You have activated a trap on the chest.");
player.getImpactHandler().manualHit(player, getHitAmount(player), HitsplatType.NORMAL);
}
/**
* Searches for traps on a chest.
* @param player the player.
* @param object the object.
*/
private void searchTraps(final Player player, final Scenery object) {
player.faceLocation(object.getLocation());
if (isRespawning()) {
player.sendMessage("It looks like this chest has already been looted.");
return;
}
player.lock();
player.animate(Animation.create(536));
if (player.getSkills().getLevel(Skills.THIEVING) < level) {
player.lock(2);
player.sendMessage("You search the chest for traps.");
player.sendMessage("You find nothing.", 1);
player.unlock();
return;
}
if (player.getInventory().freeSlots() == 0) {
player.getPacketDispatch().sendMessage("Not enough inventory space.");
return;
}
player.sendMessage("You find a trap on the chest...");
player.getImpactHandler().setDisabledTicks(6);
GameWorld.getPulser().submit(new Pulse(1, player) {
int counter;
@Override
public boolean pulse() {
switch (++counter) {
case 2:
player.sendMessage("You disable the trap.");
break;
case 4:
player.animate(Animation.create(536));
player.sendMessage("You open the chest.");
break;
case 6:
player.unlock();
for (Item i : rewards) {
player.getInventory().add(i, player);
}
player.sendMessage("You find treasure inside!");
player.getSkills().addExperience(Skills.THIEVING, experience, true);
if (object.isActive()) {
SceneryBuilder.replace(object, object.transform(2574), 3);
}
setRespawn();
return true;
}
return false;
}
});
}
/**
* Sets the respawn delay.
*/
public void setRespawn() {
currentRespawn = GameWorld.getTicks() + (int) (respawn / 0.6);
}
/**
* Checks if the chest is respawning.
* @return {@code True} if so.
*/
public boolean isRespawning() {
return currentRespawn > GameWorld.getTicks();
}
/**
* Gets the amount of damage to deal.
* @param player The player.
* @return The amount of damage.
*/
protected static int getHitAmount(Player player) {
int hit = player.getSkills().getLifepoints() / 12;
if (hit < 2) {
hit = 2;
}
return hit;
}
/**
* Gets a chest by the id.
* @param id the id.
* @return the chest.
*/
public static Chest forId(int id) {
for (Chest chest : values()) {
for (int i : chest.getObjectIds()) {
if (i == id) {
return chest;
}
}
}
return null;
}
/**
* Gets the objectId.
* @return The objectId.
*/
public int[] getObjectIds() {
return objectIds;
}
/**
* Gets the level.
* @return The level.
*/
public int getLevel() {
return level;
}
/**
* Gets the experience.
* @return The experience.
*/
public double getExperience() {
return experience;
}
/**
* Gets the rewards.
* @return The rewards.
*/
public Item[] getRewards() {
return rewards;
}
/**
* Gets the respawn.
* @return The respawn.
*/
public int getRespawn() {
return respawn;
}
}
}
@@ -0,0 +1,97 @@
package content.global.skill.thieving
import core.game.node.entity.combat.ImpactHandler
import core.game.node.entity.impl.Animator
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.audio.Audio
import core.game.node.entity.skill.Skills
import core.game.node.entity.state.EntityState
import core.game.world.update.flag.context.Animation
import core.tools.RandomFunction
import org.rs09.consts.Items
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import core.tools.secondsToTicks
class ThievingListeners : InteractionListener {
private val PICKPOCKET_ANIM = Animation(881,Animator.Priority.HIGH)
private val NPC_ANIM = Animation(422)
private val SUCCESS = Audio(2581, 1, 0)
override fun defineListeners() {
on(IntType.NPC,"pickpocket","pick-pocket"){ player, node ->
val pickpocketData = Pickpockets.forID(node.id) ?: return@on false
var successMod = 0
if(player.inCombat()){
player.sendMessage("You can't pickpocket while in combat.")
return@on true
}
if(player.skills.getLevel(Skills.THIEVING) < pickpocketData.requiredLevel){
player.sendMessage("You need a Thieving level of ${pickpocketData.requiredLevel} to do that.")
return@on true
}
if(!pickpocketData.table.canRoll(player)){
player.sendMessage("You don't have enough inventory space to do that.")
return@on true
}
if(pickpocketData == Pickpockets.FEMALE_HAM_MEMBER || pickpocketData == Pickpockets.MALE_HAM_MEMBER){
successMod += getHAMItemCount(player)
}
if(player.equipment.contains(Items.GLOVES_OF_SILENCE_10075,1)){
successMod += 3
}
player.animator.animate(PICKPOCKET_ANIM)
val chance = RandomFunction.randomDouble(1.0,100.0)
val failThreshold = pickpocketData.getSuccessChance(player) + successMod
if(chance > failThreshold){
node.asNpc().face(player)
node.asNpc().animator.animate(NPC_ANIM)
val hitSoundId = 518 + RandomFunction.random(4) // choose 1 of 4 possible hit noises
player.audioManager.send(hitSoundId, 1, 20) // OSRS defines a delay of 20
player.stateManager.set(EntityState.STUNNED, secondsToTicks(pickpocketData.stunTime))
player.lock(secondsToTicks(pickpocketData.stunTime))
player.impactHandler.manualHit(node.asNpc(),RandomFunction.random(pickpocketData.stunDamageMin,pickpocketData.stunDamageMax),ImpactHandler.HitsplatType.NORMAL)
node.asNpc().face(null)
} else {
player.audioManager.send(SUCCESS)
player.lock(2)
pickpocketData.table.roll().forEach { player.inventory.add(it) }
player.skills.addExperience(Skills.THIEVING,pickpocketData.experience)
}
return@on true
}
}
fun getHAMItemCount(player: Player): Int{
var counter = 0
for(item in player.equipment.toArray()){
item ?: continue
counter += when(item.id){
Items.HAM_LOGO_4306 -> 1
Items.HAM_ROBE_4300 -> 1
Items.HAM_HOOD_4302 -> 1
Items.HAM_CLOAK_4304 -> 1
Items.BOOTS_4310 -> 1
Items.GLOVES_4308 -> 1
else -> 0
}
}
return counter
}
}
@@ -0,0 +1,38 @@
package content.global.skill.thieving;
import core.cache.def.impl.SceneryDefinition;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Represents the plugin used to handle thieving options.
* @author 'Vexia
* @date 22/10/2013
*/
@Initializable
public class ThievingOptionPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.setOptionHandler("steal-from", this);
SceneryDefinition.setOptionHandler("steal from", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (option) {
case "steal-from":
case "steal from":
player.getPulseManager().run(new StallThiefPulse(player, (Scenery) node, Stall.forObject((Scenery) node)));
player.getLocks().lockInteractions(6);
break;
}
return true;
}
}