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:
@@ -0,0 +1,177 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* The BossKillcounter keeps track of the amount of bosses the player has slain.
|
||||
* addtoKillcount(player, npcId) should be added in the finalizeDeath() method of the combat handler for the boss.
|
||||
* @author Splinter
|
||||
*/
|
||||
public enum BossKillCounter {
|
||||
|
||||
|
||||
/* ORDINAL BOUND */
|
||||
KING_BLACK_DRAGON(new int[] { 50 }, "King Black Dragon", 14649),
|
||||
BORK(new int[] { 7133, 7134 }, "Bork", -1),
|
||||
DAGANNOTH_SUPREME(new int[] { 2881 }, "Dagannoth Supreme", 14639),
|
||||
DAGANNOTH_PRIME(new int[] { 2882 }, "Dagannoth Prime", 14640),
|
||||
DAGANNOTH_REX(new int[] { 2883 }, "Dagannoth Rex", 14641),
|
||||
CHAOS_ELEMENTAL(new int[] { 3200 }, "Chaos Elemental", 14638),
|
||||
GIANT_MOLE(new int[] { 3340 }, "Giant Mole", 14642),
|
||||
SARADOMIN(new int[] { 6247 }, "Commander Zilyana", 14647),
|
||||
ZAMORAK(new int[] { 6203 }, "K'ril Tsutsaroth", 14648),
|
||||
BANDOS(new int[] { 6260 }, "General Graardor", 14646),
|
||||
ARMADYL(new int[] { 6222 }, "Kree'arra", 14645),
|
||||
JAD(new int[] { 2745 }, "Tz-Tok Jad", 14828),
|
||||
KALPHITE_QUEEN(new int[] { 1160 }, "Kalphite Queen", 14650),
|
||||
CORPOREAL_BEAST(new int[] { 8133 }, "Corporeal Beast", 14653),
|
||||
TORMENTED_DEMONS(new int[] {
|
||||
8349, 8350, 8351, 8352, 8353, 8354,
|
||||
8355, 8356, 8357, 8358, 8359, 8360,
|
||||
8361, 8362, 8363, 8364, 8365, 8366,
|
||||
}, "Tormented demon", -1),
|
||||
CALLISTO(new int[] { 8610 }, "Callisto", 14658),
|
||||
SCORPIA(new int[] { 8611 }, "Scorpia", 14661),
|
||||
VENENATIS(new int[] { 8612 }, "Venenatis", 14657),
|
||||
VETION(new int[] { 8613 }, "Vet'ion", 14659),
|
||||
KRAKEN(new int[] { 8614 }, "Cave Kraken", 14651),
|
||||
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* The npcs that can increase the killcounter
|
||||
*/
|
||||
private final int[] npc;
|
||||
|
||||
/**
|
||||
* The name of the NPC, to be displayed as a sendMessage
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The item ID of the pet relating to the boss.
|
||||
*/
|
||||
private final int petId;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BossKillCounter} {@code Object}.
|
||||
* @param npc the npc.
|
||||
* @param name the npc's string name
|
||||
*/
|
||||
BossKillCounter(final int[] npc, final String name, final int petId) {
|
||||
this.npc = npc;
|
||||
this.name = name;
|
||||
this.petId = petId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the npc.
|
||||
* @return The npc.
|
||||
*/
|
||||
public int[] getNpc() {
|
||||
return npc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the NPC's name
|
||||
* @return their name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the petId
|
||||
* @return The petId
|
||||
*/
|
||||
public int getPetId() {
|
||||
return petId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type for the npc.
|
||||
* @param npc the npc.
|
||||
* @return the BossKillcounter
|
||||
*/
|
||||
public static BossKillCounter forNPC(final int npc) {
|
||||
for (BossKillCounter kc : BossKillCounter.values()) {
|
||||
for (int i : kc.getNpc()) {
|
||||
if (npc == i) {
|
||||
return kc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the player's killcount for that particular boss.
|
||||
* @param killer The player who killed the npc
|
||||
* @param npcid the ID of the npc that just died
|
||||
*/
|
||||
public static void addtoKillcount(Player killer, int npcid) {
|
||||
if (killer == null) {
|
||||
return;
|
||||
}
|
||||
BossKillCounter boss = BossKillCounter.forNPC(npcid);
|
||||
if (boss == null) {
|
||||
return;
|
||||
}
|
||||
killer.getSavedData().getGlobalData().getBossCounters()[boss.ordinal()]++;
|
||||
killer.getPacketDispatch().sendMessage("Your " + boss.getName() + " killcount is now: <col=ff0000>" + killer.getSavedData().getGlobalData().getBossCounters()[boss.ordinal()] + "</col>.");
|
||||
// addBossPet(killer, npcid, boss);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Gives the player the pet if they killed a certain boss.
|
||||
// * The chance by default is 1/5000. This rate lowers to 1/2200 if the <GlobalEvents> for Boss Pets is active.
|
||||
// * Note: Not all bosses have pet versions of themselves.
|
||||
// */
|
||||
// private static void addBossPet(Player killer, int npcid, BossKillCounter boss){
|
||||
// if(boss.getPetId() == -1){ //The boss does not have a pet version.
|
||||
// return;
|
||||
// }
|
||||
// int number = 5000;
|
||||
// if (npcid == 2745) {
|
||||
// number = 200;
|
||||
// if (killer.getSlayer().getTask() == Tasks.JAD) {
|
||||
// number = 100;
|
||||
// }
|
||||
// } else if (npcid == 3200) {
|
||||
// number = 300;
|
||||
// }
|
||||
// int rand = number;
|
||||
// if(rand == 10){
|
||||
// for (int i = 0; i < killer.getFamiliarManager().getInsuredPets().size(); i++) {
|
||||
// if (killer.getFamiliarManager().getInsuredPets().get(i).getBabyItemId() == boss.getPetId()) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// if(killer.getFamiliarManager().hasFamiliar() && killer.getInventory().freeSlots() < 1){
|
||||
// return;
|
||||
// }
|
||||
// if(!killer.getFamiliarManager().hasFamiliar()){
|
||||
// killer.getFamiliarManager().summon(new Item(boss.getPetId()), true);
|
||||
// killer.sendNotificationMessage("You have a funny feeling like you're being followed.");
|
||||
// } else if (killer.getInventory().freeSlots() > 0){
|
||||
// killer.getInventory().add(new Item(boss.getPetId(), 1));
|
||||
// killer.sendNotificationMessage("You feel something weird sneaking into your backpack.");
|
||||
// }
|
||||
// Repository.sendNews(killer.getUsername()+" now commands a miniature "+(boss.equals(CORPOREAL_BEAST) ? "Dark core" : boss.getName())+"!");
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Increments the player's Barrows chest counter.
|
||||
* @param player the player
|
||||
*/
|
||||
public static void addtoBarrowsCount(Player player) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
player.getSavedData().getGlobalData().setBarrowsLoots(player.getSavedData().getGlobalData().getBarrowsLoots() + 1);
|
||||
player.getPacketDispatch().sendMessage("Your Barrows chest count is: <col=ff0000>" + player.getSavedData().getGlobalData().getBarrowsLoots() + "</col>.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents a dye.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum Dyes {
|
||||
BLACK(new Item(4622)),
|
||||
RED(new Item(1763)),
|
||||
YELLOW(new Item(1765)),
|
||||
BLUE(new Item(1767)),
|
||||
ORANGE(new Item(1769)),
|
||||
GREEN(new Item(1771)),
|
||||
PURPLE(new Item(1773)),
|
||||
PINK(new Item(6955));
|
||||
|
||||
/**
|
||||
* The dye item.
|
||||
*/
|
||||
private final Item item;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Dyes} {@code Object}.
|
||||
* @param item the item.
|
||||
*/
|
||||
Dyes(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dye for the item.
|
||||
* @param item the item.
|
||||
* @return the dye.
|
||||
*/
|
||||
public static Dyes forItem(Item item) {
|
||||
for (Dyes d : values()) {
|
||||
if (d.getItem().getId() == item.getId()) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
* @return The item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
package content.data
|
||||
|
||||
import content.global.skill.magic.TeleportMethod
|
||||
import content.global.skill.slayer.SlayerManager.Companion.getInstance
|
||||
import core.api.*
|
||||
import core.game.event.TeleportEvent
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.Items
|
||||
import core.game.world.GameWorld.Pulser
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Represents an enchanted jewellery.
|
||||
* @author Vexia & downthecrop
|
||||
*/
|
||||
enum class EnchantedJewellery(
|
||||
|
||||
val options: Array<String>,
|
||||
val locations: Array<Location>, crumble: Boolean, vararg val ids: Int) {
|
||||
RING_OF_SLAYING(
|
||||
arrayOf(
|
||||
"Sumona in Pollnivneach.",
|
||||
"Morytania Slayer Tower.",
|
||||
"Rellekka Slayer Caves.",
|
||||
"Nowhere. Give me a slayer update."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(3361, 2994, 0),
|
||||
Location.create(3428, 3535, 0),
|
||||
Location.create(2792, 3615, 0),
|
||||
),
|
||||
true,
|
||||
Items.RING_OF_SLAYING8_13281,
|
||||
Items.RING_OF_SLAYING7_13282,
|
||||
Items.RING_OF_SLAYING6_13283,
|
||||
Items.RING_OF_SLAYING5_13284,
|
||||
Items.RING_OF_SLAYING4_13285,
|
||||
Items.RING_OF_SLAYING3_13286,
|
||||
Items.RING_OF_SLAYING2_13287,
|
||||
Items.RING_OF_SLAYING1_13288
|
||||
),
|
||||
|
||||
RING_OF_DUELING(
|
||||
arrayOf(
|
||||
"Al Kharid Duel Arena.",
|
||||
"Castle Wars Arena.",
|
||||
"Fist of Guthix", "Nowhere."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(3314, 3235, 0),
|
||||
Location.create(2442, 3089, 0),
|
||||
Location.create(1693, 5600, 0)
|
||||
),
|
||||
true,
|
||||
Items.RING_OF_DUELLING8_2552,
|
||||
Items.RING_OF_DUELLING7_2554,
|
||||
Items.RING_OF_DUELLING6_2556,
|
||||
Items.RING_OF_DUELLING5_2558,
|
||||
Items.RING_OF_DUELLING4_2560,
|
||||
Items.RING_OF_DUELLING3_2562,
|
||||
Items.RING_OF_DUELLING2_2564,
|
||||
Items.RING_OF_DUELLING1_2566
|
||||
),
|
||||
AMULET_OF_GLORY(
|
||||
arrayOf(
|
||||
"Edgeville",
|
||||
"Karamja",
|
||||
"Draynor Village",
|
||||
"Al-Kharid",
|
||||
"Nowhere."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(3087, 3495, 0),
|
||||
Location.create(2919, 3175, 0),
|
||||
Location.create(3104, 3249, 0),
|
||||
Location.create(3304, 3124, 0)
|
||||
),
|
||||
Items.AMULET_OF_GLORY4_1712,
|
||||
Items.AMULET_OF_GLORY3_1710,
|
||||
Items.AMULET_OF_GLORY2_1708,
|
||||
Items.AMULET_OF_GLORY1_1706,
|
||||
Items.AMULET_OF_GLORY_1704
|
||||
),
|
||||
AMULET_OF_GLORY_T(
|
||||
AMULET_OF_GLORY.options,
|
||||
AMULET_OF_GLORY.locations,
|
||||
Items.AMULET_OF_GLORYT4_10354,
|
||||
Items.AMULET_OF_GLORYT3_10356,
|
||||
Items.AMULET_OF_GLORYT2_10358,
|
||||
Items.AMULET_OF_GLORYT1_10360,
|
||||
Items.AMULET_OF_GLORYT_10362
|
||||
),
|
||||
GAMES_NECKLACE(
|
||||
arrayOf(
|
||||
"Burthorpe Games Room.",
|
||||
"Barbarian Outpost.",
|
||||
"Clan Wars.",
|
||||
"Wilderness Volcano.",
|
||||
"Corporeal Beast"
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(2899, 3563, 0),
|
||||
Location.create(2520, 3571, 0),
|
||||
Location.create(3266, 3686, 0),
|
||||
Location.create(3179, 3685, 0),
|
||||
Location.create(2885, 4372, 2)
|
||||
),
|
||||
true,
|
||||
Items.GAMES_NECKLACE8_3853,
|
||||
Items.GAMES_NECKLACE7_3855,
|
||||
Items.GAMES_NECKLACE6_3857,
|
||||
Items.GAMES_NECKLACE5_3859,
|
||||
Items.GAMES_NECKLACE4_3861,
|
||||
Items.GAMES_NECKLACE3_3863,
|
||||
Items.GAMES_NECKLACE2_3865,
|
||||
Items.GAMES_NECKLACE1_3867
|
||||
),
|
||||
DIGSITE_PENDANT(arrayOf<String>(),
|
||||
arrayOf(
|
||||
Location.create(3342, 3445, 0)
|
||||
),
|
||||
true,
|
||||
Items.DIGSITE_PENDANT_5_11194,
|
||||
Items.DIGSITE_PENDANT_4_11193,
|
||||
Items.DIGSITE_PENDANT_3_11192,
|
||||
Items.DIGSITE_PENDANT_2_11191,
|
||||
Items.DIGSITE_PENDANT_1_11190
|
||||
),
|
||||
COMBAT_BRACELET(
|
||||
arrayOf(
|
||||
"Champions' Guild",
|
||||
"Monastery",
|
||||
"Ranging Guild",
|
||||
"Warriors' Guild",
|
||||
"Nowhere."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(3191, 3365, 0),
|
||||
Location.create(3052, 3472, 0),
|
||||
Location.create(2657, 3439, 0),
|
||||
Location.create(2878, 3546, 0)
|
||||
),
|
||||
Items.COMBAT_BRACELET4_11118,
|
||||
Items.COMBAT_BRACELET3_11120,
|
||||
Items.COMBAT_BRACELET2_11122,
|
||||
Items.COMBAT_BRACELET1_11124,
|
||||
Items.COMBAT_BRACELET_11126
|
||||
),
|
||||
SKILLS_NECKLACE(
|
||||
arrayOf(
|
||||
"Fishing Guild",
|
||||
"Mining Guild",
|
||||
"Crafting Guild",
|
||||
"Cooking Guild",
|
||||
"Nowhere."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(2611, 3392, 0),
|
||||
Location.create(3016, 3338, 0),
|
||||
Location.create(2933, 3290, 0),
|
||||
Location.create(3143, 3442, 0)
|
||||
),
|
||||
Items.SKILLS_NECKLACE4_11105,
|
||||
Items.SKILLS_NECKLACE3_11107,
|
||||
Items.SKILLS_NECKLACE2_11109,
|
||||
Items.SKILLS_NECKLACE1_11111,
|
||||
Items.SKILLS_NECKLACE_11113
|
||||
),
|
||||
RING_OF_WEALTH(
|
||||
arrayOf(
|
||||
"Grand Exchange",
|
||||
"Nowhere."
|
||||
),
|
||||
arrayOf(
|
||||
Location.create(3163, 3464, 0)
|
||||
),
|
||||
Items.RING_OF_WEALTH4_14646,
|
||||
Items.RING_OF_WEALTH3_14644,
|
||||
Items.RING_OF_WEALTH2_14642,
|
||||
Items.RING_OF_WEALTH1_14640,
|
||||
Items.RING_OF_WEALTH_14638
|
||||
);
|
||||
|
||||
val isCrumble: Boolean = crumble
|
||||
|
||||
/**
|
||||
* Constructs a new `EnchantedJewelleryPlugin` `Object`.
|
||||
* @param options the dialogue options.
|
||||
* @param locations the teleport locations.
|
||||
* @param ids the ordered item ids.
|
||||
*/
|
||||
constructor(options: Array<String>, locations: Array<Location>, vararg ids: Int) : this(options, locations, false, *ids)
|
||||
|
||||
/**
|
||||
* Method used to teleport the player to the desired location.
|
||||
* @param player the player.
|
||||
* @param item the used jewellery item.
|
||||
* @param buttonID the button id.
|
||||
* @param isEquipped If the player is operating.
|
||||
*/
|
||||
fun use(player: Player, item: Item, buttonID: Int, isEquipped: Boolean) {
|
||||
if (buttonID > locations.size - 1) {
|
||||
if (isSlayerRing(item)) {
|
||||
slayerProgressDialogue(player)
|
||||
}
|
||||
return
|
||||
}
|
||||
val itemIndex = getItemIndex(item)
|
||||
val nextJewellery = Item(getNext(itemIndex))
|
||||
if (canTeleport(player, nextJewellery)) {
|
||||
Pulser.submit(object : Pulse(0) {
|
||||
private var count = 0
|
||||
private var location = getLocation(buttonID)
|
||||
override fun pulse(): Boolean {
|
||||
when (count) {
|
||||
0 -> {
|
||||
lock(player,4)
|
||||
visualize(player, ANIMATION, GRAPHICS)
|
||||
playAudio(player, AUDIO, true)
|
||||
player.impactHandler.disabledTicks = 4
|
||||
}
|
||||
3 -> {
|
||||
teleport(player,location)
|
||||
resetAnimator(player)
|
||||
if (isLastItemIndex(itemIndex)) {
|
||||
if (isCrumble) crumbleJewellery(player, item, isEquipped)
|
||||
} else {
|
||||
replaceJewellery(player, item, nextJewellery, isEquipped)
|
||||
}
|
||||
unlock(player)
|
||||
player.dispatch(TeleportEvent(TeleportManager.TeleportType.NORMAL, TeleportMethod.JEWELRY, item, location))
|
||||
return true
|
||||
}
|
||||
}
|
||||
count += 1
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceJewellery(player: Player, item: Item, nextJewellery: Item, isEquipped: Boolean) {
|
||||
if (isEquipped) {
|
||||
replaceSlot(player, item.slot, nextJewellery, item, Container.EQUIPMENT)
|
||||
} else {
|
||||
replaceSlot(player, item.slot, nextJewellery)
|
||||
}
|
||||
}
|
||||
|
||||
private fun crumbleJewellery(player: Player, item: Item, isEquipped: Boolean) {
|
||||
if (isEquipped) {
|
||||
removeItem(player, item, Container.EQUIPMENT)
|
||||
} else {
|
||||
removeItem(player, item)
|
||||
}
|
||||
if (isSlayerRing(item)) {
|
||||
addItem(player, Items.ENCHANTED_GEM_4155)
|
||||
sendMessage(player, "Your Ring of Slaying reverts back into a regular enchanted gem.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSlayerRing(item: Item): Boolean {
|
||||
return (item.id in RING_OF_SLAYING.ids)
|
||||
}
|
||||
|
||||
private fun slayerProgressDialogue(player: Player) {
|
||||
val slayerManager = getInstance(player)
|
||||
if (!slayerManager.hasTask()) {
|
||||
sendNPCDialogue(player, slayerManager.master!!.npc, "You need something new to hunt. Come and " +
|
||||
"see me When you can and I'll give you a new task.", core.game.dialogue.FacialExpression.HALF_GUILTY)
|
||||
return
|
||||
}
|
||||
sendNPCDialogue(player, slayerManager.master!!.npc, "You're currently " +
|
||||
"assigned to kill ${getSlayerTaskName(player).lowercase(Locale.getDefault())}'s; " +
|
||||
"only ${getSlayerTaskKillsRemaining(player)} more to go.", core.game.dialogue.FacialExpression.FRIENDLY)
|
||||
// Slayer tracker UI
|
||||
setVarbit(player, 2502, 0, slayerManager.flags.taskFlags shr 4)
|
||||
}
|
||||
|
||||
private fun canTeleport(player: Player, item: Item): Boolean {
|
||||
return player.zoneMonitor.teleport(1, item)
|
||||
}
|
||||
|
||||
private fun getNext(index: Int): Int {
|
||||
val i = index + 1
|
||||
if (i > ids.size - 1) {
|
||||
return ids[ids.size - 1]
|
||||
}
|
||||
return ids[i]
|
||||
}
|
||||
|
||||
private fun getLocation(index: Int): Location {
|
||||
if (index > locations.size - 1) {
|
||||
return locations[locations.size - 1]
|
||||
}
|
||||
return locations[index]
|
||||
}
|
||||
|
||||
fun getJewelleryName(item: Item): String {
|
||||
return item.name.replace(""" ?\(t?[0-9]?\)""".toRegex(), "")
|
||||
}
|
||||
|
||||
fun getJewelleryType(item: Item): String {
|
||||
return when {
|
||||
this == GAMES_NECKLACE -> "games necklace"
|
||||
this == DIGSITE_PENDANT -> "necklace"
|
||||
this == COMBAT_BRACELET -> "bracelet"
|
||||
this == SKILLS_NECKLACE -> "necklace"
|
||||
else -> item.name.split(" ")[0].lowercase(Locale.getDefault())
|
||||
}
|
||||
}
|
||||
|
||||
fun isLastItemIndex(index: Int): Boolean = index == ids.size - 1
|
||||
|
||||
fun getItemIndex(item: Item): Int {
|
||||
return ids.indexOf(item.id)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val ANIMATION = Animation(714)
|
||||
private val AUDIO = Audio(200)
|
||||
private val GRAPHICS = Graphics(308, 100, 50)
|
||||
val idMap = HashMap<Int, EnchantedJewellery>()
|
||||
|
||||
init {
|
||||
values().forEach { entry ->
|
||||
entry.ids.forEach { idMap[it] = entry }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* A god book.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum GodBook {
|
||||
HOLY_BOOK("Holy Book of Saradomin", new Item(3840), new Item(3839), new Item[] { new Item(1718) }, new Item(3827), new Item(3828), new Item(3829), new Item(3830)), BOOK_OF_BALANCE("Guthix's Book of Balance", new Item(3844), new Item(3843), new Item[] { new Item(1718), new Item(1724) }, new Item(3835), new Item(3836), new Item(3837), new Item(3838)), UNHOLY_BOOK("Unholy Book of Zamorak", new Item(3842), new Item(3841), new Item[] { new Item(1724) }, new Item(3831), new Item(3832), new Item(3833), new Item(3834));
|
||||
|
||||
/**
|
||||
* The books name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The god book.
|
||||
*/
|
||||
private final Item book;
|
||||
|
||||
/**
|
||||
* The damaged book.
|
||||
*/
|
||||
private final Item damagedBook;
|
||||
|
||||
/**
|
||||
* The items the book can bless.
|
||||
*/
|
||||
private final Item[] blessItems;
|
||||
|
||||
/**
|
||||
* The pages of items.
|
||||
*/
|
||||
private final Item[] pages;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GodBook} {@code Object}
|
||||
* @param book the book.
|
||||
* @param damagedBook the damged book.
|
||||
* @param name the name of the book.
|
||||
* @param pages the pages.
|
||||
*/
|
||||
private GodBook(String name, Item book, Item damagedBook, Item[] blessedItems, Item... pages) {
|
||||
this.book = book;
|
||||
this.damagedBook = damagedBook;
|
||||
this.name = name;
|
||||
this.blessItems = blessedItems;
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the god book for the item.
|
||||
* @param item the item.
|
||||
* @param damaged Flagged for the damaged book.
|
||||
* @return {@code GodBook} the god book.
|
||||
*/
|
||||
public static GodBook forItem(Item item, boolean damaged) {
|
||||
for (GodBook book : values()) {
|
||||
if ((!damaged ? book.getBook().getId() : book.getDamagedBook().getId()) == item.getId()) {
|
||||
return book;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has this god book.
|
||||
* @param player the player.
|
||||
* @param both if we are checking for the damaged/good.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasGodBook(Player player, boolean both) {
|
||||
return player.getInventory().containsItems(both ? new Item[] { book, damagedBook } : new Item[] { book });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a good book based on the page id.
|
||||
* @param page the page.
|
||||
* @return the respective god book.
|
||||
*/
|
||||
public static GodBook forPage(Item page) {
|
||||
for (GodBook book : values()) {
|
||||
for (Item i : book.getPages()) {
|
||||
if (i.getId() == page.getId()) {
|
||||
return book;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a page into the book.
|
||||
* @param player the player.
|
||||
* @param book the book.
|
||||
* @param page the page.
|
||||
*/
|
||||
public void insertPage(Player player, Item book, Item page) {
|
||||
if (hasPage(player, book, page)) {
|
||||
player.sendMessage("The book already has that page.");
|
||||
return;
|
||||
}
|
||||
if (player.getInventory().remove(new Item(page.getId(), 1))) {
|
||||
setPageHash(player, book, getPageIndex(page));
|
||||
player.sendMessage("You add the page to the book...");
|
||||
if (isComplete(player, book)) {
|
||||
player.getSavedData().getGlobalData().setGodPages(new boolean[4]);
|
||||
player.getSavedData().getGlobalData().setGodBook(-1);
|
||||
player.getInventory().replace(this.book, book.getSlot());
|
||||
player.getSavedData().getGlobalData().setGodBook(this);
|
||||
player.sendMessage("The book is now complete!");
|
||||
String message = this == UNHOLY_BOOK ? "unholy symbols" : this == HOLY_BOOK ? "holy symbols" : "unblessed holy symbols";
|
||||
player.sendMessage("You can now use it to bless " + (message) + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this item is a page of the book.
|
||||
* @param asItem the item.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isPage(Item asItem) {
|
||||
for (Item item : pages) {
|
||||
if (item.getId() == asItem.getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a book is complete.
|
||||
* @param book the book.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isComplete(Player player, Item book) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!hasPage(player, book, i + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a page in a book.
|
||||
* @param book the book.
|
||||
* @param page the page.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasPage(Player player, Item book, Item page) {
|
||||
return hasPage(player, book, getPageIndex(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a page hash.
|
||||
* @param book the book.
|
||||
* @param pageId the page Id.
|
||||
*/
|
||||
public void setPageHash(Player player, Item book, int pageId) {
|
||||
// int hash = getHash(book);
|
||||
// hash |= hash | (1 << pageId);
|
||||
// book.setCharge(1000 + hash);
|
||||
player.getSavedData().getGlobalData().getGodPages()[pageId - 1] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the book has a page.
|
||||
* @param book the book.
|
||||
* @param pageId the id of the page.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasPage(Player player, Item book, int pageId) {
|
||||
// return (getHash(book) & (1 << pageId)) != 0;
|
||||
return player.getSavedData().getGlobalData().getGodPages()[pageId - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hash.
|
||||
* @param book the book.
|
||||
* @return the hash.
|
||||
*/
|
||||
public int getHash(Item book) {
|
||||
return book.getCharge() - 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page index.
|
||||
* @param page the page.
|
||||
* @return the index.
|
||||
*/
|
||||
public int getPageIndex(Item page) {
|
||||
for (int i = 0; i < pages.length; i++) {
|
||||
if (pages[i].getId() == page.getId()) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the god book.
|
||||
* @return the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the book.
|
||||
* @return the book
|
||||
*/
|
||||
public Item getBook() {
|
||||
return book;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the damagedBook.
|
||||
* @return the damagedBook
|
||||
*/
|
||||
public Item getDamagedBook() {
|
||||
return damagedBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pages.
|
||||
* @return the pages
|
||||
*/
|
||||
public Item[] getPages() {
|
||||
return pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blessItem.
|
||||
* @return the blessItem
|
||||
*/
|
||||
public Item[] getBlessItem() {
|
||||
return blessItems;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.dialogue.DialogueAction;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
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.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* A god type.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum GodType {
|
||||
SARADOMIN(new Item(2412), new Item(2415), 2873, 913, "The cape disappears in a flash of light as it touches the ground."), GUTHIX(new Item(2413), new Item(2416), 2875, 914, "The cape disintegrates as it touches the earth."), ZAMORAK(new Item(2414), new Item(2417), 2874, 912, "The cape ignites and burns up as it touches the ground.");
|
||||
|
||||
/**
|
||||
* The cape.
|
||||
*/
|
||||
private final Item cape;
|
||||
|
||||
/**
|
||||
* The staff.
|
||||
*/
|
||||
private final Item staff;
|
||||
|
||||
/**
|
||||
* The statue id.
|
||||
*/
|
||||
private final int statueId;
|
||||
|
||||
/**
|
||||
* The npc id.
|
||||
*/
|
||||
private final int npcId;
|
||||
|
||||
/**
|
||||
* The drop message.
|
||||
*/
|
||||
private final String dropMessage;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GodCape} {@code Object}.
|
||||
* @param cape the cape.
|
||||
* @param staff the staff.
|
||||
* @param statueId the id.
|
||||
*/
|
||||
private GodType(Item cape, Item staff, int statueId, int npcId, String dropMessage) {
|
||||
this.cape = cape;
|
||||
this.staff = staff;
|
||||
this.statueId = statueId;
|
||||
this.npcId = npcId;
|
||||
this.dropMessage = dropMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prays at a statue.
|
||||
* @param player the player.
|
||||
* @param statue the statue.
|
||||
*/
|
||||
public void pray(final Player player, final Scenery statue) {
|
||||
if (hasAny(player)) {
|
||||
player.lock(3);
|
||||
player.animate(Animation.create(645));
|
||||
player.sendMessages("You kneel and begin to chant to " + getName() + "...", "...but there is no response.");
|
||||
return;
|
||||
}
|
||||
player.getDialogueInterpreter().sendDialogue("You kneel and begin to chant to " + getName() + "...");
|
||||
player.getDialogueInterpreter().addAction(new DialogueAction() {
|
||||
|
||||
@Override
|
||||
public void handle(final Player player, int buttonId) {
|
||||
player.lock();
|
||||
player.animate(Animation.create(645));
|
||||
GameWorld.getPulser().submit(new Pulse(3, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
Location loc = statue.getLocation().transform(0, -1, 0);
|
||||
GroundItem g = GroundItemManager.get(cape.getId(), loc, player);
|
||||
if (g == null) {
|
||||
GroundItemManager.create(cape, loc, player);
|
||||
}
|
||||
player.getPacketDispatch().sendPositionedGraphic(86, 0, 0, loc);
|
||||
player.unlock();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the god type by the statue id.
|
||||
* @param object the object.
|
||||
* @return the type.
|
||||
*/
|
||||
public static GodType forObject(int object) {
|
||||
for (GodType type : values()) {
|
||||
if (type.getStatueId() == object) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if they have a god cape & which one.
|
||||
* @param player the player.
|
||||
* @param invyOnly if invy check only.
|
||||
* @return {@code GodCape} the cape.
|
||||
*/
|
||||
public static GodType getCape(Player player, boolean invyOnly) {
|
||||
for (GodType cape : values()) {
|
||||
if (invyOnly ? player.getInventory().containsItems(cape.getCape()) : (player.getEquipment().containsItem(cape.getCape()) || player.getInventory().containsItems(cape.getCape()))) {
|
||||
return cape;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if they have a god cape.
|
||||
* @param player the player.
|
||||
* @return the cape.
|
||||
*/
|
||||
public static GodType getCape(Player player) {
|
||||
return getCape(player, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a god cape type by the id.
|
||||
* @param cape the cape.
|
||||
* @return the cape.
|
||||
*/
|
||||
public static GodType forCape(final Item cape) {
|
||||
for (GodType g : values()) {
|
||||
if (g.getCape().getId() == cape.getId()) {
|
||||
return g;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is friendly.
|
||||
* @param player the player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isFriendly(Player player) {
|
||||
return player.getEquipment().containsItem(cape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mage type.
|
||||
* @param id the id.
|
||||
* @return te type.
|
||||
*/
|
||||
public static GodType forId(int id) {
|
||||
for (GodType type : values()) {
|
||||
if (type.getNpcId() == id) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has any capes.
|
||||
* @param player the player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public static boolean hasAny(Player player) {
|
||||
for (GodType t : values()) {
|
||||
if (player.hasItem(t.getCape())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cape.
|
||||
* @return The cape.
|
||||
*/
|
||||
public Item getCape() {
|
||||
return cape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the staff.
|
||||
* @return The staff.
|
||||
*/
|
||||
public Item getStaff() {
|
||||
return staff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the statueId.
|
||||
* @return The statueId.
|
||||
*/
|
||||
public int getStatueId() {
|
||||
return statueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dropMessage.
|
||||
* @return The dropMessage.
|
||||
*/
|
||||
public String getDropMessage() {
|
||||
return dropMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the npcId.
|
||||
* @return The npcId.
|
||||
*/
|
||||
public int getNpcId() {
|
||||
return npcId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
* @return the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return StringUtils.formatDisplayName(name().toLowerCase());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents an experience lamp.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum Lamps {
|
||||
GENIE_LAMP(new Item(2528), 10),
|
||||
STRONGHOLD_LAMP(new Item(4447), 500),
|
||||
|
||||
K_ACHIEVEMENT_1(new Item(11137), 1000, 30),
|
||||
K_ACHIEVEMENT_2(new Item(11139), 5000, 40),
|
||||
K_ACHIEVEMENT_3(new Item(11141), 10000, 50),
|
||||
|
||||
V_ACHIEVEMENT_1(new Item(11753), 1000, 30),
|
||||
V_ACHIEVEMENT_2(new Item(11754), 5000, 40),
|
||||
V_ACHIEVEMENT_3(new Item(11755), 10000, 50),
|
||||
|
||||
L_ACHIEVEMENT_1(new Item(11185), 500, 1),
|
||||
L_ACHIEVEMENT_2(new Item(11186), 1000, 30),
|
||||
L_ACHIEVEMENT_3(new Item(11187), 1500, 35),
|
||||
|
||||
FALLY_ACHIEVEMENT_1(new Item(14580), 1000, 30),
|
||||
FALLY_ACHIEVEMENT_2(new Item(14581), 5000, 40),
|
||||
FALLY_ACHIEVEMENT_3(new Item(14582), 10000, 50),
|
||||
|
||||
FREM_ACHIEVEMENT_1(new Item(14574), 5000, 30),
|
||||
FREM_ACHIEVEMENT_2(new Item(14575), 10000, 40),
|
||||
FREM_ACHIEVEMENT_3(new Item(14576), 15000, 50),
|
||||
|
||||
SEERS_ACHIEVEMENT_1(new Item(14633), 1000, 30),
|
||||
SEERS_ACHIEVEMENT_2(new Item(14634), 5000, 40),
|
||||
SEERS_ACHIEVEMENT_3(new Item(14635), 10000, 50);
|
||||
|
||||
/**
|
||||
* The item id.
|
||||
*/
|
||||
private final Item item;
|
||||
|
||||
/**
|
||||
* The experience gained.
|
||||
*/
|
||||
private final int experience;
|
||||
|
||||
/**
|
||||
* The level requirement.
|
||||
*/
|
||||
private final int levelRequirement;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Lamps} {@code Object}
|
||||
* @param item the item.
|
||||
* @param experience the exp.
|
||||
* @param levelRequirement the level requirement to meet.
|
||||
*/
|
||||
Lamps(Item item, int experience, int levelRequirement) {
|
||||
this.item = item;
|
||||
this.experience = experience;
|
||||
this.levelRequirement = levelRequirement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Lamps} {@code Object}
|
||||
* @param item the item.
|
||||
* @param experience the exp.
|
||||
*/
|
||||
Lamps(Item item, int experience) {
|
||||
this(item, experience, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lamp by the item.
|
||||
* @param item the item.
|
||||
* @return the lamp.
|
||||
*/
|
||||
public static Lamps forItem(Item item) {
|
||||
for (Lamps l : values()) {
|
||||
if (l.getItem().getId() == item.getId()) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
* @return the item
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mod.
|
||||
* @return the mod
|
||||
*/
|
||||
public int getExp() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the levelRequirement.
|
||||
* @return the levelRequirement
|
||||
*/
|
||||
public int getLevelRequirement() {
|
||||
return levelRequirement;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import org.rs09.consts.Components;
|
||||
|
||||
import static org.rs09.consts.Items.*;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a light source.
|
||||
* @author Vexia
|
||||
* @author Emperor
|
||||
*/
|
||||
public enum LightSource {
|
||||
CANDLE(1, new Item(CANDLE_36, 1), new Item(LIT_CANDLE_33, 1), true, Components.DARKNESS_MEDIUM_98),
|
||||
BLACK_CANDLE(1, new Item(BLACK_CANDLE_38, 1), new Item(LIT_BLACK_CANDLE_32, 1), true, Components.DARKNESS_MEDIUM_98),
|
||||
TORCH(1, new Item(UNLIT_TORCH_596, 1), new Item(LIT_TORCH_594, 1), true, Components.DARKNESS_MEDIUM_98),
|
||||
CANDLE_LANTERN(4, new Item(CANDLE_LANTERN_4527, 1), new Item(CANDLE_LANTERN_4531, 1), false, Components.DARKNESS_MEDIUM_98),
|
||||
OIL_LAMP(12, new Item(OIL_LAMP_4522, 1), new Item(OIL_LAMP_4524, 1), true, Components.DARKNESS_LIGHT_97),
|
||||
OIL_LANTERN(26, new Item(OIL_LANTERN_4535, 1), new Item(OIL_LANTERN_4539, 1), false, Components.DARKNESS_LIGHT_97),
|
||||
BULLSEYE_LANTERN(49, new Item(BULLSEYE_LANTERN_4548, 1), new Item(BULLSEYE_LANTERN_4550, 1), false, -1),
|
||||
SAPPHIRE_LANTERN(49, new Item(SAPPHIRE_LANTERN_4701, 1), new Item(SAPPHIRE_LANTERN_4702, 1), false, -1),
|
||||
EMERALD_LANTERN(49, new Item(EMERALD_LANTERN_9064, 1), new Item(EMERALD_LANTERN_9065, 1), false, -1),
|
||||
MINING_HELMET(65, new Item(MINING_HELMET_5014, 1), new Item(MINING_HELMET_5013, 1), false, Components.DARKNESS_LIGHT_97);
|
||||
|
||||
/**
|
||||
* Represents the level required.
|
||||
*/
|
||||
private int level;
|
||||
|
||||
/**
|
||||
* Represents the raw item.
|
||||
*/
|
||||
private Item raw;
|
||||
|
||||
/**
|
||||
* Represents the product.
|
||||
*/
|
||||
private Item product;
|
||||
|
||||
/**
|
||||
* If the light source is open (eg. candles, torches, ...).
|
||||
*/
|
||||
private final boolean open;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LightSource} {@code Object}.
|
||||
* @param level the level.
|
||||
* @param raw the raw.
|
||||
* @param product the product.
|
||||
* @param open If it's an open light source.
|
||||
* @param interfaceId The overlay interface id to display.
|
||||
*/
|
||||
LightSource(int level, Item raw, Item product, boolean open, int interfaceId) {
|
||||
this.level = level;
|
||||
this.raw = raw;
|
||||
this.product = product;
|
||||
this.open = open;
|
||||
this.interfaceId = interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has a lit light source.
|
||||
* @param player The player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public static boolean hasActiveLightSource(Player player) {
|
||||
return getActiveLightSource(player) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the light source used by the player.
|
||||
* @param player The player.
|
||||
* @return The light source object, or null if the player didn't have any
|
||||
* light source.
|
||||
*/
|
||||
public static LightSource getActiveLightSource(Player player) {
|
||||
LightSource source;
|
||||
for (Item item : player.getInventory().toArray()) {
|
||||
if (item != null && (source = forProductId(item.getId())) != null) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
for (Item item : player.getEquipment().toArray()) {
|
||||
if (item != null && (source = forProductId(item.getId())) != null) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the light source by the id.
|
||||
* @param id the id.
|
||||
* @return the source.
|
||||
*/
|
||||
public static LightSource forId(int id) {
|
||||
for (LightSource light : LightSource.values()) {
|
||||
if (light.raw.getId() == id) {
|
||||
return light;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the light souce by the product id.
|
||||
* @param id the id.
|
||||
* @return the light source.
|
||||
*/
|
||||
public static LightSource forProductId(int id) {
|
||||
for (LightSource light : LightSource.values()) {
|
||||
if (light.product.getId() == id) {
|
||||
return light;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strength of the light source (1=dim, 2=medium, 3=bright).
|
||||
* @return The strength.
|
||||
*/
|
||||
public int getStrength() {
|
||||
switch (interfaceId) {
|
||||
case Components.DARKNESS_LIGHT_97:
|
||||
return 1;
|
||||
case Components.DARKNESS_MEDIUM_98:
|
||||
return 2;
|
||||
case -1:
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the light source.
|
||||
* @return The name.
|
||||
*/
|
||||
public String getName() {
|
||||
return super.name().toLowerCase().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw item.
|
||||
* @return the raw.
|
||||
*/
|
||||
public Item getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return the product.
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return the level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the open.
|
||||
* @return The open.
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interfaceId.
|
||||
* @return The interfaceId.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ids of the raw items.
|
||||
* @return The raw item ids.
|
||||
*/
|
||||
public static int[] getRawIds() {
|
||||
int array[] = new int[LightSource.values().length];
|
||||
for (int i = 0; i < LightSource.values().length -1; i++) {
|
||||
array[i] = LightSource.values()[i].getRaw().getId();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package content.data
|
||||
|
||||
enum class MeatState {
|
||||
INEDIBLE_RAW,
|
||||
INEDIBLE_BURNT,
|
||||
INEDIBLE_SPECIAL, // could be a quest item
|
||||
EDIBLE_COOKED,
|
||||
}
|
||||
|
||||
enum class Meat(val id: Int, val state: MeatState) {
|
||||
ENCHANTED_BEEF(522, MeatState.INEDIBLE_SPECIAL),
|
||||
ENCHANTED_RAT_MEAT(523, MeatState.INEDIBLE_SPECIAL),
|
||||
ENCHANTED_BEAR_MEAT(524, MeatState.INEDIBLE_SPECIAL),
|
||||
ENCHANTED_CHICKEN(525, MeatState.INEDIBLE_SPECIAL),
|
||||
RAW_UGTHANKI_MEAT(1859, MeatState.INEDIBLE_RAW),
|
||||
UGTHANKI_MEAT(1861, MeatState.EDIBLE_COOKED),
|
||||
RAW_BEEF(2132, MeatState.INEDIBLE_RAW),
|
||||
RAW_RAT_MEAT(2134, MeatState.INEDIBLE_RAW),
|
||||
RAW_BEAR_MEAT(2136, MeatState.INEDIBLE_RAW),
|
||||
RAW_CHICKEN(2138, MeatState.INEDIBLE_RAW),
|
||||
COOKED_CHICKEN(2140, MeatState.EDIBLE_COOKED),
|
||||
BURNT_CHICKEN(2140, MeatState.INEDIBLE_BURNT),
|
||||
COOKED_MEAT(2142, MeatState.EDIBLE_COOKED),
|
||||
BURNT_MEAT(2146, MeatState.INEDIBLE_BURNT),
|
||||
THIN_SNAIL_MEAT(3369, MeatState.EDIBLE_COOKED),
|
||||
LEAN_SNAIL_MEAT(3371, MeatState.EDIBLE_COOKED),
|
||||
FAT_SNAIL_MEAT(3373, MeatState.EDIBLE_COOKED),
|
||||
RAW_BEEF_UNDEAD(4287, MeatState.INEDIBLE_RAW),
|
||||
RAW_CHICKEN_UNDEAD(4289, MeatState.INEDIBLE_RAW),
|
||||
COOKED_CHICKEN_UNDEAD(4291, MeatState.EDIBLE_COOKED),
|
||||
COOKED_MEAT_UNDEAD(4293, MeatState.EDIBLE_COOKED),
|
||||
RAW_CRAB_MEAT(7518, MeatState.INEDIBLE_RAW),
|
||||
BURNT_CRAB_MEAT(7520, MeatState.INEDIBLE_BURNT),
|
||||
COOKED_CRAB_MEAT_5(7521, MeatState.EDIBLE_COOKED),
|
||||
COOKED_CRAB_MEAT_4(7523, MeatState.EDIBLE_COOKED),
|
||||
COOKED_CRAB_MEAT_3(7524, MeatState.EDIBLE_COOKED),
|
||||
COOKED_CRAB_MEAT_2(7525, MeatState.EDIBLE_COOKED),
|
||||
COOKED_CRAB_MEAT_1(7526, MeatState.EDIBLE_COOKED),
|
||||
GROUND_CRAB_MEAT(7527, MeatState.INEDIBLE_RAW),
|
||||
LOCUST_MEAT(9052, MeatState.EDIBLE_COOKED),
|
||||
RAW_BIRD_MEAT(9978, MeatState.INEDIBLE_RAW),
|
||||
ROAST_BIRD_MEAT(9980, MeatState.EDIBLE_COOKED),
|
||||
BURNT_BIRD_MEAT(9982, MeatState.INEDIBLE_BURNT),
|
||||
SKEWERED_BIRD_MEAT(9982, MeatState.INEDIBLE_RAW),
|
||||
RAW_BEAST_MEAT(9986, MeatState.INEDIBLE_RAW),
|
||||
ROAST_BEAST_MEAT(9988, MeatState.EDIBLE_COOKED),
|
||||
BURNT_BEAST_MEAT(9990, MeatState.INEDIBLE_BURNT),
|
||||
RAW_YAK_MEAT(10816, MeatState.INEDIBLE_RAW),
|
||||
RAW_PAWYA_MEAT(12535, MeatState.INEDIBLE_RAW),
|
||||
ENCHANTED_PAWYA_MEAT(12546, MeatState.INEDIBLE_SPECIAL);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package content.data;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the repair item type.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum RepairItem {
|
||||
BRONZE_HATCHET(new Item(494, 1), new Item(1351, 1), 0),
|
||||
BRONZE_PICKAXE(new Item(468, 1), new Item(1265, 1), 0),
|
||||
IRON_HATCHET(new Item(496, 1), new Item(1349, 1), 0),
|
||||
IRON_PICKAXE(new Item(470, 1), new Item(1267, 1), 0),
|
||||
STEEL_HATCHET(new Item(498, 1), new Item(1353, 1), 0),
|
||||
STEEL_PICKAXE(new Item(472, 1), new Item(1269, 1), 14),
|
||||
BLACK_HATCHET(new Item(500, 1), new Item(1361, 1), 10),
|
||||
MITHRIL_HATCHET(new Item(502, 1), new Item(1355, 1), 18),
|
||||
MITHRIL_PICKAXE(new Item(474, 1), new Item(1273, 1), 43),
|
||||
ADAMANT_HATCHET(new Item(504, 1), new Item(1357, 1), 43),
|
||||
ADAMANT_PICKAXE(new Item(476, 1), new Item(1271, 1), 107),
|
||||
RUNE_HATCHET(new Item(506, 1), new Item(1359, 1), 427),
|
||||
RUNE_PICKAXE(new Item(478, 1), new Item(1275, 1), 1100),
|
||||
DRAGON_HATCHET(new Item(6741, 1), new Item(6739, 1), 1800);
|
||||
|
||||
/**
|
||||
* The item id.
|
||||
*/
|
||||
private final Item item;
|
||||
|
||||
/**
|
||||
* The product item.
|
||||
*/
|
||||
private final Item product;
|
||||
|
||||
/**
|
||||
* The cost of the money to repair.
|
||||
*/
|
||||
private final int cost;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BobRepairItem} {@code Object}.
|
||||
* @param item the item.
|
||||
* @param product the product.
|
||||
* @param cost the cost.
|
||||
*/
|
||||
RepairItem(Item item, Item product, int cost) {
|
||||
this.item = item;
|
||||
this.product = product;
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
* @return The item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return The product.
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cost.
|
||||
* @return The cost.
|
||||
*/
|
||||
public int getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reapir item by the id.
|
||||
* @param id the id.
|
||||
* @return the repair item.
|
||||
*/
|
||||
public static RepairItem forId(int id) {
|
||||
for (RepairItem item : RepairItem.values())
|
||||
if (item.item.getId() == id)
|
||||
return item;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
package content.data.consumables;
|
||||
|
||||
import content.data.consumables.effects.*;
|
||||
import core.game.consumable.*;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.data.consumables.effects.KegOfBeerEffect;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Represents a repository of active consumables in the framework.
|
||||
*/
|
||||
public enum Consumables {
|
||||
|
||||
/** Meats */
|
||||
COOKED_MEAT(new Food(new int[] {2142}, new HealingEffect(3))),
|
||||
SHRIMPS(new Food(new int[] {315}, new HealingEffect(3))),
|
||||
COOKED_CHICKEN(new Food(new int[] {2140}, new HealingEffect(3))),
|
||||
COOKED_RABBIT(new Food(new int[] {3228}, new HealingEffect(5))),
|
||||
ANCHOVIES(new Food(new int[] {319}, new HealingEffect(1))),
|
||||
SARDINE(new Food(new int[] {325}, new HealingEffect(4))),
|
||||
POISON_KARAMBWAN(new Food(new int[] {3146}, new PoisonKarambwanEffect())),
|
||||
UGTHANKI_MEAT(new Food(new int[] {1861}, new HealingEffect(3))),
|
||||
HERRING(new Food(new int[] {347}, new HealingEffect(5))),
|
||||
MACKEREL(new Food(new int[] {355}, new HealingEffect(6))),
|
||||
ROAST_BIRD_MEAT(new Food(new int[] {9980}, new HealingEffect(6))),
|
||||
THIN_SNAIL(new Food(new int[] {3369}, new HealingEffect(5))),
|
||||
TROUT(new Food(new int[] {333}, new HealingEffect(7))),
|
||||
SPIDER_ON_STICK(new Food(new int[] {6297, 6305}, new HealingEffect(7))),
|
||||
SPIDER_ON_SHAFT(new Food(new int[] {6299}, new HealingEffect(7))),
|
||||
ROAST_RABBIT(new Food(new int[] {7223}, new HealingEffect(7))),
|
||||
LEAN_SNAIL(new Food(new int[] {3371}, new HealingEffect(8))),
|
||||
COD(new Food(new int[] {339}, new HealingEffect(7))),
|
||||
PIKE(new Food(new int[] {351}, new HealingEffect(8))),
|
||||
ROAST_BEAST_MEAT(new Food(new int[] {9988}, new HealingEffect(8))),
|
||||
COOKED_CRAB_MEAT(new Food(new int[] {7521, 7523, 7524, 7525, 7526}, new HealingEffect(2))),
|
||||
FAT_SNAIL(new Food(new int[] {3373}, new HealingEffect(9))),
|
||||
SALMON(new Food(new int[] {329}, new HealingEffect(9))),
|
||||
SLIMY_EEL(new Food(new int[] {3381}, new HealingEffect(6))),
|
||||
TUNA(new Food(new int[] {361}, new HealingEffect(10))),
|
||||
COOKED_KARAMBWAN(new Food(new int[] {3144}, new HealingEffect(18))),
|
||||
COOKED_CHOMPY(new Food(new int[] {2878}, new HealingEffect(10))),
|
||||
RAINBOW_FISH(new Food(new int[] {10136}, new HealingEffect(11))),
|
||||
CAVE_EEL(new Food(new int[] {5003}, new HealingEffect(7))),
|
||||
LOBSTER(new Food(new int[] {379}, new HealingEffect(12))),
|
||||
COOKED_JUBBLY(new Food(new int[] {7568}, new HealingEffect(15))),
|
||||
BASS(new Food(new int[] {365}, new HealingEffect(13))),
|
||||
SWORDFISH(new Food(new int[] {373}, new HealingEffect(14))),
|
||||
LAVA_EEL(new Food(new int[] {2149}, new HealingEffect(14))),
|
||||
MONKFISH(new Food(new int[] {7946}, new HealingEffect(16))),
|
||||
SHARK(new Food(new int[] {385}, new HealingEffect(20))),
|
||||
SEA_TURTLE(new Food(new int[] {397}, new HealingEffect(21))),
|
||||
MANTA_RAY(new Food(new int[] {391}, new HealingEffect(22))),
|
||||
KARAMBWANJI(new Food(new int[] {3151}, new HealingEffect(3))),
|
||||
STUFFED_SNAKE(new Food(new int[] {7579}, new HealingEffect(20), "You eat the stuffed snake-it's quite a meal! It tastes like chicken.")),
|
||||
CRAYFISH(new Food(new int[] {13433}, new HealingEffect(2))),
|
||||
GIANT_FROG_LEGS(new Food(new int [] {4517}, new HealingEffect(6))),
|
||||
|
||||
/** Breads */
|
||||
BREAD(new Food(new int[] {2309}, new HealingEffect(5))),
|
||||
BAGUETTE(new Food(new int[] {6961}, new HealingEffect(6))),
|
||||
|
||||
/** Sandwiches */
|
||||
TRIANGLE_SANDWICH(new Food(new int[] {6962}, new HealingEffect(6))),
|
||||
SQUARE_SANDWICH(new Food(new int[] {6965}, new HealingEffect(6))),
|
||||
SEAWEED_SANDWICH(new FakeConsumable(3168, new String[] {"You really, really do not want to eat that."})),
|
||||
FROGBURGER(new Food(new int[] {10962}, new HealingEffect(2))),
|
||||
|
||||
/** Kebabs */
|
||||
UGTHANKI_KEBAB(new Food(new int[] {1883}, new UgthankiKebabEffect())),
|
||||
UGTHANKI_KEBAB_SMELLING(new Food(new int[] {1885}, new SmellingUgthankiKebabEffect())),
|
||||
KEBAB(new Food(new int[] {1971}, new KebabEffect())),
|
||||
SUPER_KEBAB(new Food(new int[] {4608}, new SuperKebabEffect())),
|
||||
|
||||
/** Pies */
|
||||
REDBERRY_PIE(new HalfableFood(new int[] {2325, 2333, 2313}, new HealingEffect(5))),
|
||||
MEAT_PIE(new HalfableFood(new int[] {2327, 2331, 2313}, new HealingEffect(6))),
|
||||
APPLE_PIE(new HalfableFood(new int[] {2323, 2335, 2313}, new HealingEffect(7))),
|
||||
GARDEN_PIE(new HalfableFood(new int[] {7178, 7180, 2313}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.FARMING, 3, 0)))),
|
||||
FISH_PIE(new HalfableFood(new int[] {7188, 7190, 2313}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.FISHING, 3, 0)))),
|
||||
ADMIRAL_PIE(new HalfableFood(new int[] {7198, 7200, 2313}, new MultiEffect(new HealingEffect(8), new SkillEffect(Skills.FISHING, 5, 0)))),
|
||||
WILD_PIE(new HalfableFood(new int[] {7208, 7210, 2313}, new MultiEffect(new SkillEffect(Skills.SLAYER, 5, 0), new SkillEffect(Skills.RANGE, 4, 0), new HealingEffect(11)))),
|
||||
SUMMER_PIE(new HalfableFood(new int[] {7218, 7220, 2313}, new MultiEffect(new HealingEffect(11), new SkillEffect(Skills.AGILITY, 5, 0), new EnergyEffect(10)))),
|
||||
|
||||
/** Stews */
|
||||
STEW(new Food(new int[] {2003, 1923}, new HealingEffect(11))),
|
||||
SPICY_STEW(new Food(new int[] {7479, 1923}, new HealingEffect(11))),
|
||||
CURRY(new Food(new int[] {2011, 1923}, new HealingEffect(19))),
|
||||
BANANA_STEW(new Food(new int[] {4016, 1923}, new HealingEffect(11))),
|
||||
|
||||
/** Pizzas */
|
||||
PLAIN_PIZZA(new HalfableFood(new int[] {2289, 2291}, new HealingEffect(7))),
|
||||
MEAT_PIZZA(new HalfableFood(new int[] {2293, 2295}, new HealingEffect(8))),
|
||||
ANCHOVY_PIZZA(new HalfableFood(new int[] {2297, 2299}, new HealingEffect(9))),
|
||||
PINEAPPLE_PIZZA(new HalfableFood(new int[] {2301, 2303}, new HealingEffect(11))),
|
||||
|
||||
/** Cakes */
|
||||
CAKE(new Cake(new int[] {1891, 1893, 1895}, new HealingEffect(4), "You eat part of the cake.", "You eat some more cake.", "You eat the slice of cake.")),
|
||||
CHOCOLATE_CAKE(new Cake(new int[] {1897, 1899, 1901}, new HealingEffect(5), "You eat part of the chocolate cake.", "You eat some more of the chocolate cake.", "You eat the slice of cake.")),
|
||||
ROCK_CAKE(new Food(new int[] {2379}, new RockCakeEffect(), "The rock cake resists all attempts to eat it.")),
|
||||
DWARVEN_ROCK_CAKE(new Food(new int[] {7510, 7510}, new DwarvenRockCakeEffect(), "Ow! You nearly broke a tooth!", "The rock cake resists all attempts to eat it.")),
|
||||
HOT_DWARVEN_ROCK_CAKE(new Food(new int[] {7509, 7509}, new DwarvenRockCakeEffect(), "Ow! You nearly broke a tooth!", "The rock cake resists all attempts to eat it.")),
|
||||
COOKED_FISHCAKE(new Food(new int[] {7530}, new HealingEffect(11))),
|
||||
MINT_CAKE(new Food(new int[] {9475}, new EnergyEffect(50))),
|
||||
|
||||
/** Vegetables */
|
||||
POTATO(new Food(new int[] {1942}, new HealingEffect(1))),
|
||||
BAKED_POTATO(new Food(new int[] {6701}, new HealingEffect(2))),
|
||||
SPICY_SAUCE(new Food(new int[] {7072, 1923}, new HealingEffect(2))),
|
||||
CHILLI_CON_CARNE(new Food(new int[] {7062, 1923}, new HealingEffect(5))),
|
||||
SCRAMBLED_EGG(new Food(new int[] {7078, 1923}, new HealingEffect(5))),
|
||||
EGG_AND_TOMATO(new Food(new int[] {7064, 1923}, new HealingEffect(8))),
|
||||
SWEET_CORN(new Food(new int[] {5988}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(10)))),
|
||||
SWEETCORN_BOWL(new Food(new int[] {7088, 1923}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(10)))),
|
||||
POTATO_WITH_BUTTER(new Food(new int[] {6703}, new HealingEffect(7))),
|
||||
CHILLI_POTATO(new Food(new int[] {7054}, new HealingEffect(14))),
|
||||
FRIED_ONIONS(new Food(new int[] {7084, 1923}, new HealingEffect(5))),
|
||||
FRIED_MUSHROOMS(new Food(new int[] {7082, 1923}, new HealingEffect(5))),
|
||||
POTATO_WITH_CHEESE(new Food(new int[] {6705}, new HealingEffect(16))),
|
||||
EGG_POTATO(new Food(new int[] {7056}, new HealingEffect(11))),
|
||||
MUSHROOMS_AND_ONIONS(new Food(new int[] {7066, 1923}, new HealingEffect(11))),
|
||||
MUSHROOM_POTATO(new Food(new int[] {7058}, new HealingEffect(20))),
|
||||
TUNA_AND_CORN(new Food(new int[] {7068, 1923}, new HealingEffect(13))),
|
||||
TUNA_POTATO(new Food(new int[] {7060}, new HealingEffect(22))),
|
||||
ONION(new Food(new int[] {1957}, new HealingEffect(2), "It's always sad to see a grown man/woman cry.")),
|
||||
CABBAGE(new Food(new int[] {1965}, new HealingEffect(2), "You eat the cabbage. Yuck!")),
|
||||
DRAYNOR_CABBAGE(new Food(new int[] {1967}, new DraynorCabbageEffect(), "You eat the cabbage.", "It seems to taste nicer than normal.")),
|
||||
EVIL_TURNIP(new Food(new int[] {12134, 12136, 12138}, new HealingEffect(6))),
|
||||
SPINACH_ROLL(new Food(new int[] {1969}, new HealingEffect(2))),
|
||||
|
||||
/** Dairies */
|
||||
POT_OF_CREAM(new Food(new int[] {2130}, new HealingEffect(1))),
|
||||
CHEESE(new Food(new int[] {1985}, new HealingEffect(2))),
|
||||
CHOCOLATEY_MILK(new Drink(new int[] {1977, 1925}, new HealingEffect(4))),
|
||||
|
||||
/** Fruits */
|
||||
BANANA(new Food(new int[] {1963}, new HealingEffect(2))),
|
||||
SLICED_BANANA(new Food(new int[] {3162}, new HealingEffect(2))),
|
||||
RED_BANANA(new Food(new int[] {7572}, new HealingEffect(5), "You eat the red banana. It's tastier than your average banana.")),
|
||||
SLICED_RED_BANANA(new Food(new int[] {7574}, new HealingEffect(5), "You eat the sliced red banana. Yum.")),
|
||||
ORANGE(new Food(new int[] {2108}, new HealingEffect(2))),
|
||||
ORANGE_CHUNKS(new Food(new int[] {2110}, new HealingEffect(2))),
|
||||
ORANGE_SLICES(new Food(new int[] {2112}, new HealingEffect(2))),
|
||||
PAPAYA_FRUIT(new Food(new int[] {5972}, new HealingEffect(2))),
|
||||
TENTI_PINEAPPLE(new FakeConsumable(1851, new String[] {"Try using a knife to slice it into pieces."})),
|
||||
PINEAPPLE(new FakeConsumable(2114, new String[] {"Try using a knife to slice it into pieces."})),
|
||||
PINEAPPLE_CHUNKS(new Food(new int[] {2116}, new HealingEffect(2))),
|
||||
PINEAPPLE_RING(new Food(new int[] {2118}, new HealingEffect(2))),
|
||||
DWELLBERRIES(new Food(new int[] {2126}, new HealingEffect(2))),
|
||||
JANGERBERRIES(new Food(new int[] {247}, new MultiEffect(new SkillEffect(Skills.ATTACK, 2, 0), new SkillEffect(Skills.STRENGTH, 1, 0), new PrayerEffect(1, 0), new SkillEffect(Skills.DEFENCE, -1, 0)))),
|
||||
STRAWBERRY(new Food(new int[] {5504}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(6)))),
|
||||
TOMATO(new Food(new int[] {1982}, new HealingEffect(2))),
|
||||
WATERMELON(new FakeConsumable(5982, new String[] {"Try using a knife to slice it into pieces."})),
|
||||
WATERMELON_SLICE(new Food(new int[] {5984}, new PercentageHealthEffect(5))),
|
||||
LEMON(new Food(new int[] {2102}, new HealingEffect(2))),
|
||||
LEMON_CHUNKS(new Food(new int[] {2104}, new HealingEffect(2))),
|
||||
LEMON_SLICES(new Food(new int[] {2106}, new HealingEffect(2))),
|
||||
LIME(new Food(new int[] {2120}, new HealingEffect(2))),
|
||||
LIME_CHUNKS(new Food(new int[] {2122}, new HealingEffect(2))),
|
||||
LIME_SLICES(new Food(new int[] {2124}, new HealingEffect(2))),
|
||||
PEACH(new Food(new int[] {6883}, new HealingEffect(8))),
|
||||
WHITE_TREE_FRUIT(new Food(new int[] {6469}, new MultiEffect(new RandomEnergyEffect(5, 10), new HealingEffect(3)))),
|
||||
STRANGE_FRUIT(new Food(new int[] {464}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(30)))),
|
||||
|
||||
/** Gnome Cooking */
|
||||
TOAD_CRUNCHIES(new Food(new int[] {2217}, new HealingEffect(12))),
|
||||
PREMADE_TD_CRUNCH(new Food(new int[] {2243}, new HealingEffect(12))),
|
||||
SPICY_CRUNCHIES(new Food(new int[] {2213}, new HealingEffect(7))),
|
||||
PREMADE_SY_CRUNCH(new Food(new int[] {2241}, new HealingEffect(7))),
|
||||
WORM_CRUNCHIES(new Food(new int[] {2205}, new HealingEffect(8))),
|
||||
PREMADE_WM_CRUNC(new Food(new int[] {2237}, new HealingEffect(8))),
|
||||
CHOCCHIP_CRUNCHIES(new Food(new int[] {2209}, new HealingEffect(7))),
|
||||
PREMADE_CH_CRUNCH(new Food(new int[] {2239}, new HealingEffect(7))),
|
||||
FRUIT_BATTA(new Food(new int[] {2277}, new HealingEffect(11))),
|
||||
PREMADE_FRT_BATTA(new Food(new int[] {2225}, new HealingEffect(11))),
|
||||
TOAD_BATTA(new Food(new int[] {2255}, new HealingEffect(11))),
|
||||
PREMADE_TD_BATTA(new Food(new int[] {2221}, new HealingEffect(11))),
|
||||
WORM_BATTA(new Food(new int[] {2253}, new HealingEffect(11))),
|
||||
PREMADE_WM_BATTA(new Food(new int[] {2219}, new HealingEffect(11))),
|
||||
VEGETABLE_BATTA(new Food(new int[] {2281}, new HealingEffect(11))),
|
||||
PREMADE_VEG_BATTA(new Food(new int[] {2227}, new HealingEffect(11))),
|
||||
CHEESE_AND_TOMATOES_BATTA(new Food(new int[] {2259}, new HealingEffect(11))),
|
||||
PREMADE_CT_BATTA(new Food(new int[] {2223}, new HealingEffect(11))),
|
||||
WORM_HOLE(new Food(new int[] {2191}, new HealingEffect(12))),
|
||||
PREMADE_WORM_HOLE(new Food(new int[] {2233}, new HealingEffect(12))),
|
||||
VEG_BALL(new Food(new int[] {2195}, new HealingEffect(12))),
|
||||
PREMADE_VEG_BALL(new Food(new int[] {2235}, new HealingEffect(12))),
|
||||
TANGLED_TOADS_LEGS(new Food(new int[] {2187}, new HealingEffect(15))),
|
||||
PREMADE_TTL(new Food(new int[] {2231}, new HealingEffect(15))),
|
||||
CHOCOLATE_BOMB(new Food(new int[] {2195}, new HealingEffect(15))),
|
||||
PREMADE_CHOC_BOMB(new Food(new int[] {2229}, new HealingEffect(15))),
|
||||
TOAD_LEGS(new Food(new int[] {2152}, new HealingEffect(3))),
|
||||
KING_WORM(new Food(new int[] {2162}, new HealingEffect(2))),
|
||||
|
||||
/** Ales */
|
||||
ASGOLDIAN_ALE(new FakeConsumable(7508, new String[] {"I don't think I'd like gold in beer thanks. Leave it for the dwarves."})),
|
||||
ASGARNIAN_ALE(new Drink(new int[] {1905, 1919}, new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.STRENGTH, 2, 0), new SkillEffect(Skills.ATTACK, -4, 0)), "You drink the ale. You feel slightly reinvigorated...", "...and slightly dizzy too.")),
|
||||
ASGARNIAN_ALE_KEG(new Drink(new int[] {5785, 5783, 5781, 5779, 5769}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 2, 0), new SkillEffect(Skills.ATTACK, -4, 0)), new Animation(2289), "You drink the ale. You feel slightly reinvigorated...", "...and slightly dizzy too.")),
|
||||
ASGARNIAN_ALE_M(new Drink(new int[] {5739, 1919}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -6, 0)))),
|
||||
ASGARNIAN_ALE_M_KEG(new Drink(new int[] {5865, 5863, 5861, 5859, 5769}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -6, 0)), new Animation(2289))),
|
||||
AXEMANS_FOLLY(new Drink(new int[] {5751, 1919}, new MultiEffect(new SkillEffect(Skills.WOODCUTTING, 1, 0), new HealingEffect(1), new SkillEffect(Skills.STRENGTH, -3, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
|
||||
AXEMANS_FOLLY_KEG(new Drink(new int[] {5825, 5823, 5821, 5819, 5769}, new MultiEffect(new SkillEffect(Skills.WOODCUTTING, 1, 0), new HealingEffect(1), new SkillEffect(Skills.STRENGTH, -3, 0), new SkillEffect(Skills.ATTACK, -3, 0)), new Animation(2289))),
|
||||
AXEMANS_FOLLY_M(new Drink(new int[] {5753, 1919}, new MultiEffect(new SkillEffect(Skills.WOODCUTTING, 2, 0), new HealingEffect(2), new SkillEffect(Skills.STRENGTH, -4, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
AXEMANS_FOLLY_M_KEG(new Drink(new int[] {5905, 5903, 5901, 5899, 5769}, new MultiEffect(new SkillEffect(Skills.WOODCUTTING, 2, 0), new HealingEffect(2), new SkillEffect(Skills.STRENGTH, -4, 0), new SkillEffect(Skills.ATTACK, -4, 0)), new Animation(2289))),
|
||||
BANDITS_BREW(new Drink(new int[] {4627, 1919}, new MultiEffect(new SkillEffect(Skills.THIEVING, 1, 0), new SkillEffect(Skills.ATTACK, 1, 0), new SkillEffect(Skills.STRENGTH, -1, 0), new SkillEffect(Skills.DEFENCE, -6, 0), new HealingEffect(1)), "You drink the beer. You feel slightly reinvigorated...", "...and slightly dizzy too.")),
|
||||
BEER(new Drink(new int[] {1917, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.STRENGTH, 0, 0.04), new SkillEffect(Skills.ATTACK, 0, -0.07)), "You drink the beer. You feel slightly reinvigorated...", "...and slightly dizzy too.")),
|
||||
BEER_TANKARD(new Drink(new int[] {3803, 3805}, new MultiEffect(new SkillEffect(Skills.ATTACK, -9, 0), new SkillEffect(Skills.STRENGTH, 4, 0)), "You quaff the beer. You feel slightly reinvigorated...", "...but very dizzy too.")),
|
||||
KEG_OF_BEER(new Drink(new int[] {3801}, new KegOfBeerEffect(), new Animation(1330), "You chug the keg. You feel reinvigorated...", "...but extremely drunk too.")),
|
||||
CHEFS_DELIGHT(new Drink(new int[] {5755, 1919}, new MultiEffect(new SkillEffect(Skills.COOKING, 1, 0.05), new HealingEffect(1), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)))),
|
||||
CHEFS_DELIGHT_KEG(new Drink(new int[] {5833, 5831, 5829, 5827, 5769}, new MultiEffect(new SkillEffect(Skills.COOKING, 1, 0.05), new HealingEffect(1), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)), new Animation(2289))),
|
||||
CHEFS_DELIGHT_M(new Drink(new int[] {5757, 1919}, new MultiEffect(new SkillEffect(Skills.COOKING, 2, 0.05), new HealingEffect(2), new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.STRENGTH, -3, 0)))),
|
||||
CHEFS_DELIGHT_M_KEG(new Drink(new int[] {5913, 5911, 5909, 5907, 5769}, new MultiEffect(new SkillEffect(Skills.COOKING, 2, 0.05), new HealingEffect(2), new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.STRENGTH, -3, 0)), new Animation(2289))),
|
||||
CIDER(new Drink(new int[] {5763, 1919}, new MultiEffect(new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.FARMING, 1, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0))))),
|
||||
CIDER_KEG(new Drink(new int[] {5849, 5847, 5845, 5843, 5769}, new MultiEffect(new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.FARMING, 1, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0))), new Animation(2289))),
|
||||
MATURE_CIDER(new Drink(new int[] {5765, 1919}, new MultiEffect(new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.FARMING, 2, 0), new SkillEffect(Skills.ATTACK, -5, 0), new SkillEffect(Skills.STRENGTH, -5, 0))))),
|
||||
CIDER_M_KEG(new Drink(new int[] {5929, 5927, 5925, 5923, 5769}, new MultiEffect(new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.FARMING, 2, 0), new SkillEffect(Skills.ATTACK, -5, 0), new SkillEffect(Skills.STRENGTH, -5, 0))), new Animation(2289))),
|
||||
DRAGON_BITTER(new Drink(new int[] {1911, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.STRENGTH, 2, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
DRAGON_BITTER_KEG(new Drink(new int[] {5809, 5807, 5805, 5803, 5769}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.STRENGTH, 2, 0), new SkillEffect(Skills.ATTACK, -4, 0)), new Animation(2289))),
|
||||
DRAGON_BITTER_M(new Drink(new int[] {5745, 1919}, new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -6, 0)))),
|
||||
DRAGON_BITTER_M_KEG(new Drink(new int[] {5889, 5887, 5885, 5883, 5769}, new MultiEffect(new HealingEffect(2), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -6, 0)), new Animation(2289))),
|
||||
DWARVEN_STOUT(new Drink(new int[] {1913, 1919}, new MultiEffect(new SkillEffect(Skills.MINING, 1, 0), new SkillEffect(Skills.SMITHING, 1 ,0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0), new SkillEffect(Skills.DEFENCE, -2, 0), new HealingEffect(1)), "You drink the Dwarven Stout. It tastes foul.", "It tastes pretty strong too.")),
|
||||
DWARVEN_STOUT_KEG(new Drink(new int[] {5777, 5775, 5773, 5771, 5769}, new MultiEffect(new SkillEffect(Skills.MINING, 1, 0), new SkillEffect(Skills.SMITHING, 1 ,0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0), new SkillEffect(Skills.DEFENCE, -2, 0), new HealingEffect(1)), new Animation(2289), "You drink the Dwarven Stout. It tastes foul.", "It tastes pretty strong too.")),
|
||||
DWARVEN_STOUT_M(new Drink(new int[] {5747, 1919}, new MultiEffect(new SkillEffect(Skills.MINING, 2, 0), new SkillEffect(Skills.SMITHING, 2 ,0), new SkillEffect(Skills.ATTACK, -7, 0), new SkillEffect(Skills.STRENGTH, -7, 0), new SkillEffect(Skills.DEFENCE, -7, 0), new HealingEffect(1)))),
|
||||
DWARVEN_STOUT_M_KEG(new Drink(new int[] {5857, 5855, 5853, 5851, 5769}, new MultiEffect(new SkillEffect(Skills.MINING, 2, 0), new SkillEffect(Skills.SMITHING, 2 ,0), new SkillEffect(Skills.ATTACK, -7, 0), new SkillEffect(Skills.STRENGTH, -7, 0), new SkillEffect(Skills.DEFENCE, -7, 0), new HealingEffect(1)), new Animation(2289))),
|
||||
GREENMANS_ALE(new Drink(new int[] {1909, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.HERBLORE, 1, 0), new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.STRENGTH, -3, 0), new SkillEffect(Skills.DEFENCE, -3, 0)))),
|
||||
GREENMANS_ALE_KEG(new Drink(new int[] {5793, 5791, 5789, 5787, 5769}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.HERBLORE, 1, 0), new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.STRENGTH, -3, 0), new SkillEffect(Skills.DEFENCE, -3, 0)), new Animation(2289))),
|
||||
GREENMANS_ALE_M(new Drink(new int[] {5743, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.HERBLORE, 2, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)))),
|
||||
GREENMANS_ALE_M_KEG(new Drink(new int[] {5873, 5871, 5869, 5867, 5769}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.HERBLORE, 2, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)), new Animation(2289))),
|
||||
GROG(new Drink(new int[] {1915, 1919}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -6, 0)))),
|
||||
MOONLIGHT_MEAD(new Drink(new int[] {2955, 1919}, new HealingEffect(4), "It tastes like something just died in your mouth.")),
|
||||
MOONLIGHT_MEAD_KEG(new Drink(new int[] {5817, 5815, 5813, 5811, 5769}, new HealingEffect(4), new Animation(2289), "It tastes like something just died in your mouth.")),
|
||||
MOONLIGHT_MEAD_M(new Drink(new int[] {5749, 1919}, new HealingEffect(6))),
|
||||
MOONLIGHT_MEAD_M_KEG(new Drink(new int[] {5897, 5895, 5893, 5891, 5769}, new HealingEffect(6), new Animation(2289))),
|
||||
SLAYERS_RESPITE(new Drink(new int[] {5759, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.SLAYER, 2, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)))),
|
||||
SLAYERS_RESPITE_KEG(new Drink(new int[] {5841, 5839, 5837, 5835, 5769}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.SLAYER, 2, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)), new Animation(2289))),
|
||||
SLAYERS_RESPITE_M(new Drink(new int[] {5761, 1919}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.SLAYER, 4, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)))),
|
||||
SLAYERS_RESPITE_M_KEG(new Drink(new int[] {5841, 5839, 5837, 5835, 5769}, new MultiEffect(new HealingEffect(1), new SkillEffect(Skills.SLAYER, 4, 0), new SkillEffect(Skills.ATTACK, -2, 0), new SkillEffect(Skills.STRENGTH, -2, 0)), new Animation(2289))),
|
||||
WIZARDS_MIND_BOMB(new Drink(new int[] {1907, 1919}, new WizardsMindBombEffect(), "You drink the Wizard's Mind Bomb.", "You feel very strange.")),
|
||||
MATURE_WMB(new Drink(new int[] {5741, 1919}, new MatureWmbEffect())),
|
||||
|
||||
/** Cocktails */
|
||||
FRUIT_BLAST(new Drink(new int[] {2084, 2026}, new HealingEffect(9))),
|
||||
PREMADE_FR_BLAST(new Food(new int[] {2034, 2026}, new HealingEffect(9))),
|
||||
PINEAPPLE_PUNCH(new Drink(new int[] {2048, 2026}, new HealingEffect(9), "You drink the cocktail. It tastes great.")),
|
||||
PREMADE_P_PUNCH(new Drink(new int[] {2036, 2026}, new HealingEffect(9), "You drink the cocktail. It tastes great.")),
|
||||
WIZARD_BLIZZARD(new Drink(new int[] {2054, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
PREMADE_WIZ_BLZD(new Drink(new int[] {2040, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
SHORT_GREEN_GUY(new Drink(new int[] {2080, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 4, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
|
||||
PREMADE_SGG(new Drink(new int[] {2038, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 4, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
|
||||
DRUNK_DRAGON(new Drink(new int[] {2092, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
PREMADE_DR_DRAGON(new Drink(new int[] {2032, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
CHOC_SATURDAY(new Drink(new int[] {2074, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
PREMADE_CHOC_SDY(new Drink(new int[] {2030, 2026}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 7, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
BLURBERRY_SPECIAL(new Drink(new int[] {2064, 2026}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
PREMADE_BLURB_SP(new Drink(new int[] {2028, 2026}, new MultiEffect(new HealingEffect(6), new SkillEffect(Skills.STRENGTH, 6, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
|
||||
/** Bottled Drinks */
|
||||
KARAMJAN_RUM(new Drink(new int[] {431}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 5, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
BRAINDEATH_RUM(new Drink(new int[] {7157}, new MultiEffect(new SkillEffect(Skills.DEFENCE, 0, -0.1), new SkillEffect(Skills.ATTACK, 0, -0.05), new SkillEffect(Skills.PRAYER, 0, -0.05), new SkillEffect(Skills.RANGE, 0, -0.05), new SkillEffect(Skills.MAGIC, 0, -0.05), new SkillEffect(Skills.HERBLORE, 0, -0.05), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.MINING, 1, 0)), "With a sense of impending doom you drink the 'rum'. You try very hard not to die.")),
|
||||
RUM_TROUBLE_BREWING_RED(new Drink(new int[] {8940, 8940}, new TroubleBrewingRumEffect("Oh gods! It tastes like burning!"), new Animation(9605))),
|
||||
RUM_TROUBLE_BREWING_BLUE(new Drink(new int[] {8941, 8941}, new TroubleBrewingRumEffect("My Liver! My Liver is melting!"), new Animation(9604))),
|
||||
VODKA(new Drink(new int[] {2015}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -3, 0)))),
|
||||
GIN(new Drink(new int[] {2019}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 1, 0), new SkillEffect(Skills.ATTACK, 4, 0), new RandomHealthEffect(3, 4)))),
|
||||
BRANDY(new Drink(new int[] {2021}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.ATTACK, 4, 0)))),
|
||||
WHISKY(new Drink(new int[] {2017}, new MultiEffect(new HealingEffect(5), new SkillEffect(Skills.STRENGTH, 3, 0), new SkillEffect(Skills.ATTACK, -4, 0)))),
|
||||
BOTTLE_OF_WINE(new Drink(new int[] {2015, 7921}, new MultiEffect(new HealingEffect(14), new SkillEffect(Skills.ATTACK, -3, 0)))),
|
||||
|
||||
/** Wine */
|
||||
JUG_OF_WINE(new Drink(new int[] {1993, 1935}, new MultiEffect(new HealingEffect(11), new SkillEffect(Skills.ATTACK, -2, 0)))),
|
||||
HALF_FULL_WINE_JUG(new Drink(new int[] {1989, 1935}, new HealingEffect(7))),
|
||||
|
||||
/** Tea */
|
||||
CUP_OF_TEA(new Drink(new int[] {712, 1980}, new MultiEffect(new HealingEffect(3), new SkillEffect(Skills.ATTACK, 3, 0)), "Aaah, nothing like a nice cuppa tea!")),
|
||||
CUP_OF_TEA_NETTLE(new Drink(new int[] {4242, 1980}, new EnergyEffect(10))),
|
||||
CUP_OF_TEA_MILKY_NETTLE(new Drink(new int[] {4243, 1980}, new EnergyEffect(10))),
|
||||
NETTLE_TEA(new Drink(new int[] {4239, 1980}, new NettleTeaEffect())),
|
||||
NETTLE_TEA_MILKY(new Drink(new int[] {4240, 1980}, new NettleTeaEffect())),
|
||||
CUP_OF_TEA_CLAY(new Drink(new int[] {7730, 7728}, new SkillEffect(Skills.CONSTRUCTION, 1, 0), "You feel refreshed and ready for more building.")),
|
||||
CUP_OF_TEA_CLAY_MILKY(new Drink(new int[] {7731, 7728}, new SkillEffect(Skills.CONSTRUCTION, 1, 0))),
|
||||
CUP_OF_TEA_WHITE(new Drink(new int[] {7733, 7732}, new SkillEffect(Skills.CONSTRUCTION, 2, 0), "You feel refreshed and ready for more building.")),
|
||||
CUP_OF_TEA_WHITE_MILKY(new Drink(new int[] {7734, 7732}, new SkillEffect(Skills.CONSTRUCTION, 2, 0))),
|
||||
CUP_OF_TEA_GOLD(new Drink(new int[] {7736, 7735}, new SkillEffect(Skills.CONSTRUCTION, 3, 0), "You feel refreshed and ready for more building.")),
|
||||
CUP_OF_TEA_GOLD_MILKY(new Drink(new int[] {7737, 7735}, new SkillEffect(Skills.CONSTRUCTION, 3, 0))),
|
||||
|
||||
/** Miscellaneous */
|
||||
CHOCOLATE_BAR(new Food(new int[] {1973}, new HealingEffect(3))),
|
||||
PURPLE_SWEETS(new Food(new int[] {4561}, new HealingEffect(0))),
|
||||
PURPLE_SWEETS_STACKABLE(new Food(new int[] {10476}, new MultiEffect(new EnergyEffect(10), new RandomHealthEffect(1, 3)), "The sugary goodness heals some energy.", "The sugary goodness is yummy.")),
|
||||
FIELD_RATION(new Food(new int[] {7934}, new HealingEffect(10))),
|
||||
ROLL(new Food(new int[] {6963}, new HealingEffect(6))),
|
||||
TCHIKI_MONKEY_NUTS(new Food(new int[] {7573}, new HealingEffect(5), "You eat the Tchiki monkey nuts. They taste nutty.")),
|
||||
TCHIKI_MONKEY_PASTE(new Food(new int[] {7575}, new HealingEffect(5), "You eat the Tchiki monkey nut paste. It sticks to the roof of your mouth.")),
|
||||
OOMLIE_WRAP(new Food(new int[] {Items.COOKED_OOMLIE_WRAP_2343}, new MultiEffect(new HealingEffect(14), new AchievementEffect(DiaryType.KARAMJA, 2, 2)))),
|
||||
ROE(new Food(new int[]{11324}, new HealingEffect(3))),
|
||||
EQUA_LEAVES(new Food(new int[]{2128}, new HealingEffect(1))),
|
||||
CHOC_ICE(new Food(new int[]{6794}, new HealingEffect(6))),
|
||||
EDIBLE_SEAWEED(new Food(new int[] {403}, new HealingEffect(4))),
|
||||
|
||||
/** Special Events */
|
||||
PUMPKIN(new Food(new int[] {1959}, new HealingEffect(14))),
|
||||
EASTER_EGG(new Food(new int[] {1961}, new HealingEffect(14))),
|
||||
|
||||
/** Potions */
|
||||
STRENGTH(new Potion(new int[] {113, 115, 117, 119}, new SkillEffect(Skills.STRENGTH, 3, 0.1))),
|
||||
ATTACK(new Potion(new int[] {2428, 121, 123, 125}, new SkillEffect(Skills.ATTACK, 3, 0.1))),
|
||||
DEFENCE(new Potion(new int[] {2432, 133, 135, 137}, new SkillEffect(Skills.DEFENCE, 3, 0.1))),
|
||||
RANGING(new Potion(new int[] {2444, 169, 171, 173}, new SkillEffect(Skills.RANGE, 3, 0.1))),
|
||||
MAGIC(new Potion(new int[] {3040, 3042, 3044, 3046}, new SkillEffect(Skills.MAGIC, 3, 0.1))),
|
||||
SUPER_STRENGTH(new Potion(new int[] {2440, 157, 159, 161}, new SkillEffect(Skills.STRENGTH, 3, 0.2))),
|
||||
SUPER_ATTACK(new Potion(new int[] {2436, 145, 147, 149}, new SkillEffect(Skills.ATTACK, 3, 0.2))),
|
||||
SUPER_DEFENCE(new Potion(new int[] {2442, 163, 165, 167}, new SkillEffect(Skills.DEFENCE, 3, 0.2))),
|
||||
ANTIPOISON(new Potion(new int[] {2446, 175, 177, 179}, new MultiEffect(new SetAttributeEffect("poison:immunity", 143), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
ANTIPOISON_(new Potion(new int[] {5943, 5945, 5947, 5949}, new MultiEffect(new SetAttributeEffect("poison:immunity", 863), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
ANTIPOISON__(new Potion(new int[] {5952, 5954, 5956, 5958}, new MultiEffect(new SetAttributeEffect("poison:immunity", 2000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
SUPER_ANTIP(new Potion(new int[] {2448, 181, 183, 185}, new MultiEffect(new SetAttributeEffect("poison:immunity", 1000), new RemoveStateEffect(EntityState.POISONED.ordinal())))),
|
||||
RELICYM(new Potion(new int[] {4842, 4844, 4846, 4848}, new MultiEffect(new SetAttributeEffect("disease:immunity", 300), new RemoveStateEffect("disease")))),
|
||||
AGILITY(new Potion(new int[] {3032, 3034, 3036, 3038}, new SkillEffect(Skills.AGILITY, 3, 0))),
|
||||
HUNTER(new Potion(new int[] {9998, 10000, 10002, 10004}, new SkillEffect(Skills.HUNTER, 3, 0))),
|
||||
RESTORE(new Potion(new int[] {2430, 127, 129, 131}, new RestoreEffect(10, 0.3))),
|
||||
SARA_BREW(new Potion(new int[] {6685, 6687, 6689, 6691}, new MultiEffect(new PercentHeal(2, .15), new SkillEffect(Skills.ATTACK, 0, -0.10), new SkillEffect(Skills.STRENGTH, 0, -0.10), new SkillEffect(Skills.MAGIC, 0, -0.10), new SkillEffect(Skills.RANGE, 0, -0.10), new SkillEffect(Skills.DEFENCE, 2, 0.2)))),
|
||||
SUMMONING(new Potion(new int[] {12140, 12142, 12144, 12146}, new MultiEffect(new RestoreSummoningSpecial(), new SummoningEffect(7, 0.25)))),
|
||||
COMBAT(new Potion(new int[] {9739, 9741, 9743, 9745}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, .1), new SkillEffect(Skills.ATTACK, 3, .1)))),
|
||||
ENERGY(new Potion(new int[] {3008, 3010, 3012, 3014}, new MultiEffect(new EnergyEffect(10), new HealingEffect(3)))),
|
||||
FISHING(new Potion(new int[] {2438, 151, 153, 155}, new SkillEffect(Skills.FISHING, 3, 0))),
|
||||
PRAYER(new Potion(new int[] {2434, 139, 141, 143}, new PrayerEffect(7, 0.25))),
|
||||
SUPER_RESTO(new Potion(new int[] {3024, 3026, 3028, 3030}, new MultiEffect(new RestoreEffect(8, 0.25), new PrayerEffect(8, 0.25), new SummoningEffect(8, 0.25)))),
|
||||
ZAMMY_BREW(new Potion(new int[] {2450, 189, 191, 193}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ANTIFIRE(new Potion(new int[] {2452, 2454, 2456, 2458}, new SetAttributeEffect("fire:immune", 600, true))),
|
||||
GUTH_REST(new Potion(new int[] {4417, 4419, 4421, 4423}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new EnergyEffect(5), new HealingEffect(5)))),
|
||||
MAGIC_ESS(new Potion(new int[] {11491, 11489}, new SkillEffect(Skills.MAGIC,3,0))),
|
||||
SANFEW(new Potion(new int[] {10925, 10927, 10929, 10931}, new MultiEffect(new RestoreEffect(8,0.25), new PrayerEffect(8,0.25), new RemoveStateEffect(EntityState.POISONED.ordinal()), new RemoveStateEffect("disease")))),
|
||||
SUPER_ENERGY(new Potion(new int[] {3016, 3018, 3020, 3022}, new EnergyEffect(20))),
|
||||
BLAMISH_OIL(new FakeConsumable(1582, new String[] {"You know... I'd really rather not."})),
|
||||
|
||||
/** Barbarian Mixes */
|
||||
PRAYERMIX(new BarbarianMix(new int[] {11465, 11467}, new MultiEffect(new PrayerEffect(7, 0.25), new HealingEffect(6)))),
|
||||
ZAMMY_MIX(new BarbarianMix(new int[] {11521, 11523}, new MultiEffect(new DamageEffect(10, true), new SkillEffect(Skills.ATTACK, 0, 0.15), new SkillEffect(Skills.STRENGTH, 0, 0.25), new SkillEffect(Skills.DEFENCE, 0, -0.1), new RandomPrayerEffect(0, 10)))),
|
||||
ATT_MIX(new BarbarianMix(new int[] {11429, 11431}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new HealingEffect(3)))),
|
||||
ANTIP_MIX(new BarbarianMix(new int[] {11433, 11435}, new MultiEffect(new RemoveStateEffect(EntityState.POISONED.ordinal()), new SetAttributeEffect("poison:immunity", 143), new HealingEffect(3)))),
|
||||
RELIC_MIX(new BarbarianMix(new int[] {11437, 11439}, new MultiEffect(new RemoveStateEffect("disease"), new SetAttributeEffect("disease:immunity", 300), new HealingEffect(3)))),
|
||||
STR_MIX(new BarbarianMix(new int[] {11443, 11441}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(3)))),
|
||||
RESTO_MIX(new BarbarianMix(new int[] {11449, 11451}, new MultiEffect(new RestoreEffect(10, 0.3), new HealingEffect(3)))),
|
||||
ENERGY_MIX(new BarbarianMix(new int[] {11453, 11455}, new MultiEffect(new EnergyEffect(10), new HealingEffect(6)))),
|
||||
DEF_MIX(new BarbarianMix(new int[] {11457, 11459}, new MultiEffect(new SkillEffect(Skills.DEFENCE, 3, 0.1), new HealingEffect(6)))),
|
||||
AGIL_MIX(new BarbarianMix(new int[] {11461, 11463}, new MultiEffect(new SkillEffect(Skills.AGILITY, 3, 0), new HealingEffect(6)))),
|
||||
COMBAT_MIX(new BarbarianMix(new int[] {11445, 11447}, new MultiEffect(new SkillEffect(Skills.ATTACK, 3, 0.1), new SkillEffect(Skills.STRENGTH, 3, 0.1), new HealingEffect(6)))),
|
||||
SUPER_ATT_MIX(new BarbarianMix(new int[] {11469, 11471}, new MultiEffect(new SkillEffect(Skills.ATTACK, 5, 0.15), new HealingEffect(6)))),
|
||||
FISH_MIX(new BarbarianMix(new int[] {11477, 11479}, new MultiEffect(new SkillEffect(Skills.FISHING, 3, 0), new HealingEffect(6)))),
|
||||
SUPER_ENERGY_MIX(new BarbarianMix(new int[] {11481, 11483}, new MultiEffect(new EnergyEffect(20), new HealingEffect(6)))),
|
||||
HUNTING_MIX(new BarbarianMix(new int[] {11517, 11519}, new MultiEffect(new SkillEffect(Skills.HUNTER, 3, 0), new HealingEffect(6)))),
|
||||
SUPER_STR_MIX(new BarbarianMix(new int[] {11485, 11487}, new MultiEffect(new SkillEffect(Skills.STRENGTH, 5, 0.15), new HealingEffect(6)))),
|
||||
|
||||
/** Stealing creation potions */
|
||||
SC_PRAYER(new Potion(new int[] {14207, 14209, 14211, 14213, 14215}, new PrayerEffect(7, 0.25))),
|
||||
SC_ENERGY(new Potion(new int[] {14217, 14219, 14221, 14223, 14225}, new EnergyEffect(20))),
|
||||
SC_ATTACK(new Potion(new int[] {14227, 14229, 14231, 14233, 14235}, new SkillEffect(Skills.ATTACK, 3, 0.2))),
|
||||
SC_STRENGTH(new Potion(new int[] {14237, 14239, 14241, 14243, 14245}, new SkillEffect(Skills.STRENGTH, 3, 0.2))),
|
||||
SC_RANGE(new Potion(new int[] {14247, 14249, 14251, 14253, 14255}, new SkillEffect(Skills.RANGE, 3, 0.1))),
|
||||
SC_DEFENCE(new Potion(new int[] {14257, 14259, 14261, 14263, 14265}, new SkillEffect(Skills.DEFENCE, 3, 0.1))),
|
||||
SC_MAGIC(new Potion(new int[] {14267, 14269, 14271, 14273, 14275}, new SkillEffect(Skills.MAGIC, 3, 0.1))),
|
||||
SC_SUMMONING(new Potion(new int[] {14277, 14279, 14281, 14283, 14285}, new SummoningEffect(7, 0.25)));
|
||||
|
||||
public static HashMap<Integer,Consumable> consumables = new HashMap<>();
|
||||
|
||||
private final Consumable consumable;
|
||||
|
||||
Consumables(Consumable consumable) {
|
||||
this.consumable = consumable;
|
||||
}
|
||||
|
||||
public Consumable getConsumable() {
|
||||
return consumable;
|
||||
}
|
||||
|
||||
public static Consumable getConsumableById(final int itemId) {
|
||||
return consumables.get(itemId);
|
||||
}
|
||||
|
||||
public static void add(final Consumable consumable) {
|
||||
for (int id : consumable.getIds()) {
|
||||
consumables.putIfAbsent(id, consumable);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Static modifier used to populate search engine lists.
|
||||
*/
|
||||
static {
|
||||
for (Consumables consumable : Consumables.values()) {
|
||||
add(consumable.consumable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
|
||||
public class AchievementEffect extends ConsumableEffect {
|
||||
private final DiaryType diary;
|
||||
private final int level;
|
||||
private final int task;
|
||||
public AchievementEffect(DiaryType diary, int level, int task) {
|
||||
this.diary = diary;
|
||||
this.level = level;
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
p.getAchievementDiaryManager().finishTask(p, diary, level, task);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.combat.ImpactHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class DamageEffect extends ConsumableEffect {
|
||||
final double amt;
|
||||
final boolean isPercent;
|
||||
|
||||
public DamageEffect(double amt,boolean isPercent){
|
||||
this.amt = amt;
|
||||
this.isPercent = isPercent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
p.getImpactHandler().manualHit(p,-getHealthEffectValue(p), ImpactHandler.HitsplatType.NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
double amount = amt;
|
||||
if (isPercent) {
|
||||
amount /= 100;
|
||||
return (int) -(amount * player.getSkills().getLifepoints());
|
||||
}
|
||||
return (int) -amt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class DraynorCabbageEffect extends ConsumableEffect {
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final HealingEffect effect = new HealingEffect(getHealthEffectValue(p));
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return player.getSkills().getLevel(Skills.DEFENCE) > 50 ? 3 : 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class DwarvenRockCakeEffect extends ConsumableEffect {
|
||||
|
||||
private static final DamageEffect effect = new DamageEffect(1, false);
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (p.getSkills().getLifepoints() > 2) {
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return player.getSkills().getLifepoints() > 2 ? -1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class EnergyEffect extends ConsumableEffect {
|
||||
double amt;
|
||||
public EnergyEffect(int amt){
|
||||
this.amt = amt;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
p.getSettings().updateRunEnergy(-amt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
|
||||
public class HealingEffect extends ConsumableEffect {
|
||||
int amt;
|
||||
public HealingEffect(int amount){
|
||||
this.amt = amount;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
p.getSkills().heal(amt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return amt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
/**
|
||||
* According to the OSRS wiki, a kebab has the following possible outcomes:
|
||||
* 66% chance to heal 10% of total Hitpoints level, rounded down. Accompanied with the message "It heals some health."
|
||||
* 21% chance to heal 10–20 Hitpoints. Accompanied with the message "That was a good kebab. You feel a lot better."
|
||||
* 9% chance to heal nothing. Accompanied with the message "That kebab didn't seem to do a lot."
|
||||
* In addition, there is a chance that a non-combat skill is lowered by 3 (with the message "That tasted a bit dodgy. You feel a bit ill."), or that melee skills are lowered by 3 (with the message "That tasted very dodgy. You feel very ill.").
|
||||
* 4% chance to heal 30 Hitpoints and gain 1–3 levels in Attack, Strength and Defence. Accompanied with the message "Wow, that was an amazing kebab! You feel really invigorated."
|
||||
*/
|
||||
public class KebabEffect extends ConsumableEffect {
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final int randomNumber = RandomFunction.nextInt(100);
|
||||
ConsumableEffect effect;
|
||||
String message;
|
||||
if (randomNumber < 66) {
|
||||
effect = new PercentageHealthEffect(10);
|
||||
final int initialLifePoints = p.getSkills().getLifepoints();
|
||||
effect.activate(p);
|
||||
if (p.getSkills().getLifepoints() > initialLifePoints) {
|
||||
message = "It heals some health.";
|
||||
p.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
} else if (randomNumber < 87) {
|
||||
effect = new RandomHealthEffect(10, 20);
|
||||
effect.activate(p);
|
||||
message = "That was a good kebab. You feel a lot better.";
|
||||
p.getPacketDispatch().sendMessage(message);
|
||||
} else if (randomNumber < 96) {
|
||||
if (RandomFunction.nextInt(100) < 50) { // As the probability of lowering by 3 a non-combat skill or all melee skills is not specified, 50% is the percentage that was chosen.
|
||||
final int affectedSkillSlot = RandomFunction.nextInt(Skills.NUM_SKILLS - 1);
|
||||
switch (affectedSkillSlot) {
|
||||
case Skills.ATTACK:
|
||||
case Skills.DEFENCE:
|
||||
case Skills.STRENGTH:
|
||||
effect = new MultiEffect(new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.DEFENCE, -3, 0), new SkillEffect(Skills.STRENGTH, -3, 0));
|
||||
break;
|
||||
default:
|
||||
effect = new SkillEffect(affectedSkillSlot, -3, 0);
|
||||
}
|
||||
message = "That tasted a bit dodgy. You feel a bit ill.";
|
||||
p.getPacketDispatch().sendMessage(message);
|
||||
effect.activate(p);
|
||||
} else {
|
||||
message = "That kebab didn't seem to do a lot.";
|
||||
p.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
} else {
|
||||
effect = new MultiEffect(new HealingEffect(30), new RandomSkillEffect(Skills.ATTACK, 1, 3), new RandomSkillEffect(Skills.DEFENCE, 1, 3), new RandomSkillEffect(Skills.STRENGTH, 1, 3));
|
||||
effect.activate(p);
|
||||
message = "Wow, that was an amazing kebab! You feel really invigorated.";
|
||||
p.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package content.data.consumables.effects
|
||||
|
||||
import core.game.consumable.ConsumableEffect
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
|
||||
|
||||
class KegOfBeerEffect : ConsumableEffect() {
|
||||
|
||||
override fun activate(p: Player?) {
|
||||
val effect = MultiEffect(HealingEffect(15), SkillEffect(Skills.STRENGTH, 10.0, 0.0), SkillEffect(Skills.ATTACK, -40.0, 0.0))
|
||||
effect.activate(p)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class MatureWmbEffect extends ConsumableEffect {
|
||||
|
||||
private final static int healing = 1;
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final int magicLevelBoost = p.getSkills().getLevel(Skills.MAGIC) > 50 ? 4 : 3;
|
||||
final MultiEffect effect = new MultiEffect(new SkillEffect(Skills.MAGIC, magicLevelBoost, 0), new HealingEffect(healing), new SkillEffect(Skills.ATTACK, -5, 0), new SkillEffect(Skills.STRENGTH, -5, 0), new SkillEffect(Skills.DEFENCE, -5, 0));
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return healing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class MultiEffect extends ConsumableEffect {
|
||||
private ConsumableEffect[] effects;
|
||||
public MultiEffect(ConsumableEffect... effects){
|
||||
this.effects = effects;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
for(ConsumableEffect e : effects){
|
||||
e.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
int healing = 0;
|
||||
for (ConsumableEffect effect : effects) {
|
||||
healing += effect.getHealthEffectValue(player);
|
||||
}
|
||||
return healing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class NettleTeaEffect extends ConsumableEffect {
|
||||
|
||||
private final static int healing = 3;
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final ConsumableEffect effect = p.getSkills().getLifepoints() < p.getSkills().getMaximumLifepoints() ? new MultiEffect(new HealingEffect(3), new EnergyEffect(5)) : new HealingEffect(3);
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return healing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class PercentHeal extends ConsumableEffect {
|
||||
int base = 0;
|
||||
double percent = 0.0;
|
||||
|
||||
public PercentHeal(int base, double percent){
|
||||
this.base = base;
|
||||
this.percent = percent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
int maxHp = p.getSkills().getMaximumLifepoints();
|
||||
int curHp = p.getSkills().getLifepoints();
|
||||
int amount = (int) Math.floor(maxHp * percent);
|
||||
amount = base + Math.min(amount, (int)((1.0 + percent) * (double)maxHp - (double)curHp));
|
||||
p.getSkills().healNoRestrictions(amount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
|
||||
public class PercentageHealthEffect extends ConsumableEffect {
|
||||
|
||||
private final double percentage;
|
||||
|
||||
public PercentageHealthEffect(final int percentage) {
|
||||
this.percentage = percentage * 0.01;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final HealingEffect effect = new HealingEffect(getHealthEffectValue(p));
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return (int) (player.getSkills().getMaximumLifepoints() * percentage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.combat.ImpactHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class PoisonEffect extends ConsumableEffect {
|
||||
|
||||
private final int amount;
|
||||
|
||||
public PoisonEffect(final int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
p.getImpactHandler().manualHit(p, amount, ImpactHandler.HitsplatType.POISON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return -amount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class PoisonKarambwanEffect extends ConsumableEffect {
|
||||
|
||||
private final PoisonEffect effect = new PoisonEffect(5);
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (p.getSkills().getLifepoints() > 5) {
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class PrayerEffect extends ConsumableEffect {
|
||||
double base, bonus;
|
||||
public PrayerEffect(double base, double bonus){
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
int level = p.getSkills().getStaticLevel(Skills.PRAYER);
|
||||
double amt = base + (level * bonus);
|
||||
p.getSkills().incrementPrayerPoints(amt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
public class RandomEnergyEffect extends ConsumableEffect {
|
||||
|
||||
private final int a, b;
|
||||
|
||||
public RandomEnergyEffect(final int a, final int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final EnergyEffect effect = new EnergyEffect(RandomFunction.random(a, b));
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
public class RandomHealthEffect extends ConsumableEffect {
|
||||
|
||||
private final int a, b;
|
||||
|
||||
public RandomHealthEffect(final int a, final int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
ConsumableEffect effect;
|
||||
final int healthEffectValue = getHealthEffectValue(p);
|
||||
if (healthEffectValue > 0) {
|
||||
effect = new HealingEffect(healthEffectValue);
|
||||
} else {
|
||||
effect = new DamageEffect(healthEffectValue, false);
|
||||
}
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return RandomFunction.random(a, b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
|
||||
public class RandomPrayerEffect extends ConsumableEffect {
|
||||
|
||||
private final int a, b;
|
||||
|
||||
public RandomPrayerEffect(final int a, final int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final PrayerEffect effect = new PrayerEffect(RandomFunction.random(a, b), 0);
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
public class RandomSkillEffect extends ConsumableEffect {
|
||||
|
||||
private final int skillSlot, a, b;
|
||||
|
||||
public RandomSkillEffect(final int skillSlot, final int a, final int b) {
|
||||
this.skillSlot = skillSlot;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final SkillEffect effect = new SkillEffect(skillSlot, RandomFunction.random(a, b), 0);
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
|
||||
public class RemoveStateEffect extends ConsumableEffect {
|
||||
int state = -1;
|
||||
String statekey;
|
||||
@Deprecated
|
||||
public RemoveStateEffect(int state){
|
||||
this.state = state;
|
||||
}
|
||||
public RemoveStateEffect(String key){
|
||||
statekey = key;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if(state == -1){
|
||||
p.clearState(statekey);
|
||||
return;
|
||||
}
|
||||
p.getStateManager().remove(EntityState.values()[state]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class RestoreEffect extends ConsumableEffect {
|
||||
double base,bonus;
|
||||
public RestoreEffect(double base, double bonus){
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
}
|
||||
final int[] SKILLS = new int[] { Skills.DEFENCE, Skills.ATTACK, Skills.STRENGTH, Skills.MAGIC, Skills.RANGE };
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
Skills sk = p.getSkills();
|
||||
for(int skill : SKILLS){
|
||||
int statL = sk.getStaticLevel(skill);
|
||||
int curL = sk.getLevel(skill);
|
||||
if(curL < statL){
|
||||
int boost = (int) (base + (statL * bonus));
|
||||
p.getSkills().updateLevel(skill, boost, statL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package content.data.consumables.effects
|
||||
|
||||
import core.game.consumable.ConsumableEffect
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
class RestoreSummoningSpecial : ConsumableEffect(){
|
||||
override fun activate(p: Player) {
|
||||
val f = p.familiarManager.familiar
|
||||
f?.updateSpecialPoints(-15)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class RockCakeEffect extends ConsumableEffect {
|
||||
|
||||
private static final DamageEffect effect = new DamageEffect(10, true);
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (p.getSkills().getLifepoints() > 1) {
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return (int) (player.getSkills().getLifepoints() * -0.1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.GameWorld;
|
||||
|
||||
public class SetAttributeEffect extends ConsumableEffect {
|
||||
String attrString;
|
||||
Object attrValue;
|
||||
boolean isTicks;
|
||||
|
||||
public SetAttributeEffect(String attr, Object value, boolean isTicks){
|
||||
this.attrString = attr;
|
||||
this.attrValue = value;
|
||||
this.isTicks = isTicks;
|
||||
}
|
||||
|
||||
public SetAttributeEffect(String attr, Object value){
|
||||
this.attrString = attr;
|
||||
this.attrValue = value;
|
||||
if (value instanceof Integer){
|
||||
this.isTicks = true;
|
||||
} else {
|
||||
this.isTicks = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if(isTicks){
|
||||
int val = (Integer) attrValue + GameWorld.getTicks();
|
||||
p.setAttribute(attrString,val);
|
||||
return;
|
||||
}
|
||||
p.setAttribute(attrString,attrValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class SkillEffect extends ConsumableEffect {
|
||||
private final int skill_slot;
|
||||
private final double base;
|
||||
private final double bonus;
|
||||
public SkillEffect(int skill_slot, double base, double bonus){
|
||||
this.skill_slot = skill_slot;
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
Skills skills = p.getSkills();
|
||||
int slevel = skills.getStaticLevel(skill_slot);
|
||||
int delta = (int)(base + (bonus * slevel));
|
||||
skills.updateLevel(skill_slot, delta, delta >= 0 ? slevel + delta : 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* According to the OSRS wiki, the smelling ugthanki kebab will usually heal nothing when eaten, but sometimes heals for 9.
|
||||
* As the chances of healing are unknown, the percentage is set to 10%.
|
||||
*/
|
||||
public class SmellingUgthankiKebabEffect extends ConsumableEffect {
|
||||
|
||||
private static final int percentage = 10;
|
||||
|
||||
private static final int healing = 9;
|
||||
|
||||
private static final HealingEffect effect = new HealingEffect(healing);
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (RandomFunction.nextInt(100) < percentage) {
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return RandomFunction.nextInt(100) < percentage ? healing : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class SummoningEffect extends ConsumableEffect {
|
||||
double base, bonus;
|
||||
public SummoningEffect(double base, double bonus){
|
||||
this.base = base;
|
||||
this.bonus = bonus;
|
||||
}
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
int level = p.getSkills().getStaticLevel(Skills.SUMMONING);
|
||||
double amt = base + (level * bonus);
|
||||
p.getSkills().updateLevel(Skills.SUMMONING, (int)amt, level);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
|
||||
public class SuperKebabEffect extends ConsumableEffect {
|
||||
|
||||
private static final MultiEffect healingEffect = new MultiEffect(new HealingEffect(3), new PercentageHealthEffect(7));
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (RandomFunction.nextInt(8) < 5) {
|
||||
healingEffect.activate(p);
|
||||
}
|
||||
if (RandomFunction.nextInt(32) < 1) {
|
||||
final SkillEffect effect = new SkillEffect(RandomFunction.nextInt(Skills.NUM_SKILLS), -1, 0);
|
||||
effect.activate(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return RandomFunction.nextInt(8) < 5 ? (int) (3 + (player.getSkills().getMaximumLifepoints() * 0.07)) : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.map.Location;
|
||||
|
||||
public class TroubleBrewingRumEffect extends ConsumableEffect {
|
||||
|
||||
private static final Location TROUBLE_BREWING_MINIGAME = new Location(3813, 3022);
|
||||
|
||||
private final String forceChatMessage;
|
||||
|
||||
public TroubleBrewingRumEffect(final String forceChatMessage) {
|
||||
this.forceChatMessage = forceChatMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final Pulse teleportation = new Pulse(6) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
p.teleport(TROUBLE_BREWING_MINIGAME);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
final Pulse mainPulse = new Pulse(4) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
p.sendChat(forceChatMessage);
|
||||
p.getPulseManager().run(teleportation);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
p.getPulseManager().run(mainPulse);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
public class UgthankiKebabEffect extends ConsumableEffect {
|
||||
|
||||
private static final int healing = 19;
|
||||
|
||||
private static final HealingEffect effect = new HealingEffect(healing);
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
if (p.getSkills().getLifepoints() < p.getSkills().getMaximumLifepoints()) {
|
||||
p.sendChat("Yum!");
|
||||
}
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return healing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package content.data.consumables.effects;
|
||||
|
||||
import core.game.consumable.ConsumableEffect;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
|
||||
public class WizardsMindBombEffect extends ConsumableEffect {
|
||||
|
||||
private final static int healing = 1;
|
||||
|
||||
@Override
|
||||
public void activate(Player p) {
|
||||
final int magicLevelBoost = p.getSkills().getLevel(Skills.MAGIC) > 50 ? 3 : 2;
|
||||
final MultiEffect effect = new MultiEffect(new SkillEffect(Skills.MAGIC, magicLevelBoost, 0), new HealingEffect(healing), new SkillEffect(Skills.ATTACK, -3, 0), new SkillEffect(Skills.STRENGTH, -4, 0), new SkillEffect(Skills.DEFENCE, -4, 0));
|
||||
effect.activate(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHealthEffectValue(Player player) {
|
||||
return healing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package content.data.skill;
|
||||
|
||||
/**
|
||||
* Handles the skillcape perks.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public enum SkillcapePerks {
|
||||
|
||||
ATTACK(9747, 9748),
|
||||
STRENGTH(9750, 9751),
|
||||
DEFENCE(9753, 9754),
|
||||
RANGING(9756, 9757),
|
||||
PRAYER(9759, 9760),
|
||||
MAGIC(9762, 9763),
|
||||
RUNECRAFTING(9765, 9766),
|
||||
HITPOINTS(9768, 9769),
|
||||
AGILITY(9771, 9772),
|
||||
HERBLORE(9774, 9775),
|
||||
THIEVEING(9777, 9778),
|
||||
CRAFTING(9780, 9781),
|
||||
FLETCHING(9783, 9784),
|
||||
SLAYER(9786, 9787),
|
||||
CONSTRUCTION(9789, 9790),
|
||||
MINING(9792, 9793),
|
||||
SMITHING(9795, 9796),
|
||||
FISHING(9798, 9799),
|
||||
COOKING(9801, 9802),
|
||||
FIREMAKING(9804, 9805),
|
||||
WOODCUTTING(9807, 9808),
|
||||
FARMING(9810, 9811),
|
||||
HUNTING(9948, 9949),
|
||||
SUMMONING(12169,12170),
|
||||
MAX_CAPE(14831, 14833, 14835, 14839, 14840)
|
||||
;
|
||||
|
||||
/**
|
||||
* The skillcape Ids.
|
||||
*/
|
||||
private final int[] skillcapeIds;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructs a new {@code SkillcapePerks} object.
|
||||
* @param skillcapeIds
|
||||
*/
|
||||
SkillcapePerks(int... skillcapeIds) {
|
||||
this.skillcapeIds = skillcapeIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* The skillcapeIds.
|
||||
* @return the skillcape ids.
|
||||
*/
|
||||
public int[] getSkillcapeIds() {
|
||||
return skillcapeIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package content.data.skill;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.repository.Repository;
|
||||
|
||||
/**
|
||||
* Represents the skilling pets obtained randomly.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public enum SkillingPets {
|
||||
|
||||
BABY_RED_CHINCHOMPA(new Item(14823), "Baby Chinchompa", Skills.HUNTER),
|
||||
BABY_GREY_CHINCHOMPA(new Item(14824), "Baby Chinchompa", Skills.HUNTER),
|
||||
BEAVER(new Item(14821), "Beaver", Skills.WOODCUTTING),
|
||||
GOLEM(new Item(14822), "Rock Golem", Skills.MINING),
|
||||
HERON(new Item(14827), "Heron", Skills.FISHING);
|
||||
|
||||
/**
|
||||
* The pet item drop.
|
||||
*/
|
||||
private final Item pet;
|
||||
|
||||
/**
|
||||
* The name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The skill.
|
||||
*/
|
||||
private final int skill;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SkillingPets} object.
|
||||
* @param skill The skill id.
|
||||
* @param pet The pet item.
|
||||
*/
|
||||
SkillingPets(Item pet, String name, int skill) {
|
||||
this.pet = pet;
|
||||
this.name = name;
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the pet drop.
|
||||
* @param player The player.
|
||||
* @param pet The pet drop to check.
|
||||
*/
|
||||
public static void checkPetDrop(Player player, SkillingPets pet) {
|
||||
if (pet == null) {
|
||||
return;
|
||||
}
|
||||
int defaultChance = 15000;
|
||||
int newChance = (defaultChance / player.getSkills().getStaticLevel(pet.getSkill()) * 55);
|
||||
int outOf = (newChance > defaultChance ? defaultChance : newChance);
|
||||
int getChance = outOf;
|
||||
if (getChance != 1) {
|
||||
return;
|
||||
}
|
||||
if (player.hasItem(pet.getPet())) {
|
||||
return;
|
||||
}
|
||||
if (player.getFamiliarManager().hasFamiliar() && player.getInventory().isFull()) {
|
||||
return;
|
||||
}
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
if (player.getFamiliarManager().getFamiliar().getName().equalsIgnoreCase(pet.getName())) {
|
||||
return;
|
||||
}
|
||||
player.getInventory().add(pet.getPet());
|
||||
player.sendNotificationMessage("You feel something weird sneaking into your backpack.");
|
||||
} else {
|
||||
player.getFamiliarManager().summon(pet.getPet(), true);
|
||||
player.sendNotificationMessage("You have a funny feeling like you're being followed.");
|
||||
}
|
||||
Repository.sendNews(player.getUsername() + " has found a " + pet.getPet().getName() + "!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the pet
|
||||
*/
|
||||
public Item getPet() {
|
||||
return pet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pet name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the skill.
|
||||
*/
|
||||
public int getSkill() {
|
||||
return skill;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
package content.data.skill;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
/**
|
||||
* Represents a skilling tool (such as knife, axe, needle, ...)
|
||||
* @author Emperor
|
||||
*/
|
||||
public enum SkillingTool {
|
||||
/**
|
||||
* Represents a bronze axe (woodcutting).
|
||||
*/
|
||||
BRONZE_AXE(1351, 1, 0.05D, new Animation(879)),
|
||||
|
||||
/**
|
||||
* Represents an iron axe (woodcutting).
|
||||
*/
|
||||
IRON_AXE(1349, 1, 0.1D, new Animation(877)),
|
||||
|
||||
/**
|
||||
* Represents a steel axe (woodcutting).
|
||||
*/
|
||||
STEEL_AXE(1353, 6, 0.2D, new Animation(875)),
|
||||
|
||||
/**
|
||||
* Represents a black axe (woodcutting).
|
||||
*/
|
||||
BLACK_AXE(1361, 6, 0.25D, new Animation(873)),
|
||||
|
||||
/**
|
||||
* Represents a mithril axe (woodcutting).
|
||||
*/
|
||||
MITHRIL_AXE(1355, 21, 0.30D, new Animation(871)),
|
||||
|
||||
/**
|
||||
* Represents an adamant axe (woodcutting).
|
||||
*/
|
||||
ADAMANT_AXE(1357, 31, 0.45D, new Animation(869)),
|
||||
|
||||
/**
|
||||
* Represents a rune axe (woodcutting).
|
||||
*/
|
||||
RUNE_AXE(1359, 41, 0.65D, new Animation(867)),
|
||||
|
||||
/**
|
||||
* Represents a dragon axe (woodcutting).
|
||||
*/
|
||||
DRAGON_AXE(6739, 61, 0.85D, new Animation(2846)),
|
||||
|
||||
/**
|
||||
* Represents a bronze pickaxe (mining).
|
||||
*/
|
||||
BRONZE_PICKAXE(1265, 1, 0.05D, new Animation(625)),
|
||||
|
||||
/**
|
||||
* Represents an iron pickaxe (mining).
|
||||
*/
|
||||
IRON_PICKAXE(1267, 1, 0.1D, new Animation(626)),
|
||||
|
||||
/**
|
||||
* Represents a steel pickaxe (mining).
|
||||
*/
|
||||
STEEL_PICKAXE(1269, 6, 0.2D, new Animation(627)),
|
||||
|
||||
/**
|
||||
* Represents a mithril pickaxe (mining).
|
||||
*/
|
||||
MITHRIL_PICKAXE(1273, 21, 0.30D, new Animation(629)),
|
||||
|
||||
/**
|
||||
* Represents an adamant pickaxe (mining).
|
||||
*/
|
||||
ADAMANT_PICKAXE(1271, 31, 0.45D, new Animation(628)),
|
||||
|
||||
/**
|
||||
* Represents a rune pickaxe (mining).
|
||||
*/
|
||||
RUNE_PICKAXE(1275, 41, 0.65D, new Animation(624)),
|
||||
|
||||
/**
|
||||
* Represents the Inferno Adze (woodcutting)
|
||||
*/
|
||||
INFERNO_ADZE(13661, 61, 0.85D, new Animation(10251)),
|
||||
|
||||
/**
|
||||
* Represents the Inferno Adze (mining)
|
||||
*/
|
||||
INFERNO_ADZE2(13661, 61, 1.0D, new Animation(10222)),
|
||||
|
||||
HATCHET_CLASS1(Items.HATCHET_CLASS_1_14132, 1, 0.1, new Animation(10603)),
|
||||
HATCHET_CLASS2(Items.HATCHET_CLASS_2_14134, 20, 0.3, new Animation(10604)),
|
||||
HATCHET_CLASS3(Items.HATCHET_CLASS_3_14136, 40, 0.65, new Animation(10605)),
|
||||
HATCHET_CLASS4(Items.HATCHET_CLASS_4_14138, 60, 0.85, new Animation(10606)),
|
||||
HATCHET_CLASS5(Items.HATCHET_CLASS_5_14140, 80, 1.0, new Animation(10607)),
|
||||
PICKAXE_CLASS1(Items.PICKAXE_CLASS_1_14122, 1, 0.1, new Animation(10608)),
|
||||
PICKAXE_CLASS2(Items.PICKAXE_CLASS_2_14124, 20, 0.3, new Animation(10609)),
|
||||
PICKAXE_CLASS3(Items.PICKAXE_CLASS_3_14126, 40, 0.65, new Animation(10610)),
|
||||
PICKAXE_CLASS4(Items.PICKAXE_CLASS_4_14128, 60, 0.85, new Animation(10611)),
|
||||
PICKAXE_CLASS5(Items.PICKAXE_CLASS_5_14130, 80, 1.0, new Animation(10612)),
|
||||
HARPOON_CLASS1(Items.HARPOON_CLASS_1_14142, 1, 0.1, new Animation(10613)),
|
||||
HARPOON_CLASS2(Items.HARPOON_CLASS_2_14144, 20, 0.3, new Animation(10614)),
|
||||
HARPOON_CLASS3(Items.HARPOON_CLASS_3_14146, 40, 0.65, new Animation(10615)),
|
||||
HARPOON_CLASS4(Items.HARPOON_CLASS_4_14148, 60, 0.85, new Animation(10616)),
|
||||
HARPOON_CLASS5(Items.HARPOON_CLASS_5_14150, 80, 1.0, new Animation(10617)),
|
||||
BUTTERFLY_NET_CLASS1(Items.BUTTERFLY_NET_CLASS_1_14152, 1, 0.1, new Animation(10618)),
|
||||
BUTTERFLY_NET_CLASS2(Items.BUTTERFLY_NET_CLASS_2_14154, 20, 0.3, new Animation(10619)),
|
||||
BUTTERFLY_NET_CLASS3(Items.BUTTERFLY_NET_CLASS_3_14156, 40, 0.65, new Animation(10620)),
|
||||
BUTTERFLY_NET_CLASS4(Items.BUTTERFLY_NET_CLASS_4_14158, 60, 0.85, new Animation(10621)),
|
||||
BUTTERFLY_NET_CLASS5(Items.BUTTERFLY_NET_CLASS_5_14160, 80, 1.0, new Animation(10622));
|
||||
|
||||
|
||||
/**
|
||||
* The tool id.
|
||||
*/
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* The level required.
|
||||
*/
|
||||
private final int level;
|
||||
|
||||
/**
|
||||
* The ratio.
|
||||
*/
|
||||
private final double ratio;
|
||||
|
||||
/**
|
||||
* The animation.
|
||||
*/
|
||||
private final Animation animation;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SkillingTool} {@code Object}.
|
||||
* @param id The tool item id.
|
||||
* @param level The level required to use this.
|
||||
* @param ratio The ratio.
|
||||
* @param animation The animation.
|
||||
*/
|
||||
private SkillingTool(int id, int level, double ratio, Animation animation) {
|
||||
this.id = id;
|
||||
this.level = level;
|
||||
this.ratio = ratio;
|
||||
this.animation = animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tool by the item id.
|
||||
* @param itemId The item id.
|
||||
* @return The skilling tool, or {@code null} if the tool wasn't found.
|
||||
*/
|
||||
public static SkillingTool forId(int itemId) {
|
||||
for (SkillingTool tool : SkillingTool.values()) {
|
||||
if (tool.id == itemId) {
|
||||
return tool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hatchet used by the player.
|
||||
* @param player The player.
|
||||
* @return The hatchet.
|
||||
*/
|
||||
public static SkillingTool getHatchet(Player player) {
|
||||
SkillingTool tool = null;
|
||||
SkillingTool[] hatchetPriority = new SkillingTool[] {
|
||||
SkillingTool.HATCHET_CLASS5,
|
||||
SkillingTool.HATCHET_CLASS4,
|
||||
SkillingTool.DRAGON_AXE,
|
||||
SkillingTool.HATCHET_CLASS3,
|
||||
SkillingTool.RUNE_AXE,
|
||||
SkillingTool.ADAMANT_AXE,
|
||||
SkillingTool.HATCHET_CLASS2,
|
||||
SkillingTool.MITHRIL_AXE,
|
||||
SkillingTool.BLACK_AXE,
|
||||
SkillingTool.STEEL_AXE,
|
||||
SkillingTool.HATCHET_CLASS1,
|
||||
SkillingTool.IRON_AXE,
|
||||
SkillingTool.BRONZE_AXE
|
||||
};
|
||||
for(SkillingTool hatchet : hatchetPriority) {
|
||||
if (checkTool(player, Skills.WOODCUTTING, hatchet)) {
|
||||
tool = hatchet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checkTool(player, Skills.WOODCUTTING, SkillingTool.INFERNO_ADZE)) {
|
||||
if(player.getSkills().getLevel(Skills.FIREMAKING) >= 92) {
|
||||
tool = SkillingTool.INFERNO_ADZE;
|
||||
}
|
||||
}
|
||||
return tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pickaxe used by the player.
|
||||
* @param player The player.
|
||||
* @return The hatchet.
|
||||
*/
|
||||
public static SkillingTool getPickaxe(Player player) {
|
||||
SkillingTool tool = null;
|
||||
SkillingTool[] pickaxePriority = new SkillingTool[] {
|
||||
SkillingTool.PICKAXE_CLASS5,
|
||||
SkillingTool.PICKAXE_CLASS4,
|
||||
SkillingTool.RUNE_PICKAXE,
|
||||
SkillingTool.PICKAXE_CLASS3,
|
||||
SkillingTool.ADAMANT_PICKAXE,
|
||||
SkillingTool.PICKAXE_CLASS2,
|
||||
SkillingTool.MITHRIL_PICKAXE,
|
||||
SkillingTool.STEEL_PICKAXE,
|
||||
SkillingTool.PICKAXE_CLASS1,
|
||||
SkillingTool.IRON_PICKAXE,
|
||||
SkillingTool.BRONZE_PICKAXE,
|
||||
};
|
||||
for(SkillingTool pickaxe : pickaxePriority) {
|
||||
if (checkTool(player, Skills.MINING, pickaxe)) {
|
||||
tool = pickaxe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checkTool(player, Skills.MINING, SkillingTool.INFERNO_ADZE2)) {
|
||||
if (player.getSkills().getLevel(Skills.FIREMAKING) >= 92) {
|
||||
tool = SkillingTool.INFERNO_ADZE2;
|
||||
}
|
||||
}
|
||||
return tool;
|
||||
}
|
||||
|
||||
public static SkillingTool getHarpoon(Player player) {
|
||||
SkillingTool tool = null;
|
||||
SkillingTool[] harpoonPriority = new SkillingTool[] {
|
||||
SkillingTool.BUTTERFLY_NET_CLASS5,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS4,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS3,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS2,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS1,
|
||||
};
|
||||
for(SkillingTool harpoon : harpoonPriority) {
|
||||
if (checkTool(player, Skills.FISHING, harpoon)) {
|
||||
tool = harpoon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tool;
|
||||
}
|
||||
|
||||
public static SkillingTool getButterflyNet(Player player) {
|
||||
SkillingTool tool = null;
|
||||
SkillingTool[] butterflyNetPriority = new SkillingTool[] {
|
||||
SkillingTool.BUTTERFLY_NET_CLASS5,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS4,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS3,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS2,
|
||||
SkillingTool.BUTTERFLY_NET_CLASS1,
|
||||
};
|
||||
for(SkillingTool butterflyNet : butterflyNetPriority) {
|
||||
if (checkTool(player, Skills.HUNTER, butterflyNet)) {
|
||||
tool = butterflyNet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tool;
|
||||
}
|
||||
|
||||
public static SkillingTool getToolForSkill(Player player, int skill) {
|
||||
switch(skill) {
|
||||
case Skills.MINING:
|
||||
return getPickaxe(player);
|
||||
case Skills.WOODCUTTING:
|
||||
return getHatchet(player);
|
||||
case Skills.FISHING:
|
||||
return getHarpoon(player);
|
||||
case Skills.HUNTER:
|
||||
return getButterflyNet(player);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has a tool and if he can use it.
|
||||
* @param tool The tool.
|
||||
* @return {@code True} if the tool is usable.
|
||||
*/
|
||||
public static boolean checkTool(Player player, int skillId, SkillingTool tool) {
|
||||
if (player.getSkills().getStaticLevel(skillId) < tool.getLevel()) {
|
||||
return false;
|
||||
}
|
||||
if (player.getEquipment().getNew(3).getId() == tool.getId()) {
|
||||
return true;
|
||||
}
|
||||
return player.getInventory().contains(tool.getId(), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return The level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ratio.
|
||||
* @return The ratio.
|
||||
*/
|
||||
public double getRatio() {
|
||||
return ratio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation.
|
||||
* @return The animation.
|
||||
*/
|
||||
public Animation getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import core.ServerConstants;
|
||||
import core.tools.SystemLogger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the allotment seed drop table.
|
||||
* @author Von Hresvelg
|
||||
*/
|
||||
public final class AllotmentSeedDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the allotment seed drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 14430;
|
||||
|
||||
/**
|
||||
* The allotment seed drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public AllotmentSeedDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.ASDT_DATA_PATH != null && !new File(ServerConstants.ASDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate ASDT file at " + ServerConstants.ASDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.ASDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Allotment Seed Drop Table from " + ServerConstants.ASDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the allotment seed drop table.
|
||||
* @param file the .xml file containing the allotment seed drop table.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve() {return RandomFunction.rollWeightedChanceTable(TABLE);}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package content.data.tables;
|
||||
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.npc.drop.NPCDropTables;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.ChanceItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.tools.RandomFunction;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents a birds nest.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum BirdNest {
|
||||
SEED(new ChanceItem(5073, 1, 65),
|
||||
new ChanceItem(Items.ACORN_5312, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.APPLE_TREE_SEED_5283, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.WILLOW_SEED_5313, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.BANANA_TREE_SEED_5284, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.ORANGE_TREE_SEED_5285, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.CURRY_TREE_SEED_5286, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.MAPLE_SEED_5314, 1, NPCDropTables.DROP_RATES[1]),
|
||||
new ChanceItem(Items.PINEAPPLE_SEED_5287, 1, NPCDropTables.DROP_RATES[1]),
|
||||
new ChanceItem(Items.PAPAYA_TREE_SEED_5288, 1, NPCDropTables.DROP_RATES[1]),
|
||||
new ChanceItem(Items.YEW_SEED_5315, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.PALM_TREE_SEED_5289, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.CALQUAT_TREE_SEED_5290, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.SPIRIT_SEED_5317, 1, NPCDropTables.DROP_RATES[3]),
|
||||
new ChanceItem(Items.MAGIC_SEED_5316, 1, NPCDropTables.DROP_RATES[3])),
|
||||
RING(new ChanceItem(5074, 1, 30),
|
||||
new ChanceItem(Items.GOLD_RING_1635, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.SAPPHIRE_RING_1637, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.EMERALD_RING_1639, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.RUBY_RING_1641, 1, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.DIAMOND_RING_1643, 1, NPCDropTables.DROP_RATES[2])),
|
||||
RED(new ChanceItem(5070, 1, 5), new ChanceItem(5076)),
|
||||
GREEN(new ChanceItem(5071, 1, 5), new ChanceItem(5078)),
|
||||
BLUE(new ChanceItem(5072, 1, 5), new ChanceItem(5077)),
|
||||
RAVEN(new ChanceItem(11966, 1, 5), new ChanceItem(11964)),
|
||||
|
||||
WYSON(new ChanceItem(7413, 1, 1),
|
||||
new ChanceItem(Items.POTATO_SEED_5318, 14, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.SWEETCORN_SEED_5320, 3, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.TOMATO_SEED_5322, 6, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.CABBAGE_SEED_5324, 9, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.LIMPWURT_SEED_5100, 2, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.ONION_SEED_5319, 11, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.STRAWBERRY_SEED_5323, 3, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.WATERMELON_SEED_5321, 2, NPCDropTables.DROP_RATES[0]),
|
||||
new ChanceItem(Items.ACORN_5312, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.RANARR_SEED_5295, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.WILLOW_SEED_5313, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.MAPLE_SEED_5314, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.YEW_SEED_5315, 1, NPCDropTables.DROP_RATES[2]),
|
||||
new ChanceItem(Items.MAGIC_SEED_5316, 1, NPCDropTables.DROP_RATES[3]),
|
||||
new ChanceItem(Items.SPIRIT_SEED_5317, 1, NPCDropTables.DROP_RATES[3]));
|
||||
|
||||
/**
|
||||
* The random nest items.
|
||||
*/
|
||||
private static final ChanceItem[] NESTS = new ChanceItem[6];
|
||||
|
||||
/**
|
||||
* The empty birds nest item.
|
||||
*/
|
||||
private static final Item EMPTY = new Item(5075);
|
||||
|
||||
/**
|
||||
* The birds nest item.
|
||||
*/
|
||||
private final ChanceItem nest;
|
||||
|
||||
/**
|
||||
* The loot item from the nest.
|
||||
*/
|
||||
private final ChanceItem[] loot;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BirdNest} {@code Object}.
|
||||
* @param nest the nest.
|
||||
* @param loot the loot.
|
||||
*/
|
||||
private BirdNest(final ChanceItem nest, final ChanceItem... loot) {
|
||||
this.nest = nest;
|
||||
this.loot = loot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a birds nest.
|
||||
* @param player the player.
|
||||
*/
|
||||
public static void drop(final Player player) {
|
||||
final BirdNest nest = getRandomNest(false);
|
||||
player.getAudioManager().send(1997);
|
||||
GroundItemManager.create(nest.getNest(), player);
|
||||
player.getPacketDispatch().sendMessage("<col=FF0000>A bird's nest falls out of the tree.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a bird nest.
|
||||
* @param player the player.
|
||||
* @param item the item searched.
|
||||
*/
|
||||
public void search(final Player player, Item item) {
|
||||
if (player.getInventory().freeSlots() < 1) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough inventory space.");
|
||||
return;
|
||||
}
|
||||
final ChanceItem loot = ordinal() > 1 && this != WYSON ? getLoot()[0] : RandomFunction.getChanceItem(getLoot());
|
||||
final String name = loot.getName().toLowerCase();
|
||||
final String input = (StringUtils.isPlusN(name) ? "an" : "a") + " " + name;
|
||||
player.lock(1);
|
||||
player.getInventory().add(loot);
|
||||
player.getInventory().replace(EMPTY, item.getSlot());
|
||||
player.getPacketDispatch().sendMessage("You take " + input + " out of the bird's nest.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random nest.
|
||||
* @return the nest.
|
||||
*/
|
||||
public static BirdNest getRandomNest(boolean wyson) {
|
||||
ChanceItem item = RandomFunction.getChanceItem(NESTS);
|
||||
for (BirdNest n : BirdNest.values()) {
|
||||
if (n.getNest() == item) {
|
||||
if (wyson && n == SEED) {
|
||||
return WYSON;
|
||||
} else if (!wyson && n == WYSON) {
|
||||
return SEED;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nest by the id.
|
||||
* @param nest the nest.
|
||||
* @return the nest.
|
||||
*/
|
||||
public static BirdNest forNest(final Item nest) {
|
||||
for (BirdNest n : values()) {
|
||||
if (n.getNest().getId() == nest.getId()) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nest.
|
||||
* @return The nest.
|
||||
*/
|
||||
public ChanceItem getNest() {
|
||||
return nest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the loot.
|
||||
* @return The loot.
|
||||
*/
|
||||
public ChanceItem[] getLoot() {
|
||||
return loot;
|
||||
}
|
||||
|
||||
/**
|
||||
* static-block to add nests.
|
||||
*/
|
||||
static {
|
||||
for (int i = 0; i < NESTS.length; i++) {
|
||||
NESTS[i] = values()[i].getNest();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.ServerConstants;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.SystemLogger;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the Chaos Elemental's minor drop table. It is supposed to roll this table alongside its standard major drops on the main table.
|
||||
* @author Crash
|
||||
*/
|
||||
public final class CELEMinorTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the C. Ele minor drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 799; // Crash: Item ID 799 is currently a null, blank paper note object. Unsure if used for cutscene/cutscene items, but hijacking this as C.Ele's item container as it'll never be dropped or obtained in normal gameplay.
|
||||
|
||||
/**
|
||||
* The rare drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public CELEMinorTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.CELEDT_DATA_PATH != null && !new File(ServerConstants.CELEDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate CELEDT file at " + ServerConstants.CELEDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.CELEDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Loaded up Chaos Elemental drop table from " + ServerConstants.CELEDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the CELEDT.
|
||||
* @param file the .xml file containing the CELEDT.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import core.ServerConstants;
|
||||
import core.tools.SystemLogger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the gem drop table.
|
||||
* @author Von Hresvelg
|
||||
*/
|
||||
public final class GemDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the gem drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 14426;
|
||||
|
||||
/**
|
||||
* The gem drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public GemDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.GDT_DATA_PATH != null && !new File(ServerConstants.GDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate GDT file at " + ServerConstants.GDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.GDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Gem Drop Table from " + ServerConstants.GDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the gem drop table.
|
||||
* @param file the .xml file containing the gem drop table.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import core.ServerConstants;
|
||||
import core.tools.SystemLogger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the herb drop table.
|
||||
* @author Von Hresvelg
|
||||
*/
|
||||
public final class HerbDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the herb drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 14424;
|
||||
|
||||
/**
|
||||
* The herb drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public HerbDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.HDT_DATA_PATH != null && !new File(ServerConstants.HDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate HDT file at " + ServerConstants.HDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.HDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Herb Drop Table from " + ServerConstants.HDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the herb drop table.
|
||||
* @param file the .xml file containing the herb drop table.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.ServerConstants;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.SystemLogger;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the rare drop table.
|
||||
* @author Ceikry
|
||||
*/
|
||||
public final class RareDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the rare drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 31;
|
||||
|
||||
/**
|
||||
* The rare drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public RareDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.RDT_DATA_PATH != null && !new File(ServerConstants.RDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate RDT file at " + ServerConstants.RDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.RDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Rare Drop Table from " + ServerConstants.RDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the RDT.
|
||||
* @param file the .xml file containing the RDT.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import core.ServerConstants;
|
||||
import core.tools.SystemLogger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the rare seed drop table.
|
||||
* @author Von Hresvelg
|
||||
*/
|
||||
public final class RareSeedDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the rare seed drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 14428;
|
||||
|
||||
/**
|
||||
* The rare seed drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public RareSeedDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.RSDT_DATA_PATH != null && !new File(ServerConstants.RSDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate RSDT file at " + ServerConstants.RSDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.RSDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Rare Seed Drop Table from " + ServerConstants.RSDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the rare seed drop table.
|
||||
* @param file the .xml file containing the rare seed drop table.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package content.data.tables;
|
||||
|
||||
import core.api.StartupListener;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.tools.RandomFunction;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import core.ServerConstants;
|
||||
import core.tools.SystemLogger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static core.tools.SystemLogger.logInfo;
|
||||
|
||||
/**
|
||||
* Handles the uncommon seed drop table.
|
||||
* @author Von Hresvelg
|
||||
*/
|
||||
public final class UncommonSeedDropTable implements StartupListener {
|
||||
|
||||
/**
|
||||
* The item id of the item representing the uncommon seed drop table slot in a drop
|
||||
* table.
|
||||
*/
|
||||
public static final int SLOT_ITEM_ID = 14422;
|
||||
|
||||
/**
|
||||
* The uncommon seed drop table.
|
||||
*/
|
||||
private static final List<WeightedChanceItem> TABLE = new ArrayList<>(20);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize needed objects for xml reading/writing
|
||||
*/
|
||||
static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
static DocumentBuilder builder;
|
||||
|
||||
static {
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public UncommonSeedDropTable() throws ParserConfigurationException {}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
if(ServerConstants.USDT_DATA_PATH != null && !new File(ServerConstants.USDT_DATA_PATH).exists()){
|
||||
SystemLogger.logErr(this.getClass(), "Can't locate USDT file at " + ServerConstants.USDT_DATA_PATH);
|
||||
return;
|
||||
}
|
||||
parse(ServerConstants.USDT_DATA_PATH);
|
||||
logInfo(this.getClass(), "Initialized Uncommon Seed Drop Table from " + ServerConstants.USDT_DATA_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml file for the uncommon seed drop table.
|
||||
* @param file the .xml file containing the uncommon seed drop table.
|
||||
*/
|
||||
public static void parse(String file){
|
||||
try {
|
||||
Document doc = builder.parse(file);
|
||||
|
||||
NodeList itemNodes = doc.getElementsByTagName("item");
|
||||
for(int i = 0; i < itemNodes.getLength(); i++){
|
||||
Node itemNode = itemNodes.item(i);
|
||||
if(itemNode.getNodeType() == Node.ELEMENT_NODE){
|
||||
Element item = (Element) itemNode;
|
||||
int itemId = Integer.parseInt(item.getAttribute("id"));
|
||||
int minAmt = Integer.parseInt(item.getAttribute("minAmt"));
|
||||
int maxAmt = Integer.parseInt(item.getAttribute("maxAmt"));
|
||||
int weight = Integer.parseInt(item.getAttribute("weight"));
|
||||
|
||||
TABLE.add(new WeightedChanceItem(itemId,minAmt,maxAmt,weight));
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Item retrieve(){
|
||||
return RandomFunction.rollWeightedChanceTable(TABLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package content.global.activity.jobs
|
||||
|
||||
import core.api.*
|
||||
import content.global.activity.jobs.impl.GatheringJobs
|
||||
import content.global.activity.jobs.impl.SlayingJobs
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.game.dialogue.Topic
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
class CancelJobDialogueFile : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
START_DIALOGUE -> showTopics(
|
||||
Topic(core.game.dialogue.FacialExpression.HALF_ASKING, "How am I doing on my job?", 1),
|
||||
Topic(core.game.dialogue.FacialExpression.HALF_GUILTY, "I'd like to cancel my job.", 10)
|
||||
)
|
||||
|
||||
1 -> {
|
||||
val jobType = JobType.values()[getAttribute(player!!, "jobs:type", 0)]
|
||||
val jobId = getAttribute(player!!, "jobs:id", 0)
|
||||
val needed = getAttribute(player!!, "jobs:amount", 0)
|
||||
|
||||
when (jobType) {
|
||||
JobType.GATHERING -> {
|
||||
sendItemDialogue(
|
||||
player!!,
|
||||
Item(GatheringJobs.values()[jobId].itemId),
|
||||
"You still need to gather $needed more."
|
||||
)
|
||||
}
|
||||
|
||||
JobType.SLAYING -> {
|
||||
sendDialogue(
|
||||
player!!,
|
||||
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
10 -> npc("It will cost 500 coins.")
|
||||
.also { stage++ }
|
||||
|
||||
11 -> showTopics(
|
||||
Topic(core.game.dialogue.FacialExpression.HAPPY, "Yes, please.", 20),
|
||||
Topic(core.game.dialogue.FacialExpression.NEUTRAL, "No, thanks.", 30)
|
||||
)
|
||||
|
||||
20 -> npc("Alright then, hand over the money.")
|
||||
.also { stage++ }
|
||||
|
||||
21 -> if (inInventory(player!!, Items.COINS_995, 500)) {
|
||||
player("Here you go.")
|
||||
|
||||
removeItem(player!!, Item(Items.COINS_995, 500))
|
||||
removeAttribute(player!!, "jobs:id")
|
||||
removeAttribute(player!!, "jobs:amount")
|
||||
removeAttribute(player!!, "jobs:original_amount")
|
||||
removeAttribute(player!!, "jobs:type")
|
||||
|
||||
stage = END_DIALOGUE
|
||||
} else {
|
||||
player(
|
||||
core.game.dialogue.FacialExpression.HALF_WORRIED,
|
||||
"Oh, I don't seem to have the money..."
|
||||
).also { stage++ }
|
||||
}
|
||||
|
||||
22 -> npc("Ah, that sucks! Get to work.")
|
||||
.also { stage = END_DIALOGUE }
|
||||
|
||||
30 -> npc("Alright then, get to work!")
|
||||
.also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package content.global.activity.jobs
|
||||
|
||||
import core.api.*
|
||||
import content.global.activity.jobs.impl.GatheringJobs
|
||||
import content.global.activity.jobs.impl.SlayingJobs
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.json.simple.JSONObject
|
||||
import org.rs09.consts.Items
|
||||
import core.ServerStore
|
||||
import core.ServerStore.Companion.getInt
|
||||
|
||||
object JobManager {
|
||||
@JvmStatic
|
||||
fun updateJobRemaining(player: Player, amount: Int = 0) {
|
||||
val cur = getAttribute(player, "jobs:amount", 0)
|
||||
val new = cur - amount
|
||||
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
|
||||
val jobId = getAttribute(player, "jobs:id", 0)
|
||||
|
||||
when (jobType) {
|
||||
JobType.GATHERING -> { }
|
||||
|
||||
JobType.SLAYING -> {
|
||||
val job = SlayingJobs.values()[jobId]
|
||||
|
||||
if (new % 5 == 0 && new > 0) {
|
||||
sendMessage(
|
||||
player,
|
||||
"You have $new ${NPC(job.ids[0]).name.lowercase()} left to go."
|
||||
)
|
||||
} else if (new == 0) {
|
||||
sendMessage(
|
||||
player,
|
||||
"<col=00AA00>You have completed your job.</col>"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setAttribute(player, "jobs:amount", new)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun rewardPlayer(player: Player, npc: NPC) {
|
||||
val amt = getAttribute(player, "jobs:original_amount", 0)
|
||||
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
|
||||
val jobId = getAttribute(player, "jobs:id", 0)
|
||||
|
||||
when (jobType) {
|
||||
JobType.GATHERING -> {
|
||||
val it = Item(GatheringJobs.values()[jobId].itemId)
|
||||
var amount = amountInInventory(player, it.id)
|
||||
val needed = getAttribute(player, "jobs:amount", 0)
|
||||
|
||||
if (amount == 0) {
|
||||
openDialogue(player, CancelJobDialogueFile(), npc)
|
||||
return
|
||||
}
|
||||
|
||||
if (amount < needed) {
|
||||
sendItemDialogue(
|
||||
player,
|
||||
GatheringJobs.values()[jobId].itemId,
|
||||
"You still need to gather ${needed - amount} more."
|
||||
)
|
||||
|
||||
removeItem(player, Item(it.id, amount))
|
||||
setAttribute(player, "jobs:amount", needed - amount)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (amount > needed) {
|
||||
amount = needed
|
||||
}
|
||||
|
||||
removeItem(player, Item(it.id, amount))
|
||||
}
|
||||
|
||||
JobType.SLAYING -> {
|
||||
val needed = getAttribute(player, "jobs:amount", 0)
|
||||
|
||||
if (needed > 0) {
|
||||
sendDialogue(
|
||||
player,
|
||||
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}."
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
sendDialogue(
|
||||
player,
|
||||
"Excellent work, thank you! Here's your reward."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addItemOrDrop(player, Items.COINS_995, 250 * amt)
|
||||
|
||||
removeAttribute(player, "jobs:id")
|
||||
removeAttribute(player, "jobs:amount")
|
||||
removeAttribute(player, "jobs:original_amount")
|
||||
removeAttribute(player, "jobs:type")
|
||||
|
||||
getStoreFile()[player.username.lowercase()] = getStoreFile().getInt(player.username.lowercase()) + 1
|
||||
}
|
||||
|
||||
fun getStoreFile(): JSONObject {
|
||||
return ServerStore.getArchive("daily-jobs-tracking")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package content.global.activity.jobs
|
||||
|
||||
enum class JobType {
|
||||
GATHERING,
|
||||
SLAYING
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package content.global.activity.jobs
|
||||
|
||||
import content.global.activity.jobs.impl.GatheringJobs
|
||||
import content.global.activity.jobs.impl.SlayingJobs
|
||||
import core.api.*
|
||||
import core.game.event.EventHook
|
||||
import core.game.event.JobAssignmentEvent
|
||||
import core.game.event.NPCKillEvent
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import core.ServerStore.Companion.getInt
|
||||
import core.api.Event
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
/**
|
||||
* Handles the work-for actions for the NPCs
|
||||
* @author Ceikry
|
||||
* @author vddCore
|
||||
*/
|
||||
class WorkForInteractionListener : InteractionListener, LoginListener {
|
||||
companion object {
|
||||
private val WEAPON_ICONS = arrayListOf(
|
||||
Items.BRONZE_SCIMITAR_1321,
|
||||
Items.STEEL_SCIMITAR_1325,
|
||||
Items.RUNE_SCIMITAR_1333,
|
||||
Items.BRONZE_MACE_1422,
|
||||
Items.MITHRIL_WARHAMMER_1343
|
||||
)
|
||||
|
||||
private val EMPLOYERS_AND_JOBS = mapOf(
|
||||
NPCs.HANS_0 to listOf(
|
||||
GatheringJobs.AIR_RUNE,
|
||||
GatheringJobs.COWHIDES,
|
||||
GatheringJobs.WATER_RUNE
|
||||
),
|
||||
|
||||
NPCs.AGGIE_922 to listOf(
|
||||
GatheringJobs.ASHES,
|
||||
GatheringJobs.AIR_RUNE,
|
||||
GatheringJobs.WATER_RUNE
|
||||
),
|
||||
|
||||
NPCs.GILLIE_GROATS_3807 to listOf(
|
||||
GatheringJobs.COWHIDES
|
||||
),
|
||||
|
||||
NPCs.COOKING_TUTOR_4899 to listOf(
|
||||
GatheringJobs.CAKE,
|
||||
GatheringJobs.ANCHOVY_PIZZA,
|
||||
GatheringJobs.COOKED_SALMON,
|
||||
GatheringJobs.COOKED_TROUT,
|
||||
GatheringJobs.MEAT_PIE,
|
||||
GatheringJobs.MEAT_PIZZA,
|
||||
GatheringJobs.PLAIN_PIZZA
|
||||
),
|
||||
|
||||
NPCs.FISHING_TUTOR_4901 to listOf(
|
||||
GatheringJobs.RAW_SALMON,
|
||||
GatheringJobs.RAW_SHRIMP,
|
||||
GatheringJobs.RAW_TROUT
|
||||
),
|
||||
|
||||
NPCs.MINING_TUTOR_4902 to listOf(
|
||||
GatheringJobs.COPPER_ORE,
|
||||
GatheringJobs.TIN_ORE,
|
||||
GatheringJobs.COAL,
|
||||
GatheringJobs.IRON_ORE,
|
||||
GatheringJobs.SILVER_ORE,
|
||||
GatheringJobs.GOLD_ORE
|
||||
),
|
||||
|
||||
NPCs.PRAYER_TUTOR_4903 to listOf(
|
||||
GatheringJobs.SILVER_ORE
|
||||
),
|
||||
|
||||
NPCs.SMELTING_TUTOR_4904 to listOf(
|
||||
GatheringJobs.BRONZE_BAR,
|
||||
GatheringJobs.IRON_BAR,
|
||||
GatheringJobs.STEEL_BAR
|
||||
),
|
||||
|
||||
NPCs.WOODCUTTING_TUTOR_4906 to listOf(
|
||||
GatheringJobs.LOG,
|
||||
GatheringJobs.OAK,
|
||||
GatheringJobs.WILLOW
|
||||
)
|
||||
)
|
||||
|
||||
private val EMPLOYER_JOB_TYPES = mapOf(
|
||||
NPCs.HANS_0 to JobType.GATHERING,
|
||||
NPCs.MELEE_TUTOR_705 to JobType.SLAYING,
|
||||
NPCs.AGGIE_922 to JobType.GATHERING,
|
||||
NPCs.RANGED_TUTOR_1861 to JobType.SLAYING,
|
||||
NPCs.GILLIE_GROATS_3807 to JobType.GATHERING,
|
||||
NPCs.MAGIC_TUTOR_4707 to JobType.SLAYING,
|
||||
NPCs.COOKING_TUTOR_4899 to JobType.GATHERING,
|
||||
NPCs.FISHING_TUTOR_4901 to JobType.GATHERING,
|
||||
NPCs.MINING_TUTOR_4902 to JobType.GATHERING,
|
||||
NPCs.PRAYER_TUTOR_4903 to JobType.GATHERING,
|
||||
NPCs.SMELTING_TUTOR_4904 to JobType.GATHERING,
|
||||
NPCs.WOODCUTTING_TUTOR_4906 to JobType.GATHERING
|
||||
)
|
||||
|
||||
private val EMPLOYER_IDS = EMPLOYER_JOB_TYPES.keys.toIntArray()
|
||||
}
|
||||
|
||||
|
||||
override fun login(player: Player) {
|
||||
val remaining = getAttribute(player, "jobs:amount", -1)
|
||||
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
|
||||
|
||||
if (jobType == JobType.SLAYING && remaining > 0) {
|
||||
player.hook(Event.NPCKilled, JobKillHook)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(EMPLOYER_IDS, IntType.NPC, "work-for") { player, node ->
|
||||
if (JobManager.getStoreFile().getInt(player.username.lowercase()) == 3) {
|
||||
sendNPCDialogue(player, node.id, "You've hit your limit for the day. Come back tomorrow!")
|
||||
return@on true
|
||||
}
|
||||
|
||||
if (getAttribute(player, "jobs:id", -1) != -1) {
|
||||
JobManager.rewardPlayer(player, node.asNpc())
|
||||
return@on true
|
||||
}
|
||||
|
||||
var amount: Int
|
||||
val jobType = EMPLOYER_JOB_TYPES[node.id] ?: return@on false
|
||||
val jobId = when (jobType) {
|
||||
JobType.GATHERING -> {
|
||||
val job = EMPLOYERS_AND_JOBS[node.id]?.filter { checkRequirement(player, it) }?.randomOrNull()
|
||||
|
||||
if (job == null) {
|
||||
sendNPCDialogue(
|
||||
player,
|
||||
node.id,
|
||||
"I'm sorry, I don't currently have any jobs that you're qualified for.",
|
||||
core.game.dialogue.FacialExpression.HALF_THINKING
|
||||
)
|
||||
return@on true
|
||||
}
|
||||
|
||||
amount = job.getAmount()
|
||||
job.ordinal
|
||||
}
|
||||
|
||||
JobType.SLAYING -> {
|
||||
SlayingJobs.values().random().ordinal.also {
|
||||
amount = SlayingJobs.values()[it].getAmount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (jobType) {
|
||||
JobType.GATHERING -> {
|
||||
val job = GatheringJobs.values()[jobId]
|
||||
|
||||
sendItemDialogue(
|
||||
player,
|
||||
job.itemId,
|
||||
"You are assigned to gather $amount ${Item(job.itemId).name.lowercase()}"
|
||||
)
|
||||
}
|
||||
|
||||
JobType.SLAYING -> {
|
||||
val job = SlayingJobs.values()[jobId]
|
||||
|
||||
sendItemDialogue(
|
||||
player,
|
||||
WEAPON_ICONS.random(),
|
||||
"You are assigned to kill $amount ${NPC(job.ids[0]).name.lowercase()}"
|
||||
)
|
||||
|
||||
player.unhook(JobKillHook) //try to unhook just in case they already had it hooked, unlikely but possible.
|
||||
player.hook(Event.NPCKilled, JobKillHook)
|
||||
}
|
||||
}
|
||||
|
||||
setAttribute(player, "/save:jobs:id", jobId)
|
||||
setAttribute(player, "/save:jobs:amount", amount)
|
||||
setAttribute(player, "/save:jobs:original_amount", amount)
|
||||
setAttribute(player, "/save:jobs:type", jobType.ordinal)
|
||||
|
||||
player.dispatch(JobAssignmentEvent(jobType, node.asNpc()))
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean {
|
||||
jobs ?: return true
|
||||
|
||||
if (getStatLevel(player, jobs.skill) < jobs.lvlReq) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private object JobKillHook : EventHook<NPCKillEvent> {
|
||||
override fun process(entity: Entity, event: NPCKillEvent) {
|
||||
if (entity !is Player) return
|
||||
if (entity.isArtificial) return
|
||||
|
||||
val job = getAttribute(entity, "jobs:id", -1)
|
||||
|
||||
if (job !in 0 until SlayingJobs.values().size) {
|
||||
return
|
||||
}
|
||||
|
||||
val ids = SlayingJobs.values()[job].ids
|
||||
|
||||
if (event.npc.id in ids) {
|
||||
JobManager.updateJobRemaining(entity, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package content.global.activity.jobs.impl
|
||||
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.tools.RandomFunction
|
||||
|
||||
enum class GatheringJobs(val lower: Int, val upper: Int, val lvlReq: Int, val itemId: Int,val skill: Int) {
|
||||
LOG(20, 28, 1, 1511, Skills.WOODCUTTING),
|
||||
COWHIDES(20, 28, 1, 1739, 0),
|
||||
OAK(22, 28, 15, 1521, Skills.WOODCUTTING),
|
||||
WATER_RUNE(20, 28, 5, 555, Skills.RUNECRAFTING),
|
||||
EARTH_RUNE(20, 28, 9, 557, Skills.RUNECRAFTING),
|
||||
FIRE_RUNE(20, 28, 14, 554, Skills.RUNECRAFTING),
|
||||
AIR_RUNE(20, 28, 1, 556, Skills.RUNECRAFTING),
|
||||
RUNE_ESS(20, 28, 1, 1436, Skills.MINING),
|
||||
BALL_OF_WOOL(20, 28, 1, 1759, Skills.CRAFTING),
|
||||
LEATHER_GLOVE(20, 28, 1, 1059, Skills.CRAFTING),
|
||||
WILLOW(22, 28, 30, 1519, Skills.WOODCUTTING),
|
||||
LEATHER_BOOT(24, 24, 1, 1061, Skills.CRAFTING),
|
||||
BRONZE_DAGGER(24, 24, 1, 1205, Skills.SMITHING),
|
||||
BRONZE_HELMS(22, 22, 1, 1139, Skills.SMITHING),
|
||||
BRONZE_FULL_HELM(10, 10, 7, 1155, Skills.SMITHING),
|
||||
BRONZE_CHAINBODY(10, 10, 11, 1103, Skills.SMITHING),
|
||||
BRONZE_2H(10, 10, 14, 1307, Skills.SMITHING),
|
||||
BRONZE_SCIM(10, 10, 5, 1321, Skills.SMITHING),
|
||||
BRONZE_PLATEBODY(9, 10, 18, 1117, Skills.SMITHING),
|
||||
BRONZE_PLATELEGS(9, 10, 16, 1075, Skills.SMITHING),
|
||||
BRONZE_PLATESKIRTS(9, 10, 16, 1087, Skills.SMITHING),
|
||||
BRONZE_WARHAMMER(9, 9, 9, 1337, Skills.SMITHING),
|
||||
IRON_DAGGER(13, 13, 15, 1203, Skills.SMITHING),
|
||||
IRON_CHAINBODY(10, 10, 26, 1101, Skills.SMITHING),
|
||||
IRON_2H(9, 9, 29, 1309, Skills.SMITHING),
|
||||
STEEL_BATTLEAXE(9, 9, 40, 1365, Skills.SMITHING),
|
||||
STEEL_SCIMITAR(9, 9, 35, 1325, Skills.SMITHING),
|
||||
STEEL_PLATEBODY(9, 10, 48, 1119, Skills.SMITHING),
|
||||
STEEL_WARHAMMER(9, 10, 39, 1339, Skills.SMITHING),
|
||||
LEATHER_CHAPS(22, 28, 18, 1095, Skills.CRAFTING),
|
||||
LEATHER_BODY(22, 28, 14, 1129, Skills.CRAFTING),
|
||||
LEATHER_COWL(22, 28, 9, 1167, Skills.CRAFTING),
|
||||
LEATHER_COIF(22, 28, 38, 1169, Skills.CRAFTING),
|
||||
RAW_SHRIMP(22, 28, 1, 317, Skills.FISHING),
|
||||
COOKED_SHRIMP(22, 28, 1, 315, Skills.COOKING),
|
||||
RAW_CRAYFISH(22, 28, 1, 13435, Skills.FISHING),
|
||||
COOKED_CRAYFISH(22, 28, 1, 13433, Skills.COOKING),
|
||||
RAW_TROUT(22, 28, 20, 335, Skills.FISHING),
|
||||
COOKED_TROUT(22, 28, 15, 333, Skills.COOKING),
|
||||
RAW_SALMON(22, 28, 30, 331, Skills.FISHING),
|
||||
COOKED_SALMON(22, 28, 25, 329, Skills.COOKING),
|
||||
CAKE(12, 16, 40, 1891, Skills.COOKING),
|
||||
MEAT_PIE(12, 16, 20, 2327, Skills.COOKING),
|
||||
PLAIN_PIZZA(12, 16, 35, 2289, Skills.COOKING),
|
||||
MEAT_PIZZA(12, 16, 45, 2293, Skills.COOKING),
|
||||
ANCHOVY_PIZZA(12, 16, 55, 2297, Skills.COOKING),
|
||||
REDBERRY_PIE(12, 16, 10, 2325, Skills.COOKING),
|
||||
COPPER_ORE(22, 28, 1, 436, Skills.MINING),
|
||||
TIN_ORE(23, 26, 1, 438, Skills.MINING),
|
||||
IRON_ORE(24, 24, 15, 440, Skills.MINING),
|
||||
SILVER_ORE(22, 28, 20, 442, Skills.MINING),
|
||||
COAL(22, 26, 30, 453, Skills.MINING),
|
||||
GOLD_ORE(22, 24, 40, 444, Skills.MINING),
|
||||
BRONZE_BAR(10, 12, 1, 2349, Skills.SMITHING),
|
||||
IRON_BAR(22, 28, 15, 2351, Skills.SMITHING),
|
||||
STEEL_BAR(22, 28, 30, 2353, Skills.SMITHING),
|
||||
ASHES(26, 26, 1, 592, 0);
|
||||
|
||||
fun getAmount(): Int {
|
||||
return RandomFunction.random(lower,upper + 1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package content.global.activity.jobs.impl
|
||||
|
||||
import core.tools.RandomFunction
|
||||
|
||||
enum class SlayingJobs(val lower: Int, val upper: Int, vararg val ids: Int) {
|
||||
CHICKEN(25,26,41,1017),
|
||||
COW(25,25,397,1766,81,1767),
|
||||
GIANT_SPIDER(22,25,59,60),
|
||||
SCORPION(25,25,107,108,109,144,4402,4403),
|
||||
GOBLIN(25,25,100,101,102,298,299,444,445,489,745,1769,1770,1771,1772,1773,1774,1775,1776,2274,2275,2276,2277,2278,2279,2280,2281,2678,2679,2680,2681,3060,3264,3265,3266,3267);
|
||||
|
||||
fun getAmount(): Int {
|
||||
return RandomFunction.random(lower,upper + 1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import core.api.*
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class LarryHandler(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
options("Can I have a spy notebook?","Can I have a hint?","I'd like to turn in my points.").also { stage = 0; return true }
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin {
|
||||
return LarryHandler(player)
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
class HintPulse : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
val hint = Penguin.values()[PenguinManager.penguins.random()].hint
|
||||
player.sendMessage("Here, I know one is...")
|
||||
player.sendMessage(hint)
|
||||
return true
|
||||
}
|
||||
}
|
||||
when(stage){
|
||||
0 -> when(buttonId){
|
||||
1 -> player("Can I have a spy notebook?").also { stage++ }
|
||||
2 -> player("Can I have a hint?").also { stage = 10 }
|
||||
3 -> player("I'd like to turn in my points.").also { stage = 20 }
|
||||
}
|
||||
|
||||
//Spy notebook
|
||||
1 -> npc("Sure!").also { player.inventory.add(Item(13732));stage = 1000 }
|
||||
|
||||
//Hint
|
||||
10 -> npc("Yes, give me just one moment...").also { stage++ }
|
||||
|
||||
11 -> {
|
||||
val hint = Penguin.values()[PenguinManager.penguins.random()].hint
|
||||
npcl(core.game.dialogue.FacialExpression.FRIENDLY, "One is $hint")
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
//Point turn-in
|
||||
20 -> if(player.getAttribute("phns:points",0) > 0) npc("Sure thing, what would you like to be","rewarded with?").also { stage++ } else npc("Uh, you don't have any points","to turn in.").also{stage = 1000}
|
||||
|
||||
21 -> options("Coins","Experience").also { stage++ }
|
||||
22 -> when(buttonId){
|
||||
1 -> player.inventory.add(Item(995, 6500 * player.getAttribute("phns:points",0))).also { player("Thanks!"); player.removeAttribute("phns:points");stage = 1000 }
|
||||
2 -> {
|
||||
player.setAttribute("caller",this)
|
||||
player.interfaceManager.open(Component(134).setCloseEvent { player1: Player?, c: Component? ->
|
||||
player.interfaceManager.openDefaultTabs()
|
||||
player.removeAttribute("lamp")
|
||||
player.unlock()
|
||||
true
|
||||
}).also { end() }
|
||||
}
|
||||
}
|
||||
|
||||
1000 -> end()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handleSelectionCallback(skill: Int, player: Player) {
|
||||
val points = player.getAttribute("phns:points",0)
|
||||
if(points == 0){
|
||||
player.sendMessage("Sorry, but you have no points to redeem.")
|
||||
return
|
||||
}
|
||||
|
||||
val level = getStatLevel(player, skill)
|
||||
System.out.println("Level: $level")
|
||||
val expGained = points?.toDouble()?.times((level * 25))
|
||||
System.out.print("exp: $expGained")
|
||||
player.skills.addExperience(skill,expGained!!)
|
||||
player.setAttribute("/save:phns:points",0)
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(5424)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.interaction.OptionHandler
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import core.plugin.Plugin
|
||||
|
||||
class NotebookHandler : OptionHandler(){
|
||||
override fun handle(player: Player?, node: Node?, option: String?): Boolean {
|
||||
val total = player?.getAttribute("phns:points",0)
|
||||
player?.dialogueInterpreter?.sendDialogue("Total points: $total")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun newInstance(arg: Any?): Plugin<Any> {
|
||||
ItemDefinition.forId(13732).handlers["option:read"] = this
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import org.json.simple.JSONObject
|
||||
import core.ServerStore
|
||||
import core.game.worldevents.PluginSet
|
||||
import core.game.worldevents.WorldEvent
|
||||
import core.game.world.GameWorld
|
||||
|
||||
class PenguinHNSEvent : WorldEvent("penguin-hns"){
|
||||
val manager = PenguinManager()
|
||||
var lastTrigger: Int = 0
|
||||
var tickDelay = if(GameWorld.settings?.isDevMode == true) 100 else 100000
|
||||
|
||||
override fun checkActive(): Boolean {
|
||||
return true //this event is always active.
|
||||
}
|
||||
|
||||
override fun checkTrigger(): Boolean {
|
||||
return PenguinManager.penguins.isEmpty()
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
plugins = PluginSet(
|
||||
LarryHandler(),
|
||||
NotebookHandler(),
|
||||
)
|
||||
super.initialize()
|
||||
fireEvent()
|
||||
log("Penguin HNS initialized.")
|
||||
}
|
||||
|
||||
override fun fireEvent() {
|
||||
log("Loading penguins...")
|
||||
manager.rebuildVars()
|
||||
lastTrigger = GameWorld.ticks
|
||||
log("Penguins loaded.")
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getStoreFile() : JSONObject {
|
||||
return ServerStore.getArchive("weekly-penguinhns")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.tools.SystemLogger
|
||||
import core.game.world.map.Location
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import core.ServerStore.Companion.toJSONArray
|
||||
import java.util.*
|
||||
|
||||
class PenguinManager{
|
||||
companion object {
|
||||
var penguins: MutableList<Int> = ArrayList<Int>()
|
||||
var npcs = ArrayList<NPC>()
|
||||
val spawner = PenguinSpawner()
|
||||
var tagMapping: MutableMap<Int,JSONArray> = HashMap()
|
||||
|
||||
fun registerTag(player: Player, location: Location){
|
||||
val ordinal = Penguin.forLocation(location)?.ordinal ?: -1
|
||||
val list = tagMapping[ordinal] ?: JSONArray()
|
||||
list.add(player.username.toLowerCase())
|
||||
tagMapping[ordinal] = list
|
||||
updateStoreFile()
|
||||
}
|
||||
|
||||
fun hasTagged(player: Player, location: Location): Boolean{
|
||||
return tagMapping[Penguin.forLocation(location)?.ordinal]?.contains(player.username.toLowerCase()) ?: false
|
||||
}
|
||||
|
||||
private fun updateStoreFile(){
|
||||
val jsonTags = JSONArray()
|
||||
tagMapping.filter { it.value.isNotEmpty() }.forEach { (ordinal,taggers) ->
|
||||
SystemLogger.logInfo(this::class.java, "$ordinal - ${taggers.first()}")
|
||||
val tag = JSONObject()
|
||||
tag["ordinal"] = ordinal
|
||||
tag["taggers"] = taggers
|
||||
jsonTags.add(tag)
|
||||
}
|
||||
|
||||
PenguinHNSEvent.getStoreFile()["tag-mapping"] = jsonTags
|
||||
}
|
||||
}
|
||||
|
||||
fun rebuildVars() {
|
||||
if(!PenguinHNSEvent.getStoreFile().containsKey("spawned-penguins")) {
|
||||
penguins = spawner.spawnPenguins(10)
|
||||
PenguinHNSEvent.getStoreFile()["spawned-penguins"] = penguins.toJSONArray()
|
||||
tagMapping.clear()
|
||||
for (p in penguins) {
|
||||
tagMapping.put(p, JSONArray())
|
||||
}
|
||||
updateStoreFile()
|
||||
} else {
|
||||
val spawnedOrdinals = (PenguinHNSEvent.getStoreFile()["spawned-penguins"] as JSONArray).map { it.toString().toInt() }
|
||||
spawner.spawnPenguins(spawnedOrdinals)
|
||||
|
||||
val storedTags = (PenguinHNSEvent.getStoreFile()["tag-mapping"] as? JSONArray)?.map { jRaw ->
|
||||
val jObj = jRaw as JSONObject
|
||||
jObj["ordinal"].toString().toInt() to (jObj["taggers"] as JSONArray)
|
||||
}?.toMap()?.toMutableMap() ?: HashMap<Int,JSONArray>()
|
||||
|
||||
tagMapping = storedTags
|
||||
penguins = spawnedOrdinals.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
fun log(message: String){
|
||||
SystemLogger.logInfo(this::class.java, "[Penguins] $message")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.worldevents.WorldEvents
|
||||
|
||||
class PenguinSpawner {
|
||||
|
||||
fun spawnPenguins(amount: Int): ArrayList<Int> {
|
||||
var counter = 0
|
||||
val availableOrdinals = (0 until Penguin.values().size).toMutableList()
|
||||
val spawnedOrdinals = ArrayList<Int>()
|
||||
while(counter < amount){
|
||||
val peng = Penguin.values()[availableOrdinals.random()]
|
||||
availableOrdinals.remove(peng.ordinal)
|
||||
spawnedOrdinals.add(peng.ordinal)
|
||||
NPC(peng.id,peng.location)
|
||||
.also { PenguinManager.npcs.add(it);it.isNeverWalks = true; it.isWalks = false}.init()
|
||||
counter++
|
||||
}
|
||||
return spawnedOrdinals
|
||||
}
|
||||
|
||||
fun spawnPenguins(ordinals: List<Int>){
|
||||
ordinals.forEach {
|
||||
val peng = Penguin.values()[it]
|
||||
NPC(peng.id,peng.location)
|
||||
.also { PenguinManager.npcs.add(it); it.isNeverWalks = true; it.isWalks = false }.init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Penguin(val id: Int, val hint: String, val location: Location){
|
||||
CACTUS_1(NPCs.CACTUS_8107,"located in the northern desert.", Location(3310, 3157, 0)),
|
||||
CACTUS_2(NPCs.CACTUS_8107,"located in the southern desert.",Location.create(3259, 3052, 0)),
|
||||
BUSH_1(NPCs.BUSH_8105,"located between Fremennik and barbarians.",Location.create(2532, 3588, 0)),
|
||||
BUSH_2(NPCs.BUSH_8105,"located where banana smugglers dwell.",Location.create(2740, 3233, 0)),
|
||||
BUSH_3(NPCs.BUSH_8105,"located south of Ardougne.",Location.create(2456, 3092, 0)),
|
||||
BUSH_4(NPCs.BUSH_8105,"located deep in the jungle.",Location.create(2832, 3053, 0)),
|
||||
BUSH_5(NPCs.BUSH_8105,"located where eagles fly.",Location.create(2326, 3516, 0)),
|
||||
BUSH_6(NPCs.BUSH_8105,"located south of Ardougne.",Location.create(2513, 3154, 0)),
|
||||
BUSH_7(NPCs.BUSH_8105,"located near a big tree surrounded by short people.",Location.create(2387, 3451, 0)),
|
||||
BUSH_8(NPCs.BUSH_8105,"located in the kingdom of Asgarnia.",Location.create(2951, 3511, 0)),
|
||||
BUSH_9(NPCs.BUSH_8105,"located in the northern desert.",Location.create(3350, 3311, 0)),
|
||||
BUSH_10(NPCs.BUSH_8105,"located somewhere in the kingdom of Kandarin.",Location.create(2633, 3501, 0)),
|
||||
BUSH_11(NPCs.BUSH_8105,"located south of Ardougne.",Location.create(2440, 3206, 0)),
|
||||
BUSH_12(NPCs.BUSH_8105,"located where wizards study.",Location.create(3112, 3149, 0)),
|
||||
ROCK_1(NPCs.ROCK_8109,"located where the Imperial Guard train.",Location.create(2852, 3578, 0)),
|
||||
ROCK_2(NPCs.ROCK_8109,"located in the kingdom of Misthalin.",Location.create(3356, 3416, 0)),
|
||||
ROCK_3(NPCs.ROCK_8109,"located near some ogres.",Location.create(2631, 2980, 0)),
|
||||
ROCK_4(NPCs.ROCK_8109,"located in the Kingdom of Asgarnia.",Location.create(3013, 3501, 0)),
|
||||
ROCK_5(NPCs.ROCK_8109,"located between Fremennik and barbarians.",Location.create(2532, 3630, 0)),
|
||||
CRATE_1(NPCs.CRATE_8108,"located in the kingdom of Misthalin.",Location.create(3112, 3332, 0)),
|
||||
CRATE_2(NPCs.CRATE_8108,"located in the Kingdom of Misthalin.",Location.create(3305, 3508, 0)),
|
||||
BARREL_1(NPCs.CRATE_8108,"located where no weapons may go.",Location.create(2806, 3383, 0)),
|
||||
TOADSTOOL_1(NPCs.TOADSTOOL_8110,"located in the kingdom of Misthalin.",Location.create(3156, 3178, 0)),
|
||||
TOADSTOOL_2(NPCs.TOADSTOOL_8110,"located in the fairy realm.",Location.create(2409, 4462, 0));
|
||||
|
||||
companion object {
|
||||
private val locationMap = values().map { it.location.toString() to it }.toMap()
|
||||
|
||||
fun forLocation(location: Location): Penguin?{
|
||||
return locationMap[location.toString()]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package content.global.activity.penguinhns
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
class PenguinSpyingHandler : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
on(PENGUINS, IntType.NPC, "spy-on"){ player, node ->
|
||||
val npc = node.asNpc()
|
||||
if(PenguinManager.hasTagged(player, npc.location)){
|
||||
player.sendMessage("You've already tagged this penguin.")
|
||||
} else {
|
||||
GameWorld.submit(SpyPulse(player, npc))
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
val PENGUINS = intArrayOf(8104,8105,8107,8108,8109,8110)
|
||||
|
||||
class SpyPulse(val player: Player, val npc: NPC) : Pulse() {
|
||||
var stage = 0
|
||||
val curPoints = player.getAttribute("phns:points",0)
|
||||
|
||||
val ANIMATION = Animation(10355)
|
||||
|
||||
override fun pulse(): Boolean {
|
||||
when(stage++){
|
||||
0 -> player.lock().also { player.animator.animate(ANIMATION) }
|
||||
1 -> player.sendMessage("You manage to spy on the penguin.").also {
|
||||
player.setAttribute("/save:phns:points",curPoints + 1)
|
||||
PenguinManager.registerTag(player, npc.location)
|
||||
player.unlock()
|
||||
}
|
||||
2 -> return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
player.unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.scenery.SceneryBuilder
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.ServerStore.Companion.getBoolean
|
||||
import core.ServerStore.Companion.getInt
|
||||
import core.ServerStore.Companion.getString
|
||||
|
||||
import content.global.bots.ShootingStarBot
|
||||
import core.game.world.repository.Repository
|
||||
|
||||
/**
|
||||
* Represents a shooting star object (Only ever initialized once) (ideally)
|
||||
* @author Ceikry
|
||||
*/
|
||||
class ShootingStar(var level: ShootingStarType = ShootingStarType.values().random()){
|
||||
val crash_locations = mapOf(
|
||||
"East of Dark Wizards' Tower" to Location.create(2925, 3339, 0), // East of Dark Wizards' Tower
|
||||
"Crafting Guild" to Location.create(2940, 3280, 0), // Crafting Guild Mine
|
||||
"Falador East Bank" to Location.create(3030, 3349, 0), // Falador East Bank
|
||||
"Rimmington mining site" to Location.create(2974, 3240, 0), // Rimmington Mine 2974, 3240, 0)
|
||||
"Karamja northwestern mining site" to Location.create(2737, 3223, 0), // Karamja northwestern mining site/Brimhaven gold rocks
|
||||
"Brimhaven mining site" to Location.create(2743, 3143, 0), // Brimhaven mining site
|
||||
"South Crandor mining site" to Location.create(2822, 3239, 0), // South Crandor mining site (requires Dragon Slayer)
|
||||
"Karamja mining site" to Location.create(2854, 3032, 0), // Karamja mining site
|
||||
"Shilo Village mining site" to Location.create(2826, 2997, 0), // Shilo Village mining site/Gem rocks
|
||||
"Relleka mining site" to Location.create(2682, 3700, 0), // Rellekka mining site
|
||||
"Jatizso mine" to Location.create(2393, 3815, 0), //Jatiszo mining site (requires Fremennik Trials)
|
||||
//"Lunar Isle mine" to Location.create(2140, 3939, 0), // Lunar Isle mine (requires Lunar Diplomacy?)
|
||||
//"Miscellania coal mine" to Location.create(2529, 3887, 0), // Miscellania coal mine (requires Fremennik Trials)
|
||||
//"Neitiznot runite mine" to Location.create(2376, 3835, 0), // Near the Neitiznot runite mine (requires Fremennik Trials) currently inaccessible as bridge does not work
|
||||
"Ardougne mining site" to Location.create(2600, 3232, 0), // Ardougne mining site (Monastery)
|
||||
"Ardougne eastern mine" to Location.create(2706, 3334, 0), // Ardougne mining site (Legends Guild)
|
||||
"Kandarin Coal trucks" to Location.create(2589, 3485, 0), // Kandarin Coal trucks
|
||||
"Yanille Bank" to Location.create(2603, 3087, 0), // Yanille Bank (Wizards' Guild)
|
||||
"Port Khazard mine" to Location.create(2626, 3140, 0), // Mining spot north-east of Yanille / Port Khazard mine
|
||||
"Al Kharid bank" to Location.create(3276, 3176, 0), // Al Kharid bank
|
||||
"Al Kharid mining site" to Location.create(3296, 3297, 0), // Al Kharid mine (Scorpion mine)
|
||||
"Duel Arena bank chest" to Location.create(3342, 3267, 0), // Duel Arena bank chest
|
||||
"Kharidian Desert clay mine" to Location.create(3426, 3159, 0), // Desert clay mine / Ruins of Uzer mine
|
||||
"Nardah mining site" to Location.create(3320, 2872, 0), // Kharidian Desert gold mine / Vulture mine
|
||||
"Nardah bank" to Location.create(3434, 2888, 0), // Nardah bank
|
||||
"Granite and sandstone quarry" to Location.create(3170, 2913, 0), // Granite and sandstone quarry / Quarry on map
|
||||
"South-east Varrock mine" to Location.create(3292, 3353, 0), // South-east Varrock mine
|
||||
"South-west Varrock mine" to Location.create(3176, 3362, 0), // South-west Varrock mine / Champion's Guild mine
|
||||
"Varrock east bank" to Location.create(3259, 3407, 0), // Varrock east bank / Rune shop
|
||||
"Lumbridge Swamp south-east mine" to Location.create(3227, 3150, 0), // Lumbridge Swamp south-east mine
|
||||
//"Burgh de Rott bank" to Location.create(3500, 3219, 0), // Burgh de Rott bank (requires Quest to enter)
|
||||
"Canifis Bank" to Location.create(3504, 3487, 0), // Canifis bank
|
||||
"Mos Le'Harmless bank" to Location.create(3687, 2969, 0), // Mos Le'Harmless bank (requires Quest to enter but is currently accessible for Slayer)
|
||||
"Gnome stronghold Bank" to Location.create(2460, 3432, 0), // Gnome stronghold bank
|
||||
"Lletya bank" to Location.create(2329, 3163, 0), // Lletya bank (requires Roving Elves?)
|
||||
"Piscatoris mining site" to Location.create(2336, 3636, 0), // Piscatoris mining site
|
||||
"North Edgeville mining site" to Location.create(3101, 3569, 0), // Wilderness Steel mine / Zamorak mage mine
|
||||
"Southern wilderness mine" to Location.create(3025, 3591, 0), // Wilderness skeleton mine
|
||||
"Wilderness Volcano bank" to Location.create(3188, 3695, 0), // Wilderness Volcano bank
|
||||
"Wilderness hobgoblin mine" to Location.create(3020, 3809, 0), // Wilderness hobgoblin mine
|
||||
"Pirates' Hideout mine" to Location.create(3059, 3940, 0), // Pirates' Hideout mine
|
||||
"Lava Maze mining site" to Location.create(3062, 3885, 0), // Wilderness rune mine
|
||||
"Mage Arena bank" to Location.create(3093, 3962, 0) // Mage Arena bank
|
||||
)
|
||||
val starSprite = NPC(8091)
|
||||
var location = "Canifis Bank"
|
||||
var maxDust = level.totalStardust
|
||||
var dustLeft = level.totalStardust
|
||||
var starObject = Scenery(level.objectId, crash_locations.get(location))
|
||||
var isDiscovered = false
|
||||
var ticks = 0
|
||||
var isSpawned = false
|
||||
var spriteSpawned = false
|
||||
var firstStar = true
|
||||
var selfBots = ArrayList<ShootingStarBot>()
|
||||
var activePlayers = HashSet<Player>()
|
||||
|
||||
/**
|
||||
* Degrades a ShootingStar (or removes the starObject and spawns a Star Sprite if it's the last star)
|
||||
*/
|
||||
fun degrade() {
|
||||
if(level.ordinal == 0){
|
||||
selfBots.filter { it.isMining() }.forEach { it.sleep() }
|
||||
SceneryBuilder.remove(starObject)
|
||||
isSpawned = false
|
||||
starSprite.location = starObject.location
|
||||
starSprite.init()
|
||||
spriteSpawned = true
|
||||
ShootingStarPlugin.getStoreFile().clear()
|
||||
return
|
||||
}
|
||||
level = getNextType()
|
||||
maxDust = level.totalStardust
|
||||
dustLeft = level.totalStardust
|
||||
|
||||
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = isDiscovered
|
||||
|
||||
val newStar = Scenery(level.objectId, starObject.location)
|
||||
SceneryBuilder.replace(starObject, newStar)
|
||||
starObject = newStar
|
||||
}
|
||||
|
||||
private fun getNextType(): ShootingStarType {
|
||||
return ShootingStarType.values()[level.ordinal - 1]
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires the shooting star (spawns a new one). Only used when spawning new shooting stars, not for downgrading existing ones.
|
||||
*/
|
||||
fun fire() {
|
||||
SceneryBuilder.remove(starObject)
|
||||
rebuildVars()
|
||||
clearSprite()
|
||||
SceneryBuilder.add(starObject)
|
||||
if(!isSpawned) {
|
||||
(0..2).forEach {
|
||||
selfBots.add(ShootingStarBot.new())
|
||||
}
|
||||
}
|
||||
if (level.ordinal + 1 > 5) {
|
||||
selfBots.filter { it.isIdle() }.forEach { it.activate(true) }
|
||||
}
|
||||
isSpawned = true
|
||||
Repository.sendNews("A shooting star level ${level.ordinal + 1} just crashed near ${location.toLowerCase()}!")
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds some of the variables with new information.
|
||||
*/
|
||||
fun rebuildVars(){
|
||||
if(firstStar && ShootingStarPlugin.getStoreFile().isNotEmpty()){
|
||||
level = ShootingStarType.values()[ShootingStarPlugin.getStoreFile().getInt("level")]
|
||||
location = ShootingStarPlugin.getStoreFile().getString("location")
|
||||
isDiscovered = ShootingStarPlugin.getStoreFile().getBoolean("isDiscovered")
|
||||
} else {
|
||||
level = ShootingStarType.values().random()
|
||||
location = crash_locations.entries.random().key
|
||||
isDiscovered = false
|
||||
}
|
||||
|
||||
maxDust = level.totalStardust
|
||||
dustLeft = level.totalStardust
|
||||
starObject = Scenery(level.objectId, crash_locations.get(location))
|
||||
|
||||
ShootingStarPlugin.getStoreFile()["level"] = level.ordinal
|
||||
ShootingStarPlugin.getStoreFile()["location"] = location
|
||||
ShootingStarPlugin.getStoreFile()["isDiscovered"] = false
|
||||
|
||||
ticks = 0
|
||||
firstStar = false
|
||||
}
|
||||
|
||||
fun clearSprite() {
|
||||
starSprite.clear()
|
||||
spriteSpawned = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the amount of dust left in the current star and degrade it if the amount left is 0 or less.
|
||||
*/
|
||||
fun decDust() {
|
||||
if(--dustLeft <= 0) degrade()
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for starting to mine a shooting star
|
||||
*/
|
||||
fun mine(player: Player) {
|
||||
player.pulseManager.run(ShootingStarMiningPulse(player, starObject, this))
|
||||
}
|
||||
|
||||
/**
|
||||
* Prospecting shooting stars.
|
||||
*/
|
||||
fun prospect(player: Player) {
|
||||
player.dialogueInterpreter.sendDialogue("This is a size " + (level.ordinal + 1) + " star. A Mining level of at least " + miningLevel + " is", "required to mine this layer. There is $dustLeft stardust remaining", "until the next layer.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the star when a player begins mining it
|
||||
*/
|
||||
fun notifyNewPlayer(player: Player) {
|
||||
if(activePlayers.size < 3){
|
||||
val leavingBot = selfBots.firstOrNull { it.isMining() }
|
||||
leavingBot?.sleep()
|
||||
}
|
||||
activePlayers.add(player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the star when a player stops mining it
|
||||
*/
|
||||
fun notifyPlayerLeave(player: Player) {
|
||||
activePlayers.remove(player)
|
||||
if (activePlayers.size < 3){
|
||||
val newBot = selfBots.firstOrNull() { it.isIdle() }
|
||||
newBot?.activate(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mining level required based on the star's current level ordinal.
|
||||
*/
|
||||
val miningLevel: Int
|
||||
get() = (level.ordinal + 1) * 10
|
||||
}
|
||||
|
||||
/**
|
||||
* Various levels of shooting stars
|
||||
* @author Ceikry
|
||||
*/
|
||||
enum class ShootingStarType(val objectId: Int, val exp: Int, val totalStardust: Int,val rate: Double) {
|
||||
LEVEL_1(38668, 14, 1200, 0.05),
|
||||
LEVEL_2(38667, 25, 700, 0.1),
|
||||
LEVEL_3(38666, 29, 439, 0.3),
|
||||
LEVEL_4(38665, 32, 250, 0.4),
|
||||
LEVEL_5(38664, 47, 175, 0.5),
|
||||
LEVEL_6(38663, 71, 80, 0.70),
|
||||
LEVEL_7(38662, 114, 40, 0.80),
|
||||
LEVEL_8(38661, 145, 25, 0.85),
|
||||
LEVEL_9(38660, 210, 15, 0.95);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.SkillPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.data.skill.SkillingTool
|
||||
import core.game.node.item.Item
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.repository.Repository
|
||||
import core.tools.colorize
|
||||
|
||||
/**
|
||||
* The pulse used to handle mining shooting stars.
|
||||
*/
|
||||
class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: ShootingStar) : SkillPulse<Scenery?>(player, node) {
|
||||
/**
|
||||
* The amount of ticks it takes to get star dust.
|
||||
*/
|
||||
private var ticks = 0
|
||||
override fun start() {
|
||||
if(!star.isSpawned) return
|
||||
|
||||
if(!player.isArtificial) {
|
||||
star.notifyNewPlayer(player)
|
||||
}
|
||||
super.start()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
|
||||
if(!player.isArtificial){
|
||||
star.notifyPlayerLeave(player)
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkRequirements(): Boolean {
|
||||
tool = SkillingTool.getPickaxe(player)
|
||||
if (!star.starObject.isActive || !star.isSpawned) {
|
||||
return false
|
||||
}
|
||||
//checks if the star has been discovered and if not, awards the bonus xp. Xp can be awarded regardless of mining level as per the wiki.
|
||||
if (!star.isDiscovered && !player.isArtificial) {
|
||||
val bonusXp = 75 * player.skills.getStaticLevel(Skills.MINING)
|
||||
player.incrementAttribute("/save:shooting-star:bonus-xp", bonusXp)
|
||||
Repository.sendNews(player.username + " is the discoverer of the crashed star near " + star.location + "!")
|
||||
player.sendMessage("You have ${player.skills.experienceMutiplier * player.getAttribute("shooting-star:bonus-xp", 0).toDouble()} bonus xp towards mining stardust.")
|
||||
ShootingStarPlugin.submitScoreBoard(player)
|
||||
star.isDiscovered = true
|
||||
return player.skills.getLevel(Skills.MINING) >= star.miningLevel
|
||||
}
|
||||
|
||||
if (player.skills.getLevel(Skills.MINING) < star.miningLevel) {
|
||||
player.dialogueInterpreter.sendDialogue("You need a Mining level of at least " + star.miningLevel + " in order to mine this layer.")
|
||||
return false
|
||||
}
|
||||
if (tool == null) {
|
||||
player.packetDispatch.sendMessage("You do not have a pickaxe to use.")
|
||||
return false
|
||||
}
|
||||
if (player.inventory.freeSlots() < 1 && !player.inventory.contains(ShootingStarPlugin.STAR_DUST, 1)) {
|
||||
player.dialogueInterpreter.sendDialogue("Your inventory is too full to hold any more stardust.")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun animate() {
|
||||
player.animate(tool.animation)
|
||||
}
|
||||
|
||||
override fun reward(): Boolean {
|
||||
if (++ticks % 4 != 0) {
|
||||
return false
|
||||
}
|
||||
if (!checkReward()) {
|
||||
return false
|
||||
}
|
||||
if (GameWorld.settings?.isDevMode == true) {
|
||||
star.dustLeft = 1
|
||||
}
|
||||
star.decDust()
|
||||
|
||||
val bonusXp = player.getAttribute("shooting-star:bonus-xp", 0).toDouble()
|
||||
var xp = star.level.exp.toDouble()
|
||||
if(bonusXp > 0) {
|
||||
val delta = Math.min(bonusXp, xp)
|
||||
player.incrementAttribute("/save:shooting-star:bonus-xp", (-delta).toInt())
|
||||
xp += delta;
|
||||
if(player.getAttribute("shooting-star:bonus-xp", 0) <= 0) {
|
||||
player.sendMessage("You have obtained all of your bonus xp from the star.")
|
||||
}
|
||||
}
|
||||
|
||||
player.skills.addExperience(Skills.MINING, xp)
|
||||
if (ShootingStarPlugin.getStarDust(player) < 200) {
|
||||
player.inventory.add(Item(ShootingStarPlugin.STAR_DUST, 1))
|
||||
}
|
||||
if(!inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !inBank(player, Items.ANCIENT_BLUEPRINT_14651)){
|
||||
rollBlueprint(player)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun rollBlueprint(player: Player){
|
||||
val chance = when(star.level){
|
||||
ShootingStarType.LEVEL_9 -> 250
|
||||
ShootingStarType.LEVEL_8 -> 500
|
||||
ShootingStarType.LEVEL_7 -> 750
|
||||
ShootingStarType.LEVEL_6 -> 1000
|
||||
ShootingStarType.LEVEL_5 -> 2000
|
||||
ShootingStarType.LEVEL_4 -> 3000
|
||||
ShootingStarType.LEVEL_3 -> 4000
|
||||
ShootingStarType.LEVEL_2 -> 5000
|
||||
ShootingStarType.LEVEL_1 -> 10000
|
||||
}
|
||||
|
||||
if(RandomFunction.roll(chance)){
|
||||
addItemOrDrop(player, Items.ANCIENT_BLUEPRINT_14651, 1)
|
||||
sendMessage(player, colorize("%RWhile mining the star you find an ancient-looking blueprint."))
|
||||
sendNews("${player.username} found an Ancient Blueprint while mining a shooting star!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun message(type: Int) {
|
||||
when (type) {
|
||||
0 -> player.packetDispatch.sendMessage("You swing your pickaxe at the rock...")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player gets rewarded.
|
||||
* @return `True` if so.
|
||||
*/
|
||||
private fun checkReward(): Boolean {
|
||||
val skill = Skills.MINING
|
||||
val level = 1 + player.skills.getLevel(skill) + player.familiarManager.getBoost(skill)
|
||||
val hostRatio: Double = Math.random() * (100.0 * star.level.rate)
|
||||
val clientRatio: Double = Math.random() * ((level - star.miningLevel) * (1.0 + tool.ratio))
|
||||
return hostRatio < clientRatio
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.entity.skill.Skills
|
||||
import org.json.simple.JSONObject
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Scenery
|
||||
import core.ServerStore
|
||||
import core.ServerStore.Companion.getBoolean
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import core.tools.SystemLogger
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.world.GameWorld
|
||||
import core.tools.secondsToTicks
|
||||
|
||||
class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Commands, StartupListener {
|
||||
override fun login(player: Player) {
|
||||
if(star.isSpawned && !star.spriteSpawned)
|
||||
sendMessage(player, "<img=12><col=CC6600>News: A shooting star (Level ${star.level.ordinal + 1}) has just crashed near the ${star.location}!")
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
++star.ticks
|
||||
|
||||
val maxDelay = tickDelay + (tickDelay / 3)
|
||||
if(star.ticks > maxDelay && star.spriteSpawned){
|
||||
star.clearSprite()
|
||||
}
|
||||
|
||||
if ((star.ticks >= tickDelay && !star.spriteSpawned) || (!star.isSpawned && !star.spriteSpawned)) {
|
||||
star.fire()
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Scenery.SHOOTING_STAR_NOTICEBOARD_38669, IntType.SCENERY, "read") { player, _ ->
|
||||
var index = 0
|
||||
scoreboardEntries.forEach { entry ->
|
||||
val timeElapsed = secondsToTicks(GameWorld.ticks - entry.time) / 60
|
||||
setInterfaceText(player, "$timeElapsed minutes ago", scoreboardIface, index + 6)
|
||||
setInterfaceText(player, entry.player, scoreboardIface, index + 11)
|
||||
++index
|
||||
}
|
||||
openInterface(player, scoreboardIface)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(SHOOTING_STARS, IntType.SCENERY, "mine"){ player, _ ->
|
||||
star.mine(player)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(SHOOTING_STARS, IntType.SCENERY, "prospect"){ player, _ ->
|
||||
star.prospect(player)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(RING, IntType.ITEM, "rub", "operate"){ player, node ->
|
||||
if(getRingStoreFile().getBoolean(player.username.toLowerCase())){
|
||||
sendDialogue(player, "The ring is still recharging.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
val condition: (Player) -> Boolean = when(star.location.toLowerCase()){
|
||||
"canifis bank" -> { p -> p.questRepository.isComplete("Priest in Peril")}
|
||||
//"Burgh de Rott bank" -> { p -> p.questRepository.isComplete("Priest in Peril")} // for now, require this as it is in Morytania. remove when appropriate quests added - Crash
|
||||
"crafting guild" -> {p -> hasLevelStat(p, Skills.CRAFTING, 40) }
|
||||
"lletya bank" -> {p -> p.questRepository.isComplete("Roving Elves")}
|
||||
"jatizso mine" -> {p -> p.questRepository.isComplete("Fremennik Trials")}
|
||||
"south crandor mining site" -> {p -> p.questRepository.isComplete("Dragon Slayer")}
|
||||
else -> {_ -> true}
|
||||
}
|
||||
|
||||
if(!condition.invoke(player) || player.skullManager.isWilderness){
|
||||
sendDialogue(player, "Magical forces prevent your teleportation.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
val shouldWarn = when(star.location){
|
||||
"North Edgeville mining site",
|
||||
"Southern wilderness mine",
|
||||
"Wilderness Volcano bank",
|
||||
"Wilderness hobgoblin mine",
|
||||
"Pirates' Hideout mine",
|
||||
"Lava Maze mining site",
|
||||
"Mage Arena bank" -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
openDialogue(player, RingDialogue(shouldWarn, star))
|
||||
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineCommands() {
|
||||
define("tostar", Privilege.ADMIN) { player, _ ->
|
||||
teleport(player, star.starObject.location.transform(1,1,0))
|
||||
}
|
||||
|
||||
define("submit", Privilege.ADMIN) { _, _ ->
|
||||
star.fire()
|
||||
}
|
||||
|
||||
define("resetsprite", Privilege.ADMIN) { player, _ ->
|
||||
player.savedData.globalData.starSpriteDelay = 0L
|
||||
}
|
||||
}
|
||||
|
||||
override fun startup() {
|
||||
SystemLogger.logInfo(this::class.java, "Shooting Stars initialized.")
|
||||
}
|
||||
|
||||
private data class ScoreboardEntry(val player: String, val time: Int)
|
||||
|
||||
private class RingDialogue(val shouldWarn: Boolean, val star: ShootingStar) : DialogueFile(){
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
0 -> dialogue(if (star.spriteSpawned) "The star sprite has already been freed." else "The star sprite is still trapped.").also { if (shouldWarn) stage++ else stage += 2 }
|
||||
1 -> dialogue("WARNING: The star is located in the wilderness.").also { stage++ }
|
||||
2 -> player!!.dialogueInterpreter.sendOptions("Teleport to the star?", "Yes", "No").also { stage++ }
|
||||
3 -> when (buttonID) {
|
||||
1 -> teleport(player!!, star).also { end() }
|
||||
2 -> end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun teleport(player: Player, star: ShootingStar){
|
||||
teleport(player, star.crash_locations[star.location]!!.transform(0, -1, 0), TeleportManager.TeleportType.MINIGAME)
|
||||
getRingStoreFile()[player.username.toLowerCase()] = true
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val star = ShootingStar()
|
||||
private val tickDelay = if(GameWorld.settings?.isDevMode == true) 200 else 25000
|
||||
private val scoreboardEntries = ArrayList<ScoreboardEntry>()
|
||||
private val scoreboardIface = 787
|
||||
val SHOOTING_STARS = ShootingStarType.values().map(ShootingStarType::objectId).toIntArray()
|
||||
val STAR_DUST = Items.STARDUST_13727
|
||||
val RING = Items.RING_OF_THE_STAR_SPRITE_14652
|
||||
|
||||
|
||||
@JvmStatic fun submitScoreBoard(player: Player)
|
||||
{
|
||||
if(scoreboardEntries.size == 5)
|
||||
scoreboardEntries.removeAt(0)
|
||||
scoreboardEntries.add(ScoreboardEntry(player.username, GameWorld.ticks))
|
||||
}
|
||||
|
||||
@JvmStatic fun getStar(): ShootingStar
|
||||
{
|
||||
return star
|
||||
}
|
||||
|
||||
@JvmStatic fun getStoreFile() : JSONObject {
|
||||
return ServerStore.getArchive("shooting-star")
|
||||
}
|
||||
|
||||
@JvmStatic fun getRingStoreFile() : JSONObject {
|
||||
return ServerStore.getArchive("daily-star-ring")
|
||||
}
|
||||
|
||||
fun getStarDust(player: Player): Int {
|
||||
return player.inventory.getAmount(STAR_DUST) + player.bank.getAmount(STAR_DUST)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.state.PlayerState
|
||||
import core.game.node.entity.state.State
|
||||
import core.game.system.task.Pulse
|
||||
import core.tools.ticksToSeconds
|
||||
import org.json.simple.JSONObject
|
||||
|
||||
@PlayerState("shooting-star")
|
||||
class ShootingStarState(player: Player? = null) : State(player) {
|
||||
var ticksLeft = 1500
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
root["ticksLeft"] = ticksLeft
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("ticksLeft")){
|
||||
ticksLeft = _data["ticksLeft"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return ShootingStarState(player)
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(ticksLeft <= 0) return
|
||||
pulse = object : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
val minutes = ticksToSeconds(ticksLeft) / 60.0
|
||||
if(minutes % 5.0 == 0.0){
|
||||
player.sendMessage("<col=f0f095>You have $minutes minutes of your mining bonus left</col>")
|
||||
}
|
||||
if(ticksLeft-- <= 0){
|
||||
player.sendMessage("<col=FF0000>Your mining bonus has run out!</col>")
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package content.global.activity.shootingstar;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.plugin.PluginManifest;
|
||||
|
||||
@PluginManifest(name="ShootingStars")
|
||||
public class StarChartPlugin extends ComponentPlugin {
|
||||
private Component iface = new Component(104);
|
||||
private int index= 19;
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new StarChartOptions());
|
||||
ComponentDefinition.forId(iface.getId()).setPlugin(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public class StarChartOptions extends OptionHandler{
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.getInterfaceManager().open(iface);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(25582).getHandlers().put("option:look-at",this);
|
||||
SceneryDefinition.forId(25581).getHandlers().put("option:look-at",this);
|
||||
SceneryDefinition.forId(25580).getHandlers().put("option:look-at",this);
|
||||
SceneryDefinition.forId(25583).getHandlers().put("option:look-at",this);
|
||||
SceneryDefinition.forId(25579).getHandlers().put("option:look-at",this);
|
||||
SceneryDefinition.forId(25578).getHandlers().put("option:look-at",this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package content.global.activity.shootingstar
|
||||
|
||||
import core.api.Container
|
||||
import core.api.*
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.plugin.Initializable
|
||||
import core.tools.RandomFunction
|
||||
import org.json.simple.JSONObject
|
||||
import org.rs09.consts.Items
|
||||
import core.ServerStore
|
||||
import core.ServerStore.Companion.getBoolean
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.secondsToTicks
|
||||
import core.tools.colorize
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Dialogue for the star sprite.
|
||||
*/
|
||||
@Initializable
|
||||
class StarSpriteDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
|
||||
|
||||
/**
|
||||
* The cosmic rune item id.
|
||||
*/
|
||||
val COSMIC_RUNE = 564
|
||||
|
||||
/**
|
||||
* The astral rune item id.
|
||||
*/
|
||||
val ASTRAL_RUNE = 9075
|
||||
|
||||
/**
|
||||
* The gold ore item id.
|
||||
*/
|
||||
val GOLD_ORE = 445
|
||||
|
||||
/**
|
||||
* The coins id.
|
||||
*/
|
||||
val COINS = 995
|
||||
|
||||
/**
|
||||
* The amplifier amount.
|
||||
*/
|
||||
val AMPLIFIER = 1.0
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the star sprite dialogue.
|
||||
*/
|
||||
fun StarSpriteDialogue() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin? {
|
||||
return StarSpriteDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any): Boolean {
|
||||
npc = args[0] as NPC
|
||||
if (inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !getAttribute(player, "star-ring:bp-shown", false)) {
|
||||
npcl(core.game.dialogue.FacialExpression.NEUTRAL, "I see you got ahold of a blueprint of those silly old rings we used to make.")
|
||||
stage = 1000
|
||||
} else if (inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && getAttribute(player, "star-ring:bp-shown", false)) {
|
||||
playerl(core.game.dialogue.FacialExpression.HALF_ASKING, "So about those rings...")
|
||||
stage = 2000
|
||||
} else if (getStoreFile().getBoolean(player.username.toLowerCase()) || !player.getInventory().contains(ShootingStarPlugin.STAR_DUST, 1)) {
|
||||
npc("Hello, strange creature.")
|
||||
stage = 0
|
||||
} else {
|
||||
npc("Thank you for helping me out of here.")
|
||||
stage = 50
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
when (stage) {
|
||||
0 -> {
|
||||
npc("I'm a star sprite! I Was in my star in the sky, when it", "lost control and crashed into the ground. With half my", "star sticking into the ground, I became stuck.", "Fortunately, I was mined out by the kind creatures of")
|
||||
stage++
|
||||
}
|
||||
1 -> {
|
||||
npc("your race.")
|
||||
stage++
|
||||
}
|
||||
2 -> {
|
||||
options("What's a star sprite?", "What are you going to do without your star?", "I thought stars were huge balls of burning gas.", "Well, I'm glad you're okay.")
|
||||
stage++
|
||||
}
|
||||
3 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("What's a star sprite?")
|
||||
stage = 10
|
||||
}
|
||||
2 -> {
|
||||
player("What are you going to do without your star?")
|
||||
stage = 20
|
||||
}
|
||||
3 -> {
|
||||
player("I thought stars were huge balls of burning gas.")
|
||||
stage = 30
|
||||
}
|
||||
4 -> {
|
||||
player("Well, I'm glad you're okay.")
|
||||
stage = 40
|
||||
}
|
||||
}
|
||||
10 -> {
|
||||
npc("We're what makes the stars in the sky shine. I made", "this star shine when it was in the sky.")
|
||||
stage++
|
||||
}
|
||||
11 -> {
|
||||
options("What are you going to do without your star?", "I thought stars were huge balls of burning gas.", "Well, I'm glad you're okay.")
|
||||
stage++
|
||||
}
|
||||
12 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("What are you going to do without your star?")
|
||||
stage = 20
|
||||
}
|
||||
2 -> {
|
||||
player("I thought stars were huge balls of burning gas.")
|
||||
stage = 30
|
||||
}
|
||||
3 -> {
|
||||
player("Well, I'm glad you're okay.")
|
||||
stage = 40
|
||||
}
|
||||
}
|
||||
20 -> {
|
||||
npc("Don't worry about me. I'm sure I'll find some good", "rocks around here and get back up into the sky in no", "time.")
|
||||
stage++
|
||||
}
|
||||
21 -> {
|
||||
options("What's a star sprite?", "I thought stars were huge balls of burning gas.", "Well, I'm glad you're okay.")
|
||||
stage++
|
||||
}
|
||||
22 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("What's a star sprite?")
|
||||
stage = 10
|
||||
}
|
||||
2 -> {
|
||||
player("I thought stars were huge balls of burning gas.")
|
||||
stage = 30
|
||||
}
|
||||
3 -> {
|
||||
player("Well, I'm glad you're okay.")
|
||||
stage = 40
|
||||
}
|
||||
}
|
||||
30 -> {
|
||||
npc("Most of them are, but a lot of shooting stars on this", "plane of the multiverse are rocks with star sprites in", "them.")
|
||||
stage++
|
||||
}
|
||||
31 -> {
|
||||
options("What's a star sprite?", "What are you going to do without your star?", "Well, I'm glad you're okay.")
|
||||
stage++
|
||||
}
|
||||
32 -> when (buttonId) {
|
||||
1 -> {
|
||||
player("What's a star sprite?")
|
||||
stage = 10
|
||||
}
|
||||
2 -> {
|
||||
player("What are you going to do without your star?")
|
||||
stage = 20
|
||||
}
|
||||
3 -> {
|
||||
player("Well, I'm glad you're okay.")
|
||||
stage = 40
|
||||
}
|
||||
}
|
||||
40 -> {
|
||||
npc("Thank you.")
|
||||
stage++
|
||||
}
|
||||
41 -> end()
|
||||
50 -> {
|
||||
val wearingRing = inEquipment(player, Items.RING_OF_THE_STAR_SPRITE_14652)
|
||||
val dust = if (player.getInventory().getAmount(ShootingStarPlugin.STAR_DUST) > 200) 200 else player.getInventory().getAmount(ShootingStarPlugin.STAR_DUST)
|
||||
if (player.getInventory().remove(Item(ShootingStarPlugin.STAR_DUST, dust))) {
|
||||
val cosmicRunes = (Math.ceil(0.76 * dust) * AMPLIFIER).toInt()
|
||||
val astralRunes = (Math.ceil(0.26 * dust) * AMPLIFIER).toInt()
|
||||
val goldOre = (Math.ceil(0.1 * dust) * AMPLIFIER).toInt()
|
||||
val coins = (Math.ceil(250.0 * dust) * AMPLIFIER).toInt() // limits the amount of gp per turn-in to 90k, same as 2009 rs, and minimum from all stardust from a level 1 star works out to 50k, same as rs in 2009
|
||||
player.getInventory().add(Item(COSMIC_RUNE, cosmicRunes), player)
|
||||
player.getInventory().add(Item(ASTRAL_RUNE, astralRunes), player)
|
||||
player.getInventory().add(Item(GOLD_ORE, goldOre), player)
|
||||
player.getInventory().add(Item(COINS, coins), player)
|
||||
npc("I have rewarded you by making it so you can mine", "extra ore for the next 15 minutes. Also, have $cosmicRunes", "cosmic runes, $astralRunes astral runes, $goldOre gold ore and $coins", "coins.")
|
||||
|
||||
getStoreFile()[player.username.toLowerCase()] = true //flag daily as completed
|
||||
|
||||
player.registerState("shooting-star")?.init()
|
||||
|
||||
if(wearingRing){
|
||||
val item = intArrayOf(Items.COSMIC_RUNE_564, Items.ASTRAL_RUNE_9075, Items.GOLD_ORE_445, Items.COINS_995).random()
|
||||
val amount = when(item){
|
||||
Items.COSMIC_RUNE_564 -> cosmicRunes
|
||||
Items.ASTRAL_RUNE_9075 -> astralRunes
|
||||
Items.GOLD_ORE_445 -> goldOre
|
||||
Items.COINS_995 -> coins
|
||||
else -> 0
|
||||
}
|
||||
rollForRingBonus(player, item, amount)
|
||||
}
|
||||
}
|
||||
|
||||
if(!inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !inBank(player, Items.ANCIENT_BLUEPRINT_14651) && RandomFunction.roll(500)){
|
||||
addItemOrDrop(player, Items.ANCIENT_BLUEPRINT_14651, 1)
|
||||
sendMessage(player, colorize("%RThe Star Sprite dropped what looks like some ancient piece of paper and you pick it up."))
|
||||
sendNews("${player.username} found an Ancient Blueprint while mining a shooting star!")
|
||||
}
|
||||
stage = 52
|
||||
}
|
||||
52 -> end()
|
||||
|
||||
//Inauthentic ring-based dialogue
|
||||
1000 -> playerl(core.game.dialogue.FacialExpression.ASKING, "Oh, you mean this?").also { stage++ }
|
||||
1001 -> player.dialogueInterpreter.sendItemMessage(Items.ANCIENT_BLUEPRINT_14651, "You show the blueprint to the Star Sprite.").also { stage++ }
|
||||
1002 -> npcl(core.game.dialogue.FacialExpression.ASKING, "Yeah, that's the one, alright!").also { stage++ }
|
||||
1003 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "I'll tell you what.. if you can get ahold of the resources needed to make one, I'm sure me or one of my kin would craft it for you.").also { stage++ }
|
||||
1004 -> playerl(core.game.dialogue.FacialExpression.ASKING, "You'd just do that for me? For free?").also { stage++ }
|
||||
1005 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "I don't see why not. We used to make these for fun and hand them out to adventurers all the time.").also { stage++ }
|
||||
1006 -> playerl(core.game.dialogue.FacialExpression.ASKING, "Well, thanks! So.. what do we need to make one?").also { stage++ }
|
||||
1007 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Looking at the blueprint here...").also { stage++ }
|
||||
1008 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Yes, it seems we need a ring mould, a silver bar, a cut dragonstone and 200 stardust. Oh, and make sure to bring this blueprint with you.").also { stage++ }
|
||||
1009 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Thanks, I'll get right on it!").also { stage++ }
|
||||
1010 -> playerl(core.game.dialogue.FacialExpression.ASKING, "So just to make sure I've got it right, I need a ring mould, a silver bar, a cut dragonstone and 200 stardust, as well as this blueprint?").also { stage++ }
|
||||
1011 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Yeah, you've got it, human. Any of my kin should be able to do this for you.").also { stage++; setAttribute(player, "/save:star-ring:bp-shown", true) }
|
||||
1012 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Thanks!").also { stage = END_DIALOGUE }
|
||||
|
||||
2000 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Yes, did you bring the components to make it, human?").also { stage++ }
|
||||
2001 -> if(inInventory(player, Items.DRAGONSTONE_1615,1) && inInventory(player, Items.RING_MOULD_1592, 1) && inInventory(player, Items.STARDUST_13727, 200) && inInventory(player, Items.SILVER_BAR_2355, 1)){
|
||||
playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Yes, I have them right here, friend.").also { stage++ }
|
||||
} else {
|
||||
playerl(core.game.dialogue.FacialExpression.HALF_GUILTY, "I'm afraid not, what did I need again?").also { stage = 2100 }
|
||||
}
|
||||
2002 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Excellent, give me just a moment here...").also { stage++ }
|
||||
2003 -> sendDialogue("You watch as the Star Sprite casts some strange spell.").also { stage++ }
|
||||
2004 -> if(removeItem(player, Items.SILVER_BAR_2355, Container.INVENTORY) && removeItem(player, Items.DRAGONSTONE_1615, Container.INVENTORY) && removeItem(player, Item(Items.STARDUST_13727, 200), Container.INVENTORY)){
|
||||
addItem(player, Items.RING_OF_THE_STAR_SPRITE_14652)
|
||||
player.dialogueInterpreter.sendItemMessage(Items.RING_OF_THE_STAR_SPRITE_14652, "The Star Sprite hands you a strange ring.").also { stage++ }
|
||||
} else end()
|
||||
2005 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "There you go, I hope you enjoy it!").also { stage++ }
|
||||
2006 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Thank you!").also { stage = END_DIALOGUE }
|
||||
|
||||
2100 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL, "A ring mould, a cut dragonstone, a silver bar and 200 stardust.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray? {
|
||||
return intArrayOf(8091)
|
||||
}
|
||||
|
||||
fun rollForRingBonus(player: Player, bonusId: Int, bonusBaseAmt: Int){
|
||||
if(RandomFunction.roll(3)){
|
||||
val state = player.states["shooting-star"] as? ShootingStarState ?: return
|
||||
state.ticksLeft += secondsToTicks(TimeUnit.MINUTES.toSeconds(5).toInt())
|
||||
sendMessage(player, colorize("%RYour ring shines dimly as if imbued with energy."))
|
||||
} else if(RandomFunction.roll(5)){
|
||||
addItem(player, bonusId, bonusBaseAmt)
|
||||
sendMessage(player, colorize("%RYour ring shines brightly as if surging with energy and then fades out."))
|
||||
} else if(RandomFunction.roll(25)){
|
||||
getStoreFile()[player.username.toLowerCase()] = false //flag daily as uncompleted
|
||||
sendMessage(player, colorize("%RYour ring vibrates briefly as if surging with power, and then stops."))
|
||||
}
|
||||
}
|
||||
|
||||
fun getStoreFile(): JSONObject{
|
||||
return ServerStore.getArchive("daily-shooting-star")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.container.access.InterfaceContainer;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.world.GameWorld;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import core.api.IfaceSettingsBuilder;
|
||||
|
||||
import core.game.system.config.ClueRewardParser;
|
||||
|
||||
import static core.api.ContentAPIKt.addItemOrDrop;
|
||||
|
||||
/**
|
||||
* A clue scroll level.
|
||||
*/
|
||||
public enum ClueLevel {
|
||||
EASY(Items.CASKET_2714, 1, 5),
|
||||
MEDIUM(Items.CASKET_2717, 1, 6),
|
||||
HARD(Items.CASKET_2720, 1, 8),
|
||||
UNKNOWN(0, 0, 0)
|
||||
;
|
||||
|
||||
public int casketId, minSteps, maxSteps;
|
||||
|
||||
private ClueLevel(int casketId, int minSteps, int maxSteps) {
|
||||
this.casketId = casketId;
|
||||
this.minSteps = minSteps;
|
||||
this.maxSteps = maxSteps;
|
||||
}
|
||||
|
||||
private static ClueLevel getLevelForCasket(Item casket) {
|
||||
switch (casket.getId()) {
|
||||
case Items.CASKET_2714:
|
||||
return ClueLevel.EASY;
|
||||
case Items.CASKET_2717:
|
||||
return ClueLevel.MEDIUM;
|
||||
case Items.CASKET_2720:
|
||||
return ClueLevel.HARD;
|
||||
}
|
||||
|
||||
return ClueLevel.UNKNOWN;
|
||||
}
|
||||
|
||||
public static void open(Player player, Item casket) {
|
||||
if (casket == null || !player.getInventory().containsItem(casket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreasureTrailManager playerTrails = TreasureTrailManager.getInstance(player);
|
||||
|
||||
boolean trailCompleted = playerTrails.isCompleted();
|
||||
boolean isDevMode = GameWorld.getSettings().isDevMode();
|
||||
|
||||
ClueLevel clueLevel = getLevelForCasket(casket);
|
||||
|
||||
if (trailCompleted || isDevMode) {
|
||||
List<Item> rewards = rollLoot(player, clueLevel);
|
||||
|
||||
player.getInterfaceManager().open(new Component(364));
|
||||
|
||||
if (player.getInventory().remove(casket)) {
|
||||
long rewardValue = 0L;
|
||||
|
||||
for (Item reward : rewards) {
|
||||
addItemOrDrop(player, reward.getId(), reward.getAmount());
|
||||
rewardValue += reward.getValue();
|
||||
}
|
||||
|
||||
playerTrails.incrementClues(clueLevel);
|
||||
playerTrails.clearTrail();
|
||||
|
||||
player.sendMessage("Well done, you've completed the Treasure Trail!");
|
||||
player.sendMessage(
|
||||
getChatColor(clueLevel)
|
||||
+ "You have completed "
|
||||
+ playerTrails.getCompletedClues(clueLevel)
|
||||
+ " "
|
||||
+ clueLevel.getName().toLowerCase()
|
||||
+ " clues."
|
||||
);
|
||||
|
||||
player.sendMessage(
|
||||
"<col=990000>Your clue is worth approximately "
|
||||
+ NumberFormat.getInstance().format(rewardValue)
|
||||
+ " coins!</col>"
|
||||
);
|
||||
|
||||
int clueIfaceSettings = new IfaceSettingsBuilder().enableAllOptions().build();
|
||||
player.getPacketDispatch().sendIfaceSettings(clueIfaceSettings, 4, 364, 0, 6);
|
||||
InterfaceContainer.generateItems(
|
||||
player,
|
||||
rewards.toArray(new Item[] {}),
|
||||
new String[] {""},
|
||||
364, 4, 3, 3
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Item newClue = ClueScrollPlugin.getClue(clueLevel);
|
||||
|
||||
if (casket != null && player.getInventory().remove(casket, casket.getSlot(), true)) {
|
||||
player.getInventory().replace(newClue, casket.getSlot());
|
||||
} else {
|
||||
player.getInventory().add(newClue);
|
||||
}
|
||||
|
||||
playerTrails.setClueId(newClue.getId());
|
||||
player.getDialogueInterpreter().sendItemMessage(newClue, "You've found another clue!");
|
||||
}
|
||||
|
||||
public static List<Item> rollLoot(Player player, ClueLevel level) {
|
||||
ArrayList<Item> loot = new ArrayList();
|
||||
int itemCount = RandomFunction.random(1,6);
|
||||
|
||||
if (level == ClueLevel.HARD) {
|
||||
itemCount = Math.max(itemCount, RandomFunction.random(4,6));
|
||||
}
|
||||
|
||||
for (; itemCount > 0; itemCount--) {
|
||||
switch (level) {
|
||||
case EASY:
|
||||
loot.addAll(ClueRewardParser.getEasyTable().roll());
|
||||
break;
|
||||
case MEDIUM:
|
||||
loot.addAll(ClueRewardParser.getMedTable().roll());
|
||||
break;
|
||||
case HARD:
|
||||
loot.addAll(ClueRewardParser.getHardTable().roll());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == ClueLevel.HARD && RandomFunction.random(100) == 50) {
|
||||
loot.addAll(ClueRewardParser.getRareTable().roll());
|
||||
}
|
||||
|
||||
return loot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Chat color to send on completed clues.
|
||||
* @param level The clue level.
|
||||
* @return the chat color.
|
||||
*/
|
||||
public static String getChatColor(ClueLevel level) {
|
||||
if (level == ClueLevel.HARD) {
|
||||
return "<col=ff1a1a>";
|
||||
}
|
||||
if (level == ClueLevel.MEDIUM) {
|
||||
return "<col=b38f00>";
|
||||
}
|
||||
return "<col=00e673>";
|
||||
}
|
||||
/**
|
||||
* Gets the maximum length.
|
||||
*
|
||||
* @return the length.
|
||||
*/
|
||||
public int getMaximumLength() {
|
||||
return maxSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum length.
|
||||
*
|
||||
* @return the length.
|
||||
*/
|
||||
public int getMinimumLength() {
|
||||
return minSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bcasket.
|
||||
*
|
||||
* @return the casket
|
||||
*/
|
||||
public Item getCasket() {
|
||||
return new Item(casketId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the clue level.
|
||||
* @return the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.tools.SystemLogger;
|
||||
import core.game.world.map.zone.MapZone;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.world.map.zone.ZoneBuilder;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a clue scroll plugin.
|
||||
* @author Vexia
|
||||
*/
|
||||
public abstract class ClueScrollPlugin extends MapZone implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* The wilderness cape ids.
|
||||
*/
|
||||
protected static final int[] WILDY_CAPES = new int[] { 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 10638 };
|
||||
|
||||
/**
|
||||
* The mapping of clue scrolls.
|
||||
*/
|
||||
private static final Map<Integer, ClueScrollPlugin> CLUE_SCROLLS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A map of pre organized clue scrolls.
|
||||
*/
|
||||
private static final Map<ClueLevel, List<ClueScrollPlugin>> ORGANIZED = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The id of the clue scroll.
|
||||
*/
|
||||
protected final int clueId;
|
||||
|
||||
/**
|
||||
* The clue scroll level.
|
||||
*/
|
||||
protected final ClueLevel level;
|
||||
|
||||
/**
|
||||
* The interface id of the clue.
|
||||
*/
|
||||
protected final int interfaceId;
|
||||
|
||||
/**
|
||||
* The zone borders.
|
||||
*/
|
||||
protected final ZoneBorders[] borders;
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code ClueScrollPlugin} {@Code Object}
|
||||
* @param clueId the id.
|
||||
* @param level the level.
|
||||
* @param interfaceId the id.
|
||||
*/
|
||||
public ClueScrollPlugin(final String name, final int clueId, ClueLevel level, final int interfaceId, final ZoneBorders... borders) {
|
||||
super(name, true);
|
||||
this.clueId = clueId;
|
||||
this.level = level;
|
||||
this.interfaceId = interfaceId;
|
||||
this.borders = borders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewards the player with a casket.
|
||||
* @param player the player.
|
||||
* @param casket if we give a casket.
|
||||
*/
|
||||
public void reward(Player player, boolean casket) {
|
||||
Item clue = player.getInventory().getItem(new Item(getClueId()));
|
||||
if (clue == null) {
|
||||
return;
|
||||
}
|
||||
nextStage(player, clue);
|
||||
if (casket) {
|
||||
player.getInventory().replace(level.getCasket(), clue.getSlot());
|
||||
} else {
|
||||
player.getInventory().remove(clue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewards the player.
|
||||
* @param player the player.
|
||||
*/
|
||||
public void reward(Player player) {
|
||||
reward(player, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the next stage of the clue.
|
||||
* @param player the player.
|
||||
* @param clue the clue.
|
||||
*/
|
||||
public void nextStage(Player player, Item clue) {
|
||||
if (!TreasureTrailManager.getInstance(player).hasTrail() || TreasureTrailManager.getInstance(player).hasTrail() && clue.getId() != TreasureTrailManager.getInstance(player).getClueId()) {
|
||||
TreasureTrailManager.getInstance(player).startTrail(this);
|
||||
}
|
||||
int currentStage = TreasureTrailManager.getInstance(player).getTrailStage();
|
||||
if (currentStage >= TreasureTrailManager.getInstance(player).getTrailLength()) {
|
||||
TreasureTrailManager.getInstance(player).clearTrail();
|
||||
} else {
|
||||
TreasureTrailManager.getInstance(player).incrementStage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a clue scroll.
|
||||
* @param player the player.
|
||||
*/
|
||||
public void read(Player player) {
|
||||
if (player.getInterfaceManager().isOpened()) {
|
||||
player.sendMessage("Please finish what you're doing first.");
|
||||
return;
|
||||
}
|
||||
player.getInterfaceManager().open(new Component(interfaceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reigsters a clue scroll into the repository.
|
||||
* @param clue the plugin.
|
||||
*/
|
||||
public void register(ClueScrollPlugin clue) {
|
||||
if(clue.getClueId() == 2681)
|
||||
return;
|
||||
if (CLUE_SCROLLS.containsKey(clue.getClueId())) {
|
||||
SystemLogger.logErr(this.getClass(), "Error! Plugin already registered with clue id - " + clue.getClueId() + ", trying to register " + clue.getClass().getCanonicalName() + " the real plugin using the id is " + CLUE_SCROLLS.get(clue.getClueId()).getClass().getCanonicalName() + "!");
|
||||
return;
|
||||
}
|
||||
List<ClueScrollPlugin> organized = (List<ClueScrollPlugin>) ORGANIZED.get(clue.getLevel());
|
||||
if (organized == null) {
|
||||
organized = new ArrayList<>(20);
|
||||
}
|
||||
organized.add(clue);
|
||||
ZoneBuilder.configure(clue);
|
||||
CLUE_SCROLLS.put(clue.getClueId(), clue);
|
||||
ORGANIZED.put(clue.getLevel(), organized);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() {
|
||||
if (borders == null) {
|
||||
return;
|
||||
}
|
||||
for (ZoneBorders border : borders) {
|
||||
register(border);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a clue item.
|
||||
* @param clueLevel the level.
|
||||
* @return the item.
|
||||
*/
|
||||
public static Item getClue(ClueLevel clueLevel) {
|
||||
List<ClueScrollPlugin> clues = ORGANIZED.get(clueLevel);
|
||||
if (clues == null) {
|
||||
SystemLogger.logErr(ClueScrollPlugin.class, "Error! There are no clues for level " + clueLevel + "!");
|
||||
return null;
|
||||
}
|
||||
ClueScrollPlugin clue = clues.get(RandomFunction.random(clues.size()));
|
||||
return new Item(clue.getClueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has equipment.
|
||||
* @param player the player.
|
||||
* @param equipment the equipment.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasEquipment(Player player, int[][] equipment) {
|
||||
if (equipment == null || equipment.length == 0) {
|
||||
return true;
|
||||
}
|
||||
int hasAmt = 0;
|
||||
for (int i = 0; i < equipment.length; i++) {
|
||||
for (int k = 0; k < equipment[i].length; k++) {
|
||||
if (player.getEquipment().contains(equipment[i][k], 1)) {
|
||||
hasAmt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasAmt == equipment.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueId.
|
||||
* @return the clueId
|
||||
*/
|
||||
public int getClueId() {
|
||||
return clueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blevel.
|
||||
* @return the level
|
||||
*/
|
||||
public ClueLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueScrolls.
|
||||
* @return the clueScrolls
|
||||
*/
|
||||
public static Map<Integer, ClueScrollPlugin> getClueScrolls() {
|
||||
return CLUE_SCROLLS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the binterfaceId.
|
||||
* @return the interfaceId
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Initializes the coordinate clues.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class CoordinateCluePlugin extends CoordinateClueScroll {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CoordinateCluePlugin} {@code Object}
|
||||
*/
|
||||
public CoordinateCluePlugin() {
|
||||
this(null, -1, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CoordinateCluePlugin} {@code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param location the location.
|
||||
* @param clue the clue.
|
||||
*/
|
||||
public CoordinateCluePlugin(String name, int clueId, ClueLevel level, Location location, String clue) {
|
||||
super(name, clueId, level, location, clue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
register(new CoordinateCluePlugin("tree-gnome-coord", 2807, ClueLevel.MEDIUM, new Location(2478, 3158, 0), "00 degrees 05 minutes south<br>01 degrees 13 minutes east"));
|
||||
register(new CoordinateCluePlugin("karamja-coord", 2809, ClueLevel.MEDIUM, new Location(2888, 3153, 0), "00 degrees 13 minutes south<br>13 degrees 58 minutes east"));
|
||||
register(new CoordinateCluePlugin("brimhaven-coord", 2811, ClueLevel.MEDIUM, new Location(2743, 3151, 0), "00 degrees 18 minutes south<br>09 degrees 28 minutes east"));
|
||||
register(new CoordinateCluePlugin("lumbridge-swamp-coord", 2813, ClueLevel.MEDIUM, new Location(3183, 3151, 0), "00 degrees 20 minutes south<br>23 degrees 15 minutes east"));
|
||||
register(new CoordinateCluePlugin("zanaris-shed-coord", 2815, ClueLevel.MEDIUM, new Location(3217, 3178, 0), "00 degrees 30 minutes north<br>24 degrees 16 minutes east"));
|
||||
register(new CoordinateCluePlugin("port-sarim-coord", 2817, ClueLevel.MEDIUM, new Location(3007, 3145, 0), "00 degrees 31 minutes south<br>17 degrees 43 minutes east"));
|
||||
register(new CoordinateCluePlugin("musa-point-coord", 2819, ClueLevel.MEDIUM, new Location(2896, 3119, 0), "01 degrees 18 minutes south<br>14 degrees 15 minutes east"));
|
||||
register(new CoordinateCluePlugin("moss-giant-coord", 2821, ClueLevel.MEDIUM, new Location(2696, 3206, 0), "01 degrees 26 minutes north<br>08 degrees 01 minutes east"));
|
||||
register(new CoordinateCluePlugin("hazelmere-coord", 2823, ClueLevel.MEDIUM, new Location(2680, 3111, 0), "01 degrees 35 minutes south<br>07 degrees 28 minutes east"));
|
||||
register(new CoordinateCluePlugin("uzer-coord", 2825, ClueLevel.MEDIUM, new Location(3510, 3075, 0), "02 degrees 43 minutes south<br>33 degrees 26 minutes east"));
|
||||
register(new CoordinateCluePlugin("ham-coord", 2827, ClueLevel.MEDIUM, new Location(3161, 3251, 0), "02 degrees 48 minutes north<br>22 degrees 30 minutes east"));
|
||||
register(new CoordinateCluePlugin("ardy-zoo-coord", 2829, ClueLevel.MEDIUM, new Location(2644, 3251, 0), "02 degrees 50 minutes north<br>06 degrees 20 minutes east"));
|
||||
register(new CoordinateCluePlugin("nature-altar-coord", 2831, ClueLevel.HARD, new Location(2874, 3047, 0), "03 degrees 35 minutes south<br>13 degrees 35 minutes east"));
|
||||
register(new CoordinateCluePlugin("shilo-mine-coord", 2833, ClueLevel.MEDIUM, new Location(2849, 3033, 0), "04 degrees 00 minutes south<br>12 degrees 46 minutes east"));
|
||||
register(new CoordinateCluePlugin("bedapin-camp-coord", 2835, ClueLevel.HARD, new Location(3168, 3041, 0), "03 degrees 45 minutes south<br>22 degrees 45 minutes east"));
|
||||
// register(new CoordinateCluePlugin("gorad-coord", 2837,
|
||||
// ClueLevel.HARD, new Location(2580, 3029, 0),
|
||||
// "04 degrees 05 minutes south<br>04 degrees 24 minutes east"));
|
||||
register(new CoordinateCluePlugin("crandor-coord", 2839, ClueLevel.MEDIUM, new Location(2848, 3297, 0), "04 degrees 13 minutes north<br>12 degrees 45 minutes east"));
|
||||
register(new CoordinateCluePlugin("champions-guild-coord", 2841, ClueLevel.MEDIUM, new Location(3179, 3343, 0), "05 degrees 43 minutes north<br>23 degrees 05 minutes east"));
|
||||
register(new CoordinateCluePlugin("cairn-island-coord", 2843, ClueLevel.HARD, new Location(2764, 2974, 0), "05 degrees 50 minutes south<br>10 degrees 05 minutes east"));
|
||||
register(new CoordinateCluePlugin("bandit-camp-coord", 2845, ClueLevel.HARD, new Location(3139, 2969, 0), "06 degrees 00 minutes south<br>21 degrees 48 minutes east"));
|
||||
// register(new CoordinateCluePlugin("east-karamja-coord", 2847,
|
||||
// ClueLevel.HARD, new Location(2924, 2963, 0),
|
||||
// "06 degrees 11 minutes south<br>15 degrees 07 minutes east"));
|
||||
register(new CoordinateCluePlugin("three-ponds-coord", 2849, ClueLevel.MEDIUM, new Location(2383, 3369, 0), "06 degrees 31 minutes north<br>01 degrees 46 minutes west"));
|
||||
register(new CoordinateCluePlugin("draynor-manor-coord", 2851, ClueLevel.MEDIUM, new Location(3120, 3384, 0), "06 degrees 58 minutes north<br>21 degrees 16 minutes east"));
|
||||
register(new CoordinateCluePlugin("nature-spirit-coord", 2853, ClueLevel.MEDIUM, new Location(3430, 3388, 0), "07 degrees 05 minutes north<br>30 degrees 56 minutes east"));
|
||||
register(new CoordinateCluePlugin("southeast-taverly-coord", 2855, ClueLevel.MEDIUM, new Location(2920, 3404, 0), "07 degrees 33 minutes north<br>15 degrees 00 minutes east"));
|
||||
register(new CoordinateCluePlugin("swamp-coord", 2856, ClueLevel.HARD, new Location(3441, 3419, 0), "08 degrees 03 minutes north<br>31 degrees 16 minutes east"));
|
||||
register(new CoordinateCluePlugin("feldip-coord", 2857, ClueLevel.MEDIUM, new Location(2593, 2899, 0), "08 degrees 11 minutes south<br>4 degrees 48 minutes east"));
|
||||
register(new CoordinateCluePlugin("gnome-terribirds-coord", 2858, ClueLevel.MEDIUM, new Location(2387, 3435, 0), "08 degrees 33 minutes north<br>01 degrees 39 minutes west"));
|
||||
register(new CoordinateCluePlugin("north-gnome-terribirds-coord", 3490, ClueLevel.MEDIUM, new Location(2382, 3467, 0), "09 degrees 35 minutes north<br>01 degrees 50 minutes west"));
|
||||
register(new CoordinateCluePlugin("ice-mountain-coord", 3491, ClueLevel.MEDIUM, new Location(3006, 3475, 0), "09 degrees 48 minutes north<br>17 degrees 39 minutes east"));
|
||||
register(new CoordinateCluePlugin("coal-line-coord", 3492, ClueLevel.MEDIUM, new Location(2585, 3505, 0), "10 degrees 45 minutes north<br>04 degrees 31 minutes east"));
|
||||
register(new CoordinateCluePlugin("slayer-tower-coord", 3493, ClueLevel.MEDIUM, new Location(3442, 3515, 0), "11 degrees 03 minutes north<br>31 degrees 20 minutes east"));
|
||||
register(new CoordinateCluePlugin("gnome-stronghold-coord", 3494, ClueLevel.MEDIUM, new Location(2416, 3515, 0), "11 degrees 05 minutes north<br>00 degrees 45 minutes west"));
|
||||
register(new CoordinateCluePlugin("eagles-peak-coord", 3495, ClueLevel.MEDIUM, new Location(2362, 3531, 0), "11 degrees 33 minutes north<br>02 degrees 24 minutes west"));
|
||||
register(new CoordinateCluePlugin("burthorpe-coord", 3496, ClueLevel.MEDIUM, new Location(2920, 3534, 0), "11 degrees 41 minutes north<br>14 degrees 58 minutes east"));
|
||||
register(new CoordinateCluePlugin("fenkenstrain-castle-coord", 3497, ClueLevel.MEDIUM, new Location(3548, 3559, 0), "12 degrees 28 minutes north<br>34 degrees 37 minutes east"));
|
||||
register(new CoordinateCluePlugin("lvl-11-wildy-coord", 3498, ClueLevel.HARD, new Location(3113, 3602, 0), "13 degrees 46 minutes north<br>21 degrees 01 minutes east"));
|
||||
register(new CoordinateCluePlugin("swaying-tree-coord", 3499, ClueLevel.MEDIUM, new Location(2735, 3639, 0), "14 degrees 54 minutes north<br>9 degrees 13 minutes east"));
|
||||
register(new CoordinateCluePlugin("rellekka-coord", 3500, ClueLevel.MEDIUM, new Location(2680, 3652, 0), "15 degrees 22 minutes north<br>07 degrees 31 minutes east"));
|
||||
register(new CoordinateCluePlugin("trollheim-coord", 3501, ClueLevel.HARD, new Location(2892, 3674, 0), "16 degrees 03 minutes north<br>14 degrees 07 minutes east"));
|
||||
register(new CoordinateCluePlugin("graveyard-wildy-coord", 3502, ClueLevel.HARD, new Location(3229, 3687, 0), "16 degrees 07 minutes north<br>22 degrees 45 minutes east"));
|
||||
// not sure if this is accessible
|
||||
register(new CoordinateCluePlugin("troll-stronghold-coord", 3503, ClueLevel.HARD, new Location(2853, 3689, 0), "16 degrees 31 minutes north<br>12 degrees 54 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-22-wildy-coord", 3504, ClueLevel.HARD, new Location(3304, 3692, 0), "16 degrees 35 minutes north<br>27 degrees 01 minutes east"));
|
||||
register(new CoordinateCluePlugin("bandit-camp-coord", 3505, ClueLevel.HARD, new Location(3055, 3696, 0), "16 degrees 43 minutes north<br>19 degrees 13 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-23-wildy-coord", 3506, ClueLevel.HARD, new Location(3302, 3696, 0), "16 degrees 43 minutes north<br>26 degrees 56 minutes east"));
|
||||
register(new CoordinateCluePlugin("northeast-rellekka-coord", 3507, ClueLevel.HARD, new Location(2711, 3732, 0), "17 degrees 50 minutes north<br>08 degrees 30 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-29-wildy-coord", 3508, ClueLevel.HARD, new Location(2970, 3749, 0), "18 degrees 22 minutes north<br>16 degrees 33 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-31-wildy-coord", 3509, ClueLevel.HARD, new Location(3034, 3804, 0), "18 degrees 50 minutes north<br>20 degrees 26 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-35-wildy-coord", 3510, ClueLevel.HARD, new Location(3244, 3792, 0), "19 degrees 43 minutes north<br>25 degrees 07 minutes east"));
|
||||
register(new CoordinateCluePlugin("level-36-wildy-coord", 3512, ClueLevel.HARD, new Location(3139, 3803, 0), "20 degrees 05 minutes north<br>21 degrees 52 minutes east"));
|
||||
register(new CoordinateCluePlugin("kbd-wildy-coord", 3513, ClueLevel.HARD, new Location(3014, 3847, 0), "21 degrees 24 minutes north<br>17 degrees 54 minutes east"));
|
||||
register(new CoordinateCluePlugin("chaos-temple-wildy-coord", 3514, ClueLevel.HARD, new Location(2946, 3818, 0), "20 degrees 33 minutes north<br>15 degrees 48 minutes east"));
|
||||
register(new CoordinateCluePlugin("rune-rocks-wildy-coord", 3515, ClueLevel.HARD, new Location(3059, 3884, 0), "22 degrees 35 minutes north<br>19 degrees 18 minutes east"));
|
||||
register(new CoordinateCluePlugin("demonic-ruins-wildy-coord", 3516, ClueLevel.HARD, new Location(3290, 3889, 0), "22 degrees 45 minutes north<br>26 degrees 33 minutes east"));
|
||||
register(new CoordinateCluePlugin("rogues-castle-coord", 3518, ClueLevel.HARD, new Location(3285, 3943, 0), "24 degrees 24 minutes north<br>26 degrees 24 minutes east"));
|
||||
register(new CoordinateCluePlugin("wildy-lever-coord", 3520, ClueLevel.HARD, new Location(3158, 3958, 0), "24 degrees 56 minutes north<br>22 degrees 28 minutes east"));
|
||||
register(new CoordinateCluePlugin("pirates-hideout-coord", 3522, ClueLevel.HARD, new Location(3040, 3961, 0), "24 degrees 58 minutes north<br>18 degrees 43 minutes east"));
|
||||
register(new CoordinateCluePlugin("agility-wildy-coord", 3524, ClueLevel.HARD, new Location(2987, 3964, 0), "25 degrees 03 minutes north<br>17 degrees 05 minutes east"));
|
||||
register(new CoordinateCluePlugin("axe-hut-coord", 3525, ClueLevel.HARD, new Location(3190, 3963, 0), "25 degrees 03 minutes north<br>23 degrees 24 minutes east"));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents a coordinate clue scroll.
|
||||
* @author Vexia
|
||||
*/
|
||||
public abstract class CoordinateClueScroll extends MapClueScroll {
|
||||
|
||||
/**
|
||||
* The sextant item.
|
||||
*/
|
||||
public static final Item SEXTANT = new Item(2574);
|
||||
|
||||
/**
|
||||
* The watch item.
|
||||
*/
|
||||
public static final Item WATCH = new Item(2575);
|
||||
|
||||
/**
|
||||
* The chart item.
|
||||
*/
|
||||
public static final Item CHART = new Item(2576);
|
||||
|
||||
/**
|
||||
* The clock tower location.
|
||||
*/
|
||||
public static final Location CLOCK_TOWER = new Location(2440, 3161, 0);
|
||||
|
||||
/**
|
||||
* The clue message.
|
||||
*/
|
||||
private final String clue;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CoordinateClueScroll} {@code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param location the location.
|
||||
* @param clue the clue.
|
||||
*/
|
||||
public CoordinateClueScroll(String name, int clueId, ClueLevel level, Location location, String clue) {
|
||||
super(name, clueId, level, 345, location, 0);
|
||||
this.clue = clue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Player player) {
|
||||
for (int i = 1; i < 9; i++) {
|
||||
player.getPacketDispatch().sendString("", interfaceId, i);
|
||||
}
|
||||
super.read(player);
|
||||
player.getPacketDispatch().sendString("<br><br><br><br><br>" + clue.replace("<br>", "<br><br>"), interfaceId, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dig(Player player) {
|
||||
int killedWizardClueId = player.getAttribute("killed-wizard", -1);
|
||||
if (getLevel() == ClueLevel.HARD && (killedWizardClueId == -1 || killedWizardClueId != getClueId())) {
|
||||
NPC wizard = player.getAttribute("t-wizard", null);
|
||||
if (wizard != null && wizard.isActive()) {
|
||||
return;
|
||||
}
|
||||
spawnWizard(player);
|
||||
return;
|
||||
}
|
||||
super.dig(player);
|
||||
player.removeAttribute("killed-wizard");
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a zamorak or saradomin wizard.
|
||||
* @param player the player.
|
||||
*/
|
||||
private void spawnWizard(Player player) {
|
||||
int id = !player.getSkullManager().isWilderness() ? 1264 : 1007;
|
||||
final NPC wizard = NPC.create(id, player.getLocation().transform(1, 0, 0));
|
||||
player.setAttribute("t-wizard", wizard);
|
||||
wizard.setAttribute("clue", this);
|
||||
wizard.setAttribute("player", player);
|
||||
wizard.init();
|
||||
wizard.graphics(Graphics.create(86));
|
||||
wizard.faceTemporary(player, 1);
|
||||
wizard.sendChat(id == 1264 ? "For Saradomin!" : "Die human!");
|
||||
wizard.getProperties().getCombatPulse().attack(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clue.
|
||||
* @return the clue
|
||||
*/
|
||||
public String getClue() {
|
||||
return clue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.node.entity.player.link.emote.Emotes;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Initializes the emote clue plugins.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class EmoteCluePlugin extends EmoteClueScroll {
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code EmoteCluePlugin} {@Code Object}
|
||||
*/
|
||||
public EmoteCluePlugin() {
|
||||
super(null, -1, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code EmoteCluePlugin} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param emote the Emotes.
|
||||
* @param commenceEmote the commence Emotes.
|
||||
* @param equipment the equipment.
|
||||
* @param clue the clue.
|
||||
* @param borders the borders.
|
||||
*/
|
||||
public EmoteCluePlugin(String name, int clueId, ClueLevel level, Emotes emote, Emotes commenceEmote, int[][] equipment, String clue, ZoneBorders... borders) {
|
||||
super(name, clueId, level, emote, commenceEmote, equipment, clue, borders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code EmoteCluePlugin} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param emote the Emotes.
|
||||
* @param equipment the equipment.
|
||||
* @param clue the clue.
|
||||
* @param borders the borders.
|
||||
*/
|
||||
public EmoteCluePlugin(String name, int clueId, ClueLevel level, Emotes emote, int[][] equipment, String clue, ZoneBorders... borders) {
|
||||
super(name, clueId, level, emote, null, equipment, clue, borders);
|
||||
}
|
||||
|
||||
// register(new EmoteCluePlugin(clue, clueId, level, commenceEmote,
|
||||
// commenceEmote, equipment, clue, borders));
|
||||
// register(new EmoteCluePlugin(clue, clueId, level, commenceEmote,
|
||||
// equipment, clue, borders));
|
||||
// register(new EmoteCluePlugin());
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
Emotes emote = Emotes.BECKON;
|
||||
register(new EmoteCluePlugin("digsite-beckon", 2677, ClueLevel.MEDIUM, emote, Emotes.BOW, new int[][] { { 6328 }, { 1267 }, { 658 } }, "Beckon in the Digsite, near the<br>eastern winch. Bow or curtsy<br>before you talk to me.<br>Equip a green gnome hat,<br>snakeskin boots and an<br>iron pickaxe.", new ZoneBorders(3368, 3425, 3371, 3429)));
|
||||
register(new EmoteCluePlugin("tai-bwo-beckon", 2678, ClueLevel.MEDIUM, emote, Emotes.CLAP, new int[][] { { 1099 }, { 2552, 2554, 2556, 2558, 2560, 2562, 2564, 2568 }, { 1143 } }, "Beckon in Tai Bwo<br>Wannai. Clap before<br>you talk to me.<br>Equip green<br>dragonhide chaps, a<br>ring of dueling and a<br>mithril medium helmet.", new ZoneBorders(2771, 3053, 2814, 3074)));
|
||||
emote = Emotes.BLOW_KISS;
|
||||
//register(new EmoteCluePlugin("shilo-kiss", 2681, ClueLevel.HARD, emote, new int[][] { { 4089 }, { 5016 }, { 1127 } }, "Blow a kiss between<br>the tables in Shilo<br>Village bank. Beware<br>of double agents!<br>Equip a blue mystic<br>hat, bone spear and<br>rune plate body.", new ZoneBorders(2849, 2950, 2855, 2957)));
|
||||
emote = Emotes.BOW;
|
||||
register(new EmoteCluePlugin("legends-guild", 2682, ClueLevel.EASY, emote, new int[][] { { 1067 }, { 1696 }, { 845 } }, "Bow outside the entrance<br>to the Legends' Guild.<br>Equip iron platelegs, an<br>emerald amulet and an oak<br>longbow.", new ZoneBorders(2726, 3346, 2731, 3349)));
|
||||
emote = Emotes.RASPBERRY;
|
||||
register(new EmoteCluePlugin("monkey-cage", 2679, ClueLevel.EASY, emote, new int[][] { { 1133 }, { 1075 }, { 1379 } }, "Blow a raspberry at the<br>monkey cage in<br>Ardougne Zoo.<br>Equip a studded<br>leather body, bronze<br>platelegs and a normal<br>staff with no orb.", new ZoneBorders(2597, 3274, 2609, 3284)));
|
||||
register(new EmoteCluePlugin("keep-le-faye", 2680, ClueLevel.EASY, emote, new int[][] { { 1169 }, { 1115 }, { 1059 } }, "Blow raspberries out<br>the entrance to Keep Le<br>Faye.<br>Equip a coif, an iron<br>platebody and leather<br>gloves.", new ZoneBorders(2759, 3401, 2762, 3403)));
|
||||
// register(new EmoteCluePlugin("fishing-guild-blow", 2683,
|
||||
// ClueLevel.HARD, emote, new int[][] {{2890}, {2493}, {1347}},
|
||||
// "Blow a raspberry in the<br>Fighing Guild bank. Beware<br>of double agents!<br>Equip and elemental shield<br>,blue dragonhide chaps<br>and a rune warhammer.",
|
||||
// new ZoneBorders(2586, 3418, 2590, 3422)));
|
||||
emote = Emotes.CHEER;
|
||||
register(new EmoteCluePlugin("druid-circle-cheer", 2684, ClueLevel.EASY, emote, new int[][] { { 4310 }, { 579 }, { 1307 } }, "Cheer at the Druids'<br>Circle.<br>Equip a blue wizard<br>hat, a bronze<br>two-handed sword and<br>HAM boots.", new ZoneBorders(2920, 3478, 2930, 3940)));
|
||||
register(new EmoteCluePlugin("games-room-cheer", 2685, ClueLevel.EASY, emote, new int[][] {}, "Cheer at the games<br>room.<br>Have nothing equipped<br>at all when you do.", new ZoneBorders(2194, 4946, 2221, 4973)));
|
||||
register(new EmoteCluePlugin("barb-agility-cheer", 2686, ClueLevel.MEDIUM, emote, new int[][] { { 1119 }, { 853 }, { 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 10638 } }, "Cheer in the Barbarian<br>Agility Arena.<br>Headbang before you<br>talk to me.<br>Equip a steel plate<br>body, maple shortbow, and a wilderness<br>cape.", new ZoneBorders(2550, 3556, 2553, 3559), new ZoneBorders(2529, 3542, 2553, 3559)));
|
||||
register(new EmoteCluePlugin("edge-gen-cheer", 2687, ClueLevel.MEDIUM, emote, Emotes.DANCE, new int[][] { { 1757 }, { 1061 }, { 1059 } }, "Cheer in the Edgeville general<br>store. Dance<br>before you talk to me.<br>Equip a brown apron,<br>leather boots and<br>leather gloves.", new ZoneBorders(3076, 3507, 3084, 3513)));
|
||||
register(new EmoteCluePlugin("ogre-pen-cheer", 2688, ClueLevel.MEDIUM, emote, Emotes.ANGRY, new int[][] { { 1135 }, { 1099 }, { 1177 } }, "Cheer in the Ogre Pen<br>in the Training Camp.<br>Show you are angry<br>before you talk to me.<br>Equip a green<br>dragonhide body and<br>chaps and a steel<br>square shield.", new ZoneBorders(2523, 3373, 2533, 3377)));
|
||||
emote = Emotes.CLAP;
|
||||
register(new EmoteCluePlugin("exam-room-clap", 2689, ClueLevel.EASY, emote, new int[][] { { 1005 }, { 628 }, { 1059 } }, "Clap in the main exam room<br>in the Exam Centre.<br>Equip a white apron, green<br>gnome boots and leather<br>gloves.", new ZoneBorders(3357, 3332, 3367, 3348)));
|
||||
register(new EmoteCluePlugin("wizard-tower-clap", 2690, ClueLevel.EASY, emote, new int[][] { { 1137 }, { 1639 }, { 1005 } }, "Clap on the causeway to the<br>Wizards' Tower.<br>Equip an iron medium<br>helmet, emerald ring and a<br>white apron.", new ZoneBorders(3112, 3173, 3115, 3206)));
|
||||
// 2nd plane for ardy mill
|
||||
register(new EmoteCluePlugin("ardgoune-mill-clap", 2691, ClueLevel.EASY, emote, new int[][] { { 640 }, { 4300 }, { 5525 } }, "Clap on the top level of the<br>mill, north of East Ardougne.<br>Equip a blue gnome robe top,<br>HAM robe bottom and an<br>unenchanted tiara.", new ZoneBorders(2628, 3382, 2636, 3390, 2)));
|
||||
register(new EmoteCluePlugin("seers-court-clap", 2692, ClueLevel.MEDIUM, emote, Emotes.SPIN, new int[][] { { 3200 }, { 4093 }, { 1643 } }, "Clap in Seers court house.<br>Spin before you talk to me.<br>Equip an adamant halberd,<br>blue mystic robe bottom and<br>a diamond ring.", new ZoneBorders(2732, 3467, 2739, 3471)));
|
||||
//Fix clue remove vexia
|
||||
//emote = Emotes.CRY;
|
||||
register(new EmoteCluePlugin("catherby-range-cry", 2693, ClueLevel.MEDIUM, Emotes.CRY, Emotes.BOW, new int[][] { { 630 }, { 1131 }, { 2961 } }, "Cry in the Catherby<br>Ranging shop. Bow before you talk to me.<br>Equip blue gnome<br>boots, a hard leather<br>body and an<br>unblessed silver<br>sickle.", new ZoneBorders(2821, 3441, 2825, 3445)));
|
||||
register(new EmoteCluePlugin("catherby-shore-cry", 2694, ClueLevel.MEDIUM, Emotes.CRY, Emotes.LAUGH, new int[][] { { 1183 }, { 8872 }, { 1121 } }, "Cry on the shore of<br>Catherby beach.<br>Laugh before you talk to me.<br>Equip an adamant sq<br>shield, a bone dagger<br>and mithril platebody.", new ZoneBorders(2849, 3423, 2857, 3430), new ZoneBorders(2845, 3428, 2852, 3430)));
|
||||
emote = Emotes.DANCE;
|
||||
register(new EmoteCluePlugin("draynor-cross-dance", 2695, ClueLevel.EASY, emote, new int[][] { { 1101 }, { 1637 }, { 839 } }, "Dance at the<br>crossroads north of<br>Draynor.<br>Equip an iron chain<br>body, a sapphire ring<br>and a longbow.", new ZoneBorders(3109, 3293, 3110, 3296), new ZoneBorders(3108, 3294, 3111, 3295)));
|
||||
register(new EmoteCluePlugin("fally-party-dance", 2696, ClueLevel.EASY, emote, new int[][] { { 1157 }, { 1119 }, { 1081 } }, "Dance in the Party<br>Room.<br>Equip a steel full<br>helmet, steel<br>platebody and an iron<br>plateskirt.", new ZoneBorders(3041, 3372, 3050, 3384), new ZoneBorders(3051, 3371, 3054, 3385), new ZoneBorders(3073, 3371, 3040, 3385)));
|
||||
register(new EmoteCluePlugin("fish-guild-jig", 2697, ClueLevel.EASY, Emotes.JIG, new int[][] { { 1639 }, { 1694 }, { 1103 } }, "Dance a jig by the<br>entrance to the<br>Fishing Guild.<br>Equip an emerald ring,<br>a sapphire amulet,<br>and a bronze chain<br>body.", new ZoneBorders(2610, 3392, 2612, 3393)));
|
||||
register(new EmoteCluePlugin("lumb-shack-dance", 2698, ClueLevel.EASY, emote, new int[][] { { 1205 }, { 1153 }, { 1635 } }, "Dance in<br>the shack in Lumbridge Swamp.<br>Equip a bronze<br>dagger, iron full helmet<br>and a gold ring.", new ZoneBorders(3202, 3167, 3205, 3170)));
|
||||
register(new EmoteCluePlugin("lumb-cave-dance", 2699, ClueLevel.MEDIUM, emote, Emotes.BLOW_KISS, new int[][] { { 1381 }, { 1155 }, { 1731 } }, "Dance in the dark<br>cave beneath<br>Lumbridge Swamp.<br>Blow a kiss before<br>you talk to me.<br>Equip an air staff,<br>bronze full helm and<br>an amulet of power.", new ZoneBorders(3139, 9534, 3260, 9587)));
|
||||
register(new EmoteCluePlugin("shantay-guild-jig", 2700, ClueLevel.MEDIUM, Emotes.JIG, Emotes.BOW, new int[][] { { 3343 }, { 1381 }, { 1173 } }, "Dance a jig under<br>Shantay's Awning.<br>Bow before you talk to<br>me.<br>Equip a pointed blue<br>snail helmet, an air<br>staff and a bronze<br>square shield.", new ZoneBorders(3302, 3122, 3305, 3125)));
|
||||
register(new EmoteCluePlugin("cat-entrance-dance", 2701, ClueLevel.HARD, emote, new int[][] { { 2570 }, { 1704 }, { 1317 } }, "Dance at the<br>cat doored pyramid in<br>Sophanem. Beware of double agents!<br>Equip a ring of life<br>an uncharged amulet of glory<br>and an adamant two handed sword.", new ZoneBorders(3293, 2781, 3296, 2782)));
|
||||
emote = Emotes.HEADBANG;
|
||||
register(new EmoteCluePlugin("al-kharid-headbang", 2702, ClueLevel.EASY, emote, new int[][] { { 1833 }, { 1059 }, { 1061 } }, "Headbang in the mine north of Al<br>Kharid.<br>Equip a desert shirt, leather gloves and<br>leather boots.", new ZoneBorders(3297, 3286, 3301, 3316)));
|
||||
//Removed Vexia code that bricked emotes for certain clues.
|
||||
//Fixed JFJ and Laugh Clues
|
||||
//When Vexia emote is removed below.
|
||||
//emote = Emotes.JUMP_FOR_JOY;
|
||||
register(new EmoteCluePlugin("beehive-jump", 2703, ClueLevel.EASY, Emotes.JUMP_FOR_JOY, new int[][] { { 1833 }, { 648 }, { 1353 } }, "Jump for joy at the beehives.<br>Equip a desert shirt, green<br>gnome robe bottoms and a<br>steel axe.", new ZoneBorders(2762, 3439, 2764, 3441)));
|
||||
// And emote, is replaced with what it is shortcutting Emotes.JUMP_FOR_JOY
|
||||
// the clues work perfect. It seems to only be a problem with multiple emote clues.
|
||||
// If you look around EmoteCluePlugin you will see there are multiple emote, shortcuts
|
||||
// I do not know what should be done as there are so many.
|
||||
register(new EmoteCluePlugin("yanille-jump", 2704, ClueLevel.MEDIUM, Emotes.JUMP_FOR_JOY, Emotes.JIG, new int[][] { { 1757 }, { 1145 }, { 6324 } }, "Jump for joy in Yanille<br>bank. Dance a jig before you<br>talk to me.<br>Equip a brown apron,<br>adamantite medium helmet<br>and snakeskin chaps.", new ZoneBorders(2609, 3088, 2614, 3097)));
|
||||
register(new EmoteCluePlugin("tzhaar-jump", 2705, ClueLevel.MEDIUM, Emotes.JUMP_FOR_JOY, Emotes.SHRUG, new int[][] { { 1295 }, { 2499 }, { 4095 } }, "Jump for joy in the TzHaar<br>sword shop. Shrug before you<br>talk to me.<br>Equip a Steel longsword,<br>Blue D'hide body and blue<br>mystic gloves.", new ZoneBorders(2477, 5144, 2480, 5147)));
|
||||
//Removed Vexia code that bricked emotes for certain clues.
|
||||
register(new EmoteCluePlugin("jokul-tent-laugh", 2706, ClueLevel.HARD, Emotes.LAUGH, new int[][] { { 1163 }, { 2493 }, { 1393 } }, "Laugh in the Jokul's tent in the<br>Mountain Camp.<br>Beware of double agents! Equip a<br>rune full helmet, blue dragonhide<br>chaps and a fire battlestaff.", new ZoneBorders(2811, 3678, 2813, 3682)));
|
||||
emote = Emotes.PANIC;
|
||||
register(new EmoteCluePlugin("limestone-mine-panic", 2707, ClueLevel.EASY, emote, new int[][] { { 1075 }, { 1269 }, { 1141 } }, "Panic in the<br>Limestone Mine.<br>Equip bronze<br>platelegs, a steel<br>pickaxe and a steel<br>medium helmet.", new ZoneBorders(3368, 3496, 3374, 3505)));
|
||||
register(new EmoteCluePlugin("fish-trawler-panic", 2708, ClueLevel.EASY, emote, new int[][] {}, "Panic on the pier<br>where you catch the<br>Fishing trawler.<br>Have nothing equipped<br>at all when you do.", new ZoneBorders(2675, 3162, 2677, 3175)));
|
||||
emote = Emotes.SALUTE;
|
||||
// vexia make banana saulte so it won't work if u are wearing anything
|
||||
// on chest or legs
|
||||
register(new EmoteCluePlugin("banana-salute", 2710, ClueLevel.HARD, emote, new int[][] { { 1643 }, { 1731 } }, "Salute in the banana<br>plantation. Beware of<br>double agents!<br>Equip a diamond ring,<br>amulet of power, and nothing on<br>your chest and legs.", new ZoneBorders(2911, 3156, 2935, 3175)));
|
||||
emote = Emotes.SHRUG;
|
||||
register(new EmoteCluePlugin("rimmington-shrug", 2711, ClueLevel.EASY, emote, new int[][] { { 1654 }, { 1635 }, { 1237 } }, "Shrug in the mine near<br>Rimmington.<br>Equip a gold<br>necklace, a gold ring<br>and a bronze spear.", new ZoneBorders(2970, 3230, 2987, 3251)));
|
||||
register(new EmoteCluePlugin("catherby-shrug", 2712, ClueLevel.MEDIUM, emote, Emotes.YAWN, new int[][] { { 851 }, { 1099 }, { 1137 } }, "Shrug in Catherby<br>bank. Yawn before<br>you talk to me.<br>Equip a maple<br>longbow, green d'hide<br>chaps and an iron<br>med helm.", new ZoneBorders(2806, 3438, 2812, 3442)));
|
||||
register(new EmoteCluePlugin("zammy-altar-shrug", 2713, ClueLevel.HARD, emote, new int[][] { { 1079 }, { 1115 }, { 2487 } }, "Shrug in the Zamorak<br>temple found in the<br>Eastern Wilderness.<br>Beware of double<br>agents!<br>Equip rune plate legs,<br>an iron plate body and<br>blue dragonhide<br>vambraces.", new ZoneBorders(3233, 3603, 3246, 3614)));
|
||||
emote = Emotes.SPIN;
|
||||
register(new EmoteCluePlugin("rimmington-cross-spin", 2716, ClueLevel.EASY, emote, new int[][] { { 658 }, { 642 }, { 1095 } }, "Spin at the crossroads<br>north of Rimmington.<br>Equip a green gnome<br>hat, cream gnome top<br>and leather chaps.", new ZoneBorders(2979, 3275, 2985, 3279)));
|
||||
register(new EmoteCluePlugin("draynor-manor-spin", 2719, ClueLevel.EASY, emote, new int[][] { { 1115 }, { 1097 }, { 1155 } }, "Spin in the Draynor<br>Manor by the fountain.<br>Equip an iron<br>platebody, studded<br>leather chaps and a<br>bronze full helmet.", new ZoneBorders(3085, 3332, 3090, 3337)));
|
||||
register(new EmoteCluePlugin("varrock-court-spin", 2722, ClueLevel.EASY, emote, new int[][] { { 1361 }, { 1169 }, { 1641 } }, "Spin in the Varrock<br>Castle courtyard.<br>Equip a black axe, a<br>coif and a ruby ring.", new ZoneBorders(3202, 3459, 3223, 3468)));
|
||||
register(new EmoteCluePlugin("barb-bridge-spin", 2723, ClueLevel.MEDIUM, emote, Emotes.SALUTE, new int[][] { { 2942 }, { 1193 }, { 1159 } }, "Spin on the bridge by<br>the Barbarian Village.<br>Salute before you talk<br>to me.<br>Equip purple gloves, a<br>steel kiteshield and a<br>mithril full helmet.", new ZoneBorders(3102, 3419, 3108, 3422)));
|
||||
emote = Emotes.THINK;
|
||||
register(new EmoteCluePlugin("lumb-wheat-think", 2725, ClueLevel.EASY, emote, new int[][] { { 640 }, { 654 }, { 843 } }, "Think in middle of the<br>wheat field by the<br>lumbridge mill.<br>Equip a blue gnome<br> robetop, a turquoise<br> gnome robe bottom<br>and an oak shortbow.", new ZoneBorders(3157, 3298, 3159, 3300)));
|
||||
// register(new EmoteCluePlugin("observatory-think", 2727,
|
||||
// ClueLevel.MEDIUM, emote, Emotes.SPIN, new int[][] {{1109}, {1099},
|
||||
// {1698}},
|
||||
// "Think in the centre of<br>the Observatory. Spin<br>before you talk to me.<br>Equip a mithril chain<br>body, green<br>dragonhide chaps and<br>a ruby amulet.",
|
||||
// new ZoneBorders(2439, 3160, 2442, 3163)));
|
||||
emote = Emotes.WAVE;
|
||||
register(new EmoteCluePlugin("lumber-wave", 2729, ClueLevel.EASY, emote, new int[][] { { 1131 }, { 1095 }, { 1351 } }, "Wave along the south fence of<br>the Lumber Yard.<br>Equip a hard leather body,<br>leather chaps and a<br>bronze axe.", new ZoneBorders(3306, 3490, 3309, 3492)));
|
||||
register(new EmoteCluePlugin("fally-gem-wave", 2731, ClueLevel.EASY, emote, new int[][] { { 1273 }, { 1125 }, { 1191 } }, "Wave in the Falador<br>gem store.<br>Equip a Mithril pickaxe,<br>Black platebody and<br>an Iron Kiteshield.", new ZoneBorders(2944, 3332, 2946, 3337)));
|
||||
register(new EmoteCluePlugin("mudskipper-wave", 2733, ClueLevel.EASY, emote, new int[][] { { 1019 }, { 1095 }, { 1424 } }, "Wave on Mudskipper Point.<br>Equip a black cape, leather<br>chaps and a steel mace.", new ZoneBorders(2979, 3105, 3008, 3115)));
|
||||
emote = Emotes.YAWN;
|
||||
register(new EmoteCluePlugin("varrock-library-yawn", 2735, ClueLevel.EASY, emote, new int[][] { { 638 }, { 4300 }, { 1335 } }, "Yawn in the Varrock<br>library.<br>Equip a green gnome<br>robe top, HAM robe<br>bottom and an iron<br>warhammer.", new ZoneBorders(3207, 3490, 3214, 3497), new ZoneBorders(3214, 3494, 3217, 3497)));
|
||||
register(new EmoteCluePlugin("draynor-market-yawn", 2737, ClueLevel.EASY, emote, new int[][] { { 1097 }, { 1191 }, { 1295 } }, "Yawn in Draynor<br>Marketplace.<br>Equip studded leather<br>chaps, an iron<br>kiteshield and a steel<br>longsword.", new ZoneBorders(3075, 3245, 3086, 3255)));
|
||||
register(new EmoteCluePlugin("castle-wars-yawn", 2739, ClueLevel.MEDIUM, emote, Emotes.SHRUG, new int[][] { { 1698 }, { 1329 }, WILDY_CAPES }, "Yawn in the Castle<br>Wars lobby. Shrug<br>before you talk to me.<br>Equip ruby amulet, a<br>mithril scimitar and a<br>Wilderness cape.", new ZoneBorders(2434, 3061, 2464, 3102)));
|
||||
register(new EmoteCluePlugin("rogue-gen-yawn", 2741, ClueLevel.HARD, emote, new int[][] { { 1183 }, { 2487 }, { 1275 } }, "Yawn in the rogues'<br>general store. Beware<br>of double agents!<br>Equip an adamant<br>square shield, blue<br>dragon vambraces<br>and a rune pickaxe.", new ZoneBorders(3024, 3699, 3027, 3704)));
|
||||
ClassScanner.definePlugin(new UriNPC());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.emote.Emotes;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Handles an emote clue scroll.
|
||||
* @author Vexia
|
||||
*/
|
||||
public abstract class EmoteClueScroll extends ClueScrollPlugin {
|
||||
|
||||
/**
|
||||
* The emote id.
|
||||
*/
|
||||
private final Emotes emote;
|
||||
|
||||
/**
|
||||
* The commening emote.
|
||||
*/
|
||||
private final Emotes commenceEmote;
|
||||
|
||||
/**
|
||||
* The equipment ids.
|
||||
*/
|
||||
private final int[][] equipment;
|
||||
|
||||
/**
|
||||
* The clue message.
|
||||
*/
|
||||
private final String clue;
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code EmoteClueScroll} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param emote the emote.
|
||||
* @param commenceEmote the emote.
|
||||
* @param equipment the equipment.
|
||||
* @param clue the clue.
|
||||
* @param borders the borders.
|
||||
*/
|
||||
public EmoteClueScroll(String name, int clueId, ClueLevel level, Emotes emote, Emotes commenceEmote, int[][] equipment, final String clue, ZoneBorders... borders) {
|
||||
super(name, clueId, level, 345, borders);
|
||||
this.emote = emote;
|
||||
this.commenceEmote = commenceEmote;
|
||||
this.equipment = equipment;
|
||||
this.clue = clue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actionButton(Player player, int interfaceId, int buttonId, int slot, int itemId, int opcode) {
|
||||
if (!player.getInventory().contains(clueId, 1)) {
|
||||
return false;
|
||||
}
|
||||
final Emotes emote = Emotes.forId(buttonId);
|
||||
if (emote == null) {
|
||||
return false;
|
||||
}
|
||||
if (emote == this.emote) {
|
||||
NPC oldUri = player.getAttribute("uri", null);
|
||||
if (oldUri != null && oldUri.isActive()) {
|
||||
return false;
|
||||
}
|
||||
spawnUri(player);
|
||||
} else if (emote == commenceEmote) {
|
||||
player.setAttribute("commence-emote", true);
|
||||
}
|
||||
if(this.emote == emote) {
|
||||
return super.actionButton(player, interfaceId, buttonId, slot, itemId, opcode);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Player player) {
|
||||
for (int i = 1; i < 9; i++) {
|
||||
player.getPacketDispatch().sendString("", interfaceId, i);
|
||||
}
|
||||
super.read(player);
|
||||
player.getPacketDispatch().sendString(clue.replace("<br>", "<br><br>"), interfaceId, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the uri npc for the player.
|
||||
* @param player the player.
|
||||
*/
|
||||
public void spawnUri(Player player) {
|
||||
boolean doubleAgent = level == ClueLevel.HARD && player.getAttribute("killed-agent", 0) != clueId;
|
||||
//changed this
|
||||
int id = 5141;
|
||||
if (doubleAgent) {
|
||||
boolean wilderness = player.getSkullManager().isWilderness();
|
||||
if (wilderness) {
|
||||
id = 5141;
|
||||
doubleAgent = false;
|
||||
} else {
|
||||
id = 5145;
|
||||
}
|
||||
}
|
||||
final NPC uri = NPC.create(id, player.getLocation().transform(1, 0, 0));
|
||||
player.setAttribute("uri", uri);
|
||||
player.removeAttribute("commence-emote");
|
||||
uri.setAttribute("double-agent", doubleAgent);
|
||||
uri.setAttribute("player", player);
|
||||
uri.setAttribute("clue", this);
|
||||
uri.init();
|
||||
uri.graphics(Graphics.create(86));
|
||||
uri.faceTemporary(player, 1);
|
||||
if (doubleAgent) {
|
||||
uri.sendChat("I expect you to die!");
|
||||
uri.getProperties().getCombatPulse().attack(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a commence emote is needed.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasCommencEmote() {
|
||||
return commenceEmote != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the emote.
|
||||
* @return the emote.
|
||||
*/
|
||||
public Emotes getEmote() {
|
||||
return emote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bequipment.
|
||||
* @return the equipment
|
||||
*/
|
||||
public int[][] getEquipment() {
|
||||
return equipment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bcommenceEmote.
|
||||
* @return the commenceEmote
|
||||
*/
|
||||
public Emotes getCommenceEmote() {
|
||||
return commenceEmote;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Initializes the map clues.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class MapCluePlugin extends MapClueScroll {
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MapCluePlugin} {@Code Object}
|
||||
*/
|
||||
public MapCluePlugin() {
|
||||
this(null, -1, null, -1, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MapCluePlugin} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param interfaceId the interface id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public MapCluePlugin(String name, int clueId, ClueLevel level, int interfaceId, Location location) {
|
||||
super(name, clueId, level, interfaceId, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MapCluePlugin} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param interfaceId the interface id.
|
||||
* @param location the location.
|
||||
* @param object the object.
|
||||
* @param borders the borders.
|
||||
*/
|
||||
public MapCluePlugin(String name, int clueId, ClueLevel level, int interfaceId, Location location, int object, ZoneBorders... borders) {
|
||||
super(name, clueId, level, interfaceId, location, object, borders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
register(new MapCluePlugin("mc-grubber-crate", 2743, ClueLevel.MEDIUM, 355, Location.create(2658, 3488, 0), 357, new ZoneBorders(2657, 3487, 2660, 3489)));
|
||||
register(new MapCluePlugin("ardy-crate", 2747, ClueLevel.MEDIUM, 361, Location.create(2565, 3248, 0), 354, new ZoneBorders(2564, 3247, 2566, 3249)));
|
||||
register(new MapCluePlugin("wildy-crate", 2773, ClueLevel.HARD, 359, Location.create(3026, 3628, 0), 354, new ZoneBorders(3025, 3627, 3027, 3629)));
|
||||
register(new MapCluePlugin("goblin-crate", 2774, ClueLevel.HARD, 358, Location.create(2457, 3182, 0), 18506, new ZoneBorders(2456, 3181, 2458, 3183)));
|
||||
register(new MapCluePlugin("miscellania-dig", 2776, ClueLevel.MEDIUM, 340, Location.create(2536, 3865, 0)));
|
||||
register(new MapCluePlugin("crafting-guild-dig", 2778, ClueLevel.MEDIUM, 352, Location.create(2906, 3294, 0)));
|
||||
register(new MapCluePlugin("wizard-tower-dig", 2745, ClueLevel.EASY, 356, Location.create(3110, 3152, 0)));
|
||||
register(new MapCluePlugin("east-dig", 2805, ClueLevel.EASY, 360, Location.create(2651, 3231, 0)));
|
||||
register(new MapCluePlugin("rimmington", 2780, ClueLevel.MEDIUM, 362, Location.create(2924, 3209, 0)));
|
||||
register(new MapCluePlugin("west-ardy", 2782, ClueLevel.HARD, 357, Location.create(2488, 3308, 0)));
|
||||
register(new MapCluePlugin("yanille", 2783, ClueLevel.HARD, 353, Location.create(2616, 3077, 0)));
|
||||
register(new MapCluePlugin("mcgrubber", 2785, ClueLevel.EASY, 354, Location.create(2611, 3481, 0)));
|
||||
register(new MapCluePlugin("falador-stone", 2786, ClueLevel.EASY, 351, Location.create(3043, 3399, 0)));
|
||||
register(new MapCluePlugin("champion's-guild", 2788, ClueLevel.EASY, 346, Location.create(3166, 3360, 0)));
|
||||
register(new MapCluePlugin("falador-statue", 2790, ClueLevel.EASY, 337, Location.create(2970, 3415, 0)));
|
||||
register(new MapCluePlugin("varrock-mine", 2792, ClueLevel.EASY, 347, Location.create(3289, 3373, 0)));
|
||||
register(new MapCluePlugin("khazard-altar", 2793, ClueLevel.MEDIUM, 342, Location.create(2455, 3230, 0)));
|
||||
register(new MapCluePlugin("light-house", 2794, ClueLevel.MEDIUM, 343, Location.create(2578, 3597, 0)));
|
||||
register(new MapCluePlugin("north-seers", 2796, ClueLevel.MEDIUM, 344, Location.create(2666, 3562, 0)));
|
||||
register(new MapCluePlugin("legends-guild", 2797, ClueLevel.HARD, 339, Location.create(2723, 3338, 0)));
|
||||
register(new MapCluePlugin("wilderness", 2799, ClueLevel.HARD, 338, Location.create(3021, 3911, 0)));
|
||||
register(new MapCluePlugin("draynor", 2801, ClueLevel.MEDIUM, 348, Location.create(3092, 3227, 0)));
|
||||
register(new MapCluePlugin("abandoned-mine", 2803, ClueLevel.MEDIUM, 341, Location.create(3434, 3266, 0)));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.global.action.DigAction;
|
||||
import core.game.global.action.DigSpadeHandler;
|
||||
import core.game.interaction.Option;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
|
||||
/**
|
||||
* A map clue scroll.
|
||||
* @author Vexia
|
||||
*/
|
||||
public abstract class MapClueScroll extends ClueScrollPlugin {
|
||||
|
||||
/**
|
||||
* The location of the x spot.
|
||||
*/
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* The object id.
|
||||
*/
|
||||
private final int object;
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MapClueScroll} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param interfaceId the interface id.
|
||||
* @param location the location.
|
||||
* @param object the object.
|
||||
*/
|
||||
public MapClueScroll(String name, int clueId, ClueLevel level, int interfaceId, Location location, final int object, ZoneBorders... borders) {
|
||||
super(name, clueId, level, interfaceId, borders);
|
||||
this.location = location;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MapClueScroll} {@Code Object}
|
||||
* @param name the name.
|
||||
* @param clueId the clue id.
|
||||
* @param level the level.
|
||||
* @param interfaceId the interface id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public MapClueScroll(String name, int clueId, ClueLevel level, int interfaceId, Location location) {
|
||||
this(name, clueId, level, interfaceId, location, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interact(Entity e, Node target, Option option) {
|
||||
if (e instanceof Player) {
|
||||
Player p = e.asPlayer();
|
||||
if (target.getId() == object && option.getName().equals("Search")) {
|
||||
if (!p.getInventory().contains(clueId, 1) || !target.getLocation().equals(location)) {
|
||||
p.sendMessage("Nothing interesting happens.");
|
||||
return false;
|
||||
}
|
||||
reward(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.interact(e, target, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() {
|
||||
DigSpadeHandler.register(getLocation(), new MapDigAction());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
/**
|
||||
* The dig method called when the player digs.
|
||||
* @param player the player.
|
||||
*/
|
||||
public void dig(Player player) {
|
||||
reward(player);
|
||||
player.getDialogueInterpreter().sendItemMessage(405, "You've found a casket!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the map digging reward.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class MapDigAction implements DigAction {
|
||||
|
||||
@Override
|
||||
public void run(Player player) {
|
||||
if (!hasRequiredItems(player)) {
|
||||
player.sendMessage("Nothing interesting happens.");
|
||||
return;
|
||||
}
|
||||
dig(player);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has the required items.
|
||||
* @param player the player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasRequiredItems(Player player) {
|
||||
return player.getInventory().contains(clueId, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blocation.
|
||||
* @return the location
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bobject.
|
||||
* @return the object
|
||||
*/
|
||||
public int getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.spell.CombatSpell;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.plugin.Plugin;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.node.entity.combat.MultiSwingHandler;
|
||||
|
||||
/**
|
||||
* Handles saradomin npc.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class SaradominWizardNPC extends AbstractNPC {
|
||||
|
||||
/**
|
||||
* The combat handler to use.
|
||||
*/
|
||||
private static final MultiSwingHandler COMBAT_HANDLER = new MultiSwingHandler(new SwitchAttack(CombatStyle.MELEE).setUseHandler(true), new SwitchAttack(CombatStyle.MAGIC).setUseHandler(true));
|
||||
|
||||
/**
|
||||
* The npc ids.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 1264 };
|
||||
|
||||
/**
|
||||
* The clue scroll.
|
||||
*/
|
||||
private ClueScrollPlugin clueScroll;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SaradominWizardNPC} {@code Object}
|
||||
*/
|
||||
public SaradominWizardNPC() {
|
||||
super(0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code SaradominWizardNPC} {@Code Object}
|
||||
* @param id the id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public SaradominWizardNPC(int id, Location location) {
|
||||
super(id, location, false);
|
||||
this.setRespawn(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNPC construct(int id, Location location, Object... objects) {
|
||||
return new SaradominWizardNPC(id, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Player player = getAttribute("player", null);
|
||||
ClueScrollPlugin clueScroll = getAttribute("clue", null);
|
||||
if (player != null) {
|
||||
this.player = player;
|
||||
}
|
||||
if (clueScroll != null) {
|
||||
this.clueScroll = clueScroll;
|
||||
}
|
||||
if (player != null) {
|
||||
location = RegionManager.getSpawnLocation(player, this);
|
||||
if (location == null) {
|
||||
location = player.getLocation();
|
||||
}
|
||||
}
|
||||
super.init();
|
||||
getProperties().setSpell((CombatSpell) SpellBook.MODERN.getSpell(41));
|
||||
getProperties().setAutocastSpell((CombatSpell) SpellBook.MODERN.getSpell(41));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalizeDeath(Entity killer) {
|
||||
if (killer instanceof Player) {
|
||||
Player p = killer.asPlayer();
|
||||
if (p == player) {
|
||||
p.setAttribute("killed-wizard", clueScroll.getClueId());
|
||||
}
|
||||
}
|
||||
super.finalizeDeath(killer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
if (player != null) {
|
||||
if (player.getLocation().getDistance(getLocation()) > 10 || !player.isActive()) {
|
||||
clear();
|
||||
}
|
||||
if (!getProperties().getCombatPulse().isAttacking()) {
|
||||
getProperties().getCombatPulse().attack(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombatSwingHandler getSwingHandler(boolean swing) {
|
||||
return COMBAT_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (player != null) {
|
||||
Player p = entity.asPlayer();
|
||||
return p == player;
|
||||
}
|
||||
return super.canAttack(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (player != null) {
|
||||
Player p = entity.asPlayer();
|
||||
return p == player;
|
||||
}
|
||||
return super.isAttackable(entity, style, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelectTarget(Entity target) {
|
||||
return target == player;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
return super.newInstance(arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return IDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bplayer.
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baplayer.
|
||||
* @param player the player to set.
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueScroll.
|
||||
* @return the clueScroll
|
||||
*/
|
||||
public ClueScrollPlugin getClueScroll() {
|
||||
return clueScroll;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.api.LoginListener;
|
||||
import core.api.PersistPlayer;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
import core.tools.RandomFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
/**
|
||||
* Handles the treasure trail of a player.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class TreasureTrailManager implements LoginListener, PersistPlayer {
|
||||
|
||||
/**
|
||||
* The ids of the clues.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 2677, 2678, 2679, 2680, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2716, 2719, 2722, 2723, 2725, 2727, 2729, 2731, 2733, 2735, 2737, 2739, 2741, 2743, 2745, 2747, 2773, 2774, 2776, 2778, 2780, 2782, 2783, 2785, 2786, 2788, 2790, 2792, 2793, 2794, 2796, 2797, 2799, 2801, 2803, 2805, 2807, 2809, 2811, 2813, 2815, 2817, 2819, 2821, 2823, 2825, 2827, 2829, 2831, 2833, 2835, 2837, 2839, 2841, 2843, 2845, 2847, 2848, 2849, 2851, 2853, 2855, 2856, 2857, 2858, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3512, 3513, 3514, 3515, 3516, 3518, 3520, 3522, 3524, 3525, 3526, 3528, 3530, 3532, 3534, 3536, 3538, 3540, 3542, 3544, 3546, 3548, 3550, 3552, 3554, 3556, 3558, 3560, 3562, 3564, 3566, 3568, 3570, 3572, 3573, 3574, 3575, 3577, 3579, 3580, 3582, 3584, 3586, 3588, 3590, 3592, 3594, 3596, 3598, 3599, 3601, 3602, 3604, 3605, 3607, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 7236, 7238, 7239, 7241, 7243, 7245, 7247, 7248, 7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, 7258, 7260, 7262, 7264, 7266, 7268, 7270, 7272, 7274, 7276, 7278, 7280, 7282, 7284, 7286, 7288, 7290, 7292, 7294, 7296, 7298, 7300, 7301, 7303, 7304, 7305, 7307, 7309, 7311, 7313, 7315, 7317, 10180, 10182, 10184, 10186, 10188, 10190, 10192, 10194, 10196, 10198, 10200, 10202, 10204, 10206, 10208, 10210, 10212, 10214, 10216, 10218, 10220, 10222, 10224, 10226, 10228, 10230, 10232, 10234, 10236, 10238, 10240, 10242, 10244, 10246, 10248, 10250, 10252, 10254, 10256, 10258, 10260, 10262, 10264, 10266, 10268, 10270, 10272, 10274, 10276, 10278, 13010, 13012, 13014, 13016, 13018, 13020, 13022, 13024, 13026, 13028, 13030, 13032, 13034, 13036, 13038, 13040, 13041, 13042, 13044, 13046, 13048, 13049, 13050, 13051, 13053, 13055, 13056, 13058, 13060, 13061, 13063, 13065, 13067, 13068, 13069, 13070, 13071, 13072, 13074, 13075, 13076, 13078, 13079, 13080 };
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The current clue id.
|
||||
*/
|
||||
private int clueId;
|
||||
|
||||
/**
|
||||
* The clue level.
|
||||
*/
|
||||
private ClueLevel level;
|
||||
|
||||
/**
|
||||
* The trail stage.
|
||||
*/
|
||||
private int trailStage;
|
||||
|
||||
/**
|
||||
* The current length of the trail.
|
||||
*/
|
||||
private int trailLength;
|
||||
|
||||
/**
|
||||
* The amount of completed clues.
|
||||
*/
|
||||
private final int[] completedClues = new int[3];
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code TreasureTrailManager} {@Code
|
||||
* Object}
|
||||
* @param player the player.
|
||||
*/
|
||||
public TreasureTrailManager(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public TreasureTrailManager() {this.player = null;}
|
||||
|
||||
@Override
|
||||
public void login(@NotNull Player player) {
|
||||
TreasureTrailManager instance = new TreasureTrailManager(player);
|
||||
player.setAttribute("tt-manager", instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parsePlayer(@NotNull Player player, @NotNull JSONObject data) {
|
||||
TreasureTrailManager instance = getInstance(player);
|
||||
JSONObject ttData = (JSONObject) data.get("treasureTrails");
|
||||
if(ttData == null) return;
|
||||
JSONArray cc = (JSONArray) ttData.get("completedClues");
|
||||
for(int i = 0; i < cc.size(); i++)
|
||||
{
|
||||
instance.completedClues[i] = Integer.parseInt(cc.get(i).toString());
|
||||
}
|
||||
if(ttData.containsKey("trail"))
|
||||
{
|
||||
JSONObject trail = (JSONObject) ttData.get("trail");
|
||||
instance.clueId = Integer.parseInt(trail.get("clueId").toString());
|
||||
instance.trailLength = Integer.parseInt(trail.get("length").toString());
|
||||
instance.trailStage = Integer.parseInt(trail.get("stage").toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void savePlayer(@NotNull Player player, @NotNull JSONObject save) {
|
||||
TreasureTrailManager instance = getInstance(player);
|
||||
JSONObject treasureTrailManager = new JSONObject();
|
||||
if(instance.hasTrail()){
|
||||
JSONObject trail = new JSONObject();
|
||||
trail.put("clueId", Integer.toString(instance.clueId));
|
||||
trail.put("length", Integer.toString(instance.trailLength));
|
||||
trail.put("stage", Integer.toString(instance.trailStage));
|
||||
treasureTrailManager.put("trail",trail);
|
||||
}
|
||||
JSONArray completedClues = new JSONArray();
|
||||
for(int clue : instance.completedClues)
|
||||
{
|
||||
completedClues.add(Integer.toString(clue));
|
||||
}
|
||||
treasureTrailManager.put("completedClues",completedClues);
|
||||
save.put("treasureTrails",treasureTrailManager);
|
||||
}
|
||||
|
||||
public void parse(JSONObject data){
|
||||
JSONArray cc = (JSONArray) data.get("completedClues");
|
||||
for(int i = 0; i < cc.size(); i++){
|
||||
completedClues[i] = Integer.parseInt(cc.get(i).toString());
|
||||
}
|
||||
|
||||
if(data.containsKey("trail")){
|
||||
JSONObject trail = (JSONObject) data.get("trail");
|
||||
clueId = Integer.parseInt(trail.get("clueId").toString());
|
||||
trailLength = Integer.parseInt(trail.get("length").toString());
|
||||
trailStage = Integer.parseInt(trail.get("stage").toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a treasure trail.
|
||||
* @param clue the clue.
|
||||
*/
|
||||
public void startTrail(ClueScrollPlugin clue) {
|
||||
setClue(clue);
|
||||
trailLength = RandomFunction.random(clue.getLevel().getMinimumLength(), clue.getLevel().getMaximumLength());
|
||||
trailStage = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the trail.
|
||||
*/
|
||||
public void clearTrail() {
|
||||
clueId = 0;
|
||||
level = null;
|
||||
trailLength = 0;
|
||||
trailStage = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current clue.
|
||||
* @param clue the clue.
|
||||
*/
|
||||
public void setClue(ClueScrollPlugin clue) {
|
||||
clueId = clue.getClueId();
|
||||
level = clue.getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has a clue.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasClue() {
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
if (player.hasItem(ClueLevel.EASY.getCasket()) || player.hasItem(ClueLevel.MEDIUM.getCasket()) || player.hasItem(ClueLevel.HARD.getCasket())) {
|
||||
return true;
|
||||
}
|
||||
for (int id : IDS) {
|
||||
if (player.getInventory().contains(id, 1) || player.getBank().contains(id, 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a trail stage.
|
||||
*/
|
||||
public void incrementStage() {
|
||||
trailStage += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the trail is completed.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
return trailStage != 0 && trailLength != 0 && trailStage >= trailLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has an active trail.
|
||||
* @return the trail.
|
||||
*/
|
||||
public boolean hasTrail() {
|
||||
return clueId != 0 && level != null & trailLength != 0 && trailStage != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incremented the clues.
|
||||
*/
|
||||
public void incrementClues(ClueLevel level) {
|
||||
completedClues[level.ordinal()]++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of completed clues for the level.
|
||||
* @param level the level.
|
||||
* @return the amount.
|
||||
*/
|
||||
public int getCompletedClues(ClueLevel level) {
|
||||
return completedClues[level.ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the completed clue amount.
|
||||
* @return the completed clues.
|
||||
*/
|
||||
public int[] getCompletedClues() {
|
||||
return completedClues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueId.
|
||||
* @return the clueId
|
||||
*/
|
||||
public int getClueId() {
|
||||
return clueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baclueId.
|
||||
* @param clueId the clueId to set.
|
||||
*/
|
||||
public void setClueId(int clueId) {
|
||||
this.clueId = clueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blevel.
|
||||
* @return the level
|
||||
*/
|
||||
public ClueLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the balevel.
|
||||
* @param level the level to set.
|
||||
*/
|
||||
public void setLevel(ClueLevel level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bplayer.
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the btrailLength.
|
||||
* @return the trailLength
|
||||
*/
|
||||
public int getTrailLength() {
|
||||
return trailLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the batrailLength.
|
||||
* @param trailLength the trailLength to set.
|
||||
*/
|
||||
public void setTrailLength(int trailLength) {
|
||||
this.trailLength = trailLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the btrailStage.
|
||||
* @return the trailStage
|
||||
*/
|
||||
public int getTrailStage() {
|
||||
return trailStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the batrailStage.
|
||||
* @param trailStage the trailStage to set.
|
||||
*/
|
||||
public void setTrailStage(int trailStage) {
|
||||
this.trailStage = trailStage;
|
||||
}
|
||||
|
||||
public static TreasureTrailManager getInstance(Player player)
|
||||
{
|
||||
return player.getAttribute("tt-manager", new TreasureTrailManager());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import content.global.skill.agility.AgilityHandler;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.ItemPlugin;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Handles the clue scroll options.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class TreasureTrailPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* The ids of the clues.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 2677, 2678, 2679, 2680, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2716, 2719, 2722, 2723, 2725, 2727, 2729, 2731, 2733, 2735, 2737, 2739, 2741, 2743, 2745, 2747, 2773, 2774, 2776, 2778, 2780, 2782, 2783, 2785, 2786, 2788, 2790, 2792, 2793, 2794, 2796, 2797, 2799, 2801, 2803, 2805, 2807, 2809, 2811, 2813, 2815, 2817, 2819, 2821, 2823, 2825, 2827, 2829, 2831, 2833, 2835, 2837, 2839, 2841, 2843, 2845, 2847, 2848, 2849, 2851, 2853, 2855, 2856, 2857, 2858, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3512, 3513, 3514, 3515, 3516, 3518, 3520, 3522, 3524, 3525, 3526, 3528, 3530, 3532, 3534, 3536, 3538, 3540, 3542, 3544, 3546, 3548, 3550, 3552, 3554, 3556, 3558, 3560, 3562, 3564, 3566, 3568, 3570, 3572, 3573, 3574, 3575, 3577, 3579, 3580, 3582, 3584, 3586, 3588, 3590, 3592, 3594, 3596, 3598, 3599, 3601, 3602, 3604, 3605, 3607, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 7236, 7238, 7239, 7241, 7243, 7245, 7247, 7248, 7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, 7258, 7260, 7262, 7264, 7266, 7268, 7270, 7272, 7274, 7276, 7278, 7280, 7282, 7284, 7286, 7288, 7290, 7292, 7294, 7296, 7298, 7300, 7301, 7303, 7304, 7305, 7307, 7309, 7311, 7313, 7315, 7317, 10180, 10182, 10184, 10186, 10188, 10190, 10192, 10194, 10196, 10198, 10200, 10202, 10204, 10206, 10208, 10210, 10212, 10214, 10216, 10218, 10220, 10222, 10224, 10226, 10228, 10230, 10232, 10234, 10236, 10238, 10240, 10242, 10244, 10246, 10248, 10250, 10252, 10254, 10256, 10258, 10260, 10262, 10264, 10266, 10268, 10270, 10272, 10274, 10276, 10278, 13010, 13012, 13014, 13016, 13018, 13020, 13022, 13024, 13026, 13028, 13030, 13032, 13034, 13036, 13038, 13040, 13041, 13042, 13044, 13046, 13048, 13049, 13050, 13051, 13053, 13055, 13056, 13058, 13060, 13061, 13063, 13065, 13067, 13068, 13069, 13070, 13071, 13072, 13074, 13075, 13076, 13078, 13079, 13080 };
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : IDS) {
|
||||
ItemDefinition.forId(id).getHandlers().put("option:read", this);
|
||||
}
|
||||
for (ClueLevel level : ClueLevel.values()) {
|
||||
ItemDefinition.forId(level.getCasket().getId()).getHandlers().put("option:open", this);
|
||||
}
|
||||
ItemDefinition.forId(CoordinateClueScroll.SEXTANT.getId()).getHandlers().put("option:look through", this);
|
||||
ClassScanner.definePlugin(new MapCluePlugin());
|
||||
ClassScanner.definePlugin(new ClueItemPlugin());
|
||||
ClassScanner.definePlugin(new EmoteCluePlugin());
|
||||
ClassScanner.definePlugin(new TTrailOptionHandler());
|
||||
ClassScanner.definePlugin(new SextantComponentPlugin());
|
||||
ClassScanner.definePlugin(new CoordinateCluePlugin());
|
||||
ClassScanner.definePlugin(new SaradominWizardNPC());
|
||||
ClassScanner.definePlugin(new ZamorakWizardNPC());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.lock(1);
|
||||
switch (option) {
|
||||
case "read":
|
||||
final ClueScrollPlugin plugin = ClueScrollPlugin.getClueScrolls().get(node.getId());
|
||||
if (plugin == null) {
|
||||
player.sendMessage("Unused clue scroll item! Removed.");
|
||||
player.getInventory().remove((Item) node);
|
||||
return false;
|
||||
}
|
||||
plugin.read(player);
|
||||
break;
|
||||
case "open":
|
||||
if (!player.getInventory().containsItem(node.asItem())) {
|
||||
return true;
|
||||
}
|
||||
ClueLevel.open(player, (Item) node);
|
||||
break;
|
||||
case "look through":
|
||||
player.getInterfaceManager().open(new Component(365));
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWalk() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles options related to treasure trails.
|
||||
* @author Vexia
|
||||
*/
|
||||
public static final class TTrailOptionHandler extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(19171).getHandlers().put("option:squeeze-through", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
switch (node.getId()) {
|
||||
case 19171:
|
||||
Location start = player.getLocation().getX() <= 2522 ? node.getLocation() : node.getLocation().transform(1, 0, 0);
|
||||
player.lock(1);
|
||||
AgilityHandler.forceWalk(player, -1, start, start.transform(player.getLocation().getX() <= 2522 ? 1 : -1, 0, 0), Animation.create(2240), 5, 1, null, 0);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a clue scroll item.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class ClueItemPlugin extends ItemPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
register(IDS);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPickUp(Player player, GroundItem item, int type) {
|
||||
if (hasClue(player)) {
|
||||
player.sendMessage("A magical force prevents you from picking the clue scroll up.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createDrop(Item item, Player player, NPC npc, Location l) {
|
||||
return !hasClue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getItem(Item item, NPC npc) {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has a clue.
|
||||
* @param player the player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
private boolean hasClue(Player player) {
|
||||
return TreasureTrailManager.getInstance(player).hasClue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the sextant interface.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class SextantComponentPlugin extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.forId(365).setPlugin(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
switch (button) {
|
||||
case 5:// horizon up
|
||||
break;
|
||||
case 4:// horizon down
|
||||
break;
|
||||
case 6:// sun down
|
||||
break;
|
||||
case 7:// sun up
|
||||
break;
|
||||
case 11:
|
||||
player.sendMessage("You need to get the horizon in the middle of the eye piece.");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the uri npc.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class UriNPC extends AbstractNPC {
|
||||
|
||||
/**
|
||||
* The npc ids.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 5141, 5142, 5143, 5144, 5145 };
|
||||
|
||||
/**
|
||||
* The clue scroll.
|
||||
*/
|
||||
private ClueScrollPlugin clueScroll;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code UriNPC} {@Code Object}
|
||||
*/
|
||||
public UriNPC() {
|
||||
super(0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code UriNPC} {@Code Object}
|
||||
* @param id the id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public UriNPC(int id, Location location) {
|
||||
super(id, location, false);
|
||||
this.setRespawn(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNPC construct(int id, Location location, Object... objects) {
|
||||
return new UriNPC(id, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Player player = getAttribute("player", null);
|
||||
ClueScrollPlugin clueScroll = getAttribute("clue", null);
|
||||
if (player != null) {
|
||||
this.player = player;
|
||||
}
|
||||
if (clueScroll != null) {
|
||||
this.clueScroll = clueScroll;
|
||||
}
|
||||
if (player != null) {
|
||||
location = RegionManager.getSpawnLocation(player, this);
|
||||
if (location == null) {
|
||||
location = player.getLocation();
|
||||
}
|
||||
}
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalizeDeath(Entity killer) {
|
||||
if (killer instanceof Player) {
|
||||
Player p = killer.asPlayer();
|
||||
if (p == player && isDoubleAgent()) {
|
||||
p.setAttribute("killed-agent", clueScroll.getClueId());
|
||||
}
|
||||
}
|
||||
super.finalizeDeath(killer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
if (player != null) {
|
||||
if (player.getLocation().getDistance(getLocation()) > 10 || !player.isActive()) {
|
||||
clear();
|
||||
}
|
||||
if (isDoubleAgent()) {
|
||||
if (!getProperties().getCombatPulse().isAttacking()) {
|
||||
getProperties().getCombatPulse().attack(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (player != null) {
|
||||
Player p = entity.asPlayer();
|
||||
return p == player;
|
||||
}
|
||||
return super.isAttackable(entity, style, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelectTarget(Entity target) {
|
||||
return target == player;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new UriDialogue());
|
||||
return super.newInstance(arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return IDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if uri is a double agent.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isDoubleAgent() {
|
||||
return getAttribute("double-agent", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bplayer.
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baplayer.
|
||||
* @param player the player to set.
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueScroll.
|
||||
* @return the clueScroll
|
||||
*/
|
||||
public ClueScrollPlugin getClueScroll() {
|
||||
return clueScroll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the uri dialogue.
|
||||
* @author Vexia
|
||||
*/
|
||||
public static final class UriDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* The quotes uri says.
|
||||
*/
|
||||
private static final String[] QUOTES = new String[] { "Once, I was a poor man, but then I found a party hat.", "There were three goblins in a bar, which one left first?", "Would you like to buy a pewter spoon?", "In the end, only the three-legged survive.", "I heard that the tall man fears only strong winds.", "In Canifis the men are known for eating much spam.", "I am the egg man, are you one of the egg men?", "I believe that it is very rainy in Varrock.", "The slowest of fishermen catch the swiftest of fish.", "It is quite easy being green.", "Don't forget to find the jade monkey.", "Don't forget to find the jade monkey.", "Do you want ants? Because that's how you get ants.", "I once named a duck after a girl. Big mistake.", "Loser says what.", "I'm looking for a girl named Molly. I can't find her.", "Guys, let's lake dive!", "I gave you what you needed; not what you think you needed.", "Want to see me bend a spoon?", "Is that Deziree?", "This is the last night you'll spend alone.", "(Breathing intensifies)", "Init doe. Lyk, I hope yer reward iz goodd aye?" };
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code UriDialogue} {@Code Object}
|
||||
*/
|
||||
public UriDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code UriDialogue} {@Code Object}
|
||||
* @param player
|
||||
*/
|
||||
public UriDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new UriDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (!canSpeak()) {
|
||||
npc("I do not believe we have any business, Comrade.");
|
||||
stage = -1;
|
||||
return true;
|
||||
}
|
||||
npc(RandomFunction.getRandomElement(QUOTES));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case -1:
|
||||
end();
|
||||
break;
|
||||
case 0:
|
||||
player("What?");
|
||||
asUri().getClueScroll().reward(player);
|
||||
stage++;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendItemMessage(405, "You've been given a casket!");
|
||||
stage++;
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close() {
|
||||
if (stage >= 1) {
|
||||
npc.clear();
|
||||
player.removeAttribute("killed-agent");
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can speak to the npc.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean canSpeak() {
|
||||
EmoteClueScroll scroll = (EmoteClueScroll) asUri().getClueScroll();
|
||||
if (asUri().getPlayer() != player || !player.getAttribute("commence-emote", !scroll.hasCommencEmote())) {
|
||||
return false;
|
||||
}
|
||||
return scroll.hasEquipment(player, scroll.getEquipment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts to the uri npc.
|
||||
* @return the npc.
|
||||
*/
|
||||
public UriNPC asUri() {
|
||||
return (UriNPC) npc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return IDS;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package content.global.activity.ttrail;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.spell.CombatSpell;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles saradomin npc.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class ZamorakWizardNPC extends AbstractNPC {
|
||||
|
||||
/**
|
||||
* The npc ids.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 1007 };
|
||||
|
||||
/**
|
||||
* The clue scroll.
|
||||
*/
|
||||
private ClueScrollPlugin clueScroll;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SaradominWizardNPC} {@code Object}
|
||||
*/
|
||||
public ZamorakWizardNPC() {
|
||||
super(0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code SaradominWizardNPC} {@Code Object}
|
||||
* @param id the id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public ZamorakWizardNPC(int id, Location location) {
|
||||
super(id, location, false);
|
||||
this.setRespawn(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNPC construct(int id, Location location, Object... objects) {
|
||||
return new ZamorakWizardNPC(id, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Player player = getAttribute("player", null);
|
||||
ClueScrollPlugin clueScroll = getAttribute("clue", null);
|
||||
if (player != null) {
|
||||
this.player = player;
|
||||
}
|
||||
if (clueScroll != null) {
|
||||
this.clueScroll = clueScroll;
|
||||
}
|
||||
if (player != null) {
|
||||
location = RegionManager.getSpawnLocation(player, this);
|
||||
if (location == null) {
|
||||
location = player.getLocation();
|
||||
}
|
||||
}
|
||||
super.init();
|
||||
getProperties().setSpell((CombatSpell) SpellBook.MODERN.getSpell(43));
|
||||
getProperties().setAutocastSpell((CombatSpell) SpellBook.MODERN.getSpell(43));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalizeDeath(Entity killer) {
|
||||
if (killer instanceof Player) {
|
||||
Player p = killer.asPlayer();
|
||||
if (p == player) {
|
||||
p.setAttribute("killed-wizard", clueScroll.getClueId());
|
||||
}
|
||||
}
|
||||
super.finalizeDeath(killer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
if (player != null) {
|
||||
if (player.getLocation().getDistance(getLocation()) > 10 || !player.isActive()) {
|
||||
clear();
|
||||
}
|
||||
if (!getProperties().getCombatPulse().isAttacking()) {
|
||||
getProperties().getCombatPulse().attack(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (player != null) {
|
||||
Player p = entity.asPlayer();
|
||||
return p == player;
|
||||
}
|
||||
return super.isAttackable(entity, style, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(Entity entity) {
|
||||
if (!(entity instanceof Player)) {
|
||||
return false;
|
||||
}
|
||||
if (player != null) {
|
||||
Player p = entity.asPlayer();
|
||||
return p == player;
|
||||
}
|
||||
return super.canAttack(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSelectTarget(Entity target) {
|
||||
return target == player;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
return super.newInstance(arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return IDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bplayer.
|
||||
* @return the player
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baplayer.
|
||||
* @param player the player to set.
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bclueScroll.
|
||||
* @return the clueScroll
|
||||
*/
|
||||
public ClueScrollPlugin getClueScroll() {
|
||||
return clueScroll;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package content.global.ame
|
||||
|
||||
import core.api.Commands
|
||||
import core.api.LoginListener
|
||||
import core.game.event.EventHook
|
||||
import core.game.event.TickEvent
|
||||
import core.api.getAttribute
|
||||
import core.api.setAttribute
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import core.tools.RandomFunction
|
||||
import core.api.Event
|
||||
import core.tools.SystemLogger
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.repository.Repository
|
||||
import kotlin.random.Random
|
||||
|
||||
class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<TickEvent>, Commands {
|
||||
var event: content.global.ame.RandomEventNPC? = null
|
||||
var enabled: Boolean = false
|
||||
var nextSpawn = 0
|
||||
val skills = arrayOf("WoodcuttingSkillPulse","FishingPulse","MiningSkillPulse","BoneBuryingOptionPlugin")
|
||||
|
||||
override fun login(player: Player) {
|
||||
if(player.isArtificial) return
|
||||
val instance = content.global.ame.RandomEventManager(player)
|
||||
player.hook(Event.Tick, instance)
|
||||
setAttribute(player, "random-manager", instance)
|
||||
instance.rollNextSpawn()
|
||||
instance.enabled = true
|
||||
SystemLogger.logRE("Initialized REManager for ${player.username}.")
|
||||
}
|
||||
|
||||
override fun process(entity: Entity, event: TickEvent) {
|
||||
if (GameWorld.ticks > nextSpawn && getAttribute(player!!, "tutorial:complete", false)) fireEvent()
|
||||
}
|
||||
|
||||
fun fireEvent() {
|
||||
if(!enabled){
|
||||
rollNextSpawn()
|
||||
return
|
||||
}
|
||||
if (player!!.zoneMonitor.isRestricted(ZoneRestriction.RANDOM_EVENTS)) {
|
||||
nextSpawn = GameWorld.ticks + 3000
|
||||
return
|
||||
}
|
||||
if (getAttribute<content.global.ame.RandomEventNPC?>(player, "re-npc", null) != null) return
|
||||
val currentAction = player.pulseManager.current?.toString() ?: "None"
|
||||
val ame: content.global.ame.RandomEvents = if(currentAction.contains("WoodcuttingSkillPulse") && Random.nextBoolean()){
|
||||
content.global.ame.RandomEvents.TREE_SPIRIT
|
||||
} else if(currentAction.contains("FishingPulse") && Random.nextBoolean()){
|
||||
content.global.ame.RandomEvents.RIVER_TROLL
|
||||
} else if(currentAction.contains("MiningSkillPulse") && Random.nextBoolean()){
|
||||
content.global.ame.RandomEvents.ROCK_GOLEM
|
||||
} else if(currentAction.contains("BoneBuryingOptionPlugin") && Random.nextBoolean()){
|
||||
content.global.ame.RandomEvents.SHADE
|
||||
} else {
|
||||
content.global.ame.RandomEvents.values().filter { it.type != "skill" }.random()
|
||||
}
|
||||
event = ame.npc.create(player,ame.loot,ame.type)
|
||||
if (event!!.spawnLocation == null) {
|
||||
nextSpawn = GameWorld.ticks + 3000
|
||||
SystemLogger.logWarn(this::class.java, "Tried to spawn random event for ${player.username} but spawn location was null!")
|
||||
return
|
||||
}
|
||||
event!!.init()
|
||||
rollNextSpawn()
|
||||
SystemLogger.logRE("Fired ${event!!.name} for ${player.username}")
|
||||
}
|
||||
|
||||
private fun rollNextSpawn() {
|
||||
nextSpawn = GameWorld.ticks + RandomFunction.random(content.global.ame.RandomEventManager.Companion.MIN_DELAY_TICKS, content.global.ame.RandomEventManager.Companion.MAX_DELAY_TICKS)
|
||||
}
|
||||
|
||||
override fun defineCommands() {
|
||||
define("targeted-ame", Privilege.ADMIN, "targeted-ame username", "Summons a random for the given user") {player, args ->
|
||||
val username = args[1]
|
||||
val target = Repository.getPlayerByName(username)
|
||||
|
||||
if (target == null)
|
||||
reject(player, "Unable to find player $username!")
|
||||
|
||||
content.global.ame.RandomEventManager.Companion.getInstance(target!!)?.fireEvent()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val AVG_DELAY_TICKS = 6000 // 60 minutes
|
||||
const val MIN_DELAY_TICKS = content.global.ame.RandomEventManager.Companion.AVG_DELAY_TICKS / 2
|
||||
const val MAX_DELAY_TICKS = content.global.ame.RandomEventManager.Companion.MIN_DELAY_TICKS + content.global.ame.RandomEventManager.Companion.AVG_DELAY_TICKS // window of 60 min centered on 60 min (30 to 90 min)
|
||||
|
||||
@JvmStatic fun getInstance(player: Player): content.global.ame.RandomEventManager?
|
||||
{
|
||||
return getAttribute(player, "random-manager", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package content.global.ame
|
||||
|
||||
import content.global.ame.events.MysteriousOldManNPC
|
||||
import core.api.poofClear
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.integrations.discord.Discord
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.tools.secondsToTicks
|
||||
import kotlin.random.Random
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
abstract class RandomEventNPC(id: Int) : NPC(id) {
|
||||
lateinit var player: Player
|
||||
abstract var loot: WeightBasedTable?
|
||||
var spawnLocation: Location? = null
|
||||
val SMOKE_GRAPHICS = Graphics(86)
|
||||
var initialized = false
|
||||
var finalized = false
|
||||
var timerPaused = false
|
||||
var ticksLeft = secondsToTicks(180)
|
||||
|
||||
open fun create(player: Player, loot: WeightBasedTable? = null, type: String = ""): RandomEventNPC {
|
||||
val event = this::class.createInstance()
|
||||
if (event is MysteriousOldManNPC) event.type = type
|
||||
event.loot = loot
|
||||
event.player = player
|
||||
event.spawnLocation = RegionManager.getSpawnLocation(player, this)
|
||||
return event
|
||||
}
|
||||
|
||||
open fun terminate() {
|
||||
finalized = true
|
||||
pulseManager.clear(PulseType.STANDARD)
|
||||
content.global.ame.RandomEventManager.getInstance(player)?.event = null
|
||||
if (initialized) {
|
||||
poofClear(this)
|
||||
}
|
||||
}
|
||||
|
||||
open fun follow() {
|
||||
pulseManager.run((object : MovementPulse(this, player, Pathfinder.DUMB) {
|
||||
override fun pulse(): Boolean {
|
||||
face(player)
|
||||
return false
|
||||
}
|
||||
}), PulseType.STANDARD)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
if(player.getAttribute<RandomEventNPC?>("re-npc", null) != this){
|
||||
terminate()
|
||||
return
|
||||
}
|
||||
if (!player.getAttribute("random:pause", false)) {
|
||||
ticksLeft--
|
||||
}
|
||||
|
||||
if (!pulseManager.hasPulseRunning() && !finalized) {
|
||||
follow()
|
||||
}
|
||||
if (!player.isActive || !player.location.withinDistance(location, 10)) {
|
||||
terminate()
|
||||
}
|
||||
if (ticksLeft <= 0 && initialized) {
|
||||
onTimeUp()
|
||||
initialized = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
initialized = true
|
||||
finalized = false
|
||||
timerPaused = false
|
||||
spawnLocation ?: terminate()
|
||||
location = spawnLocation
|
||||
player.setAttribute("re-npc", this)
|
||||
super.init()
|
||||
}
|
||||
|
||||
open fun onTimeUp() {
|
||||
noteAndTeleport()
|
||||
terminate()
|
||||
}
|
||||
|
||||
fun noteAndTeleport() {
|
||||
for (item in player.inventory.toArray()) {
|
||||
if (item == null) continue
|
||||
if (item.definition.isUnnoted) {
|
||||
player.inventory.remove(item)
|
||||
player.inventory.add(Item(item.noteChange, item.amount))
|
||||
}
|
||||
}
|
||||
if (Random.nextBoolean()) {
|
||||
player.properties.teleportLocation = Location.create(3197, 3223, 0)
|
||||
} else {
|
||||
player.properties.teleportLocation = Location.create(3212, 9620, 0)
|
||||
}
|
||||
player.graphics(SMOKE_GRAPHICS)
|
||||
Discord.postPlayerAlert(player.username, "Ignored Random")
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
super.clear()
|
||||
if(player.getAttribute<RandomEventNPC?>("re-npc", null) == this) player.removeAttribute("re-npc")
|
||||
}
|
||||
|
||||
abstract fun talkTo(npc: NPC)
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.ame
|
||||
|
||||
import org.rs09.consts.Items
|
||||
import content.global.ame.events.MysteriousOldManNPC
|
||||
import content.global.ame.events.certer.CerterNPC
|
||||
import content.global.ame.events.drilldemon.SeargentDamienNPC
|
||||
import content.global.ame.events.evilchicken.EvilChickenNPC
|
||||
import content.global.ame.events.genie.GenieNPC
|
||||
import content.global.ame.events.rivertroll.RiverTrollRENPC
|
||||
import content.global.ame.events.rockgolem.RockGolemRENPC
|
||||
import content.global.ame.events.sandwichlady.SandwichLadyRENPC
|
||||
import content.global.ame.events.shade.ShadeRENPC
|
||||
import content.global.ame.events.treespirit.TreeSpiritRENPC
|
||||
import content.global.ame.events.zombie.ZombieRENPC
|
||||
|
||||
import core.api.utils.WeightBasedTable
|
||||
import core.api.utils.WeightedItem
|
||||
|
||||
enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = null) {
|
||||
SANDWICH_LADY(SandwichLadyRENPC()),
|
||||
GENIE(GenieNPC()),
|
||||
CERTER(CerterNPC(), WeightBasedTable.create(
|
||||
WeightedItem(Items.UNCUT_SAPPHIRE_1623,1,1,3.4),
|
||||
WeightedItem(Items.KEBAB_1971,1,1,1.7),
|
||||
WeightedItem(Items.UNCUT_EMERALD_1621,1,1,1.7),
|
||||
WeightedItem(Items.SPINACH_ROLL_1969,1,1,1.5),
|
||||
WeightedItem(Items.COINS_995,80,80,1.1),
|
||||
WeightedItem(Items.COINS_995,160,160,1.1),
|
||||
WeightedItem(Items.COINS_995,320,320,1.1),
|
||||
WeightedItem(Items.COINS_995,480,480,1.1),
|
||||
WeightedItem(Items.COINS_995,640,640,1.1),
|
||||
WeightedItem(Items.UNCUT_RUBY_1619,1,1,0.86),
|
||||
WeightedItem(Items.COINS_995,240,240,0.65),
|
||||
WeightedItem(Items.COSMIC_TALISMAN_1454,1,1,0.43),
|
||||
WeightedItem(Items.UNCUT_DIAMOND_1617,1,1,0.22),
|
||||
WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985,1,1,0.1),
|
||||
WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1)
|
||||
)),
|
||||
DRILL_DEMON(SeargentDamienNPC()),
|
||||
EVIL_CHICKEN(EvilChickenNPC()),
|
||||
SURPRISE_EXAM(MysteriousOldManNPC(),"sexam"),
|
||||
TREE_SPIRIT(TreeSpiritRENPC(),"skill"),
|
||||
RIVER_TROLL(RiverTrollRENPC(),"skill"),
|
||||
ROCK_GOLEM(RockGolemRENPC(),"skill"),
|
||||
SHADE(ShadeRENPC(),"skill"),
|
||||
ZOMBIE(ZombieRENPC(),"skill");
|
||||
|
||||
var type: String = ""
|
||||
private set
|
||||
|
||||
constructor(npc: RandomEventNPC, type: String) : this(npc,null){
|
||||
this.type = type
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val randomIDs = values().map { it.npc.id }.toList()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.ame.events
|
||||
|
||||
import core.game.node.entity.player.Player
|
||||
import content.global.ame.events.supriseexam.SurpriseExamUtils
|
||||
import core.game.dialogue.DialogueFile
|
||||
|
||||
class MysteriousOldManDialogue(val type: String) : DialogueFile() {
|
||||
|
||||
val CHOICE_STAGE = 50000
|
||||
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
|
||||
if(type == "sexam" && stage < CHOICE_STAGE){
|
||||
npc("Would you like to come do a surprise exam?")
|
||||
stage = CHOICE_STAGE
|
||||
}
|
||||
|
||||
else if(stage >= CHOICE_STAGE){
|
||||
when(stage) {
|
||||
CHOICE_STAGE -> options("Yeah, sure!", "No, thanks.").also { stage++ }
|
||||
CHOICE_STAGE.substage(1) -> when(buttonID){
|
||||
1 -> {
|
||||
end()
|
||||
teleport(player!!,type)
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)?.event?.terminate()
|
||||
}
|
||||
2 -> {
|
||||
end()
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)?.event?.terminate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun teleport(player: Player,type: String){
|
||||
when(type){
|
||||
"sexam" -> SurpriseExamUtils.teleport(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package content.global.ame.events
|
||||
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.NPCs
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
class MysteriousOldManNPC(var type: String = "", override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.MYSTERIOUS_OLD_MAN_410) {
|
||||
override fun init() {
|
||||
super.init()
|
||||
sayLine()
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
if(RandomFunction.random(1,10) == 5) sayLine()
|
||||
}
|
||||
|
||||
fun sayLine() {
|
||||
when(type){
|
||||
"sexam" -> sendChat("Surprise exam, ${player.username.capitalize()}!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
when(type){
|
||||
"sexam" -> player.dialogueInterpreter.open(MysteriousOldManDialogue("sexam"),this.asNpc())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package content.global.ame.events.certer
|
||||
|
||||
import core.api.addItemOrDrop
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.player.link.emote.Emotes
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class CerterDialogue(val initial: Boolean) : DialogueFile() {
|
||||
val CERTER_INTERFACE = 184
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
if (initial && !player!!.getAttribute("certer:reward", false)) {
|
||||
when (stage) {
|
||||
0 -> npc("Ah, hello, ${player!!.username.capitalize()}. Could you", "please help me identify this?").also { stage++ }
|
||||
1 -> {
|
||||
end()
|
||||
player!!.interfaceManager.open(Component(CERTER_INTERFACE))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player!!.setAttribute("random:pause", true)
|
||||
val isCorrect = player!!.getAttribute("certer:correct", false)
|
||||
val receivedReward = player!!.getAttribute("certer:reward", false)
|
||||
if (receivedReward == true) {
|
||||
stage = 1
|
||||
}
|
||||
when (stage) {
|
||||
0 -> if (!isCorrect) {
|
||||
npc("Sorry, I don't think so.").also {
|
||||
player!!.setAttribute("certer:reward", true)
|
||||
stage = END_DIALOGUE
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)?.event?.terminate()
|
||||
}
|
||||
} else {
|
||||
npc("Thank you, I hope you like your present. I must be", "leaving now though.").also {
|
||||
player!!.setAttribute("certer:reward", true)
|
||||
stage = END_DIALOGUE
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event!!.loot!!.roll().forEach { addItemOrDrop(player!!, it.id, it.amount) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun end() {
|
||||
super.end()
|
||||
if (player!!.getAttribute("certer:reward", false)) {
|
||||
// Remove movement pulse to stop following player
|
||||
npc!!.pulseManager.clear(PulseType.STANDARD)
|
||||
// Wave goodbye
|
||||
npc!!.animate(Emotes.WAVE.animation)
|
||||
// Terminate the event
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)?.event?.terminate()
|
||||
} else {
|
||||
player!!.setAttribute("random:pause", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package content.global.ame.events.certer
|
||||
|
||||
import content.global.ame.RandomEventManager
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.InterfaceListener
|
||||
|
||||
class CerterEventInterface : InterfaceListener {
|
||||
val CERTER_INTERFACE = 184
|
||||
val OPTION_A_CHILD = 1
|
||||
val OPTION_B_CHILD = 2
|
||||
val OPTION_C_CHILD = 3
|
||||
val ITEM_CHILD = 7
|
||||
val items = mapOf(
|
||||
/*
|
||||
* NOTE: We use these "NULL" items to get their model id + zoom values.
|
||||
* These were the actual items used by this random event before they
|
||||
* decided to swap over to using model ids instead.
|
||||
*/
|
||||
Items.BOWL_1923 to "A bowl.",
|
||||
Items.NULL_6189 to "A fish.",
|
||||
Items.NULL_6190 to "A bass.",
|
||||
Items.NULL_6191 to "A sword.",
|
||||
Items.NULL_6192 to "A battleaxe.",
|
||||
Items.NULL_6193 to "A helmet.",
|
||||
Items.NULL_6194 to "A kiteshield.",
|
||||
Items.NULL_6195 to "A pair of shears.",
|
||||
Items.NULL_6196 to "A shovel.",
|
||||
Items.NULL_6197 to "A ring.",
|
||||
Items.NULL_6198 to "A necklace."
|
||||
)
|
||||
val falseOptions = arrayOf("An axe.", "An arrow.", "A pair of boots.", "A pair of gloves.", "A staff.", "A bow.", "A feather.", "The disenfrachaised youth of 1940's Columbia.")
|
||||
override fun defineInterfaceListeners() {
|
||||
on(CERTER_INTERFACE) { player, _, _, buttonID, _, _ ->
|
||||
val answer = buttonID - 7
|
||||
val correctAnswer = player.getAttribute("certer:correctIndex", 0)
|
||||
player.setAttribute("certer:correct", correctAnswer == answer)
|
||||
player.interfaceManager.close()
|
||||
player.dialogueInterpreter.open(CerterDialogue(false), RandomEventManager.getInstance(player)!!.event?.asNpc())
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(CERTER_INTERFACE) { player, _ ->
|
||||
generateOptions(player)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
onClose(CERTER_INTERFACE) { player, _ ->
|
||||
player.setAttribute("random:pause", false)
|
||||
return@onClose true
|
||||
}
|
||||
}
|
||||
|
||||
fun generateOptions(player: Player) {
|
||||
val correct = items.keys.random()
|
||||
val indexes = arrayListOf(1, 2, 3)
|
||||
val correctIndex = indexes.random()
|
||||
val correctItem = Item(correct).definition
|
||||
val iFaceModelId = correctItem.interfaceModelId
|
||||
val iFaceZoom = correctItem.modelZoom
|
||||
indexes.remove(correctIndex)
|
||||
player.setAttribute("certer:correctIndex", correctIndex)
|
||||
|
||||
player.packetDispatch.sendString(items[correct], CERTER_INTERFACE, optionFromIndex(correctIndex))
|
||||
|
||||
val tempOptions = falseOptions.toMutableList()
|
||||
val false1 = tempOptions.random()
|
||||
tempOptions.remove(false1)
|
||||
val false2 = tempOptions.random()
|
||||
|
||||
player.packetDispatch.sendString(false1, CERTER_INTERFACE, optionFromIndex(indexes[0]))
|
||||
player.packetDispatch.sendString(false2, CERTER_INTERFACE, optionFromIndex(indexes[1]))
|
||||
player.packetDispatch.sendModelOnInterface(iFaceModelId, CERTER_INTERFACE, ITEM_CHILD, iFaceZoom)
|
||||
}
|
||||
|
||||
fun optionFromIndex(index: Int): Int {
|
||||
return when (index) {
|
||||
1 -> OPTION_A_CHILD
|
||||
2 -> OPTION_B_CHILD
|
||||
3 -> OPTION_C_CHILD
|
||||
else -> OPTION_A_CHILD
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package content.global.ame.events.certer
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.link.emote.Emotes
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.NPCs
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.animate
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
class CerterNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.GILES_2538) {
|
||||
lateinit var pName: String
|
||||
lateinit var phrases: Array<String>
|
||||
|
||||
override fun tick() {
|
||||
// Don't speak if we have the interface opened
|
||||
if (!timerPaused) {
|
||||
// Over allotted time phrase
|
||||
if (ticksLeft <= 2) {
|
||||
player.lock(2)
|
||||
sendChat(phrases[4])
|
||||
|
||||
// Say a phrase every 20 ticks starting at 280 ticks
|
||||
// as to not interfere with the init chat phrase
|
||||
} else if (ticksLeft <= 280 && ticksLeft % 20 == 0) {
|
||||
sendChat(phrases[RandomFunction.random(1, 3)])
|
||||
}
|
||||
}
|
||||
super.tick()
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
player.setAttribute("random:pause", true)
|
||||
player.dialogueInterpreter.open(CerterDialogue(true),npc)
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
pName = player.username.capitalize()
|
||||
phrases = arrayOf("Greetings $pName, I need your help.",
|
||||
"ehem... Hello $pName, please talk to me!",
|
||||
"Hello, are you there $pName?",
|
||||
"It's really rude to ignore someone, $pName!",
|
||||
"No-one ignores me!")
|
||||
player.setAttribute("random:pause", false)
|
||||
player.setAttribute("certer:reward", false)
|
||||
sendChat(phrases[0])
|
||||
animate(this, Emotes.BOW.animation, true)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package content.global.ame.events.drilldemon
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.system.task.Pulse
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
class DrillDemonListeners : InteractionListener {
|
||||
val MATS = intArrayOf(10076,10077,10078,10079)
|
||||
override fun defineListeners() {
|
||||
|
||||
on(MATS, IntType.SCENERY, "use"){ player, node ->
|
||||
val correctTask = player.getAttribute(DrillDemonUtils.DD_KEY_TASK,-1)
|
||||
if(correctTask == -1){
|
||||
player.sendMessage("You can't do that right now.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
val task = DrillDemonUtils.getMatTask(node.id,player)
|
||||
val npc = NPC(NPCs.SERGEANT_DAMIEN_2790)
|
||||
|
||||
player.lock()
|
||||
val anim = DrillDemonUtils.animationForTask(task)
|
||||
player.walkingQueue.reset()
|
||||
player.walkingQueue.addPath(node.location.x,4820)
|
||||
player.pulseManager.run(object : Pulse(){
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when(counter++){
|
||||
2 -> player.faceLocation(player.location.transform(0,-1,0))
|
||||
3 -> player.animator.animate(DrillDemonUtils.animationForTask(task)).also { delay = anim.duration / 2 }
|
||||
6 -> {
|
||||
if(task == correctTask){
|
||||
player.incrementAttribute(DrillDemonUtils.DD_CORRECT_COUNTER)
|
||||
player.dialogueInterpreter.open(SeargentDamienDialogue(true),npc)
|
||||
} else {
|
||||
player.dialogueInterpreter.open(SeargentDamienDialogue(false),npc)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package content.global.ame.events.drilldemon
|
||||
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
object DrillDemonUtils {
|
||||
val DD_KEY_NPC = "drilldemon:npc"
|
||||
val DD_KEY_TASK = "drilldemon:task"
|
||||
val DD_KEY_RETURN_LOC = "drilldemon:original-loc"
|
||||
val DD_SIGN_VARP = 531
|
||||
val DD_SIGN_JOG = 0
|
||||
val DD_SIGN_SITUP = 1
|
||||
val DD_SIGN_PUSHUP = 2
|
||||
val DD_SIGN_JUMP = 3
|
||||
val DD_CORRECT_OFFSET = "drilldemon:offset"
|
||||
val DD_CORRECT_COUNTER = "drilldemon:numcorrect"
|
||||
|
||||
fun teleport(player: Player){
|
||||
player.setAttribute(DD_KEY_RETURN_LOC,player.location)
|
||||
player.properties.teleportLocation = Location.create(3163, 4819, 0)
|
||||
player.interfaceManager.closeDefaultTabs()
|
||||
player.packetDispatch.sendInterfaceConfig(548, 69, true)
|
||||
player.packetDispatch.sendInterfaceConfig(746, 12, true)
|
||||
|
||||
registerLogoutListener(player, "drilldemon"){p ->
|
||||
teleport(p, player.getAttribute(DD_KEY_RETURN_LOC, p.location))
|
||||
}
|
||||
|
||||
changeSignsAndAssignTask(player)
|
||||
}
|
||||
|
||||
fun changeSignsAndAssignTask(player: Player){
|
||||
player.varpManager.get(DD_SIGN_VARP).clearBitRange(0,31)
|
||||
val tempList = arrayListOf(DD_SIGN_JOG, DD_SIGN_JUMP, DD_SIGN_PUSHUP, DD_SIGN_SITUP).shuffled().toMutableList()
|
||||
val tempOffsetList = arrayListOf(0,2,4,6).shuffled().toMutableList()
|
||||
val task = tempList.random()
|
||||
val taskOffset = tempOffsetList.random()
|
||||
|
||||
player.setAttribute(DD_KEY_TASK,task)
|
||||
player.setAttribute(DD_CORRECT_OFFSET,taskOffset)
|
||||
|
||||
tempList.remove(task)
|
||||
tempOffsetList.remove(taskOffset)
|
||||
player.varpManager.get(DD_SIGN_VARP).setVarbit(taskOffset,task).send(player)
|
||||
for(i in 0 until tempList.size){
|
||||
player.varpManager.get(DD_SIGN_VARP).setVarbit(tempOffsetList[i],tempList[i]).send(player)
|
||||
}
|
||||
|
||||
player.dialogueInterpreter.sendDialogues(NPCs.SERGEANT_DAMIEN_2790, core.game.dialogue.FacialExpression.OLD_NORMAL,when(task){
|
||||
DD_SIGN_JOG -> "Get over there and jog in place!"
|
||||
DD_SIGN_JUMP -> "I need 40 jumping jacks stat!"
|
||||
DD_SIGN_PUSHUP -> "Get over there and give me 20 pushups!"
|
||||
DD_SIGN_SITUP -> "I need 30 situps pronto!"
|
||||
else -> "REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
|
||||
})
|
||||
player.unlock()
|
||||
}
|
||||
|
||||
fun getOffsetForID(id: Int): Int{
|
||||
return when(id){
|
||||
10076 -> 0
|
||||
10077 -> 2
|
||||
10078 -> 4
|
||||
10079 -> 6
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
fun getMatTask(id: Int, player: Player): Int{
|
||||
return player.varpManager.get(DD_SIGN_VARP).getVarbitValue(getOffsetForID(id)) ?: 0
|
||||
}
|
||||
|
||||
fun cleanup(player: Player){
|
||||
clearLogoutListener(player, "drilldemon")
|
||||
player.properties.teleportLocation = player.getAttribute(DD_KEY_RETURN_LOC)
|
||||
player.removeAttribute(DD_KEY_NPC)
|
||||
player.removeAttribute(DD_KEY_RETURN_LOC)
|
||||
player.removeAttribute(DD_KEY_TASK)
|
||||
player.removeAttribute(DD_CORRECT_OFFSET)
|
||||
player.removeAttribute(DD_CORRECT_COUNTER)
|
||||
player.interfaceManager.openDefaultTabs()
|
||||
player.packetDispatch.sendInterfaceConfig(548, 69, false)
|
||||
player.packetDispatch.sendInterfaceConfig(746, 12, false)
|
||||
}
|
||||
|
||||
fun animationForTask(task: Int): Animation {
|
||||
return when(task){
|
||||
DD_SIGN_SITUP -> Animation(2763)
|
||||
DD_SIGN_PUSHUP -> Animation(2762)
|
||||
DD_SIGN_JUMP -> Animation(2761)
|
||||
DD_SIGN_JOG -> Animation(2764)
|
||||
else -> Animation(-1)
|
||||
}
|
||||
}
|
||||
|
||||
fun reward(player: Player){
|
||||
val hasHat = player.inventory.contains(Items.CAMO_HELMET_6656,1) || player.bank.contains(Items.CAMO_HELMET_6656,1) || player.equipment.contains(Items.CAMO_HELMET_6656,1)
|
||||
val hasShirt = player.inventory.contains(Items.CAMO_TOP_6654,1) || player.bank.contains(Items.CAMO_TOP_6654,1) || player.equipment.contains(Items.CAMO_TOP_6654,1)
|
||||
val hasPants = player.inventory.contains(Items.CAMO_BOTTOMS_6655,1) || player.bank.contains(Items.CAMO_BOTTOMS_6655,1) || player.equipment.contains(Items.CAMO_BOTTOMS_6655,1)
|
||||
val reward = if(!hasHat){
|
||||
Item(Items.CAMO_HELMET_6656)
|
||||
} else if(!hasShirt){
|
||||
Item(Items.CAMO_TOP_6654)
|
||||
} else if(!hasPants){
|
||||
Item(Items.CAMO_BOTTOMS_6655)
|
||||
} else {
|
||||
Item(Items.COINS_995, 500)
|
||||
}
|
||||
if(!player.inventory.add(reward)){
|
||||
GroundItemManager.create(reward,player)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package content.global.ame.events.drilldemon
|
||||
|
||||
import core.game.dialogue.DialoguePlugin
|
||||
import core.game.node.entity.player.Player
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.NPCs
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class SeargentDamienDefaultPlugin(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
|
||||
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin {
|
||||
return SeargentDamienDefaultPlugin(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
npc("GET BACK TO WORK MAGGOT!")
|
||||
stage = END_DIALOGUE
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SERGEANT_DAMIEN_2790)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package content.global.ame.events.drilldemon
|
||||
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
class SeargentDamienDialogue(val isCorrect: Boolean = false) : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
var correctAmt = player!!.getAttribute(DrillDemonUtils.DD_CORRECT_COUNTER,0)
|
||||
if(correctAmt == 4 && content.global.ame.RandomEventManager.getInstance(player!!)!!.event == null) {
|
||||
when(stage){
|
||||
0 -> npc(core.game.dialogue.FacialExpression.OLD_NORMAL,"My god you actually did it, you limp","wristed worm-bodied MAGGOT! Take this","and get out of my sight.").also { stage++ }
|
||||
1 -> {
|
||||
end()
|
||||
player!!.unlock()
|
||||
DrillDemonUtils.cleanup(player!!)
|
||||
player!!.pulseManager.run(object : Pulse(2){
|
||||
override fun pulse(): Boolean {
|
||||
DrillDemonUtils.reward(player!!)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if(content.global.ame.RandomEventManager.getInstance(player!!)!!.event == null){
|
||||
when(stage){
|
||||
START_DIALOGUE -> if(isCorrect) npc(core.game.dialogue.FacialExpression.OLD_NORMAL,"Good! Now...").also { stage++ } else npc(core.game.dialogue.FacialExpression.OLD_ANGRY1,"WRONG, MAGGOT!").also { stage++ }
|
||||
1 -> {
|
||||
end()
|
||||
DrillDemonUtils.changeSignsAndAssignTask(player!!)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when(stage){
|
||||
START_DIALOGUE -> npc(core.game.dialogue.FacialExpression.OLD_NORMAL,"Would you like to come work out?").also { stage++ }
|
||||
1 -> options("Yes, please.", "No, thanks.").also { stage++ }
|
||||
2 -> when(buttonID){
|
||||
1 -> {
|
||||
end()
|
||||
DrillDemonUtils.teleport(player!!)
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event?.terminate()
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
2 -> {
|
||||
end()
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event?.terminate()
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package content.global.ame.events.drilldemon
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.NPCs
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
class SeargentDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
sendChat(player.username.capitalize() + "! Drop and give me 20!")
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
if(RandomFunction.random(1,10) == 5){
|
||||
sendChat(player.username.capitalize() + "! Drop and give me 20!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
player.dialogueInterpreter.open(SeargentDamienDialogue(),npc)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.ame.events.evilchicken
|
||||
|
||||
import core.api.getWorldTicks
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import java.lang.Integer.max
|
||||
|
||||
val ids = 2463..2468
|
||||
|
||||
class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(2463) {
|
||||
val phrases = arrayOf("Bwuk","Bwuk bwuk bwuk","Flee from me, @name!","Begone, @name!","Bwaaaauuuk bwuk bwuk","MUAHAHAHAHAAA!")
|
||||
override fun talkTo(npc: NPC) {}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = max(0, (player.properties.combatLevel / 20) - 1)
|
||||
val id = ids.toList()[index]
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat(phrases.random().replace("@name",player.name.capitalize()))
|
||||
this.isRespawn = false
|
||||
}
|
||||
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
GroundItemManager.create(Item(Items.FEATHER_314, RandomFunction.random(50,300)), this.dropLocation, player)
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
if(getWorldTicks() % 10 == 0){
|
||||
sendChat(phrases.random().replace("@name",player.name.capitalize()))
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package content.global.ame.events.genie
|
||||
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class GenieDialogue : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
val assigned = player!!.getAttribute("genie:item",0)
|
||||
npcl(core.game.dialogue.FacialExpression.NEUTRAL, "Ah, so you are there, ${player!!.name.capitalize()}. I'm so glad you summoned me. Please take this lamp and make your wish.")
|
||||
addItemOrDrop(player!!, assigned)
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event?.terminate()
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package content.global.ame.events.genie
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
class GenieNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.GENIE_409) {
|
||||
val phrases = arrayOf("Greetings, @name!","Ehem... Master @name?","Are you there, Master @name?","No one ignores me!")
|
||||
var assigned_item = 0
|
||||
val items = arrayOf(Items.LAMP_2528)
|
||||
|
||||
override fun tick() {
|
||||
if(RandomFunction.random(1,15) == 5){
|
||||
sendChat(phrases.random().replace("@name",player.name.capitalize()))
|
||||
}
|
||||
super.tick()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
assignItem()
|
||||
sendChat(phrases.random().replace("@name",player.name.capitalize()))
|
||||
}
|
||||
|
||||
fun assignItem(){
|
||||
assigned_item = items.random()
|
||||
player.setAttribute("genie:item",assigned_item)
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
player.dialogueInterpreter.open(GenieDialogue(),npc)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user