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,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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package content.global.ame.events.rivertroll
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import java.lang.Integer.max
|
||||
|
||||
|
||||
val ids = 391..396
|
||||
|
||||
class RiverTrollRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(391){
|
||||
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("Fishies be mine, leave dem fishies!")
|
||||
this.isRespawn = false
|
||||
}
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
}
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package content.global.ame.events.rockgolem
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
val ids = 413..418
|
||||
|
||||
class RockGolemRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(413){
|
||||
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("Raarrrgghh! Flee human!")
|
||||
this.isRespawn = false
|
||||
}
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
}
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package content.global.ame.events.sandwichlady
|
||||
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.combat.ImpactHandler
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class SandwichLadyDialogue(val isChoice: Boolean) : DialogueFile() {
|
||||
val SANDWICH_INTERFACE = 297
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
val assigned = player!!.getAttribute("sandwich-lady:item",0)
|
||||
val choice = player!!.getAttribute("sandwich-lady:choice",0)
|
||||
if(!isChoice) {
|
||||
when (stage) {
|
||||
0 -> npc("Have a ${ItemDefinition.forId(assigned).name.toLowerCase()}, dear.").also { stage++ }
|
||||
1 -> {
|
||||
end()
|
||||
player!!.interfaceManager.open(Component(SANDWICH_INTERFACE))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when(stage){
|
||||
0 -> if(choice != assigned){
|
||||
npc!!.sendChat("That's not what I said you could have!")
|
||||
player!!.impactHandler.manualHit(npc,3,ImpactHandler.HitsplatType.NORMAL)
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event?.terminate()
|
||||
} else {
|
||||
npc("Here you are, dear. I hope you enjoy it!")
|
||||
if(!player!!.inventory.add(Item(assigned))){
|
||||
GroundItemManager.create(Item(assigned),player)
|
||||
}
|
||||
content.global.ame.RandomEventManager.getInstance(player!!)!!.event?.terminate()
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package content.global.ame.events.sandwichlady
|
||||
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.InterfaceListener
|
||||
|
||||
class SandwichLadyInterface : InterfaceListener {
|
||||
|
||||
val SANDWICH_INTERFACE = 297
|
||||
val baguette = Items.BAGUETTE_6961
|
||||
val triangle_sandwich = Items.TRIANGLE_SANDWICH_6962
|
||||
val sandwich = Items.SQUARE_SANDWICH_6965
|
||||
val roll = Items.ROLL_6963
|
||||
val pie = Items.MEAT_PIE_2327
|
||||
val kebab = Items.KEBAB_1971
|
||||
val chocobar = Items.CHOCOLATE_BAR_1973
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
on(SANDWICH_INTERFACE){player, _, _, buttonID, _, _ ->
|
||||
val item =
|
||||
when(buttonID) {
|
||||
7 -> {Item(baguette)}
|
||||
8 -> {Item(triangle_sandwich)}
|
||||
9 -> {Item(sandwich)}
|
||||
10 -> {Item(roll)}
|
||||
11 -> {Item(pie)}
|
||||
12 -> {Item(kebab)}
|
||||
13 -> {Item(chocobar)}
|
||||
else -> {Item(baguette)}
|
||||
}
|
||||
|
||||
player.setAttribute("sandwich-lady:choice",item.id)
|
||||
player.interfaceManager.close()
|
||||
player.dialogueInterpreter.open(SandwichLadyDialogue(true), content.global.ame.RandomEventManager.getInstance(player)!!.event)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package content.global.ame.events.sandwichlady
|
||||
|
||||
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 SandwichLadyRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SANDWICH_LADY_3117) {
|
||||
val phrases = arrayOf("Hello, @name, can you hear me?","Sandwiches, @name!","Are you ignoring me @name??","Yoohoo! Sandwiches, @name!","Hello, @name?", "Come get your sandwiches @name!", "How could you ignore me like this @name?!", "Do you even want your sandwiches, @name?")
|
||||
var assigned_item = 0
|
||||
val items = arrayOf(Items.BAGUETTE_6961,Items.TRIANGLE_SANDWICH_6962,Items.SQUARE_SANDWICH_6965,Items.ROLL_6963,Items.MEAT_PIE_2327,Items.KEBAB_1971,Items.CHOCOLATE_BAR_1973)
|
||||
|
||||
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("sandwich-lady:item",assigned_item)
|
||||
}
|
||||
|
||||
override fun talkTo(npc: NPC) {
|
||||
player.dialogueInterpreter.open(SandwichLadyDialogue(false),npc)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package content.global.ame.events.shade
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
|
||||
val ids = 425..430
|
||||
|
||||
class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(425){
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = (player.properties.combatLevel / 20) - 1
|
||||
val id = ids.toList()[index]
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Leave this place!")
|
||||
this.isRespawn = false
|
||||
}
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
}
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package content.global.ame.events.supriseexam
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class MordautDialogue(val examComplete: Boolean, val questionCorrect: Boolean = false, val fromInterface: Boolean = false) : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
if(examComplete){
|
||||
if(player!!.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1) == -1){
|
||||
SurpriseExamUtils.pickRandomDoor(player!!)
|
||||
}
|
||||
val door = player!!.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1)
|
||||
val doortext = when(door){
|
||||
2188 -> "red cross"
|
||||
2189 -> "blue star"
|
||||
2192 -> "purple circle"
|
||||
2193 -> "green square"
|
||||
else -> "REEEEEEEEEEEEEEEE"
|
||||
}
|
||||
|
||||
npc("Please exit through the $doortext door.")
|
||||
stage = END_DIALOGUE
|
||||
} else if(fromInterface){
|
||||
|
||||
if(questionCorrect){
|
||||
if(player!!.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT,0) == 3){
|
||||
player!!.dialogueInterpreter.open(MordautDialogue(true),npc)
|
||||
} else {
|
||||
when(stage++){
|
||||
0 -> npc("Excellent work!")
|
||||
1 -> npc("Now for another...")
|
||||
2 -> {
|
||||
end()
|
||||
player!!.interfaceManager.open(Component(SurpriseExamUtils.INTERFACE))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when(stage++){
|
||||
0 -> npc("I'm afraid that isn't correct.")
|
||||
1 -> npc("Now for another...")
|
||||
2 -> {
|
||||
end()
|
||||
player!!.interfaceManager.open(Component(SurpriseExamUtils.INTERFACE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
when(stage++){
|
||||
0 -> npc("Please answer these questions for me.")
|
||||
1 -> {
|
||||
end()
|
||||
player!!.interfaceManager.open(Component(SurpriseExamUtils.INTERFACE))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun npc(vararg messages: String?): Component? {
|
||||
return super.npc(core.game.dialogue.FacialExpression.OLD_NORMAL,*messages)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package content.global.ame.events.supriseexam
|
||||
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
class SEDoorDialogue(val preExam: Boolean) : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
stage = if(preExam){
|
||||
dialogue("I should probably speak with Mr. Mordaut first.")
|
||||
END_DIALOGUE
|
||||
} else {
|
||||
dialogue("The door won't budge. Perhaps I should","ask for directions.")
|
||||
END_DIALOGUE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package content.global.ame.events.supriseexam
|
||||
|
||||
import core.game.node.entity.npc.NPC
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.interaction.InterfaceListener
|
||||
|
||||
class SEPatternInterface : InterfaceListener {
|
||||
|
||||
val COMPONENT = Components.PATTERN_NEXT_103
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
|
||||
on(COMPONENT){player, component, opcode, buttonID, slot, itemID ->
|
||||
val index = buttonID - 10
|
||||
val correctIndex = player.getAttribute(SurpriseExamUtils.SE_KEY_INDEX,0)
|
||||
player.interfaceManager.close()
|
||||
|
||||
if(index == correctIndex){
|
||||
player.incrementAttribute(SurpriseExamUtils.SE_KEY_CORRECT)
|
||||
val done = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT,0) == 3
|
||||
player.dialogueInterpreter.open(MordautDialogue(examComplete = done,questionCorrect = true,fromInterface = true), NPC(NPCs.MR_MORDAUT_6117))
|
||||
} else {
|
||||
player.dialogueInterpreter.open(MordautDialogue(examComplete = false,questionCorrect = false,fromInterface = true),NPC(NPCs.MR_MORDAUT_6117))
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(COMPONENT){player, component ->
|
||||
SurpriseExamUtils.generateInterface(player)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package content.global.ame.events.supriseexam
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import content.global.handlers.iface.ExperienceInterface
|
||||
|
||||
class SupriseExamListeners : InteractionListener {
|
||||
val MORDAUT = NPCs.MR_MORDAUT_6117
|
||||
val BOOK_OF_KNOWLEDGE = Items.BOOK_OF_KNOWLEDGE_11640
|
||||
override fun defineListeners() {
|
||||
|
||||
on(MORDAUT, IntType.NPC, "talk-to"){ player, node ->
|
||||
player.faceLocation(Location.create(1886, 5024, 0))
|
||||
val examComplete = player.getAttribute(SurpriseExamUtils.SE_KEY_CORRECT,0) == 3
|
||||
player.dialogueInterpreter.open(MordautDialogue(examComplete),node.asNpc())
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open"){ player, node ->
|
||||
val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1)
|
||||
|
||||
if(correctDoor == -1){
|
||||
player.dialogueInterpreter.open(SEDoorDialogue(true))
|
||||
return@on true
|
||||
}
|
||||
|
||||
if(node.id == correctDoor){
|
||||
SurpriseExamUtils.cleanup(player)
|
||||
return@on true
|
||||
}
|
||||
|
||||
player.dialogueInterpreter.open(SEDoorDialogue(false))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(BOOK_OF_KNOWLEDGE, IntType.ITEM, "read"){ player, _ ->
|
||||
player.setAttribute("caller"){skill: Int,p: Player ->
|
||||
if(p.inventory.remove(Item(BOOK_OF_KNOWLEDGE))) {
|
||||
val level = p.skills.getStaticLevel(skill)
|
||||
val experience = level * 15.0
|
||||
p.skills.addExperience(skill, experience)
|
||||
}
|
||||
}
|
||||
player.interfaceManager.open(Component(ExperienceInterface.COMPONENT_ID))
|
||||
return@on true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun defineDestinationOverrides() {
|
||||
setDest(IntType.NPC,MORDAUT){ _, _ ->
|
||||
return@setDest Location.create(1886, 5025, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package content.global.ame.events.supriseexam
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
|
||||
object SurpriseExamUtils {
|
||||
|
||||
val SE_KEY_LOC = "supexam:loc"
|
||||
val SE_KEY_INDEX = "supexam:index"
|
||||
val SE_LOGOUT_KEY = "suprise_exam"
|
||||
val SE_DOOR_KEY = "supexam:door"
|
||||
val INTER_PATTERN_CHILDS = intArrayOf(6,7,8)
|
||||
val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13)
|
||||
val SE_DOORS = intArrayOf(2188,2189,2192,2193)
|
||||
val INTERFACE = Components.PATTERN_NEXT_103
|
||||
val SE_KEY_CORRECT = "supexam:correct"
|
||||
val sets = arrayOf(
|
||||
intArrayOf(Items.GARDENING_TROWEL_5325,Items.SECATEURS_5329,Items.SEED_DIBBER_5343,Items.RAKE_5341),
|
||||
intArrayOf(Items.SALMON_329,Items.SHARK_385,Items.TROUT_333,Items.SHRIMPS_315),
|
||||
intArrayOf(Items.BRONZE_SWORD_1277,Items.WOODEN_SHIELD_1171,Items.BRONZE_MED_HELM_1139,Items.ADAMANT_BATTLEAXE_1371),
|
||||
intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311)
|
||||
)
|
||||
|
||||
fun teleport(player: Player){
|
||||
player.setAttribute(SE_KEY_LOC,player.location)
|
||||
|
||||
registerLogoutListener(player, SE_LOGOUT_KEY){p ->
|
||||
teleport(p, p.getAttribute(SE_KEY_LOC, p.location))
|
||||
}
|
||||
|
||||
player.properties.teleportLocation = Location.create(1886, 5025, 0)
|
||||
}
|
||||
|
||||
fun cleanup(player: Player){
|
||||
player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC,null)
|
||||
clearLogoutListener(player, SE_LOGOUT_KEY)
|
||||
player.removeAttribute(SE_KEY_LOC)
|
||||
player.removeAttribute(SE_KEY_INDEX)
|
||||
player.removeAttribute(SE_KEY_CORRECT)
|
||||
player.pulseManager.run(object : Pulse(2){
|
||||
override fun pulse(): Boolean {
|
||||
val reward = Item(Items.BOOK_OF_KNOWLEDGE_11640)
|
||||
if(!player.inventory.add(reward)){
|
||||
GroundItemManager.create(reward,player)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}, PulseType.CUSTOM_1)
|
||||
}
|
||||
|
||||
fun generateInterface(player: Player){
|
||||
val set = sets.random()
|
||||
val setIndex = sets.indexOf(set)
|
||||
|
||||
val tempList = set.toList().shuffled().toMutableList()
|
||||
val correctOpt = tempList.random()
|
||||
val optIndex = tempList.indexOf(correctOpt)
|
||||
|
||||
tempList.remove(correctOpt)
|
||||
for(i in INTER_PATTERN_CHILDS.indices) player.packetDispatch.sendItemOnInterface(tempList[i],1, INTERFACE, INTER_PATTERN_CHILDS[i])
|
||||
for(i in INTER_OPTION_CHILDS.indices){
|
||||
if(i == optIndex) player.packetDispatch.sendItemOnInterface(correctOpt,1, INTERFACE, INTER_OPTION_CHILDS[i])
|
||||
else player.packetDispatch.sendItemOnInterface(getFalseSet(setIndex)[i],1, INTERFACE, INTER_OPTION_CHILDS[i])
|
||||
}
|
||||
player.setAttribute(SE_KEY_INDEX,optIndex)
|
||||
}
|
||||
|
||||
fun getFalseSet(trueSetIndex: Int): IntArray{
|
||||
val tempSets = sets.toMutableList()
|
||||
tempSets.removeAt(trueSetIndex)
|
||||
return tempSets.random()
|
||||
}
|
||||
|
||||
fun pickRandomDoor(player: Player){
|
||||
player.setAttribute(SE_DOOR_KEY, SE_DOORS.random())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package content.global.ame.events.treespirit
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
val ids = 438..443
|
||||
|
||||
class TreeSpiritRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(438){
|
||||
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("Leave these woods and never return!")
|
||||
this.isRespawn = false
|
||||
}
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
}
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package content.global.ame.events.zombie
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import content.global.ame.RandomEventNPC
|
||||
import core.api.utils.WeightBasedTable
|
||||
|
||||
|
||||
val ids = 419..424
|
||||
|
||||
class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(419){
|
||||
override fun talkTo(npc: NPC) {}
|
||||
override fun init() {
|
||||
super.init()
|
||||
val index = (player.properties.combatLevel / 20) - 1
|
||||
val id = ids.toList()[index]
|
||||
this.transform(id)
|
||||
this.attack(player)
|
||||
sendChat("Brainsssss!")
|
||||
this.isRespawn = false
|
||||
}
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
}
|
||||
override fun tick() {
|
||||
if(!player.location.withinDistance(this.location,8)){
|
||||
this.terminate()
|
||||
}
|
||||
super.tick()
|
||||
if(!player.viewport.currentPlane.npcs.contains(this)) this.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.update.flag.*
|
||||
import core.tools.RandomFunction
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import core.ServerConstants
|
||||
import core.game.bots.AIRepository
|
||||
import core.game.bots.CombatBotAssembler
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
/**
|
||||
* A bot script for Adventurers who explore the world!
|
||||
* @param counter used in the bots random idling function.
|
||||
* @param random is used to generate random number.
|
||||
* @param city determines the home city of the bot.
|
||||
* @param freshspawn determines if the bot has just been spawned.
|
||||
* @param random_city is the list of cities that can be randomly chosen as the home city.
|
||||
* @param tree_list is the list of trees that a bot can start cutting randomly.
|
||||
* @author Sir Kermit
|
||||
* @author Ceikry
|
||||
*/
|
||||
|
||||
//Adventure Bots v4.0.0 -Expansion Edition-
|
||||
class Adventurer(val style: CombatStyle): Script() {
|
||||
|
||||
var city: Location = lumbridge
|
||||
var ticks = 0
|
||||
var freshspawn = true
|
||||
var sold = false
|
||||
private val geloc: Location = if (Random.nextBoolean()){
|
||||
Location.create(3165, 3487, 0)
|
||||
}else{
|
||||
Location.create(3164, 3492, 0)
|
||||
}
|
||||
|
||||
var counter: Int = 0
|
||||
var random: Int = (5..30).random()
|
||||
|
||||
val type = when(style){
|
||||
CombatStyle.MELEE -> CombatBotAssembler.Type.MELEE
|
||||
CombatStyle.MAGIC -> CombatBotAssembler.Type.MAGE
|
||||
CombatStyle.RANGE -> CombatBotAssembler.Type.RANGE
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.AGILITY] = 99
|
||||
inventory.add(Item(1359))//Rune Axe
|
||||
skills[Skills.WOODCUTTING] = 95
|
||||
inventory.add(Item(590))//Tinderbox
|
||||
skills[Skills.FISHING] = 90
|
||||
inventory.add(Item(1271))//Addy Pickaxe
|
||||
skills[Skills.MINING] = 90
|
||||
skills[Skills.SLAYER] = 90
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city"
|
||||
}
|
||||
|
||||
private var state = State.START
|
||||
|
||||
fun getRandomCity(): Location{
|
||||
return cities.random()
|
||||
}
|
||||
|
||||
fun getRandomPoi(): Location{
|
||||
return pois.random()
|
||||
}
|
||||
|
||||
//TODO: Optimise and adjust how bots handle picking up ground items further.
|
||||
fun immerse() {
|
||||
if (counter++ == 180) {state = State.TELEPORTING
|
||||
}
|
||||
val items = AIRepository.groundItems[bot]
|
||||
if (Random.nextBoolean()) {
|
||||
if (items.isNullOrEmpty()) {
|
||||
scriptAPI.attackNpcsInRadius(bot, 8)
|
||||
state = State.LOOT_DELAY
|
||||
}
|
||||
if (bot.inventory.isFull) {
|
||||
if(bankMap[city] == null){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
} else {
|
||||
if(bankMap[city]?.insideBorder(bot) == true){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (bot.inventory.isFull){
|
||||
if(bankMap[city] == null){
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
} else {
|
||||
if(bankMap[city]?.insideBorder(bot) == true){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
scriptAPI.walkTo(bankMap[city]?.randomLoc ?: Location(0, 0, 0))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val resources = listOf(
|
||||
"Rocks","Tree","Oak","Willow",
|
||||
"Maple tree","Yew","Magic tree",
|
||||
"Teak","Mahogany")
|
||||
val resource = scriptAPI.getNearestNodeFromList(resources,true)
|
||||
if(resource != null){
|
||||
if(resource.name.contains("ocks")) InteractionListeners.run(resource.id,
|
||||
IntType.SCENERY,"mine",bot,resource)
|
||||
else InteractionListeners.run(resource.id, IntType.SCENERY,"chop down",bot,resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
scriptAPI.teleport(lumbridge)
|
||||
freshspawn = true
|
||||
state = State.START
|
||||
}
|
||||
|
||||
var poi = false
|
||||
var poiloc = karamja
|
||||
|
||||
//Adventure Bots Actual Code STARTS HERE!!!
|
||||
override fun tick() {
|
||||
ticks++
|
||||
if (ticks++ >= 800) {
|
||||
ticks = 0
|
||||
refresh()
|
||||
return
|
||||
}
|
||||
|
||||
// zoneborder checker
|
||||
if(ticks % 30 == 0){
|
||||
for((zone, resolution) in common_stuck_locations){
|
||||
if(zone.insideBorder(bot)){
|
||||
resolution(this)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(state){
|
||||
|
||||
State.LOOT_DELAY -> {
|
||||
bot.pulseManager.run(object : Pulse() {
|
||||
var counter1 = 0
|
||||
override fun pulse(): Boolean {
|
||||
when (counter1++) {
|
||||
7 -> return true.also { state = State.LOOT }
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
State.LOOT -> {
|
||||
val items = AIRepository.groundItems[bot]
|
||||
if (items?.isNotEmpty() == true && !bot.inventory.isFull) {
|
||||
items.toTypedArray().forEach {
|
||||
scriptAPI.takeNearestGroundItem(it.id)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
state = State.EXPLORE
|
||||
}
|
||||
}
|
||||
|
||||
State.START -> {
|
||||
if (freshspawn) {
|
||||
freshspawn = false
|
||||
scriptAPI.randomWalkTo(lumbridge, 20)
|
||||
} else {
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
}
|
||||
|
||||
State.TELEPORTING -> {
|
||||
ticks = 0
|
||||
counter = 0
|
||||
if (bot.location != city) {
|
||||
poi = false
|
||||
scriptAPI.teleport(city)
|
||||
} else {
|
||||
poi = false
|
||||
state = State.EXPLORE
|
||||
}
|
||||
}
|
||||
|
||||
State.EXPLORE -> {
|
||||
if (counter++ == 350) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
|
||||
val chance = if (city == ge || city == ge2) 5000 else 2500
|
||||
if (RandomFunction.random(chance) <= 10) {
|
||||
val nearbyPlayers = RegionManager.getLocalPlayers(bot)
|
||||
if (nearbyPlayers.isNotEmpty()) {
|
||||
ticks = 0
|
||||
dialogue()
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 150 && !poi) {
|
||||
val roamDistance = if (city != ge && city != ge2) 225 else 7
|
||||
if ((city == ge || city == ge2) && RandomFunction.random(100) < 90) {
|
||||
if (!bot.bank.isEmpty) {
|
||||
state = State.FIND_GE
|
||||
}
|
||||
return
|
||||
}
|
||||
scriptAPI.randomWalkTo(city, roamDistance)
|
||||
return
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 50 && poi){
|
||||
val roamDistancePoi = when(poiloc){
|
||||
teakfarm, crawlinghands -> 5
|
||||
treegnome -> 50
|
||||
isafdar -> 40
|
||||
eaglespeek -> 40
|
||||
keldagrimout -> 30
|
||||
teak1 -> 30
|
||||
miningguild -> 5
|
||||
magics, coal -> 7
|
||||
gemrocks, chaosnpc, chaosnpc2 -> 1
|
||||
else -> 60
|
||||
}
|
||||
scriptAPI.randomWalkTo(poiloc,roamDistancePoi)
|
||||
return
|
||||
}
|
||||
|
||||
if (RandomFunction.random(1000) <= 75) {
|
||||
if (city != ge && city != ge2) {
|
||||
immerse()
|
||||
return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomFunction.random(20000) <= 60 && !poi) {
|
||||
poiloc = getRandomPoi()
|
||||
city = teak1
|
||||
poi = true
|
||||
scriptAPI.teleport(poiloc)
|
||||
return
|
||||
}
|
||||
|
||||
if ((city == ge || city == ge2) && RandomFunction.random(1000) >= 999) {
|
||||
ticks = 0
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
|
||||
if (city == ge || city == ge2) {
|
||||
return
|
||||
}
|
||||
|
||||
if (city == teak1 && counter++ >= 240){
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
|
||||
if (counter++ >= 240 && RandomFunction.random(100) >= 10) {
|
||||
city = getRandomCity()
|
||||
if (RandomFunction.random(100) % 2 == 0) {
|
||||
counter = 0
|
||||
ticks = 0
|
||||
state = State.TELEPORTING
|
||||
} else {
|
||||
if (citygroupA.contains(city)) {
|
||||
city = citygroupA.random()
|
||||
} else {
|
||||
city = citygroupB.random()
|
||||
}
|
||||
counter = 0
|
||||
ticks = 0
|
||||
state = State.FIND_CITY
|
||||
}
|
||||
counter = 0
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.GE -> {
|
||||
var ge = false
|
||||
if (counter++ == 180) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
if (!sold) {
|
||||
if (counter++ >= 15) {
|
||||
sold = true
|
||||
ge = true
|
||||
counter = 0
|
||||
ticks = 0
|
||||
scriptAPI.sellAllOnGeAdv()
|
||||
return
|
||||
}
|
||||
} else if (ge && sold) {
|
||||
ge = false
|
||||
city = getRandomCity()
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_GE -> {
|
||||
if (counter++ == 180) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
sold = false
|
||||
val ge: Scenery? = scriptAPI.getNearestNode("Desk", true) as Scenery?
|
||||
if (ge == null || bot.bank.isEmpty) state = State.EXPLORE
|
||||
class GEPulse : MovementPulse(bot, ge, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(ge?.location)
|
||||
state = State.GE
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (ge != null && !bot.bank.isEmpty) {
|
||||
counter = 0
|
||||
scriptAPI.randomWalkTo(geloc, 3)
|
||||
GameWorld.Pulser.submit(GEPulse())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
val bank: Scenery? = scriptAPI.getNearestNode("Bank booth", true) as Scenery?
|
||||
if (badedge.insideBorder(bot) || bot.location == badedge2 || bot.location == badedge3 || bot.location == badedge4) {
|
||||
bot.randomWalk(5, 5)
|
||||
}
|
||||
if (bank == null) state = State.EXPLORE
|
||||
class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank?.location)
|
||||
state = State.IDLE_BANKS
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (bank != null) {
|
||||
bot.pulseManager.run(BankingPulse())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.IDLE_BANKS -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
if (RandomFunction.random(1000) < 100) {
|
||||
for (item in bot.inventory.toArray()) {
|
||||
item ?: continue
|
||||
when (item.id) {
|
||||
1359, 590, 1271, 995 -> continue
|
||||
}
|
||||
bot.bank.add(item)
|
||||
bot.inventory.remove(item)
|
||||
}
|
||||
counter = 0
|
||||
state = State.EXPLORE
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.FIND_CITY -> {
|
||||
if (counter++ >= 600 || (city == ge || city == ge2)) {
|
||||
counter = 0
|
||||
scriptAPI.teleport(getRandomCity().also { city = it })
|
||||
state = State.EXPLORE
|
||||
}
|
||||
if (bot.location.equals(city)) {
|
||||
state = State.EXPLORE
|
||||
} else {
|
||||
scriptAPI.randomWalkTo(city, 5)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
State.IDLE_CITY -> {
|
||||
if (counter++ == 300) {
|
||||
state = State.TELEPORTING
|
||||
}
|
||||
var random = (120..300).random()
|
||||
if (counter++ == random && RandomFunction.random(1000) % 33 == 0) {
|
||||
counter = 0
|
||||
state = State.EXPLORE
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun dialogue() {
|
||||
val localPlayer = RegionManager.getLocalPlayers(bot).random()
|
||||
val until = 1225 - dateCode
|
||||
val lineStd = dialogue.getLines("standard").rand()
|
||||
var lineAlt = ""
|
||||
|
||||
when {
|
||||
//Celebrates Halloween!
|
||||
dateCode == 1031 -> lineAlt = dialogue.getLines("halloween").rand()
|
||||
|
||||
//Celebrates lead up to Christmas!
|
||||
until in 2..23 -> lineAlt = dialogue.getLines("approaching_christmas").rand()
|
||||
|
||||
//Celebrates Christmas Day!
|
||||
dateCode == 1225 -> lineAlt = dialogue.getLines("christmas_day").rand()
|
||||
|
||||
//Celebrates Christmas Eve
|
||||
dateCode == 1224 -> lineAlt = dialogue.getLines("christmas_eve").rand()
|
||||
|
||||
//New years eve
|
||||
dateCode == 1231 -> lineAlt = dialogue.getLines("new_years_eve").rand()
|
||||
|
||||
//New years
|
||||
dateCode == 101 -> lineAlt = dialogue.getLines("new_years").rand()
|
||||
|
||||
//Valentines
|
||||
dateCode == 214 -> lineAlt = dialogue.getLines("valentines").rand()
|
||||
|
||||
//Easter
|
||||
dateCode == 404 -> lineAlt = dialogue.getLines("easter").rand()
|
||||
}
|
||||
|
||||
val chat = if (lineAlt.isNotEmpty() && Random.nextBoolean()) { lineAlt } else { lineStd }
|
||||
.replace("@name", localPlayer.username)
|
||||
.replace("@timer", until.toString())
|
||||
|
||||
scriptAPI.sendChat(chat)
|
||||
}
|
||||
|
||||
enum class State{
|
||||
START,
|
||||
EXPLORE,
|
||||
FIND_BANK,
|
||||
IDLE_BANKS,
|
||||
FIND_CITY,
|
||||
IDLE_CITY,
|
||||
GE,
|
||||
TELEPORTING,
|
||||
LOOT,
|
||||
LOOT_DELAY,
|
||||
FIND_GE
|
||||
}
|
||||
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = Adventurer(style)
|
||||
script.state = State.START
|
||||
val tier = CombatBotAssembler.Tier.MED
|
||||
if (type == CombatBotAssembler.Type.RANGE)
|
||||
script.bot = CombatBotAssembler().RangeAdventurer(tier, bot.startLocation)
|
||||
else
|
||||
script.bot = CombatBotAssembler().MeleeAdventurer(tier, bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
companion object {
|
||||
val badedge = ZoneBorders(3094, 3494, 3096, 3497)
|
||||
val badedge2 = Location.create(3094, 3492, 0)
|
||||
val badedge3 = Location.create(3094, 3490, 0)
|
||||
val badedge4 = Location.create(3094, 3494, 0)
|
||||
|
||||
val yanille: Location = Location.create(2615, 3104, 0)
|
||||
val ardougne: Location = Location.create(2662, 3304, 0)
|
||||
val seers: Location = Location.create(2726, 3485, 0)
|
||||
val edgeville: Location = Location.create(3088, 3486, 0)
|
||||
val ge: Location = Location.create(3168, 3487, 0)
|
||||
val ge2: Location = Location.create(3161, 3493, 0)
|
||||
val catherby: Location = Location.create(2809, 3435, 0)
|
||||
val falador: Location = Location.create(2965, 3380, 0)
|
||||
val varrock: Location = Location.create(3213, 3428, 0)
|
||||
val draynor: Location = Location.create(3080, 3250, 0)
|
||||
val rimmington: Location = Location.create(2977, 3239, 0)
|
||||
val lumbridge: Location = Location.create(3222, 3219, 0)
|
||||
val karamja = Location.create(2849, 3033, 0)
|
||||
val alkharid = Location.create(3297, 3219, 0)
|
||||
val feldiphills = Location.create(2535, 2919, 0)
|
||||
val isafdar = Location.create(2241, 3217, 0)
|
||||
val eaglespeek = Location.create(2333, 3579, 0)
|
||||
val canafis = Location.create(3492, 3485, 0)
|
||||
val treegnome = Location.create(2437, 3441, 0)
|
||||
val teak1 = Location.create(2334, 3048, 0)
|
||||
val teakfarm = Location.create(2825, 3085, 0)
|
||||
val keldagrimout = Location.create(2724,3692,0)
|
||||
val miningguild = Location.create(3046,9740,0)
|
||||
val magics = Location.create(2285,3146,0)
|
||||
val coal = Location.create(2581,3481,0)
|
||||
val crawlinghands = Location.create(3422,3548,0)
|
||||
val gemrocks = Location.create(2825,2997,0)
|
||||
val chaosnpc = Location.create(2612,9484,0)
|
||||
val chaosnpc2 = Location.create(2580,9501,0)
|
||||
val taverly = Location.create(2909, 3436, 0)
|
||||
var citygroupA = listOf(falador, varrock, draynor, rimmington, lumbridge, edgeville)
|
||||
var citygroupB = listOf(yanille, ardougne, seers, catherby)
|
||||
|
||||
var bankMap = mapOf<Location, ZoneBorders>(
|
||||
falador to ZoneBorders(2950, 3374, 2943, 3368),
|
||||
varrock to ZoneBorders(3182, 3435, 3189, 3446),
|
||||
draynor to ZoneBorders(3092, 3240, 3095, 3246),
|
||||
edgeville to ZoneBorders(3093, 3498, 3092, 3489),
|
||||
yanille to ZoneBorders(2610, 3089, 2613, 3095),
|
||||
ardougne to ZoneBorders(2649, 3281, 2655, 3286),
|
||||
seers to ZoneBorders(2729, 3493, 2722, 3490),
|
||||
catherby to ZoneBorders(2807, 3438, 2811, 3441)
|
||||
)
|
||||
|
||||
val cities = listOf(yanille, ardougne, seers, catherby, falador, varrock,
|
||||
draynor, rimmington, lumbridge, ge, ge2, edgeville)
|
||||
|
||||
val pois = listOf(
|
||||
karamja, karamja, alkharid,
|
||||
alkharid, feldiphills, feldiphills,
|
||||
isafdar, eaglespeek, eaglespeek,
|
||||
canafis, treegnome, treegnome,
|
||||
teak1, teakfarm, keldagrimout,
|
||||
miningguild, coal, crawlinghands,
|
||||
magics, gemrocks, chaosnpc, chaosnpc,
|
||||
chaosnpc2, taverly)
|
||||
|
||||
private val whiteWolfMountainTop = Location(2850, 3496, 0)
|
||||
private val catherbyToTopOfWhiteWolf = arrayOf(Location(2856, 3442, 0), Location(2848, 3455, 0), Location(2848, 3471, 0), Location(2848, 3487, 0))
|
||||
private val tavleryToTopOfWhiteWolf = arrayOf(Location(2872, 3425, 0), Location(2863, 3440, 0), Location(2863, 3459, 0), Location(2854, 3475, 0), Location(2859, 3488, 0))
|
||||
val common_stuck_locations = mapOf(
|
||||
// South of Tavlery dungeon
|
||||
ZoneBorders(2878, 3386, 2884, 3395) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// West of Tavlery dungeon
|
||||
ZoneBorders(2874, 3390, 2880, 3401) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// South of White Wolf Mountain in Tavlery
|
||||
ZoneBorders(2865,3408,2874,3423) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// On beginning of White Wolf Mountain in Tavlery
|
||||
ZoneBorders(2855, 3454, 2852, 3450) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// South of White Wolf Mountain in Catherby
|
||||
ZoneBorders(2861,3425,2867, 3432) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(catherbyToTopOfWhiteWolf + whiteWolfMountainTop + tavleryToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// On beginning of White Wolf Mountain in Catherby
|
||||
ZoneBorders(2863, 3441, 2859, 3438) to { it: Adventurer ->
|
||||
it.scriptAPI.walkArray(catherbyToTopOfWhiteWolf + whiteWolfMountainTop + tavleryToTopOfWhiteWolf.reversedArray())
|
||||
},
|
||||
// At the Crumbling Wall in Falador
|
||||
ZoneBorders(2937,3356,2936,3353) to { it: Adventurer ->
|
||||
// Interact with the Crumbling Wall
|
||||
val wall = it.scriptAPI.getNearestNode("Crumbling wall", true);
|
||||
if (wall == null) {
|
||||
it.refresh()
|
||||
it.ticks = 0
|
||||
return@to
|
||||
}
|
||||
it.scriptAPI.interact(it.bot, wall, "Climb-over")
|
||||
},
|
||||
// Northwest corner of Draynor Bank
|
||||
ZoneBorders(3092, 3246, 3091, 3247) to { it: Adventurer ->
|
||||
// Walk into Draynor Bank
|
||||
it.scriptAPI.walkTo(Location(3093, 3243, 0))
|
||||
},
|
||||
// West of GE, stuck in the corner south of the outlaw place
|
||||
ZoneBorders(3140, 3468, 3140, 3468) to { it: Adventurer ->
|
||||
// Walk to Barbarian village
|
||||
it.scriptAPI.walkArray(arrayOf(Location.create(3135, 3516, 0), Location.create(3103, 3489, 0), Location.create(3082, 3423, 0)))
|
||||
},
|
||||
)
|
||||
|
||||
val dialogue: JSONObject
|
||||
val dateCode: Int
|
||||
|
||||
init {
|
||||
val reader = FileReader(ServerConstants.BOT_DATA_PATH + File.separator + "bot_dialogue.json")
|
||||
val parser = org.json.simple.parser.JSONParser()
|
||||
val data = parser.parse(reader) as JSONObject
|
||||
|
||||
dialogue = data
|
||||
|
||||
val formatter = DateTimeFormatter.ofPattern("MMdd")
|
||||
val current = LocalDateTime.now()
|
||||
val formatted: String = current.format(formatter)
|
||||
dateCode = formatted.toInt()
|
||||
}
|
||||
|
||||
private fun JSONObject.getLines(category: String): JSONArray {
|
||||
return this[category] as JSONArray
|
||||
}
|
||||
|
||||
private fun JSONArray.rand(): String {
|
||||
return this.random() as String
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Chicken Killer")
|
||||
@ScriptDescription("Kills chickens and loots feathers. Start in any chicken area.")
|
||||
@ScriptIdentifier("chicken_killer")
|
||||
class ChickenKiller : Script(){
|
||||
var state = State.INIT
|
||||
var chickenCounter = 0
|
||||
var overlay: ScriptAPI.BottingOverlay? = null
|
||||
var startLocation = Location(0,0,0)
|
||||
var timer = 3
|
||||
var lootFeathers = false
|
||||
var featherNearby = false
|
||||
var currentFeathers = 0
|
||||
val chickenPen = ZoneBorders(3231,3300,3235,3287)
|
||||
|
||||
override fun tick() {
|
||||
when(state){
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Chickens")
|
||||
overlay!!.setTaskLabel("Chickens KO'd:")
|
||||
overlay!!.setAmount(0)
|
||||
state = State.CONFIG
|
||||
bot.dialogueInterpreter.sendOptions("Loot Feathers and bury bones?","Yes","No")
|
||||
bot.dialogueInterpreter.addAction{player,button ->
|
||||
lootFeathers = button == 2
|
||||
state = State.KILLING
|
||||
}
|
||||
startLocation = bot.location
|
||||
}
|
||||
|
||||
State.KILLING -> {
|
||||
val chicken = scriptAPI.getNearestNode("Chicken")
|
||||
if(chicken == null){
|
||||
scriptAPI.randomWalkTo(startLocation,3)
|
||||
} else {
|
||||
scriptAPI.attackNpcInRadius(bot,"Chicken",10)
|
||||
if(lootFeathers) {
|
||||
state = State.IDLE
|
||||
timer = 4
|
||||
}
|
||||
chickenCounter++
|
||||
overlay!!.setAmount(chickenCounter)
|
||||
}
|
||||
}
|
||||
|
||||
State.IDLE -> {
|
||||
if(timer-- <= 0){
|
||||
featherNearby = scriptAPI.takeNearestGroundItem(Items.FEATHER_314)
|
||||
currentFeathers = 0
|
||||
if (featherNearby) {
|
||||
state = State.LOOTFEATHER
|
||||
}else{
|
||||
state = State.LOOTBONES
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.LOOTFEATHER -> {
|
||||
timer = 1
|
||||
if(timer-- >= 0) {
|
||||
currentFeathers = bot.inventory.getAmount(Items.FEATHER_314)
|
||||
scriptAPI.takeNearestGroundItem(Items.FEATHER_314)
|
||||
featherNearby = false
|
||||
}
|
||||
state = State.LOOTBONES
|
||||
}
|
||||
|
||||
State.LOOTBONES -> {
|
||||
timer = 1
|
||||
if(timer-- >= 0){
|
||||
scriptAPI.takeNearestGroundItem(Items.BONES_526)
|
||||
}
|
||||
state = State.BURYBONES
|
||||
}
|
||||
|
||||
State.BURYBONES -> {
|
||||
timer = 1
|
||||
var hasBone = bot.hasItem(Item(Items.BONES_526))
|
||||
var bone = bot.inventory.getItem(Item(Items.BONES_526))
|
||||
if (hasBone) {
|
||||
bone.interaction.handleItemOption(bot,bone.interaction.get(0),bot.inventory)
|
||||
}
|
||||
state = State.KILLING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
return this
|
||||
}
|
||||
|
||||
enum class State {
|
||||
IDLE,
|
||||
INIT,
|
||||
KILLING,
|
||||
LOOTING,
|
||||
RETURN,
|
||||
CONFIG,
|
||||
LOOTFEATHER,
|
||||
LOOTBONES,
|
||||
BURYBONES
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package content.global.bots
|
||||
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.api.*
|
||||
import core.game.bots.*
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Falador Coal Miner")
|
||||
@ScriptDescription("Start in Falador East Bank with a pick equipped","or in your inventory.")
|
||||
@ScriptIdentifier("fally_coal")
|
||||
class CoalMiner : Script() {
|
||||
var state = State.INIT
|
||||
var ladderSwitch = false
|
||||
val bottomLadder = ZoneBorders(3016,9736,3024,9742)
|
||||
val topLadder = ZoneBorders(3016,3336,3022,3342)
|
||||
val mine = ZoneBorders(3027,9733,3054,9743)
|
||||
val bank = ZoneBorders(3009,3355,3018,3358)
|
||||
var overlay: ScriptAPI.BottingOverlay? = null
|
||||
var coalAmount = 0
|
||||
|
||||
override fun tick() {
|
||||
when(state){
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
ladderSwitch = true
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Mining")
|
||||
overlay!!.setTaskLabel("Coal Mined:")
|
||||
overlay!!.setAmount(0)
|
||||
|
||||
if (mine.insideBorder(bot)){
|
||||
ladderSwitch = false
|
||||
state = State.MINING
|
||||
} else {
|
||||
state = State.TO_MINE
|
||||
}
|
||||
}
|
||||
|
||||
State.MINING -> {
|
||||
bot.interfaceManager.close()
|
||||
if(bot.inventory.freeSlots() == 0){
|
||||
state = State.TO_BANK
|
||||
}
|
||||
if(!mine.insideBorder(bot)){
|
||||
scriptAPI.walkTo(mine.randomLoc)
|
||||
} else {
|
||||
val rock = scriptAPI.getNearestNode("rocks",true)
|
||||
rock?.let { InteractionListeners.run(rock.id, IntType.SCENERY,"mine",bot,rock) }
|
||||
}
|
||||
overlay!!.setAmount(amountInInventory(bot, Items.COAL_453) + coalAmount)
|
||||
}
|
||||
|
||||
State.TO_BANK -> {
|
||||
if(bank.insideBorder(bot)){
|
||||
val bank = scriptAPI.getNearestNode("bank booth",true)
|
||||
if(bank != null) {
|
||||
bot.pulseManager.run(object : BankingPulse(this, bank){
|
||||
override fun pulse(): Boolean {
|
||||
state = State.BANKING
|
||||
return super.pulse()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
} else {
|
||||
if(!ladderSwitch) {
|
||||
val ladder = scriptAPI.getNearestNode(30941, true)
|
||||
ladder ?: scriptAPI.walkTo(bottomLadder.randomLoc).also { return }
|
||||
ladder?.interaction?.handle(bot, ladder.interaction[0]).also { ladderSwitch = true }
|
||||
} else {
|
||||
if (!bank.insideBorder(bot)) scriptAPI.walkTo(bank.randomLoc).also { return }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
coalAmount += bot.inventory.getAmount(Items.COAL_453)
|
||||
scriptAPI.bankAll()
|
||||
state = State.TO_MINE
|
||||
}
|
||||
|
||||
State.TO_MINE -> {
|
||||
if(ladderSwitch){
|
||||
bot.interfaceManager.close()
|
||||
if(!topLadder.insideBorder(bot.location)){
|
||||
scriptAPI.walkTo(topLadder.randomLoc)
|
||||
} else {
|
||||
val ladder = scriptAPI.getNearestNode("Ladder",true)
|
||||
if(ladder != null){
|
||||
ladder.interaction.handle(bot,ladder.interaction[0])
|
||||
ladderSwitch = false
|
||||
} else {
|
||||
scriptAPI.walkTo(topLadder.randomLoc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!mine.insideBorder(bot)){
|
||||
scriptAPI.walkTo(mine.randomLoc)
|
||||
} else {
|
||||
state = State.MINING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.TO_GE -> {
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.SELLING
|
||||
}
|
||||
|
||||
State.SELLING -> {
|
||||
scriptAPI.sellOnGE(Items.COAL_453)
|
||||
state = State.GO_BACK
|
||||
}
|
||||
|
||||
State.GO_BACK -> {
|
||||
scriptAPI.teleport(bank.randomLoc)
|
||||
state = State.TO_MINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class BankingPulse(val script: Script, val bank: Node) : MovementPulse(script.bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
script.bot.faceLocation(bank.location)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = CoalMiner()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
enum class State {
|
||||
MINING,
|
||||
TO_MINE,
|
||||
TO_BANK,
|
||||
BANKING,
|
||||
TO_GE,
|
||||
SELLING,
|
||||
GO_BACK,
|
||||
INIT
|
||||
}
|
||||
|
||||
init {
|
||||
equipment.add(Item(Items.IRON_PICKAXE_1267))
|
||||
skills.put(Skills.MINING,75)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.CombatBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class CowKiller : Script() {
|
||||
var state = State.KILLING
|
||||
var spawnZone = ZoneBorders(3254,3255,3264,3281)
|
||||
var cowZone = ZoneBorders(3242, 3254,3265, 3296)
|
||||
val bankZone = ZoneBorders(3208, 3217,3210, 3220)
|
||||
init {
|
||||
cowZone.addException(ZoneBorders(3242,3254,3252,3277))
|
||||
cowZone.addException(ZoneBorders(3242,3277,3242,3296))
|
||||
cowZone.addException(ZoneBorders(3253, 3267,3253, 3267))
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
when(state){
|
||||
State.KILLING -> {
|
||||
scriptAPI.attackNpcInRadius(bot,"Cow",10)
|
||||
state = State.LOOTING
|
||||
}
|
||||
|
||||
State.LOOTING -> {
|
||||
bot.pulseManager.run(object: Pulse(4){
|
||||
override fun pulse(): Boolean {
|
||||
state = State.KILLING
|
||||
scriptAPI.takeNearestGroundItem(Items.COWHIDE_1739)
|
||||
state = if(bot.inventory.getAmount(Items.COWHIDE_1739) > 22){
|
||||
State.TO_BANK
|
||||
} else {
|
||||
State.KILLING
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
State.TO_BANK -> {
|
||||
if(cowZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(Location.create(3253, 3267, 0))
|
||||
else{
|
||||
val closedGate = scriptAPI.getNearestNode(15516,true)
|
||||
if(closedGate != null && closedGate.location.withinDistance(bot.location,2)){
|
||||
closedGate.interaction.handle(bot,closedGate.interaction[0])
|
||||
} else {
|
||||
when (bot.location) {
|
||||
Location.create(3212, 3227, 0) -> {
|
||||
val stairs = scriptAPI.getNearestGameObject(bot.location, 36776)
|
||||
stairs?.interaction?.handle(bot, stairs.interaction[0])
|
||||
}
|
||||
Location.create(3206, 3229, 1) -> {
|
||||
val stairs = scriptAPI.getNearestNode(36777, true)
|
||||
stairs?.interaction?.handle(bot, stairs.interaction[1])
|
||||
}
|
||||
Location.create(3206, 3229, 2) -> {
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
state = State.BANKING
|
||||
}
|
||||
else -> scriptAPI.walkTo(Location.create(3212, 3227, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
if(bankZone.insideBorder(bot)) {
|
||||
val bank = scriptAPI.getNearestNode(36786, true)
|
||||
bot.pulseManager.run(object : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
scriptAPI.bankItem(Items.COWHIDE_1739)
|
||||
if (bot.bank.getAmount(Items.COWHIDE_1739) > 75) {
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.TELE_GE
|
||||
} else {
|
||||
state = State.BACK_TO_COWS
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
State.BACK_TO_COWS -> {
|
||||
if (bankZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(Location.create(3206, 3229, 2))
|
||||
else {
|
||||
when (bot.location) {
|
||||
Location.create(3206, 3229, 2) -> {
|
||||
val stairs = scriptAPI.getNearestNode(36778, true)
|
||||
stairs?.interaction?.handle(bot, stairs.interaction[0])
|
||||
}
|
||||
Location.create(3206, 3229, 1) -> {
|
||||
val stairs = scriptAPI.getNearestNode(36777, true)
|
||||
stairs?.interaction?.handle(bot, stairs.interaction[2])
|
||||
}
|
||||
Location.create(3252, 3267, 0) -> {
|
||||
val closedGate = scriptAPI.getNearestNode(15516, true)
|
||||
if (closedGate != null && closedGate.location.withinDistance(bot.location, 2)) {
|
||||
closedGate.interaction.handle(bot, closedGate.interaction[0])
|
||||
} else {
|
||||
scriptAPI.walkTo(cowZone.randomLoc)
|
||||
state = State.KILLING
|
||||
}
|
||||
}
|
||||
else -> scriptAPI.walkTo(Location.create(3252, 3267, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
State.TELE_GE -> {
|
||||
if(bot.location == Location.create(3165, 3482, 0))
|
||||
state = State.SELL_GE
|
||||
else
|
||||
scriptAPI.walkTo(Location.create(3165, 3482, 0))
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
state = State.TELE_LUM
|
||||
scriptAPI.sellOnGE(Items.COWHIDE_1739)
|
||||
}
|
||||
|
||||
State.TELE_LUM -> {
|
||||
state = State.BACK_TO_COWS
|
||||
scriptAPI.teleport(Location.create(3222, 3218, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class State {
|
||||
KILLING,
|
||||
LOOTING,
|
||||
BANKING,
|
||||
TO_BANK,
|
||||
BACK_TO_COWS,
|
||||
SELL_GE,
|
||||
TELE_GE,
|
||||
TELE_LUM
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = CowKiller()
|
||||
script.bot = CombatBotAssembler().produce(CombatBotAssembler.Type.values().random(), CombatBotAssembler.Tier.LOW,spawnZone.randomLoc)
|
||||
script.state = State.KILLING
|
||||
return script
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.container.Container
|
||||
import core.game.interaction.Option._P_TRADE
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.request.trade.TradeModule
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.update.flag.context.ChatMessage
|
||||
import core.game.world.update.flag.player.ChatFlag
|
||||
import core.integrations.discord.Discord
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import org.rs09.consts.Items
|
||||
import core.ServerConstants
|
||||
import core.game.bots.AIRepository
|
||||
import content.global.bots.Adventurer.Companion.lumbridge
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.world.ImmerseWorld
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.util.Random
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* A bot that doubles money
|
||||
* 30% chance to double money, 70% chance to scam
|
||||
* @author dginovker
|
||||
*/
|
||||
class DoublingMoney : Script() {
|
||||
/**
|
||||
* If we're in ScamMode, we will never trade away any more coins
|
||||
*/
|
||||
private var scamMode = false
|
||||
|
||||
/**
|
||||
* Whether the bot has run its setup (gotten appearance made/etc.)
|
||||
*/
|
||||
private var setup = false
|
||||
|
||||
/**
|
||||
* Player who most recently traded with this bot
|
||||
*/
|
||||
var victim: Player? = null
|
||||
|
||||
/**
|
||||
* Player who the bot took money from
|
||||
*/
|
||||
private var playerOwed: Player? = null
|
||||
|
||||
/**
|
||||
* Whether we sent a trade request to the player we owe yet
|
||||
*/
|
||||
private var sentTradeRequest = false
|
||||
|
||||
/**
|
||||
* Amount the bot owes the player (2x the amount the player gave the bot)
|
||||
*/
|
||||
private var debtOwed: Int = 0
|
||||
|
||||
/**
|
||||
* How many ticks the bot has run for
|
||||
*/
|
||||
var ticks = 0
|
||||
|
||||
/**
|
||||
* Duration for how long the bot will take a nap
|
||||
*/
|
||||
private var sleepTime = 0
|
||||
|
||||
/**
|
||||
* Debug information about what state the bot is in
|
||||
*/
|
||||
private var stateString = "init"
|
||||
|
||||
/**
|
||||
* How long the bot will stay around for
|
||||
*/
|
||||
private val maxTicks = (400..750).random()
|
||||
|
||||
enum class Effort {
|
||||
LOW,
|
||||
HIGH,
|
||||
VERY_HIGH
|
||||
}
|
||||
|
||||
/**
|
||||
* Characteristics about how hard the bot will work
|
||||
* Most likely to be LOW, small chance to be HIGH, very small chance to be VERY_HIGH
|
||||
*/
|
||||
private val effort = when (Random().nextInt(100)) {
|
||||
in 0..90 -> Effort.LOW
|
||||
in 90..98 -> Effort.HIGH
|
||||
else -> Effort.VERY_HIGH
|
||||
}
|
||||
|
||||
// Priority calculation -> Execute method mapping. Priority calculation with the highest return value is executed
|
||||
var states = mapOf(
|
||||
fun(): Int {
|
||||
if (setup) return -1
|
||||
return 250
|
||||
} to {
|
||||
stateString = "Putting on my outfit.."
|
||||
var appearance = if (Math.random() < 0.5) "noob" else "intermediate"
|
||||
if (effort == Effort.VERY_HIGH && Math.random() < 0.5) appearance = "veteran"
|
||||
val appearancesArray = botAppearances[appearance] as JSONArray
|
||||
scriptAPI.loadAppearanceAndEquipment(appearancesArray.random() as JSONObject)
|
||||
setup = true
|
||||
},
|
||||
fun(): Int {
|
||||
val botTradeModule = TradeModule.getExtension(bot)
|
||||
if (botTradeModule != null) return -1
|
||||
return 0
|
||||
} to {
|
||||
stateString = "Doing nothing"
|
||||
},
|
||||
fun(): Int {
|
||||
return 1
|
||||
} to {
|
||||
stateString = "Saying Doubling money"
|
||||
when (effort) {
|
||||
Effort.LOW -> {
|
||||
scriptAPI.sendChat("Doubling money")
|
||||
sleepTime = 7
|
||||
}
|
||||
Effort.HIGH -> {
|
||||
val message = arrayOf("Doubling Money", "Doubling Money", "Doubling Money!", "Doubling moneyy").random()
|
||||
val messageEffect = arrayOf(0, 256).random()
|
||||
val ctx = ChatMessage(bot, message, messageEffect, message.length)
|
||||
bot.updateMasks.register(ChatFlag(ctx))
|
||||
sleepTime = 8
|
||||
}
|
||||
Effort.VERY_HIGH -> {
|
||||
val message = arrayOf("Doubling money!", "Doubling money").random()
|
||||
val messageEffect = arrayOf(771, 2818, 2562, 768, 512, 2304, 2560, 769, 1792).random()
|
||||
val ctx = ChatMessage(bot, message, messageEffect, message.length)
|
||||
bot.updateMasks.register(ChatFlag(ctx))
|
||||
sleepTime = 9
|
||||
}
|
||||
}
|
||||
},
|
||||
fun(): Int {
|
||||
if (victim == null) return -1
|
||||
return 10
|
||||
} to {
|
||||
stateString = "Accepting trade request"
|
||||
// Send trade request back to victim
|
||||
InteractionListeners.run(-1, IntType.PLAYER, "trade with", bot, victim!!)
|
||||
victim = null
|
||||
sleepTime = 3
|
||||
},
|
||||
fun(): Int {
|
||||
if (debtOwed >= 0) return -1
|
||||
val botTradeModule = TradeModule.getExtension(bot) ?: return -1
|
||||
val playerTradeModule = TradeModule.getExtension(botTradeModule.target) ?: return -1
|
||||
if (!playerTradeModule.container!!.containsAtLeastOneItem(Items.COINS_995)) return 15
|
||||
return -1
|
||||
} to {
|
||||
val botTradeModule = TradeModule.getExtension(bot)
|
||||
stateString = "Waiting for ${botTradeModule!!.target} to post money"
|
||||
sleepTime = 5
|
||||
},
|
||||
fun(): Int {
|
||||
// If we have debt and are in the trade screen with the player who we owe, but have not put up coins, put up coins
|
||||
if (debtOwed == 0) return -1
|
||||
val botTradeModule = TradeModule.getExtension(bot) ?: return -1
|
||||
if (botTradeModule.target != playerOwed) return -1
|
||||
if (!botTradeModule.container!!.containsAtLeastOneItem(Items.COINS_995)) return 150
|
||||
return -1
|
||||
} to {
|
||||
stateString = "Paying off ${playerOwed!!.username} $debtOwed coins"
|
||||
val botTradeModule = TradeModule.getExtension(bot)
|
||||
val coinSlot = bot.inventory.getSlot(Item(Items.COINS_995))
|
||||
botTradeModule!!.container!!.offer(coinSlot, debtOwed)
|
||||
debtOwed = 0
|
||||
playerOwed = null
|
||||
},
|
||||
fun(): Int {
|
||||
val botTradeModule = TradeModule.getExtension(bot) ?: return -1
|
||||
val playerTradeModule = TradeModule.getExtension(botTradeModule.target) ?: return -1
|
||||
if (botTradeModule.container!!.containsAtLeastOneItem(Items.COINS_995)) return 200
|
||||
if (playerTradeModule.container!!.containsAtLeastOneItem(Items.COINS_995)) return 200
|
||||
return -1
|
||||
} to {
|
||||
stateString = "Accepting any trade screen that has coins put up"
|
||||
val botTradeModule = TradeModule.getExtension(bot)
|
||||
val playerTradeModule = TradeModule.getExtension(botTradeModule!!.target)
|
||||
if (botTradeModule.isAccepted) return@to
|
||||
|
||||
sleepTime = (1..if (botTradeModule.getInterface() == TradeModule.MAIN_INTERFACE) 2 else 5).random()
|
||||
|
||||
val coinsFromBot = botTradeModule.container!!.getAmount(Items.COINS_995)
|
||||
if (botTradeModule.getInterface() == TradeModule.ACCEPT_INTERFACE && coinsFromBot > 0 && effort == Effort.VERY_HIGH) {
|
||||
val message = "Payed ${(if (coinsFromBot < 1000) "${coinsFromBot}gp" else "${coinsFromBot / 1000}k")}"
|
||||
val ctx = ChatMessage(bot, message, 512, message.length)
|
||||
bot.updateMasks.register(ChatFlag(ctx))
|
||||
|
||||
sleepTime = 7
|
||||
}
|
||||
if (botTradeModule.getInterface() == TradeModule.ACCEPT_INTERFACE && Math.random() < 0.2 && effort == Effort.HIGH && coinsFromBot > 0) {
|
||||
scriptAPI.sendChat("Enjoy")
|
||||
sleepTime += 4
|
||||
}
|
||||
|
||||
if (botTradeModule.getInterface() == TradeModule.MAIN_INTERFACE && scamMode) {
|
||||
sleepTime = maxOf(3, sleepTime)
|
||||
}
|
||||
|
||||
if (botTradeModule.getInterface() == TradeModule.ACCEPT_INTERFACE) {
|
||||
val player = botTradeModule.target
|
||||
var playerNetPoL = player!!.getAttribute("double-money-net-pol", "0").toInt()
|
||||
playerNetPoL += coinsFromBot
|
||||
playerNetPoL -= playerTradeModule!!.container!!.getAmount(Items.COINS_995)
|
||||
player.setAttribute("double-money-net-pol", playerNetPoL.toString())
|
||||
// if playerNetPoL > 100k, send a Discord notification
|
||||
if (playerNetPoL > 100_000) {
|
||||
Discord.postPlayerAlert(player.username, "Made too much off Doubling Money bots: ${playerNetPoL / 1000}k")
|
||||
}
|
||||
}
|
||||
// If we're in scamMode, we cannot actually setAccepted to true if we're giving away coins! (Gotta fake em out ;)
|
||||
if (scamMode && botTradeModule.getInterface() == TradeModule.ACCEPT_INTERFACE && coinsFromBot > 0) {
|
||||
botTradeModule.decline()
|
||||
} else {
|
||||
botTradeModule.setAccepted(true, update = true)
|
||||
}
|
||||
sentTradeRequest = false
|
||||
},
|
||||
fun(): Int {
|
||||
if (sentTradeRequest) return 50
|
||||
return -1
|
||||
} to {
|
||||
// Wait for the other player to accept
|
||||
},
|
||||
fun(): Int {
|
||||
if (TradeModule.getExtension(bot) == null && debtOwed > 0 && playerOwed != null) return 25
|
||||
return -1
|
||||
} to {
|
||||
// Scam over 200k payout or 70% chance
|
||||
if (Math.random() < 0.7 || debtOwed > 200_000) {
|
||||
stateString = "Scamming"
|
||||
scamMode = true
|
||||
if (effort != Effort.VERY_HIGH || Math.random() < 0.5) {
|
||||
// At high scam effort, there's a chance we fake giving them coins back to keep milking
|
||||
// with scamMode = true, we will never accept giving coins away at the second trade screen again
|
||||
terminate()
|
||||
}
|
||||
}
|
||||
stateString = "Sending trade request to ${playerOwed!!.name} to give them $debtOwed coins"
|
||||
playerOwed!!.interaction.handle(bot, _P_TRADE)
|
||||
InteractionListeners.run(-1, IntType.PLAYER, "trade with", bot, playerOwed!!)
|
||||
sentTradeRequest = true
|
||||
},
|
||||
fun(): Int {
|
||||
// If we're not near a doubling loc, or another doubling bot is on our loc, walk to random one
|
||||
var minDist = 1000.0
|
||||
for (loc in doublingLocs) {
|
||||
minDist = min(minDist, loc.getDistance(bot.location))
|
||||
}
|
||||
if (minDist > 1) return 2
|
||||
RegionManager.forId(bot.location.regionId).planes[bot.location.z].players.forEach {
|
||||
if (AIRepository.PulseRepository[it?.username?.lowercase()]?.botScript is DoublingMoney
|
||||
&& it != bot
|
||||
&& it.location.getDistance(bot.location) <= 1) {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
return -1
|
||||
} to {
|
||||
stateString = "Walking to doubling location"
|
||||
val loc = doublingLocs.random()
|
||||
scriptAPI.walkTo(loc)
|
||||
sleepTime = 5
|
||||
},
|
||||
fun(): Int {
|
||||
// If we're past the max ticks, log out
|
||||
if (ticks > maxTicks) return 30
|
||||
return -1
|
||||
} to {
|
||||
stateString = "Logging out"
|
||||
terminate()
|
||||
},
|
||||
fun(): Int {
|
||||
// If we're past 1,000 ticks, force terminate
|
||||
if (ticks > 1000) return 1_000_000
|
||||
return -1
|
||||
} to {
|
||||
stateString = "Force terminating"
|
||||
terminate()
|
||||
}
|
||||
)
|
||||
|
||||
override fun toString(): String {
|
||||
return "stateString: $stateString, sleepTime: $sleepTime, ticks: $ticks, maxTicks: $maxTicks, debtOwed: $debtOwed, playerOwed: $playerOwed, victim: $victim, effort: $effort, scamMode: $scamMode"
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if(!bot.isActive){
|
||||
running = false
|
||||
return
|
||||
}
|
||||
ticks ++
|
||||
if (sleepTime > 0) {
|
||||
sleepTime --
|
||||
return
|
||||
}
|
||||
|
||||
// Execute the priority calculations, then execute the method of the one which returned highest
|
||||
states.maxByOrNull { it.key() }?.value?.invoke()
|
||||
}
|
||||
|
||||
fun tradeReceived(p: Player) {
|
||||
victim = p
|
||||
}
|
||||
|
||||
fun itemsReceived(p: Player, container: Container?) {
|
||||
if (container == null) return
|
||||
val coins: Item = container.get(Item(Items.COINS_995)) ?: return
|
||||
playerOwed = p
|
||||
debtOwed = coins.amount * 2
|
||||
if (effort == Effort.VERY_HIGH) {
|
||||
val message = "Received ${(if (coins.amount < 1000) "${coins.amount}gp" else "${coins.amount / 1000}k")}"
|
||||
val ctx = ChatMessage(bot, message, 256, message.length)
|
||||
bot.updateMasks.register(ChatFlag(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
fun terminate() {
|
||||
scriptAPI.teleport(lumbridge)
|
||||
debtOwed = 0
|
||||
bot.isActive = false
|
||||
sleepTime = 500
|
||||
AIRepository.PulseRepository.remove(bot.username.lowercase())
|
||||
|
||||
ImmerseWorld.spawnDoubleMoneyBot(true)
|
||||
}
|
||||
|
||||
override fun newInstance(): Script? {
|
||||
// this straight doesn't get called....
|
||||
return null
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.AGILITY] = 99
|
||||
inventory.add(Item(Items.COINS_995, 1_000_000))
|
||||
}
|
||||
|
||||
companion object {
|
||||
val startingLocs = arrayOf(Location.create(3184, 3488, 0),
|
||||
Location.create(3167, 3461, 0),
|
||||
Location.create(3170, 3444, 0),
|
||||
Location.create(3165, 3487, 0),
|
||||
Location.create(3167, 3489, 0),
|
||||
Location.create(3162, 3491, 0))
|
||||
|
||||
val doublingLocs = arrayOf(Location.create(3159, 3492, 0),
|
||||
Location.create(3164, 3484, 0),
|
||||
Location.create(3169, 3486, 0),
|
||||
Location.create(3172, 3489, 0),
|
||||
Location.create(3168, 3483, 0),
|
||||
Location.create(3166, 3493, 0),
|
||||
Location.create(3157, 3498, 0),
|
||||
Location.create(3157, 3485, 0)
|
||||
)
|
||||
|
||||
// load from data/botdata/ge_bot_appearances_and_equipment.json
|
||||
private val jsonFilePath = "${ServerConstants.BOT_DATA_PATH}/ge_bot_appearances_and_equipment.json"
|
||||
private val jsonFile = File(jsonFilePath)
|
||||
private val parser = JSONParser()
|
||||
val botAppearances = parser.parse(FileReader(jsonFile)) as JSONObject
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class DraynorFisher : Script() {
|
||||
val fishingZone = ZoneBorders(3085, 3223,3089, 3233)
|
||||
val bankZone = ZoneBorders(3092, 3240,3094, 3246)
|
||||
|
||||
|
||||
var state = State.FISHING
|
||||
override fun tick() {
|
||||
when(state){
|
||||
State.FISHING -> {
|
||||
if(!fishingZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(fishingZone.randomLoc)
|
||||
else {
|
||||
val spot = scriptAPI.getNearestNode(316,false)
|
||||
spot?.interaction?.handle(bot,spot.interaction[0]) ?: scriptAPI.walkTo(fishingZone.randomLoc)
|
||||
if(bot.inventory.getMaximumAdd(Item(4151)) < 5)
|
||||
state = State.BANKING
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
if(!bankZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
else {
|
||||
val bank = scriptAPI.getNearestNode("Bank booth")
|
||||
if (bank != null){
|
||||
bot.pulseManager.run(object : MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.inventory.clear()
|
||||
state = State.FISHING
|
||||
bot.inventory.add(Item(Items.SMALL_FISHING_NET_303))
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = DraynorFisher()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR, Location.create(3094, 3242, 0))
|
||||
return script
|
||||
}
|
||||
|
||||
init {
|
||||
inventory.add(Item(Items.SMALL_FISHING_NET_303))
|
||||
}
|
||||
|
||||
enum class State {
|
||||
FISHING,
|
||||
BANKING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package content.global.bots
|
||||
import core.game.bots.*
|
||||
import core.game.component.Component
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.tools.colorize
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Draynor Willows")
|
||||
@ScriptDescription("Start in Draynor with an axe equipped or in inventory.")
|
||||
@ScriptIdentifier("draynor_trees")
|
||||
class DraynorWillows : Script(){
|
||||
val willowZone = ZoneBorders(3084, 3225,3091, 3239)
|
||||
val bankZone = ZoneBorders(3092, 3245,3092, 3242)
|
||||
var state = State.INIT
|
||||
var logCount = 0
|
||||
|
||||
override fun tick() {
|
||||
when(state){
|
||||
State.INIT -> {
|
||||
if(true){
|
||||
bot.interfaceManager.openOverlay(Component(195))
|
||||
bot.packetDispatch.sendString("Woodcutting",195,7)
|
||||
bot.packetDispatch.sendString(colorize("%BLogs Chopped:"),195,8)
|
||||
bot.packetDispatch.sendString(colorize("%B0"),195,9)
|
||||
bot.packetDispatch.sendInterfaceConfig(195,5,true)
|
||||
}
|
||||
state = State.CHOPPING
|
||||
}
|
||||
|
||||
State.CHOPPING -> {
|
||||
if (!willowZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(willowZone.randomLoc)
|
||||
else {
|
||||
val willowtree = scriptAPI.getNearestNode("willow", true)
|
||||
bot.interfaceManager.close()
|
||||
willowtree?.let { InteractionListeners.run(willowtree.id,
|
||||
IntType.SCENERY,"Chop down",bot,willowtree) }
|
||||
if (bot.inventory.isFull)
|
||||
state = State.BANKING
|
||||
}
|
||||
|
||||
bot.packetDispatch.sendString(colorize("%B${logCount + bot.inventory.getAmount(Items.WILLOW_LOGS_1519)}"), 195, 9)
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
if(!bankZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
else{
|
||||
val bank = scriptAPI.getNearestNode("Bank Booth",true)
|
||||
if(bank != null){
|
||||
bot.pulseManager.run(object : MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
val logs = bot.inventory.getAmount(Item(Items.WILLOW_LOGS_1519))
|
||||
logCount += logs
|
||||
bot.inventory.remove(Item(Items.WILLOW_LOGS_1519,logs))
|
||||
bot.bank.add(Item(Items.WILLOW_LOGS_1519,logs))
|
||||
state = State.CHOPPING
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
inventory.add(Item(Items.ADAMANT_AXE_1357))
|
||||
skills[Skills.WOODCUTTING] = 35
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = DraynorWillows()
|
||||
return script
|
||||
}
|
||||
|
||||
enum class State {
|
||||
CHOPPING,
|
||||
BANKING,
|
||||
INIT
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package content.global.bots
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
|
||||
class FarmerThiever : Script() {
|
||||
val pickpocketZone = ZoneBorders(3074,3245,3086,3255)
|
||||
val bankZone = ZoneBorders(3092, 3245,3092, 3242)
|
||||
val food = Items.JUG_OF_WINE_1993
|
||||
val foodAmount = 10
|
||||
var state = State.PICKPOCKETING
|
||||
|
||||
|
||||
override fun tick() {
|
||||
when(state) {
|
||||
|
||||
State.PICKPOCKETING -> {
|
||||
if (!pickpocketZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(pickpocketZone.randomLoc)
|
||||
if (bot.inventory.isFull)
|
||||
state = State.BANKING
|
||||
else {
|
||||
val farmer = scriptAPI.getNearestNode(NPCs.MASTER_FARMER_2234, false)
|
||||
bot.interfaceManager.close()
|
||||
scriptAPI.eat(food)
|
||||
if (farmer != null) {
|
||||
InteractionListeners.run(farmer.id, IntType.NPC, "Pickpocket", bot, farmer)
|
||||
}
|
||||
}
|
||||
}
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode("Bank Booth",true)
|
||||
bank ?: return
|
||||
if (!bankZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
else {
|
||||
bot.faceLocation(bank.location)
|
||||
bot.inventory.clear()
|
||||
bot.inventory.add(Item(food, foodAmount))
|
||||
state = State.PICKPOCKETING
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = FarmerThiever()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
enum class State {
|
||||
BANKING,
|
||||
PICKPOCKETING
|
||||
}
|
||||
|
||||
init {
|
||||
inventory.add(Item(food,foodAmount))
|
||||
skills[Skills.THIEVING] = 80
|
||||
skills[Skills.HITPOINTS] = 10
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.global.skill.fletching.Fletching
|
||||
import content.global.skill.fletching.FletchingPulse
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class FletchingBankstander : Script(){
|
||||
var state = State.FLETCHING
|
||||
override fun tick() {
|
||||
val bank = scriptAPI.getNearestNode("Bank booth")
|
||||
bot.faceLocation(bank?.location)
|
||||
state = when(state){
|
||||
State.FLETCHING -> {
|
||||
bot.inventory.add(Item(Items.KNIFE_946))
|
||||
bot.inventory.add(Item(Items.LOGS_1511,27))
|
||||
bot.pulseManager.run(FletchingPulse(bot, Item(Items.LOGS_1511),27, Fletching.FletchingItems.ARROW_SHAFT))
|
||||
State.BANKING
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
bot.inventory.clear()
|
||||
State.FLETCHING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.FLETCHING] = 99
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = FletchingBankstander()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.AVERAGE,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
enum class State {
|
||||
FLETCHING,
|
||||
BANKING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.AIRepository
|
||||
import core.game.bots.Script
|
||||
|
||||
/**
|
||||
* A bot that does various random slayer tasks throughout the game and sells the loot on the GE.
|
||||
* @author Ceikry
|
||||
*/
|
||||
class GenericSlayerBot : Script() {
|
||||
var state = State.GETTING_TASK
|
||||
var task = Task.CAVE_CRAWLER //default value to ensure non-nullability
|
||||
var assignment = Assignment("",0) //same as above
|
||||
var teleportFlag = false //have we teleported?
|
||||
val FOOD_ID = Items.LOBSTER_379
|
||||
val varrockBankBorders = ZoneBorders(3184, 3435,3187, 3441)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Per-tick actions (they don't run if the bot already has a pulse running, such as moving or combat.)
|
||||
*/
|
||||
override fun tick() {
|
||||
scriptAPI.eat(FOOD_ID) //try to eat every tick (does nothing if health isn't low enough)
|
||||
|
||||
when(state){
|
||||
|
||||
/**
|
||||
* State that handles getting a new task
|
||||
*/
|
||||
State.GETTING_TASK -> {
|
||||
populateTaskAndAssignment()
|
||||
state = State.GOING_TO_HUB //switch states
|
||||
}
|
||||
|
||||
/**
|
||||
* State that handles going to the "hub" for the task. Such as fremmy slayer cave or slayer tower.
|
||||
*/
|
||||
State.GOING_TO_HUB -> {
|
||||
when(task.hub){
|
||||
|
||||
TaskHub.FREMENNIK_CAVE -> {
|
||||
if(!teleportFlag) {
|
||||
scriptAPI.teleport(Location.create(2781, 3615, 0)) //tele -> fremennik fairy ring
|
||||
teleportFlag = !teleportFlag //teleportFlag -> true
|
||||
}
|
||||
else {
|
||||
val entrance = scriptAPI.getNearestNode(4499,true) //returns the object if within render distance, null if not.
|
||||
if(entrance == null || !entrance.location.withinDistance(bot.location,2)) {
|
||||
scriptAPI.walkTo(Location.create(2796, 3615, 0))
|
||||
} else {
|
||||
entrance.interaction.handle(bot,entrance.interaction[0]) //bot -> use interaction [0] of cave object
|
||||
teleportFlag = !teleportFlag //teleportFlag -> false
|
||||
state = State.KILLING_ENEMY //switch states
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* State used for combat. Handles moving the bot back into the zone for the monster and looting as well.
|
||||
*/
|
||||
State.KILLING_ENEMY -> {
|
||||
val items = AIRepository.groundItems.get(bot) //retrieve drops that belong to this bot
|
||||
if(items != null && items.isNotEmpty()){ //if we have loot...
|
||||
if(bot.inventory.freeSlots() == 0){
|
||||
if(bot.inventory.contains(FOOD_ID,1)){
|
||||
scriptAPI.forceEat(FOOD_ID)
|
||||
return
|
||||
}
|
||||
}
|
||||
scriptAPI.takeNearestGroundItem(items.get(0).id)
|
||||
if(bot.inventory.getAmount(Item(FOOD_ID)) == 0){
|
||||
state = State.GOING_TO_BANK
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(assignment.amount > 0) {
|
||||
if (task.borders.insideBorder(bot)) { //make sure bot is within the borders of the task's zone.
|
||||
scriptAPI.attackNpcInRadius(bot, task.npc_name, 20) //attack nearest NPC with given task name within radius.
|
||||
assignment.amount--
|
||||
} else {
|
||||
scriptAPI.walkTo(task.borders.randomLoc)
|
||||
}
|
||||
} else {
|
||||
state = State.GOING_TO_BANK //switch states and bank.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State used to handle traveling to a bank. Due to the dynamic nature of where these bots might be
|
||||
* in this state, they simply teleport to Varrock and then walk to the west bank to bank.
|
||||
*/
|
||||
State.GOING_TO_BANK -> {
|
||||
if(!teleportFlag){
|
||||
scriptAPI.teleport(Location.create(3213, 3426, 0))
|
||||
teleportFlag = !teleportFlag
|
||||
} else {
|
||||
if(!varrockBankBorders.insideBorder(bot)) {
|
||||
scriptAPI.walkTo(varrockBankBorders.randomLoc)
|
||||
} else {
|
||||
val bank = scriptAPI.getNearestNode("Bank Booth",true)
|
||||
bank ?: return
|
||||
/**
|
||||
* Run a pulse that moves the bot to the bank booth and then faces it, and then swaps to the actual banking state
|
||||
*/
|
||||
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
state = State.BANKING
|
||||
teleportFlag = !teleportFlag
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State used to handle banking itself. Runs a pulse with a delay of 10 (to make it look like the bot is idling at the bank booth a bit.)
|
||||
* the pulse adds every item in the bot's inventory to its bank and then clears the bot's inventory. Re-adds lobsters to the inventory afterwords.
|
||||
*/
|
||||
State.BANKING -> {
|
||||
bot.pulseManager.run(object: Pulse(10){
|
||||
override fun pulse(): Boolean {
|
||||
for(item in bot.inventory.toArray()){
|
||||
item ?: continue
|
||||
if(item.checkIgnored()) continue
|
||||
bot.bank.add(item)
|
||||
}
|
||||
bot.inventory.clear()
|
||||
for(item in inventory)
|
||||
bot.inventory.add(item)
|
||||
scriptAPI.withdraw(org.rs09.consts.Items.LOBSTER_379,10)
|
||||
bot.fullRestore()
|
||||
|
||||
if(assignment.amount <= 0){
|
||||
state = State.GOING_TO_GE
|
||||
} else {
|
||||
state = State.GOING_TO_HUB
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* State used to handle travelling to the GE.
|
||||
*/
|
||||
State.GOING_TO_GE -> {
|
||||
if(bot.location != Location.create(3165, 3487, 0)) {
|
||||
scriptAPI.walkTo(Location.create(3165, 3487, 0))
|
||||
} else {
|
||||
state = State.SELLING
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State used to handle selling items on the GE
|
||||
*/
|
||||
State.SELLING -> {
|
||||
scriptAPI.sellAllOnGe()
|
||||
state = State.GETTING_TASK
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a bot needs to be regenerated, like when a bot dies.
|
||||
*/
|
||||
override fun newInstance(): Script {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate task and assignment vars
|
||||
*/
|
||||
fun populateTaskAndAssignment() {
|
||||
task = Task.values().random() //get a new random task from the enum
|
||||
assignment = Assignment(task.npc_name, RandomFunction.random(task.minAmt, task.maxAmt + 1)) //produce a new Assignment class with values from our Task.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Item extension function to check for ignored items when banking.
|
||||
*/
|
||||
fun Item.checkIgnored(): Boolean {
|
||||
if(name.toLowerCase().contains("charm")) return true
|
||||
if(name.toLowerCase().contains("lobster")) return true
|
||||
if(name.toLowerCase().contains("clue")) return true
|
||||
if(!definition.isTradeable) return true
|
||||
return when(id){
|
||||
Items.BONES_2530 -> true
|
||||
995 -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The state enums
|
||||
*/
|
||||
enum class State {
|
||||
GETTING_TASK,
|
||||
GOING_TO_HUB,
|
||||
KILLING_ENEMY,
|
||||
LOOTING,
|
||||
GOING_TO_BANK,
|
||||
BANKING,
|
||||
GOING_TO_GE,
|
||||
SELLING
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign default skills and initial inventory
|
||||
*/
|
||||
init {
|
||||
skills[Skills.SLAYER] = 99
|
||||
inventory.add(Item(Items.LOBSTER_379,10))
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List of tasks that this bot can receive
|
||||
*/
|
||||
enum class Task(val npc_name: String, val minAmt: Int, val maxAmt: Int, val hub: TaskHub, val borders: ZoneBorders) {
|
||||
CAVE_CRAWLER("Cave crawler",20,100, TaskHub.FREMENNIK_CAVE, ZoneBorders(2778, 9988,2798, 10002))
|
||||
}
|
||||
|
||||
/**
|
||||
* The task hubs
|
||||
*/
|
||||
enum class TaskHub {
|
||||
FREMENNIK_CAVE,
|
||||
SLAYER_TOWER,
|
||||
TAVERLY_DUNGEON
|
||||
}
|
||||
|
||||
class Assignment(val npc_name: String, var amount: Int) //class used to keep track of current assignment and how many are left.
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.bots
|
||||
|
||||
import content.global.handlers.iface.GlassInterface
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.global.skill.crafting.GlassProduct
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class GlassBlowingBankstander : Script(){
|
||||
var state = State.BLOWING
|
||||
override fun tick() {
|
||||
val bank = scriptAPI.getNearestNode("Bank booth")
|
||||
bot.faceLocation(bank?.location)
|
||||
state = when(state){
|
||||
State.BLOWING -> {
|
||||
bot.inventory.add(Item(Items.GLASSBLOWING_PIPE_1785))
|
||||
bot.inventory.add(Item(Items.MOLTEN_GLASS_1775,27))
|
||||
GlassInterface.make(bot, GlassProduct.ORB,27)
|
||||
State.BANKING
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
bot.inventory.clear()
|
||||
State.BLOWING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = GlassBlowingBankstander()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.AVERAGE,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.CRAFTING] = 99
|
||||
}
|
||||
|
||||
enum class State {
|
||||
BLOWING,
|
||||
BANKING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Gnome Agility Course Script")
|
||||
@ScriptDescription("Start the script while standing front of the balancing log")
|
||||
@ScriptIdentifier("gnome_agility")
|
||||
class GnomeAgility : Script() {
|
||||
|
||||
var state = State.INIT
|
||||
val startzone = ZoneBorders(2473,3436,2475,3437,0)
|
||||
val afterlog = ZoneBorders(2474,3429,2474,3429,0)
|
||||
val beforefirstnet = ZoneBorders(2473,3426,2474,3427,0)
|
||||
val afterfirstnet = ZoneBorders(2471,3424,2476,3424,1)
|
||||
val beforebranchup = ZoneBorders(2473,3423,2473,3423,1)
|
||||
val afterbranchup = ZoneBorders(2473,3420,2473,3420,2)
|
||||
val beforerope = ZoneBorders(2477,3420,2477,3420,2)
|
||||
val afterrope = ZoneBorders(2483,3420,2483,3420,2)
|
||||
val beforebranchdown = ZoneBorders(2485,3419,2486,3420,2)
|
||||
val afterbranchdown = ZoneBorders(2487,3420,2487,3420,0)
|
||||
val beforesecondnet = ZoneBorders(2483,3425,2488,3425,0)
|
||||
val aftersecondnet = ZoneBorders(2483,3427,2488,3427,0)
|
||||
val beforepipe = ZoneBorders(2484,3430,2487,3430,0)
|
||||
val afterpipe = ZoneBorders(2484,3437,2487,3437,0)
|
||||
var overlay: ScriptAPI.BottingOverlay? = null
|
||||
var totalLaps = 0
|
||||
|
||||
override fun tick() {
|
||||
|
||||
when (state) {
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Agility Course")
|
||||
overlay!!.setTaskLabel("Laps Run")
|
||||
overlay!!.setAmount(0)
|
||||
|
||||
state = State.START
|
||||
}
|
||||
|
||||
State.START -> {
|
||||
if(!startzone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(startzone.randomLoc)
|
||||
}
|
||||
if(startzone.insideBorder(bot)){
|
||||
state = State.LOG
|
||||
}
|
||||
}
|
||||
|
||||
State.LOG -> {
|
||||
val log = scriptAPI.getNearestNode("log balance",true)
|
||||
if(startzone.insideBorder(bot)) {
|
||||
scriptAPI.interact(bot, log, "walk-across")
|
||||
}
|
||||
if(afterlog.insideBorder(bot)){
|
||||
state = State.FIRSTNET
|
||||
}
|
||||
}
|
||||
|
||||
State.FIRSTNET -> {
|
||||
val firstnet = scriptAPI.getNearestNode("obstacle net",true)
|
||||
if(!beforefirstnet.insideBorder(bot)){
|
||||
scriptAPI.walkTo(beforefirstnet.randomLoc)
|
||||
}
|
||||
if(beforefirstnet.insideBorder(bot)) {
|
||||
scriptAPI.interact(bot, firstnet, "climb-over")
|
||||
}
|
||||
if(afterfirstnet.insideBorder(bot)){
|
||||
state = State.BRANCHUP
|
||||
}
|
||||
}
|
||||
|
||||
State.BRANCHUP -> {
|
||||
val branchup = scriptAPI.getNearestNode("tree branch", true)
|
||||
if(!beforebranchup.insideBorder(bot) && !afterbranchup.insideBorder(bot)){
|
||||
scriptAPI.walkTo(beforebranchup.randomLoc)
|
||||
}
|
||||
else if(beforebranchup.insideBorder(bot)){
|
||||
scriptAPI.interact(bot,branchup,"climb")
|
||||
}
|
||||
else if(afterbranchup.insideBorder(bot)){
|
||||
state = State.ROPE
|
||||
}
|
||||
}
|
||||
|
||||
State.ROPE -> {
|
||||
val rope = scriptAPI.getNearestNode("balancing rope",true)
|
||||
if(!beforerope.insideBorder(bot) && !afterrope.insideBorder(bot)){
|
||||
scriptAPI.walkTo(beforerope.randomLoc)
|
||||
}
|
||||
else if(beforerope.insideBorder(bot)){
|
||||
scriptAPI.interact(bot,rope,"walk-on")
|
||||
}
|
||||
else if(afterrope.insideBorder(bot)){
|
||||
state = State.BRANCHDOWN
|
||||
}
|
||||
}
|
||||
|
||||
State.BRANCHDOWN -> {
|
||||
val branchdown = scriptAPI.getNearestNode("tree branch",true)
|
||||
if(!beforebranchdown.insideBorder(bot) && !afterbranchdown.insideBorder(bot)){
|
||||
scriptAPI.walkTo(beforebranchdown.randomLoc)
|
||||
}
|
||||
else if(beforebranchdown.insideBorder(bot)){
|
||||
scriptAPI.interact(bot,branchdown,"climb-down")
|
||||
}
|
||||
else if(afterbranchdown.insideBorder(bot)){
|
||||
state = State.SECONDNET
|
||||
}
|
||||
}
|
||||
|
||||
State.SECONDNET -> {
|
||||
val secondnet = scriptAPI.getNearestNode("obstacle net",true)
|
||||
if(!beforesecondnet.insideBorder(bot) && !aftersecondnet.insideBorder(bot)){
|
||||
scriptAPI.walkTo(beforesecondnet.randomLoc)
|
||||
}
|
||||
else if(beforesecondnet.insideBorder(bot)){
|
||||
scriptAPI.interact(bot,secondnet,"climb-over")
|
||||
}
|
||||
else if(aftersecondnet.insideBorder(bot)){
|
||||
state = State.PIPE
|
||||
}
|
||||
}
|
||||
|
||||
State.PIPE -> {
|
||||
val pipe = scriptAPI.getNearestNode("obstacle pipe",true)
|
||||
if(!beforepipe.insideBorder(bot) && !afterpipe.insideBorder(bot)){
|
||||
scriptAPI.walkTo((beforepipe.randomLoc))
|
||||
}
|
||||
if(beforepipe.insideBorder(bot)){
|
||||
scriptAPI.interact(bot,pipe,"squeeze-through")
|
||||
}
|
||||
if(afterpipe.insideBorder(bot)){
|
||||
totalLaps += 1
|
||||
overlay!!.setAmount(totalLaps)
|
||||
state = State.START
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = GnomeAgility()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
enum class State {
|
||||
START,
|
||||
LOG,
|
||||
FIRSTNET,
|
||||
BRANCHUP,
|
||||
ROPE,
|
||||
BRANCHDOWN,
|
||||
SECONDNET,
|
||||
PIPE,
|
||||
INIT
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import content.global.skill.crafting.spinning.SpinningItem
|
||||
import content.global.skill.crafting.spinning.SpinningPulse
|
||||
import core.game.bots.*
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Gnome Stronghold Bowstring")
|
||||
@ScriptDescription("Start in Gnome Stronghold, South of the Agility Course")
|
||||
@ScriptIdentifier("gnome_bowstring")
|
||||
class GnomeBowstring : Script() {
|
||||
var state = State.PICKING
|
||||
var stage = 0
|
||||
var bLadderSwitch = false
|
||||
var sLadderSwitch = false
|
||||
val flaxzone = ZoneBorders(2457,3391,2493,3413,0)
|
||||
val bankbottomLadder = ZoneBorders(2444, 3413, 2445, 3414, 0)
|
||||
val banktopLadder = ZoneBorders(2445, 3415, 2446, 3414, 1)
|
||||
val spinnerbottomLadder = ZoneBorders (2475, 3400, 2476, 3399, 0)
|
||||
val spinnertopLadder = ZoneBorders (2474, 3397, 2476, 3399, 1)
|
||||
val pick = ZoneBorders(2478, 3394, 339, 9)
|
||||
val bank = ZoneBorders(2447, 3415, 2444, 3434)
|
||||
var overlay: ScriptAPI.BottingOverlay? = null
|
||||
override fun tick() {
|
||||
|
||||
when(state){
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Picking")
|
||||
overlay!!.setTaskLabel("Flax Picked")
|
||||
overlay!!.setAmount(0)
|
||||
}
|
||||
|
||||
State.PICKING -> {
|
||||
bot.interfaceManager.close()
|
||||
if(!flaxzone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(flaxzone.randomLoc)
|
||||
} else if(flaxzone.insideBorder(bot)) {
|
||||
var flax = scriptAPI.getNearestNode(2646, true)
|
||||
scriptAPI.interact(bot,flax,"pick")
|
||||
}
|
||||
if(bot.inventory.getAmount(Items.FLAX_1779) > 27){
|
||||
sLadderSwitch = true
|
||||
state = State.TO_SPINNER
|
||||
}
|
||||
}
|
||||
|
||||
State.TO_SPINNER -> {
|
||||
if(sLadderSwitch){
|
||||
if(!spinnerbottomLadder.insideBorder(bot.location)){
|
||||
scriptAPI.walkTo(spinnerbottomLadder.randomLoc)
|
||||
} else {
|
||||
val ladder = scriptAPI.getNearestNode("Staircase", true)
|
||||
if(ladder != null){
|
||||
ladder.interaction.handle(bot, ladder.interaction[0])
|
||||
sLadderSwitch = false
|
||||
} else {
|
||||
scriptAPI.walkTo(spinnerbottomLadder.randomLoc)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(stage == 0)
|
||||
Pathfinder.find(bot, Location.create(2475,3399, 1)).walk(bot).also { stage++ }
|
||||
when(bot.location){
|
||||
Location.create(2475,3399, 1) -> Pathfinder.find(bot, Location.create(2477, 3399,1)).walk(bot)
|
||||
Location.create(2477,3399, 1) -> Pathfinder.find(bot, Location.create(2477,3398, 1)).walk(bot)
|
||||
Location.create(2477,3398, 1) -> Pathfinder.find(bot, Location.create(2476,3398, 1)).walk(bot)
|
||||
Location.create(2476,3398, 1) -> {
|
||||
val spinner = scriptAPI.getNearestNode(2644, true)
|
||||
bot.faceLocation(spinner?.location)
|
||||
bot.pulseManager.run(object: MovementPulse(bot,spinner, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(spinner?.location)
|
||||
state = State.SPINNING
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.SPINNING -> {
|
||||
bot.pulseManager.run(SpinningPulse(bot, Item(Items.FLAX_1779),bot.inventory.getAmount(Items.FLAX_1779), SpinningItem.FLAX))
|
||||
sLadderSwitch = true
|
||||
state = State.FIND_BANK
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
if(sLadderSwitch){
|
||||
val ladder = scriptAPI.getNearestNode("staircase", true)
|
||||
if(ladder != null){
|
||||
ladder.interaction.handle(bot, ladder.interaction[0])
|
||||
sLadderSwitch = false
|
||||
}
|
||||
}
|
||||
if(!bankbottomLadder.insideBorder(bot.location) && !spinnertopLadder.insideBorder(bot)){
|
||||
scriptAPI.walkTo(bankbottomLadder.randomLoc)
|
||||
}else if(bankbottomLadder.insideBorder(bot)){
|
||||
bLadderSwitch = true
|
||||
}
|
||||
if(bLadderSwitch){
|
||||
val ladder = scriptAPI.getNearestNode("staircase", true)
|
||||
if(ladder != null){
|
||||
ladder.interaction.handle(bot, ladder.interaction[0])
|
||||
bLadderSwitch = false
|
||||
}
|
||||
}
|
||||
if(banktopLadder.insideBorder(bot)){
|
||||
state = State.BANKING
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode(2213, true)
|
||||
if(bank != null) {
|
||||
bot.pulseManager.run(object : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
scriptAPI.bankItem(Items.BOW_STRING_1777)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
if(freeSlots(bot) > 27){
|
||||
bLadderSwitch = true
|
||||
state = State.RETURN_TO_FLAX
|
||||
}
|
||||
}
|
||||
|
||||
State.RETURN_TO_FLAX -> {
|
||||
if(!banktopLadder.insideBorder(bot.location) && bLadderSwitch){
|
||||
scriptAPI.walkTo(banktopLadder.randomLoc)
|
||||
} else if(bLadderSwitch){
|
||||
val ladder = scriptAPI.getNearestNode("Staircase", true)
|
||||
if(ladder != null){
|
||||
ladder.interaction.handle(bot, ladder.interaction[0])
|
||||
bLadderSwitch = false
|
||||
} else {
|
||||
scriptAPI.walkTo(banktopLadder.randomLoc)
|
||||
}
|
||||
}
|
||||
if(!flaxzone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(flaxzone.randomLoc)
|
||||
} else if(flaxzone.insideBorder(bot)){
|
||||
state = State.PICKING
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun newInstance(): Script {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
enum class State {
|
||||
PICKING,
|
||||
MINING,
|
||||
SPINNING,
|
||||
TO_SPINNER,
|
||||
FIND_BANK,
|
||||
RETURN_TO_FLAX,
|
||||
BANKING,
|
||||
INIT
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.combat.InteractionType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.global.skill.prayer.BoneBuryingOptionPlugin
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.impl.WildernessZone
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.AIRepository
|
||||
import core.game.bots.CombatBotAssembler
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.node.entity.combat.CombatSwingHandler
|
||||
import core.game.node.entity.combat.MeleeSwingHandler
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* A bot script for killing green dragons in the wilderness.. Capable of banking, selling on ge, eating, trash talking, buries bones when fleeing and more.
|
||||
* @param style The combat style the bot is going to use.
|
||||
* @param area (optional) What area the bot tries to kill dragons in.
|
||||
* @author Ceikry
|
||||
*/
|
||||
class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Script() {
|
||||
companion object {
|
||||
val westDragons = ZoneBorders(2971,3606,2991,3628)
|
||||
val wildernessLine = ZoneBorders(3078,3523,3096,3523)
|
||||
val edgevilleLine = ZoneBorders(3078,3520,3096,3520)
|
||||
val bankZone = ZoneBorders(3092,3489,3094,3493)
|
||||
val trashTalkLines = arrayOf("Bro, seriously?", "Ffs.", "Jesus christ.", "????", "Friendly!", "Get a life dude", "Do you mind??? lol", "Lol.", "Kek.", "One sec burying all the bones.", "Yikes.", "Yeet", "Ah shit, here we go again.", "Cmonnnn", "Plz", "Do you have nothing better to do?", "Cmon bro pls", "I just need to get my prayer up bro jesus", "Reeeeeee", "I cant believe you've done this", "Really m8", "Zomg", "Aaaaaaaaaaaaaaaaaaaaa", "Rofl.", "Oh god oh fuck oh shit", "....", ":|", "A q p", "Hcim btw", "I hope the revenants kill your mum", "Wrap your ass titties", "Why do this", "Bruh", "Straight sussin no cap fr fr", "This ain't bussin dawg", "Really bro?")
|
||||
}
|
||||
var state = State.TO_BANK
|
||||
var handler: CombatSwingHandler? = null
|
||||
var lootDelay = 0
|
||||
var offerMade = false
|
||||
var trashTalkDelay = 0
|
||||
|
||||
var food = if (Random.nextBoolean()){
|
||||
Items.LOBSTER_379
|
||||
} else if(Random.nextBoolean()){
|
||||
Items.SWORDFISH_373
|
||||
} else {
|
||||
Items.SHARK_385
|
||||
}
|
||||
|
||||
var myBorders: ZoneBorders? = null
|
||||
val type = CombatBotAssembler.Type.MELEE
|
||||
|
||||
override fun tick() {
|
||||
if(!bot.isActive){
|
||||
running = false
|
||||
return
|
||||
}
|
||||
|
||||
checkFoodStockAndEat()
|
||||
|
||||
when(state){
|
||||
|
||||
State.KILLING -> {
|
||||
bot.properties.combatPulse.temporaryHandler = handler
|
||||
scriptAPI.attackNpcInRadius(bot,"Green dragon",20)
|
||||
state = State.LOOT_DELAYER
|
||||
}
|
||||
|
||||
State.LOOT_DELAYER -> {
|
||||
if(lootDelay < 3)
|
||||
lootDelay++
|
||||
else
|
||||
state = State.LOOTING
|
||||
}
|
||||
|
||||
|
||||
State.RUNNING -> {
|
||||
val players = RegionManager.getLocalPlayers(bot.location)
|
||||
if(players.isEmpty()){
|
||||
state = State.TO_DRAGONS
|
||||
} else {
|
||||
if(bot.skullManager.level < 21){
|
||||
if (scriptAPI.teleportToGE())
|
||||
state = State.REFRESHING
|
||||
return
|
||||
}
|
||||
sendTrashTalk()
|
||||
attemptToBuryBone()
|
||||
scriptAPI.walkTo(WildernessZone.getInstance().borders.random().randomLoc)
|
||||
}
|
||||
}
|
||||
|
||||
State.LOOTING -> {
|
||||
lootDelay = 0
|
||||
val items = AIRepository.groundItems.get(bot)
|
||||
if(items.isNullOrEmpty()) {state = State.KILLING; return}
|
||||
if(bot.inventory.isFull) {
|
||||
if(bot.inventory.containsItem(Item(food))){
|
||||
scriptAPI.forceEat(food)
|
||||
} else {
|
||||
state = State.TO_BANK
|
||||
}
|
||||
return
|
||||
}
|
||||
items.toTypedArray().forEach {it: Item -> scriptAPI.takeNearestGroundItem(it.id)}
|
||||
}
|
||||
|
||||
State.TO_BANK -> {
|
||||
if(!wildernessLine.insideBorder(bot) && bot.location.y > 3521)
|
||||
scriptAPI.walkTo(wildernessLine.randomLoc)
|
||||
if(wildernessLine.insideBorder(bot)){
|
||||
val ditch = scriptAPI.getNearestNode("Wilderness Ditch",true)
|
||||
ditch ?: return
|
||||
ditch.interaction.handle(bot,ditch.interaction[0])
|
||||
}
|
||||
if(!bankZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
if(bankZone.insideBorder(bot)){
|
||||
val bank = scriptAPI.getNearestNode("Bank Booth",true)
|
||||
bank ?: return
|
||||
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
state = State.BANKING
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
bot.pulseManager.run(object: Pulse(25){
|
||||
override fun pulse(): Boolean {
|
||||
for(item in bot.inventory.toArray()){
|
||||
item ?: continue
|
||||
if(item.name.toLowerCase().contains("lobster") || item.name.toLowerCase().contains("swordfish") || item.name.toLowerCase().contains("shark")) continue
|
||||
if(item.id == 995) continue
|
||||
bot.bank.add(item)
|
||||
}
|
||||
bot.inventory.clear()
|
||||
state = if(bot.bank.getAmount(food) < 10)
|
||||
State.TO_GE
|
||||
else
|
||||
State.TO_DRAGONS
|
||||
for(item in inventory)
|
||||
bot.inventory.add(item)
|
||||
scriptAPI.withdraw(food,10)
|
||||
bot.fullRestore()
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
State.BUYING_FOOD -> {
|
||||
state = State.TO_DRAGONS
|
||||
bot.bank.add(Item(food,50))
|
||||
bot.bank.refresh()
|
||||
scriptAPI.withdraw(food, 10)
|
||||
}
|
||||
|
||||
State.TO_DRAGONS -> {
|
||||
offerMade = false
|
||||
if(bot.location.x >= 3143){
|
||||
if(bot.location != Location.create(3144, 3514, 0))
|
||||
scriptAPI.walkTo(Location.create(3144, 3514, 0))
|
||||
else {
|
||||
val shortcut = scriptAPI.getNearestNode("Underwall Tunnel",true)
|
||||
shortcut ?: return
|
||||
InteractionListeners.run(shortcut.id, IntType.SCENERY, "climb-into", bot, shortcut)
|
||||
}
|
||||
} else {
|
||||
if (!edgevilleLine.insideBorder(bot) && bot.location.y < 3520) {
|
||||
scriptAPI.walkTo(edgevilleLine.randomLoc)
|
||||
return
|
||||
}
|
||||
if (edgevilleLine.insideBorder(bot)) {
|
||||
val ditch = scriptAPI.getNearestNode("Wilderness Ditch", true)
|
||||
ditch ?: return
|
||||
ditch.interaction.handle(bot, ditch.interaction[0]).also { return }
|
||||
}
|
||||
if (bot.location.y > 3520 && !myBorders!!.insideBorder(bot))
|
||||
scriptAPI.walkTo(myBorders!!.randomLoc).also { return }
|
||||
if (myBorders!!.insideBorder(bot))
|
||||
state = State.KILLING
|
||||
}
|
||||
}
|
||||
|
||||
State.TO_GE -> {
|
||||
if(bot.location.x < 3143) {
|
||||
if(bot.location == Location.create(3136, 3517, 0)){
|
||||
val shortcut = scriptAPI.getNearestNode("Underwall Tunnel",true)
|
||||
shortcut ?: return
|
||||
InteractionListeners.run(shortcut.id, IntType.SCENERY, "climb-into", bot, shortcut)
|
||||
} else {
|
||||
scriptAPI.walkTo(Location.create(3136, 3517, 0))
|
||||
}
|
||||
return
|
||||
}
|
||||
if(bot.location != Location.create(3165, 3487, 0)) {
|
||||
scriptAPI.walkTo(Location.create(3165, 3487, 0))
|
||||
} else {
|
||||
state = State.SELL_GE
|
||||
}
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
scriptAPI.sellAllOnGe()
|
||||
state = State.BUYING_FOOD
|
||||
}
|
||||
|
||||
State.REFRESHING -> {
|
||||
running = false
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun attemptToBuryBone() {
|
||||
if (bot.inventory.containsAtLeastOneItem(Items.DRAGON_BONES_536)) {
|
||||
BoneBuryingOptionPlugin().handle(bot, bot.inventory.get(Item(Items.DRAGON_BONES_536)), "bury")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFoodStockAndEat() {
|
||||
if (bot.inventory.getAmount(food) < 3 && state == State.KILLING)
|
||||
state = State.TO_BANK
|
||||
scriptAPI.eat(food)
|
||||
}
|
||||
|
||||
private fun sendTrashTalk() {
|
||||
if (trashTalkDelay-- == 0)
|
||||
scriptAPI.sendChat(trashTalkLines.random())
|
||||
else
|
||||
trashTalkDelay = RandomFunction.random(10, 30)
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = GreenDragonKiller(style)
|
||||
val tier = CombatBotAssembler.Tier.MED
|
||||
script.bot = CombatBotAssembler().assembleMeleeDragonBot(tier, bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
enum class State {
|
||||
KILLING,
|
||||
RUNNING,
|
||||
LOOTING,
|
||||
LOOT_DELAYER,
|
||||
BANKING,
|
||||
TO_BANK,
|
||||
TO_DRAGONS,
|
||||
TO_GE,
|
||||
SELL_GE,
|
||||
REFRESHING,
|
||||
BUYING_FOOD
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
handler = MeleeSwinger(this)
|
||||
equipment.add(Item(Items.ANTI_DRAGON_SHIELD_1540))
|
||||
myBorders = westDragons
|
||||
skills[Skills.AGILITY] = 99
|
||||
bankZone.addException(ZoneBorders(3094, 3492,3094, 3492))
|
||||
bankZone.addException(ZoneBorders(3094, 3490,3094, 3490))
|
||||
}
|
||||
|
||||
internal class MeleeSwinger(val script: GreenDragonKiller) : MeleeSwingHandler() {
|
||||
override fun canSwing(entity: Entity, victim: Entity): InteractionType? {
|
||||
if(victim is Player || victim.name.contains("revenant", ignoreCase = true)) {
|
||||
script.state = State.RUNNING
|
||||
script.bot.pulseManager.clear()
|
||||
}
|
||||
return super.canSwing(entity, victim)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.Script
|
||||
|
||||
class Idler : Script(){
|
||||
override fun tick() {
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import core.game.world.GameWorld
|
||||
import kotlin.random.Random
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Catherby Lobs")
|
||||
@ScriptDescription("Start in Catherby bank with a lobster pot in your inventory.")
|
||||
@ScriptIdentifier("cath_lobs")
|
||||
class LobsterCatcher : Script() {
|
||||
private val ANIMATION = Animation(714)
|
||||
val offers = HashMap<Int, Int>()
|
||||
val limit = 2000
|
||||
var myCounter = 0
|
||||
/**
|
||||
* Represents the graphics to use.
|
||||
*/
|
||||
private val GRAPHICS = Graphics(308, 100, 50)
|
||||
internal enum class Sets(val equipment: List<Item>) {
|
||||
SET_1(listOf(Item(2643), Item(9470), Item(10756), Item(10394), Item(88), Item(9793))),
|
||||
SET_2(listOf(Item(2643), Item(6585), Item(10750), Item(10394), Item(88), Item(9793))),
|
||||
SET_3(listOf(Item(9472), Item(9470), Item(10750), Item(10394), Item(88), Item(9786))),
|
||||
SET_4(listOf(Item(2639), Item(6585), Item(10752), Item(10394), Item(88), Item(9786))),
|
||||
SET_5(listOf(Item(2639), Item(9470), Item(10750), Item(10394), Item(88), Item(9784))),
|
||||
SET_6(listOf(Item(2639), Item(6585), Item(10750), Item(10394), Item(88), Item(9784)));
|
||||
|
||||
}
|
||||
|
||||
private var bots = 0
|
||||
private var lobstopper = false
|
||||
var overlay: ScriptAPI.BottingOverlay?= null
|
||||
var fishCounter = 0
|
||||
|
||||
private var state = State.INIT
|
||||
private var tick = 0
|
||||
override fun tick() {
|
||||
when(state){
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Fishing")
|
||||
overlay!!.setTaskLabel("Lobs Caught:")
|
||||
overlay!!.setAmount(0)
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
|
||||
|
||||
State.BANKING -> {
|
||||
fishCounter += bot.inventory.getAmount(Items.RAW_LOBSTER_377)
|
||||
scriptAPI.bankItem(Items.RAW_LOBSTER_377)
|
||||
state = State.IDLE
|
||||
}
|
||||
|
||||
|
||||
State.FISHING -> {
|
||||
bot.interfaceManager.close()
|
||||
val spot = scriptAPI.getNearestNode(333, false)
|
||||
if(spot == null){
|
||||
state = State.IDLE
|
||||
} else {
|
||||
InteractionListeners.run(spot.id, IntType.NPC,"cage",bot,spot)
|
||||
}
|
||||
if(bot.inventory.isFull){
|
||||
state = State.FIND_BANK
|
||||
}
|
||||
overlay!!.setAmount(fishCounter + bot.inventory.getAmount(Items.RAW_LOBSTER_377))
|
||||
}
|
||||
|
||||
State.IDLE -> {
|
||||
if (Random.nextBoolean()){
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
else if(myCounter++ >= RandomFunction.random(1,25)){
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
}
|
||||
|
||||
State.FIND_SPOT -> {
|
||||
val spot = scriptAPI.getNearestNode(333, false)
|
||||
if (spot != null) {
|
||||
bot.walkingQueue.reset()
|
||||
state = State.FISHING
|
||||
} else {
|
||||
if (bot.location.x < 2837) {
|
||||
Pathfinder.find(bot, Location.create(2837, 3435, 0)).walk(bot)
|
||||
} else {
|
||||
Pathfinder.find(bot, Location.create(2854, 3427, 0)).walk(bot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
State.FIND_BANK -> {
|
||||
val bank = scriptAPI.getNearestGameObject(bot.location, 2213)
|
||||
class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank!!.location)
|
||||
state = State.BANKING
|
||||
return true
|
||||
}
|
||||
}
|
||||
if(bank != null){
|
||||
bot.pulseManager.run(BankingPulse())
|
||||
} else {
|
||||
if (bot.location.x > 2837) {
|
||||
Pathfinder.find(bot, Location.create(2837, 3435, 0)).walk(bot)
|
||||
} else if (bot.location.x > 2821) {
|
||||
Pathfinder.find(bot, Location.create(2821, 3435, 0)).walk(bot)
|
||||
} else if (bot.location.x > 2809){
|
||||
Pathfinder.find(bot,Location.create(2809, 3436, 0)).walk(bot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
State.TELEPORT_GE -> {
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.SELL_GE
|
||||
}
|
||||
|
||||
|
||||
State.SELL_GE -> {
|
||||
scriptAPI.sellOnGE(Items.RAW_LOBSTER_377)
|
||||
state = State.TELE_CATH
|
||||
}
|
||||
|
||||
State.TELE_CATH -> {
|
||||
if(tick++ == 10) {
|
||||
bot.lock()
|
||||
bot.visualize(ANIMATION, GRAPHICS)
|
||||
bot.impactHandler.disabledTicks = 4
|
||||
val location = Location.create(2819, 3437, 0)
|
||||
GameWorld.Pulser.submit(object : Pulse(4, bot) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.unlock()
|
||||
bot.properties.teleportLocation = location
|
||||
bot.animator.reset()
|
||||
state = State.IDLE
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
val setUp = RandomFunction.random(Sets.values().size)
|
||||
equipment.addAll(Sets.values()[setUp].equipment)
|
||||
inventory.add(Item(301))
|
||||
skills[Skills.FISHING] = 40
|
||||
}
|
||||
|
||||
enum class State{
|
||||
FISHING,
|
||||
BANKING,
|
||||
FIND_BANK,
|
||||
FIND_SPOT,
|
||||
TELEPORT_GE,
|
||||
SELL_GE,
|
||||
TELE_CATH,
|
||||
IDLE,
|
||||
INIT
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
if (!lobstopper && bots <= 0) {
|
||||
val script = LobsterCatcher()
|
||||
script.bot = AIPlayer(bot.startLocation)
|
||||
script.state = State.FIND_SPOT
|
||||
bots = 1
|
||||
return script
|
||||
}else if (tick++ == 6000 && lobstopper) {
|
||||
tick = 0
|
||||
lobstopper = false
|
||||
}
|
||||
return newInstance()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.node.item.Item
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import java.util.*
|
||||
|
||||
class ManThiever : Script() {
|
||||
override fun tick() {
|
||||
val man = scriptAPI.getNearestNode("Man")
|
||||
bot.interfaceManager.close()
|
||||
man?.let { InteractionListeners.run(man.id,
|
||||
IntType.NPC,"Pickpocket",bot,man) }
|
||||
}
|
||||
|
||||
override fun newInstance(): Script? {
|
||||
val script = ManThiever()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR, bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
init {
|
||||
equipment.addAll(Arrays.asList(Item(1103), Item(1139), Item(1265)))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.api.produceGroundItem
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
|
||||
class NonBankingMiner : Script() {
|
||||
override fun tick() {
|
||||
val rock = scriptAPI.getNearestNode(11957,true)
|
||||
if(rock != null && !bot.inventory.isFull){
|
||||
InteractionListeners.run(rock.id, IntType.SCENERY,"mine",bot,rock)
|
||||
}
|
||||
//checks if the bot has tin ore in his inventory and drops it if he does
|
||||
if(bot.inventory.containsAtLeastOneItem(Items.TIN_ORE_438)){
|
||||
produceGroundItem(null,438,1,bot.location)
|
||||
bot.inventory.remove(Item(Items.TIN_ORE_438,1))
|
||||
}
|
||||
//The following is to prevent lucky bots from breaking by having a full inventory of gems
|
||||
if(bot.inventory.isFull && (!bot.inventory.containsAtLeastOneItem(Items.TIN_ORE_438))){
|
||||
bot.inventory.clear()
|
||||
bot.inventory.add(Item(Items.MITHRIL_PICKAXE_1273))
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = NonBankingMiner()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.ATTACK] = 99
|
||||
inventory.add(Item(Items.MITHRIL_PICKAXE_1273))
|
||||
skills[Skills.MINING] = 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.global.skill.crafting.spinning.SpinningItem
|
||||
import content.global.skill.crafting.spinning.SpinningPulse
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class SeersFlax : Script(){
|
||||
var state = State.PICKING
|
||||
var stage = 0
|
||||
var doorOpen = false
|
||||
override fun tick() {
|
||||
|
||||
when(state){
|
||||
|
||||
State.PICKING -> {
|
||||
val flax = scriptAPI.getNearestNode(2646,true)
|
||||
flax?.interaction?.handle(bot,flax.interaction[1])
|
||||
if(bot.inventory.getAmount(Items.FLAX_1779) > 25){
|
||||
state = State.TO_SPINNER
|
||||
}
|
||||
}
|
||||
|
||||
State.TO_SPINNER -> {
|
||||
if(stage == 0)
|
||||
Pathfinder.find(bot, Location.create(2736, 3442, 0)).walk(bot).also { stage++ }
|
||||
when(bot.location){
|
||||
Location.create(2736, 3442, 0) -> Pathfinder.find(bot,Location.create(2722, 3456, 0)).walk(bot)
|
||||
Location.create(2722, 3456, 0) -> Pathfinder.find(bot,Location.create(2716, 3472, 0)).walk(bot)
|
||||
Location.create(2716, 3472, 0) -> {
|
||||
val door = scriptAPI.getNearestNode(25819,true)
|
||||
if(door != null && door.location?.withinDistance(bot.location,2)!!){
|
||||
door.interaction?.handle(bot, door.interaction[0])
|
||||
doorOpen = true
|
||||
} else {
|
||||
val ladder = scriptAPI.getNearestNode(25938,true)
|
||||
ladder?.interaction?.handle(bot,ladder.interaction[0]) }
|
||||
}
|
||||
Location.create(2714, 3470, 1) -> {
|
||||
val spinner = scriptAPI.getNearestNode(25824,true)
|
||||
bot.faceLocation(spinner?.location)
|
||||
bot.pulseManager.run(object: MovementPulse(bot,spinner, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(spinner?.location)
|
||||
state = State.SPINNING.also { stage = 0; doorOpen = false }
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.SPINNING -> {
|
||||
bot.pulseManager.run(SpinningPulse(bot, Item(Items.FLAX_1779),bot.inventory.getAmount(Items.FLAX_1779), SpinningItem.FLAX))
|
||||
state = State.FIND_BANK
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
when(bot.location){
|
||||
Location.create(2711, 3471, 1) -> {
|
||||
val ladder = scriptAPI.getNearestNode(25939,true)
|
||||
ladder?.interaction?.handle(bot,ladder?.interaction[0])
|
||||
}
|
||||
Location.create(2714, 3470, 0) -> Pathfinder.find(bot,Location.create(2715, 3472, 0)).walk(bot)
|
||||
Location.create(2715, 3472, 0) -> {
|
||||
val door = scriptAPI.getNearestNode(25819,true)
|
||||
if(door != null && door.location?.withinDistance(bot.location,2)!!){
|
||||
door.interaction?.handle(bot, door.interaction[0])
|
||||
doorOpen = true
|
||||
} else {
|
||||
Pathfinder.find(bot,Location.create(2726, 3481, 0)).walk(bot)
|
||||
}
|
||||
}
|
||||
Location.create(2726, 3481, 0) -> Pathfinder.find(bot,Location.create(2724, 3491, 0)).walk(bot)
|
||||
Location.create(2724, 3491, 0) -> state = State.BANKING
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode(25808,true)
|
||||
if(bank != null)
|
||||
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
scriptAPI.bankItem(Items.BOW_STRING_1777)
|
||||
if(bot.bank.getAmount(Items.BOW_STRING_1777) > 500){
|
||||
state = State.TELE_GE
|
||||
return true
|
||||
}
|
||||
state = State.RETURN_TO_FLAX
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
State.RETURN_TO_FLAX -> {
|
||||
if(bot.location == Location.create(2756, 3478, 0))
|
||||
Pathfinder.find(bot,Location.create(2726, 3486, 0)).walk(bot)
|
||||
if(stage == 0)
|
||||
Pathfinder.find(bot,Location.create(2726, 3486, 0)).walk(bot).also { stage++ }
|
||||
when(bot.location){
|
||||
Location.create(2726, 3486, 0) -> Pathfinder.find(bot,Location.create(2729, 3469, 0)).walk(bot)
|
||||
Location.create(2729, 3469, 0) -> Pathfinder.find(bot,Location.create(2734, 3447, 0)).walk(bot)
|
||||
Location.create(2734, 3447, 0) -> state = State.PICKING.also { stage = 0 }
|
||||
}
|
||||
}
|
||||
|
||||
State.TELE_GE -> {
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.SELL_GE
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
scriptAPI.sellOnGE(Items.BOW_STRING_1777)
|
||||
state = State.TELE_CAMELOT
|
||||
}
|
||||
|
||||
State.TELE_CAMELOT -> {
|
||||
scriptAPI.teleport(Location.create(2756, 3478, 0))
|
||||
stage = 0
|
||||
state = State.RETURN_TO_FLAX
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
enum class State {
|
||||
PICKING,
|
||||
SPINNING,
|
||||
TO_SPINNER,
|
||||
FIND_BANK,
|
||||
BANKING,
|
||||
TELE_GE,
|
||||
SELL_GE,
|
||||
RETURN_TO_FLAX,
|
||||
TELE_CAMELOT
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.CRAFTING] = 10
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = SeersFlax()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptName("Seers Magics")
|
||||
@ScriptDescription("Start in Seers Bank with an axe equipped or in your inventory.")
|
||||
@ScriptIdentifier("seers_magics")
|
||||
class SeersMagicTrees : Script(){
|
||||
var state = State.INIT
|
||||
var stage = 0
|
||||
val bankZone = ZoneBorders(2722,3490,2727,3493)
|
||||
val magicsZone = ZoneBorders(2700, 3396,2704, 3399)
|
||||
var overlay: ScriptAPI.BottingOverlay? = null
|
||||
var logCounter = 0
|
||||
|
||||
override fun tick() {
|
||||
when(state){
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Woodcutting")
|
||||
overlay!!.setTaskLabel("Logs cut:")
|
||||
overlay!!.setAmount(0)
|
||||
state = State.RETURN_TO_TREES
|
||||
}
|
||||
|
||||
State.CHOPPING -> {
|
||||
val tree = scriptAPI.getNearestNode(1306,true)
|
||||
bot.interfaceManager.close()
|
||||
tree?.let { InteractionListeners.run(tree.id, IntType.SCENERY,"Chop down",bot,tree) }
|
||||
if(bot.inventory.isFull){
|
||||
state = State.FIND_BANK
|
||||
}
|
||||
overlay!!.setAmount(logCounter + bot.inventory.getAmount(Items.MAGIC_LOGS_1513))
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
if(!bankZone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
} else {
|
||||
state = State.BANKING
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode(25808,true)
|
||||
if(bank != null)
|
||||
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
logCounter += bot.inventory.getAmount(Items.MAGIC_LOGS_1513)
|
||||
scriptAPI.bankItem(Items.MAGIC_LOGS_1513)
|
||||
state = State.RETURN_TO_TREES
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
State.RETURN_TO_TREES -> {
|
||||
bot.interfaceManager.close()
|
||||
if(!magicsZone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(magicsZone.randomLoc)
|
||||
} else {
|
||||
state = State.CHOPPING
|
||||
}
|
||||
}
|
||||
|
||||
State.TELE_GE -> {
|
||||
state = State.SELL_GE
|
||||
scriptAPI.teleportToGE()
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
state = State.TELE_SEERS
|
||||
scriptAPI.sellOnGE(Items.MAGIC_LOGS_1513)
|
||||
}
|
||||
|
||||
State.TELE_SEERS -> {
|
||||
state = State.RETURN_TO_TREES
|
||||
scriptAPI.teleport(Location.create(2756, 3478, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
inventory.add(Item(Items.RUNE_AXE_1359))
|
||||
skills[Skills.WOODCUTTING] = RandomFunction.random(75,99)
|
||||
}
|
||||
|
||||
enum class State {
|
||||
CHOPPING,
|
||||
FIND_BANK,
|
||||
BANKING,
|
||||
RETURN_TO_TREES,
|
||||
TELE_GE,
|
||||
SELL_GE,
|
||||
TELE_SEERS,
|
||||
INIT
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = SeersMagicTrees()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.AVERAGE,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
import kotlin.random.Random
|
||||
|
||||
/*
|
||||
Grabs all amounts in GE
|
||||
val offers = HashMap<Int, Int>()
|
||||
for (offer in GEOfferDispatch.offerMapping.values) {
|
||||
val item = offer.itemId
|
||||
val amount = offer.amount - offer.completedAmount
|
||||
if (offers[item] == null) { offers[item] = amount }
|
||||
else { offers[item] = offers[item]!!.plus(amount) }
|
||||
|
||||
if (offers[383]!!.plus(amount) >= 1000) {
|
||||
*/
|
||||
/*
|
||||
Grabs just one offer
|
||||
for (offer in GEOfferDispatch.offerMapping.values) {
|
||||
if (offer.itemId == 383 && offer.amount >= 1000) {
|
||||
*/
|
||||
/**
|
||||
* A bot script for fishing sharks in the Fishing Guild - Fishes, Banks, Sells.
|
||||
* @param mycounter used in the bots random idling function.
|
||||
* @param pause is currently not used.
|
||||
* @param limit is the number of Raw Sharks in the GE the bots will sleep at.
|
||||
* @author Sir Kermit
|
||||
* Training Wheel Manufacturer @Ceikry
|
||||
* Very slight ge modifications by @Angle
|
||||
*/
|
||||
@PlayerCompatible
|
||||
@ScriptName("Guild Sharks")
|
||||
@ScriptDescription("Start in the fishing guild with a harpoon","in your inventory.")
|
||||
@ScriptIdentifier("guild_sharks")
|
||||
class SharkCatcher : Script() {
|
||||
//val shark = Items.RAW_SHARK
|
||||
val pause = (1000..3000)
|
||||
val limit = 5000
|
||||
var myCounter = 0
|
||||
//val fishzone = ZoneBorders(2597, 3410, 2612, 3426)
|
||||
internal enum class Sets(val equipment: List<Item>) {
|
||||
SET_1(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(1007))),
|
||||
SET_2(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(1007))),
|
||||
SET_3(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(1019))),
|
||||
SET_4(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(1019))),
|
||||
SET_5(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(3765))),
|
||||
SET_6(listOf(Item(10721), Item(8283), Item(10412), Item(10414), Item(88), Item(3765)));
|
||||
|
||||
}
|
||||
private var state = State.INIT
|
||||
private var tick = 0
|
||||
var fishCounter = 0
|
||||
var overlay: ScriptAPI.BottingOverlay?= null
|
||||
|
||||
override fun tick() {
|
||||
val fishguild = Location.create(2596, 3410, 0)
|
||||
if (tick++ >= 500){
|
||||
scriptAPI.teleport(fishguild)
|
||||
state = State.FIND_SPOT
|
||||
return
|
||||
}
|
||||
when(state){
|
||||
|
||||
State.INIT -> {
|
||||
overlay = scriptAPI.getOverlay()
|
||||
overlay!!.init()
|
||||
overlay!!.setTitle("Fishing")
|
||||
overlay!!.setTaskLabel("Sharks Caught:")
|
||||
overlay!!.setAmount(0)
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
fishCounter += bot.inventory.getAmount(Items.RAW_SHARK_383)
|
||||
scriptAPI.bankItem(Items.RAW_SHARK_383)
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
|
||||
State.STOP -> {
|
||||
val botAmount = bot.bank.getAmount(Items.RAW_SHARK_383) + 1
|
||||
var geAmount = 0//OfferManager.getQuantitySoldForItem(Items.RAW_SHARK_383)
|
||||
val totalAmount = (geAmount + botAmount) + 1
|
||||
if((totalAmount > limit) && myCounter++ == 300){
|
||||
bot.randomWalk(5,5)
|
||||
myCounter = 0
|
||||
return
|
||||
} else if (myCounter++ == 300){
|
||||
myCounter = 0
|
||||
State.TELE_FISH
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
State.IDLE -> {
|
||||
if (Random.nextBoolean()){
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
else if(myCounter++ >= RandomFunction.random(1,25)){
|
||||
myCounter = 0
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
}
|
||||
|
||||
State.FISHING -> {
|
||||
bot.interfaceManager.close()
|
||||
if (Random.nextBoolean()) {
|
||||
tick = 0
|
||||
val spot = scriptAPI.getNearestNode(334, false)
|
||||
spot?.let { InteractionListeners.run(spot.id, IntType.NPC,"harpoon",bot,spot) }
|
||||
if(bot.inventory.isFull){
|
||||
state = State.FIND_BANK
|
||||
} else {
|
||||
state = State.IDLE
|
||||
}
|
||||
}
|
||||
else{
|
||||
state = State.IDLE
|
||||
}
|
||||
overlay!!.setAmount(fishCounter + bot.inventory.getAmount(Items.RAW_SHARK_383))
|
||||
}
|
||||
|
||||
State.FIND_SPOT -> {
|
||||
val spot = scriptAPI.getNearestNode(334, false)
|
||||
if (spot != null) {
|
||||
bot.walkingQueue.reset()
|
||||
state = State.FISHING
|
||||
} else {
|
||||
if(bot.location.x < 2591) {
|
||||
scriptAPI.walkTo(Location.create(2604, 3421, 0))
|
||||
} else {
|
||||
scriptAPI.walkTo(Location.create(2608, 3414, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.FIND_BANK -> {
|
||||
val bank = scriptAPI.getNearestGameObject(bot.location, 2213)
|
||||
class BankingPulse : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank!!.location)
|
||||
state = State.BANKING
|
||||
return true
|
||||
}
|
||||
}
|
||||
if(bank != null){
|
||||
bot.pulseManager.run(BankingPulse())
|
||||
} else {
|
||||
if (bot.location.x != 2596) {
|
||||
scriptAPI.walkTo(Location.create(2596, 3415, 0))
|
||||
} else if (bot.location.x < 2591) {
|
||||
scriptAPI.walkTo(Location.create(2591, 3415, 0))
|
||||
} else if (bot.location.x < 2587){
|
||||
scriptAPI.walkTo(Location.create(2587, 3420, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.TELEPORT_GE -> {
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.SELL_GE
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
val botAmount = bot.bank.getAmount(Items.RAW_SHARK_383) + 1
|
||||
var geAmount = 0//OfferManager.getQuantitySoldForItem(Items.RAW_SHARK_383)
|
||||
val totalAmount = (geAmount + botAmount) + 1
|
||||
if(totalAmount > limit){
|
||||
scriptAPI.walkTo(Location.create(3164, 3487, 0))
|
||||
scriptAPI.sellOnGE(Items.RAW_SHARK_383)
|
||||
state = State.STOP//.also { println("STOPPING") }
|
||||
} else {
|
||||
scriptAPI.walkTo(Location.create(3164, 3487, 0))
|
||||
scriptAPI.sellOnGE(Items.RAW_SHARK_383)
|
||||
state = State.TELE_FISH
|
||||
}
|
||||
}
|
||||
|
||||
State.TELE_FISH -> {
|
||||
scriptAPI.teleport(fishguild)
|
||||
state = State.FIND_SPOT
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
val setUp = RandomFunction.random(Sets.values().size)
|
||||
equipment.addAll(Sets.values()[setUp].equipment)
|
||||
inventory.add(Item(311))
|
||||
skills[Skills.FISHING] = 90
|
||||
}
|
||||
|
||||
enum class State{
|
||||
FISHING,
|
||||
BANKING,
|
||||
FIND_BANK,
|
||||
FIND_SPOT,
|
||||
TELEPORT_GE,
|
||||
SELL_GE,
|
||||
TELE_FISH,
|
||||
IDLE,
|
||||
STOP,
|
||||
INIT
|
||||
}
|
||||
override fun newInstance(): Script {
|
||||
val script = SharkCatcher()
|
||||
script.bot = AIPlayer(bot.startLocation)
|
||||
script.state = State.FIND_SPOT
|
||||
return script
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.GeneralBotCreator
|
||||
import content.global.activity.shootingstar.ShootingStarPlugin
|
||||
import core.game.bots.Script
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
|
||||
class ShootingStarBot : Script() {
|
||||
private var state = State.FULL_IDLE
|
||||
private var timerCountdown = 0
|
||||
val star = ShootingStarPlugin.getStar()
|
||||
|
||||
override fun tick() {
|
||||
bot.fullRestore()
|
||||
|
||||
if(timerCountdown > 0) {
|
||||
--timerCountdown
|
||||
return
|
||||
}
|
||||
|
||||
when(state) {
|
||||
State.FULL_IDLE -> {}
|
||||
|
||||
State.TELEPORT_TO -> {
|
||||
scriptAPI.teleport(star.crash_locations[star.location]!!.transform(0, -1, 0))
|
||||
state = State.MINING
|
||||
timerCountdown = 15
|
||||
}
|
||||
|
||||
State.MINING -> {
|
||||
InteractionListeners.run(star.starObject.id, IntType.SCENERY, "mine", bot, star.starObject)
|
||||
}
|
||||
|
||||
State.TELEPORT_BACK -> {
|
||||
scriptAPI.teleport(spawnLoc)
|
||||
timerCountdown = 15
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.ATTACK] = 41
|
||||
skills[Skills.RANGE] = RandomFunction.random(30,99)
|
||||
skills[Skills.MINING] = 99
|
||||
skills[Skills.HITPOINTS] = 99
|
||||
skills[Skills.DEFENCE] = 99
|
||||
skills[Skills.SUMMONING] = 99
|
||||
skills[Skills.PRAYER] = 99
|
||||
inventory.add(Item(Items.RUNE_PICKAXE_1275))
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
return ShootingStarBot()
|
||||
}
|
||||
|
||||
fun activate(instant: Boolean) {
|
||||
state = State.TELEPORT_TO
|
||||
if(!instant)
|
||||
timerCountdown = RandomFunction.random(500)
|
||||
}
|
||||
|
||||
fun sleep() {
|
||||
state = State.TELEPORT_BACK
|
||||
}
|
||||
|
||||
fun isMining() : Boolean {
|
||||
return state == State.MINING
|
||||
}
|
||||
|
||||
fun isIdle() : Boolean {
|
||||
return state == State.FULL_IDLE
|
||||
}
|
||||
|
||||
internal enum class State {
|
||||
FULL_IDLE,
|
||||
TELEPORT_TO,
|
||||
MINING,
|
||||
TELEPORT_BACK
|
||||
}
|
||||
|
||||
companion object {
|
||||
val spawnLoc = Location.create(2230, 3339, 0)
|
||||
fun new() : ShootingStarBot {
|
||||
val script = ShootingStarBot()
|
||||
GeneralBotCreator(script, spawnLoc)
|
||||
return script
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.bots.*
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListeners
|
||||
|
||||
@PlayerCompatible
|
||||
@ScriptDescription("Start in varrock bank with rune mysteries complete and a pickaxe equipped/in inventory")
|
||||
@ScriptName("Varrock Essence Miner")
|
||||
@ScriptIdentifier("essence_miner")
|
||||
class VarrockEssenceMiner : Script(){
|
||||
|
||||
var state = State.TO_ESSENCE
|
||||
val auburyZone = ZoneBorders(3252, 3398, 3254, 3402)
|
||||
val bankZone = ZoneBorders(3251, 3420,3254, 3422)
|
||||
override fun tick() {
|
||||
|
||||
when(state){
|
||||
State.TO_ESSENCE -> {
|
||||
bot.interfaceManager.close()
|
||||
if(!auburyZone.insideBorder(bot))
|
||||
scriptAPI.walkTo(auburyZone.randomLoc)
|
||||
else {
|
||||
val aubury = scriptAPI.getNearestNode("Aubury")
|
||||
aubury?.interaction?.handle(bot,aubury.interaction[3])
|
||||
state = State.MINING
|
||||
}
|
||||
/*val bank = scriptAPI.getNearestNode("Bank booth",true)
|
||||
if(bank != null && bank.location?.withinDistance(bot.location,2) == true){
|
||||
Pathfinder.find(bot, Location.create(3259, 3405, 0)).walk(bot)
|
||||
} else {
|
||||
when(bot.location){
|
||||
Location.create(3165, 3487, 0) -> scriptAPI.teleport(Location.create(3254, 3421, 0))
|
||||
Location.create(3259, 3405, 0) -> Pathfinder.find(bot,Location.create(3253, 3400, 0)).walk(bot)
|
||||
Location.create(3253, 3400, 0) -> {
|
||||
val aubury = scriptAPI.getNearestNode("Aubury")
|
||||
aubury?.interaction?.handle(bot,aubury.interaction[3])
|
||||
}
|
||||
Location.create(2922, 4820, 0) -> {
|
||||
state = State.MINING
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
State.MINING -> {
|
||||
val essence = scriptAPI.getNearestNode(2491,true)
|
||||
essence?.let { InteractionListeners.run(essence.id, IntType.SCENERY,"mine",bot,essence) }
|
||||
if(bot.inventory.isFull)
|
||||
state = State.TO_BANK
|
||||
}
|
||||
|
||||
State.TO_BANK -> {
|
||||
val portal = scriptAPI.getNearestNode("Portal",true)
|
||||
if(portal != null && portal.location.withinDistance(bot.location,20))
|
||||
portal.interaction.handle(bot,portal.interaction[0])
|
||||
else {
|
||||
if(!bankZone.insideBorder(bot)){
|
||||
scriptAPI.walkTo(bankZone.randomLoc)
|
||||
} else {
|
||||
state = State.BANKING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode("bank booth",true)
|
||||
val item =
|
||||
if(bot.inventory.getAmount(Items.RUNE_ESSENCE_1436) > 0) Items.RUNE_ESSENCE_1436 else Items.PURE_ESSENCE_7936
|
||||
if(bank != null){
|
||||
bot.pulseManager.run(object : MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
scriptAPI.bankItem(item)
|
||||
state = State.TO_ESSENCE
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
State.TELE_GE -> {
|
||||
if(bot.location != Location.create(3165, 3482, 0))
|
||||
scriptAPI.walkTo(Location.create(3165, 3482, 0))
|
||||
else
|
||||
state = State.SELL_GE
|
||||
}
|
||||
|
||||
State.SELL_GE -> {
|
||||
scriptAPI.sellOnGE(Items.PURE_ESSENCE_7936)
|
||||
state = State.TO_ESSENCE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class State{
|
||||
TO_ESSENCE,
|
||||
TO_BANK,
|
||||
MINING,
|
||||
BANKING,
|
||||
TELE_GE,
|
||||
SELL_GE
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = VarrockEssenceMiner()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
|
||||
return script
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package content.global.bots
|
||||
|
||||
import core.game.interaction.DestinationFlag
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.global.skill.smithing.Bars
|
||||
import content.global.skill.smithing.SmithingPulse
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Location
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import core.game.bots.SkillingBotAssembler
|
||||
import core.game.bots.Script
|
||||
|
||||
class VarrockSmither : Script() {
|
||||
var state = State.SMITHING
|
||||
override fun tick() {
|
||||
when(state) {
|
||||
State.SMITHING -> {
|
||||
for (i in inventory) {
|
||||
bot.inventory.add(i)
|
||||
}
|
||||
val anvil = scriptAPI.getNearestNode("anvil", true)
|
||||
if (anvil != null) {
|
||||
bot.pulseManager.run(object : MovementPulse(bot, anvil, DestinationFlag.OBJECT) {
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(anvil.location)
|
||||
bot.pulseManager.run(SmithingPulse(bot, Item(2353), Bars.STEEL_ARROW_TIPS, 27))
|
||||
state = State.BANKING
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
State.BANKING -> {
|
||||
val bank = scriptAPI.getNearestNode("Bank booth")
|
||||
if(bank != null)
|
||||
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
||||
override fun pulse(): Boolean {
|
||||
bot.faceLocation(bank.location)
|
||||
bot.inventory.clear()
|
||||
state = State.SMITHING
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = VarrockSmither()
|
||||
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.RICH, Location.create(3189, 3436, 0))
|
||||
return script
|
||||
}
|
||||
|
||||
init {
|
||||
skills[Skills.SMITHING] = RandomFunction.random(33,99)
|
||||
inventory.add(Item(Items.HAMMER_2347))
|
||||
inventory.add(Item(Items.STEEL_BAR_2353,27))
|
||||
}
|
||||
|
||||
enum class State {
|
||||
SMITHING,
|
||||
BANKING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package content.global.dialogue
|
||||
|
||||
import core.api.dumpBeastOfBurden
|
||||
import core.api.dumpContainer
|
||||
import core.api.sendMessage
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
/**
|
||||
* Represents the dialogue shown when the user presses
|
||||
* "Deposit Beast of Burden" button on the Bank Interface.
|
||||
*
|
||||
* @author vddCore
|
||||
*/
|
||||
class BankDepositDialogue : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
START_DIALOGUE -> options(
|
||||
"Deposit Inventory",
|
||||
"Deposit Worn Equipment",
|
||||
"Deposit Beast of Burden",
|
||||
"Cancel"
|
||||
).also { stage++ }
|
||||
|
||||
1 -> when (buttonID) {
|
||||
1 -> player?.let {
|
||||
end()
|
||||
|
||||
if (it.inventory.isEmpty) {
|
||||
sendMessage(it, "You have nothing in your inventory that you can deposit.")
|
||||
} else {
|
||||
dumpContainer(it, it.inventory)
|
||||
}
|
||||
}
|
||||
|
||||
2 -> player?.let {
|
||||
end()
|
||||
|
||||
if (it.equipment.isEmpty) {
|
||||
sendMessage(it, "You have no equipment that you can deposit.")
|
||||
} else {
|
||||
dumpContainer(it, it.equipment)
|
||||
}
|
||||
}
|
||||
|
||||
3 -> player?.let {
|
||||
end()
|
||||
dumpBeastOfBurden(it)
|
||||
}
|
||||
|
||||
4 -> end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package content.global.dialogue
|
||||
|
||||
import core.api.openInterface
|
||||
import core.api.sendDialogue
|
||||
import core.api.sendItemDialogue
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
import core.game.dialogue.DialogueFile
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
/**
|
||||
* Represents the dialogue shown when the user presses
|
||||
* the "?" button on the Bank Interface.
|
||||
*
|
||||
* @author vddCore
|
||||
*/
|
||||
class BankHelpDialogue : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when (stage) {
|
||||
START_DIALOGUE -> options(
|
||||
"Check Bank Value",
|
||||
"Banking Assistance",
|
||||
"Close"
|
||||
).also { stage++ }
|
||||
|
||||
1 -> when (buttonID) {
|
||||
1 -> player?.let {
|
||||
end()
|
||||
|
||||
val wealth = it.bank.wealth
|
||||
|
||||
if (wealth > 0) {
|
||||
val word = if (wealth != 1) "coins" else "coin"
|
||||
|
||||
sendItemDialogue(
|
||||
it,
|
||||
Item(Items.COINS_995, wealth),
|
||||
"<br>Your bank is worth <col=a52929>${wealth}</col> ${word}."
|
||||
)
|
||||
} else {
|
||||
sendDialogue(it, "You have no valuables in your bank.")
|
||||
}
|
||||
}
|
||||
|
||||
2 -> player?.let {
|
||||
end()
|
||||
|
||||
it.bank.close()
|
||||
openInterface(it, Components.BANK_V2_HELP_767)
|
||||
}
|
||||
|
||||
3 -> end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package content.global.dialogue
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.IronmanMode
|
||||
import core.plugin.Initializable
|
||||
import core.game.dialogue.IfTopic
|
||||
import core.game.dialogue.Topic
|
||||
import content.global.handlers.npc.BankerNPC
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.START_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class BankerDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
when (stage) {
|
||||
START_DIALOGUE -> when {
|
||||
hasIronmanRestriction(player, IronmanMode.ULTIMATE) -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.ANNOYED,
|
||||
"My apologies, dear ${if (player.isMale) "sir" else "madam"}, " +
|
||||
"our services are not available for Ultimate ${if (player.isMale) "Ironmen" else "Ironwomen"}"
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
else -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Good day, how may I help you?"
|
||||
).also {
|
||||
if (hasAwaitingGrandExchangeCollections(player)) {
|
||||
stage++
|
||||
} else {
|
||||
stage += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Before we go any further, I should inform you that you " +
|
||||
"have items ready for collection from the Grand Exchange."
|
||||
).also { stage++ }
|
||||
|
||||
2 -> showTopics(
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to access my bank account, please.", 10),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to switch to my ${getBankAccountName(player, true)} bank account.",
|
||||
13,
|
||||
hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
IfTopic(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"I'd like to open a secondary bank account.",
|
||||
20,
|
||||
!hasActivatedSecondaryBankAccount(player)
|
||||
),
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to check my PIN settings.", 11),
|
||||
Topic(core.game.dialogue.FacialExpression.FRIENDLY, "I'd like to collect items.", 12),
|
||||
Topic(core.game.dialogue.FacialExpression.ASKING, "What is this place?", 3),
|
||||
)
|
||||
|
||||
3 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"This is a branch of the Bank of Gielinor. We have branches in many towns."
|
||||
).also { stage++ }
|
||||
|
||||
4 -> playerl(
|
||||
core.game.dialogue.FacialExpression.ASKING,
|
||||
"And what do you do?"
|
||||
).also { stage++ }
|
||||
|
||||
5 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"We will look after your items and money for you. " +
|
||||
"Leave your valuables with us if you want to keep them safe."
|
||||
).also { stage = END_DIALOGUE }
|
||||
|
||||
10 -> {
|
||||
openBankAccount(player)
|
||||
end()
|
||||
}
|
||||
|
||||
11 -> {
|
||||
openBankPinSettings(player)
|
||||
end()
|
||||
}
|
||||
|
||||
12 -> {
|
||||
openGrandExchangeCollectionBox(player)
|
||||
end()
|
||||
}
|
||||
|
||||
13 -> {
|
||||
toggleBankAccount(player)
|
||||
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Your active bank account has been switched. " +
|
||||
"You can now access your ${getBankAccountName(player)} account."
|
||||
).also { stage = 2 }
|
||||
}
|
||||
|
||||
20 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Certainly. We offer secondary accounts to all our customers."
|
||||
).also { stage++ }
|
||||
|
||||
21 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"The secondary account comes with a standard fee of 5,000,000 coins. The fee is non-refundable " +
|
||||
"and account activation is permanent."
|
||||
).also { stage++ }
|
||||
|
||||
22 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"If your inventory does not contain enough money to cover the costs, we will complement " +
|
||||
"the amount with the money inside your primary bank account."
|
||||
).also { stage++ }
|
||||
|
||||
23 -> npcl(
|
||||
core.game.dialogue.FacialExpression.ASKING,
|
||||
"Knowing all this, would you like to proceed with opening your secondary bank account?"
|
||||
).also { stage++ }
|
||||
|
||||
24 -> showTopics(
|
||||
Topic(core.game.dialogue.FacialExpression.HAPPY, "Yes, I am still interested.", 25),
|
||||
Topic(core.game.dialogue.FacialExpression.ANNOYED, "Actually, I've changed my mind.", 26)
|
||||
)
|
||||
|
||||
25 -> {
|
||||
when (activateSecondaryBankAccount(player)) {
|
||||
SecondaryBankAccountActivationResult.ALREADY_ACTIVE -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Your bank account was already activated, there is no need to pay twice."
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
SecondaryBankAccountActivationResult.INTERNAL_FAILURE -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.ANNOYED,
|
||||
"I must apologize, the transaction was not successful. Please check your " +
|
||||
"primary bank account and your inventory - if there's money missing, please " +
|
||||
"screenshot your chat box and contact the game developers."
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
SecondaryBankAccountActivationResult.NOT_ENOUGH_MONEY -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.ANNOYED,
|
||||
"It appears that you do not have the money necessary to cover the costs " +
|
||||
"associated with opening a secondary bank account. I will be waiting here " +
|
||||
"until you do."
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
SecondaryBankAccountActivationResult.SUCCESS -> {
|
||||
npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Your secondary bank account has been opened and can be accessed through any " +
|
||||
"of the Bank of Gielinor's employees. Thank you for choosing our services."
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26 -> npcl(
|
||||
core.game.dialogue.FacialExpression.FRIENDLY,
|
||||
"Very well. Should you decide a secondary bank account is needed, do not hesitate to " +
|
||||
"contact any of the Bank of Gielinor's stationary employees. We will be happy to help."
|
||||
).also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray = BankerNPC.NPC_IDS
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package content.global.dialogue;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the plugin used for the fur trader.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FurTradePlugin extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FurTradePlugin} {@code Object}.
|
||||
*/
|
||||
public FurTradePlugin() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FurTradePlugin} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public FurTradePlugin(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new FurTradePlugin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Would you like to trade in fur?");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendOptions("Select an Option", "Yes.", "No.");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
end();
|
||||
npc.openShop(player);
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No, thanks.");
|
||||
stage = 20;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 573 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package content.global.dialogue
|
||||
|
||||
import content.global.skill.farming.FarmerPayOptionDialogue
|
||||
import content.global.skill.farming.Farmers
|
||||
import content.global.skill.farming.FarmingPatch
|
||||
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 org.rs09.consts.Items
|
||||
import core.tools.END_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class GardenerDialoguePlugin(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
|
||||
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin {
|
||||
return GardenerDialoguePlugin(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
npc = args[0] as NPC
|
||||
options("Would you look after my crops for me?","Can you sell me something?")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
when(stage){
|
||||
0 -> when(buttonId){
|
||||
1 -> player("Would you look after my crops for me?").also { stage = 10 }
|
||||
2 -> player("Can you sell me something?").also { stage = 30 }
|
||||
}
|
||||
|
||||
10 -> npc("I might. Which one were you thinking of?").also { stage++ }
|
||||
11 -> when(npc.id){
|
||||
Farmers.ELSTAN.id, Farmers.LYRA.id -> options("The north-western allotment.","The south-eastern allotment.").also { stage = 15 }
|
||||
Farmers.DANTAERA.id, Farmers.KRAGEN.id -> options("The north allotment.","The south allotment.").also { stage = 15 }
|
||||
else -> player("Uh, that one.").also { stage++ }
|
||||
}
|
||||
|
||||
12 -> npc("Oh, right. My bad.").also { stage++ }
|
||||
13 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0])
|
||||
|
||||
15 -> when(buttonId){
|
||||
1 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[0])
|
||||
2 -> checkPatch(player,Farmers.forId(npc.id)!!.patches[1])
|
||||
}
|
||||
|
||||
30 -> npc("That depends on whether I have it to sell.","What is it that you're looking for?").also { stage++ }
|
||||
31 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 }
|
||||
32 -> when(buttonId){
|
||||
1 -> player("Some plant cure.").also { stage = 100 }
|
||||
2 -> player("A bucket of compost.").also { stage = 200 }
|
||||
3 -> player("A rake.").also { stage = 300 }
|
||||
4 -> options("A watering can.","A gardening trowel.","A seed dibber.","(See previous items)").also { stage++ }
|
||||
}
|
||||
33 -> when(buttonId){
|
||||
1 -> player("A watering can.").also { stage = 400 }
|
||||
2 -> player("A gardening trowel.").also { stage = 500 }
|
||||
3 -> player("A seed dibber.").also { stage = 600 }
|
||||
4 -> options("Some plant cure.","A bucket of compost.","A rake.","(See more items)").also { stage = 32 }
|
||||
}
|
||||
|
||||
100 -> npc("Plant cure, eh? I might have some put aside for myself.","Tell you what, I'll sell you some plant cure","for 25 gp if you like.").also { stage++ }
|
||||
101 -> options("Yes, that sounds like a fair price.","No thanks, I can get that much cheaper.").also { stage++ }
|
||||
102 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,25))){
|
||||
player.inventory.add(Item(Items.PLANT_CURE_6036))
|
||||
} else {
|
||||
player.sendMessage("You need 25 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
|
||||
200 -> npc("A bucket of compost, eh? I might have one spare...","tell you what, I'll sell it to you for 35 gp if you like.").also { stage++ }
|
||||
201 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
202 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,35))){
|
||||
player.inventory.add(Item(Items.COMPOST_6032))
|
||||
} else {
|
||||
player.sendMessage("You need 35 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
|
||||
300 -> npc("A rake, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
301 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
302 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.RAKE_5341))
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
|
||||
400 -> npc("A watering can, eh? I might have one spare...","tell you what, I'll sell it to you for 25 gp if you like.").also { stage++ }
|
||||
401 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
402 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,25))){
|
||||
player.inventory.add(Item(Items.WATERING_CAN8_5340))
|
||||
} else {
|
||||
player.sendMessage("You need 25 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
|
||||
500 -> npc("A gardening trowel, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
501 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
502 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.GARDENING_TROWEL_5325))
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
|
||||
600 -> npc("A seed dibber, eh? I might have one spare...","tell you what, I'll sell it to you for 15 gp if you like.").also { stage++ }
|
||||
601 -> options("Yes, that sounds fair.","No thanks, I can get that cheaper.").also { stage++ }
|
||||
602 -> when(buttonId){
|
||||
1 -> {
|
||||
player("Yes, that sounds like a fair price.").also { stage = END_DIALOGUE }
|
||||
if(player.inventory.remove(Item(995,15))){
|
||||
player.inventory.add(Item(Items.SEED_DIBBER_5343))
|
||||
} else {
|
||||
player.sendMessage("You need 15 gp to pay for that.")
|
||||
}
|
||||
}
|
||||
2 -> end()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun checkPatch(player: Player,fPatch: FarmingPatch){
|
||||
if(fPatch.getPatchFor(player).isWeedy()){
|
||||
npc("You don't have anything planted in that patch.","Plant something and I might agree to look after it for you.").also { stage = END_DIALOGUE }
|
||||
} else if(fPatch.getPatchFor(player).isGrown()){
|
||||
npc("That patch is already fully grown!","I don't know what you want me to do with it!").also { stage = END_DIALOGUE }
|
||||
} else if(fPatch.getPatchFor(player).protectionPaid) {
|
||||
npc("Are you alright? You've already", "paid me for that.").also { stage = END_DIALOGUE }
|
||||
} else {
|
||||
end()
|
||||
player.dialogueInterpreter.open(FarmerPayOptionDialogue(fPatch.getPatchFor(player)),npc)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return Farmers.values().map(Farmers::id).toIntArray()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package content.global.dialogue;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.plugin.Initializable;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.item.Item;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the man dialogues.
|
||||
*
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class ManDialoguePlugin extends DialoguePlugin {
|
||||
private static final Item CIDER = new Item(Items.CIDER_5763);
|
||||
|
||||
/**
|
||||
* The NPC ids that use this dialogue plugin.
|
||||
*/
|
||||
private static final int[] NPC_IDS = {1, 2, 3, 4, 5, 6, 16, 24, 25, 170, 351, 352, 353, 354, 359, 360, 361, 362, 363, 726, 727, 728, 729, 730, 1086, 2675, 2776, 3224, 3225, 3227, 5923, 5924,};
|
||||
|
||||
public ManDialoguePlugin() {
|
||||
}
|
||||
|
||||
public ManDialoguePlugin(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new ManDialoguePlugin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (npc == null)
|
||||
return false;
|
||||
if (args.length > 1
|
||||
&& args[1] instanceof Item
|
||||
&& ((Item) args[1]).equals(CIDER)
|
||||
&& player.getInventory().remove(CIDER)) {
|
||||
|
||||
// Seers achievement diary
|
||||
if (!player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0, 6)) {
|
||||
if (player.getAttribute("diary:seers:pub-cider", 0) >= 4) {
|
||||
player.setAttribute("/save:diary:seers:pub-cider", 5);
|
||||
player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).updateTask(player, 0, 6, true);
|
||||
} else {
|
||||
player.setAttribute("/save:diary:seers:pub-cider", player.getAttribute("diary:seers:pub-cider", 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
npc("Ah, a glass of cider, that's very generous of you. I", "don't mind if I do. Thanks!");
|
||||
stage = 999;
|
||||
return true;
|
||||
}
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello, how's it going?");
|
||||
stage = RandomFunction.random(0, 5);
|
||||
if (stage == 1) {
|
||||
stage = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I'm very well thank you.");
|
||||
stage = 999;
|
||||
break;
|
||||
case 999:
|
||||
end();
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Who are you?");
|
||||
stage = 20;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I'm fine, how are you?");
|
||||
stage = 30;
|
||||
break;
|
||||
case 4:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "No, I don't want to buy anything!");
|
||||
stage = 999;
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I think we need a new king. The one we've got isn't", "very good.");
|
||||
stage = 999;
|
||||
break;
|
||||
case 20:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm a bold adventurer.");
|
||||
stage = 21;
|
||||
break;
|
||||
case 21:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ah, a very noble profession.");
|
||||
stage = 999;
|
||||
break;
|
||||
case 30:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Very well thank you.");
|
||||
stage = 999;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return NPC_IDS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package content.global.dialogue;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Handles the generic shop keeper dialogue.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class
|
||||
ShopkeeperDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ShopkeeperDialogue} {@code Object}.
|
||||
*/
|
||||
public ShopkeeperDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ShopkeeperDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public ShopkeeperDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new ShopkeeperDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Can I help you at all?");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendOptions("Select an Option", "Yes, please. What are you selling?", "No, thanks.");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player("Yes, please. I'd like to see your stock.");
|
||||
stage = 11;
|
||||
break;
|
||||
case 2:
|
||||
player("No thanks, I must be going now.");
|
||||
stage = 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
end();
|
||||
break;
|
||||
case 11:
|
||||
end();
|
||||
npc.openShop(player);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 523, 522, 520, 521, 1699,555 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package content.global.dialogue;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the town crier dialogue plugin.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class TownCrierDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code TownCrierDialogue} {@code Object}.
|
||||
*/
|
||||
public TownCrierDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code TownCrierDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public TownCrierDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new TownCrierDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
npc("Hear ye! Hear ye! Player Moderators massive help to ", GameWorld.getSettings().getName().substring(0, GameWorld.getSettings().getName().length() - 3) + "-");
|
||||
stage = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
|
||||
switch (stage) {
|
||||
case 1:
|
||||
npc("Oh, hello citizen. Are you here to find out about Player", "Moderators? Or perhaps would you like to know about the", "laws of the land?");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
options("Tell me about Player Moderators.", "Tell me about the Rules of " + GameWorld.getSettings().getName() + ".", "Can you give me a handy tip please?", "Bye!");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player("Tell me about Player Moderators.");
|
||||
stage = 50;
|
||||
break;
|
||||
case 2:
|
||||
player("Tell me about the Rules of " + GameWorld.getSettings().getName() + ".");
|
||||
stage = 70;
|
||||
break;
|
||||
case 3:
|
||||
player("Can you give me a handy tip please?");
|
||||
stage = 100;
|
||||
break;
|
||||
case 4:
|
||||
player("Bye!");
|
||||
stage = 400;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 400:
|
||||
npc("Nice meeting you.");
|
||||
stage = 401;
|
||||
break;
|
||||
case 401:
|
||||
end();
|
||||
break;
|
||||
case 50:
|
||||
npc("Of course. What would you like to know?");
|
||||
stage = 51;
|
||||
break;
|
||||
case 51:
|
||||
options("What is a Player Moderator?", "What can Player Moderators do?", "How do I become a Player Moderator?", "What can Player Moderators not do?");
|
||||
stage = 52;
|
||||
break;
|
||||
case 52:
|
||||
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player(" What is a Player Moderator?");
|
||||
stage = 150;
|
||||
break;
|
||||
case 2:
|
||||
npc("What can Player Moderators do?");
|
||||
stage = 160;
|
||||
break;
|
||||
case 3:
|
||||
player("How do I become a Player Moderator?");
|
||||
stage = 170;
|
||||
break;
|
||||
case 4:
|
||||
player("What can Player Moderators not do?");
|
||||
stage = 180;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 70:
|
||||
player.lock(4);
|
||||
npc("At once. Take a look at my book here.");
|
||||
npc.animate(new Animation(6866));
|
||||
GameWorld.getPulser().submit(new Pulse(4) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
//player.getDialogueInterpreter().open(496107759); // TODO rulebook broken
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// Find out about the Rules of Conduct from the Draynor<br><br>Town Crier
|
||||
if (npc.getId() == 6136) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 10);
|
||||
}
|
||||
stage = 71;
|
||||
break;
|
||||
case 71:
|
||||
end();
|
||||
break;
|
||||
|
||||
case 100:
|
||||
int rand = RandomFunction.random(1, 5);
|
||||
switch (rand) {
|
||||
case 1:
|
||||
npc("If the chat window is moving too quickly to report a", "player accurately, run to a quiet spot and review the chat", "at your leisure!");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
npc("If you're lost and have no idea where to go, use the Home", "Teleporter spell for free!");
|
||||
stage = 2;
|
||||
break;
|
||||
case 3:
|
||||
npc("Make your recovery questions and answers hard to guess", "but easy to remember.");
|
||||
stage = 2;
|
||||
break;
|
||||
case 4:
|
||||
npc("Beware of players trying to lue you into the wilderness.", "Your items cannot be returned if you lose them!");
|
||||
stage = 2;
|
||||
break;
|
||||
default:
|
||||
npc("" + GameWorld.getSettings().getName() + " will never email you asking for your log-in details.");
|
||||
stage = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 150:
|
||||
npc("Player Moderators are normal players of the game, just", "like you. However, since they have shown themselves to be", "trustworthy and active reporters, they have been invited", "by Jagex to monitor the game and take appropriate");
|
||||
stage = 151;
|
||||
break;
|
||||
case 151:
|
||||
npc("reward when they see rule breaking. You can spot a Player", "Moderator in game by looking at the chat screen - when a", "Player Moderator speaks, a silver crown appears to the", "left of their name. Remember, if there's no silver crown");
|
||||
stage = 152;
|
||||
break;
|
||||
case 152:
|
||||
npc("there, they are not a Player Moderator! You can check", "out the website if you'd like more information.");
|
||||
stage = 153;
|
||||
break;
|
||||
case 153:
|
||||
player("Thanks!");
|
||||
stage = 154;
|
||||
break;
|
||||
case 154:
|
||||
npc("Is there anything else you'd like to know?");
|
||||
stage = 51;
|
||||
break;
|
||||
case 160:
|
||||
npc("Player Moderators, or 'P-mods', have the ability to mute", "rule breakers and " + GameWorld.getSettings().getName() + " view their reports as a priority so", "that reward is taken as quickly as possible. P-Mods also", "have acces to the Player Moderator Centre. Within the");
|
||||
stage = 161;
|
||||
break;
|
||||
case 161:
|
||||
npc("Centre are tools to help them Moderate " + GameWorld.getSettings().getName() + ".", "These tools include dedicated forums, the Player", "Moderator Guidelines and the Player Moderator Code of", "Conduct.");
|
||||
stage = 153;
|
||||
break;
|
||||
case 170:
|
||||
npc("" + GameWorld.getSettings().getName() + " picks players who spend their time and effort to", "help better the " + GameWorld.getSettings().getName() + " community. To increase your", "chances of becoming a Player Moderator:");
|
||||
stage = 171;
|
||||
break;
|
||||
case 171:
|
||||
npc("Keep your account secure! This is very important, as a", "player with poor security will never be a P-Mod. Read our", "Security Tips for more information.");
|
||||
stage = 173;
|
||||
break;
|
||||
case 173:
|
||||
npc("Play by the rules! The rules of " + GameWorld.getSettings().getName() + " are enforced", "for a reason, to make the game a fair and enjoyable", "environment for all.");
|
||||
stage = 174;
|
||||
break;
|
||||
case 174:
|
||||
npc("Report accuratley! When " + GameWorld.getSettings().getName() + " consider an account for", "review they look for quality, not quantity. Ensure your", "reports are of a high quality by following the report", "guidelines.");
|
||||
stage = 175;
|
||||
break;
|
||||
case 175:
|
||||
npc("Be nice to each other! Treat others as you would", "want to be treated yourself. Respect your fellow player.", "More information can be found on the website.");
|
||||
stage = 153;
|
||||
break;
|
||||
case 180:
|
||||
npc("P-Mods cannot ban your account - they can only report", "offences. " + GameWorld.getSettings().getName() + " then take reward based on the evidence", "received. If you lose your password or get scamme dby", "another player, P_Mods cannot help you get your account");
|
||||
stage = 181;
|
||||
break;
|
||||
case 181:
|
||||
npc("back. All they can do is recommend you to go to Player", "Support. They cannot retrieve any items you may have", "lost and they certainly do not recieve any free items", "from " + GameWorld.getSettings().getName() + " for moderating the game. They are players");
|
||||
stage = 182;
|
||||
break;
|
||||
case 182:
|
||||
npc("who give their all to help the community, out of the", "goodness of their hearts! P-mods do not work for " + GameWorld.getSettings().getName() + "", "and so cannot make you a Moderator, or recommend", "other accounts to become Moderators. If you wish yo");
|
||||
stage = 183;
|
||||
break;
|
||||
case 183:
|
||||
npc("become a Moderator, feel free to ask me!");
|
||||
stage = 153;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6135, 6136, 6137, 6138, 6139 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to handle the agility ticket interface.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class AgilityTicketInterface extends ComponentPlugin {
|
||||
|
||||
/**
|
||||
* Represents the pirate hook item.
|
||||
*/
|
||||
private static final Item PIRATE_HOOK = new Item(2997);
|
||||
|
||||
/**
|
||||
* Represents the toadflax item.
|
||||
*/
|
||||
private static final Item TOADFLAX = new Item(2998);
|
||||
|
||||
/**
|
||||
* Represents the snapdragon item.
|
||||
*/
|
||||
private static final Item SNAPDRAGON = new Item(3000);
|
||||
|
||||
/**
|
||||
* Represents the aerna ticket.
|
||||
*/
|
||||
private static final int ARENA_TICKET = 2996;
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.forId(6).setPlugin(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
Item reward = null;
|
||||
double experience = 0;
|
||||
int tickets = 0;
|
||||
switch (button) {
|
||||
case 21:// 1 exp
|
||||
experience = 240;
|
||||
tickets = 1;
|
||||
break;
|
||||
case 22:// 10 exp.
|
||||
experience = 2480;
|
||||
tickets = 10;
|
||||
break;
|
||||
case 23:// 25 exp.
|
||||
experience = 6500;
|
||||
tickets = 25;
|
||||
break;
|
||||
case 24:// 100 exp.
|
||||
experience = 28000;
|
||||
tickets = 100;
|
||||
break;
|
||||
case 25:// 1000 exp.
|
||||
experience = 320000;
|
||||
tickets = 1000;
|
||||
break;
|
||||
case 8:// toadflax.
|
||||
reward = TOADFLAX;
|
||||
tickets = 3;
|
||||
break;
|
||||
case 9:// snap dragon.
|
||||
reward = SNAPDRAGON;
|
||||
tickets = 10;
|
||||
break;
|
||||
case 10:// pirates hook.
|
||||
reward = PIRATE_HOOK;
|
||||
tickets = 800;
|
||||
break;
|
||||
}
|
||||
if (experience > 0 && !player.getInventory().contains(ARENA_TICKET, tickets)) {
|
||||
player.getPacketDispatch().sendMessage("This Agility experience costs " + tickets + " tickets.");
|
||||
}
|
||||
if (reward != null && !player.getInventory().contains(ARENA_TICKET, tickets)) {
|
||||
player.getPacketDispatch().sendMessage(StringUtils.formatDisplayName(reward.getName().replace("Clean", "").trim()) + " costs " + tickets + " tickets.");
|
||||
}
|
||||
if (!player.getInventory().contains(ARENA_TICKET, tickets)) {
|
||||
return true;
|
||||
}
|
||||
if (experience > 0) {
|
||||
if (!player.getInventory().containsItem(new Item(ARENA_TICKET, tickets))) {
|
||||
return false;
|
||||
}
|
||||
if (player.getInventory().remove(new Item(ARENA_TICKET, tickets))) {
|
||||
if (player.getAchievementDiaryManager().getKaramjaGlove() >= 1) {
|
||||
experience *= 1.1;
|
||||
}
|
||||
player.getSkills().addExperience(Skills.AGILITY, experience);
|
||||
player.getPacketDispatch().sendMessage("You have been granted some Agility experience!");
|
||||
}
|
||||
}
|
||||
if (reward != null) {
|
||||
if (player.getInventory().remove(new Item(ARENA_TICKET, tickets))) {
|
||||
player.getInventory().add(reward);
|
||||
player.getPacketDispatch().sendMessage("You have been granted a " + StringUtils.formatDisplayName(reward.getName().replace("Clean", "").trim()) + ".");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the auto casting component plugin.
|
||||
* @author Emperor
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public final class AutocastSelectPlugin extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.forId(797).setPlugin(this);
|
||||
ComponentDefinition.forId(319).setPlugin(this);
|
||||
ComponentDefinition.forId(310).setPlugin(this);
|
||||
ComponentDefinition.forId(406).setPlugin(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
if (!player.getAttribute("autocast_select", false)) {
|
||||
return true;
|
||||
}
|
||||
player.removeAttribute("autocast_select");
|
||||
final WeaponInterface w = player.getExtension(WeaponInterface.class);
|
||||
if (w != null) {
|
||||
w.selectAutoSpell(button, true);
|
||||
player.getInterfaceManager().openTab(w);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.spell.MagicStaff;
|
||||
import core.game.node.entity.combat.spell.Runes;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the component plugin used to handle the bolt enchanting interface.
|
||||
* @author Emperor
|
||||
* @author SonicForce41
|
||||
*/
|
||||
@Initializable
|
||||
public final class BoltEnchantingInterface extends ComponentPlugin {
|
||||
|
||||
/**
|
||||
* Represents the graphics to use.
|
||||
*/
|
||||
private static final Graphics GRAPHICS = new Graphics(759);
|
||||
|
||||
/**
|
||||
* Represents the animation to use.
|
||||
*/
|
||||
private static final Animation ANIMATION = new Animation(4462);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.put(432, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
final Bolts bolts = Bolts.forId(button);
|
||||
if (bolts != null) {
|
||||
player.getInterfaceManager().close();
|
||||
if (player.getSkills().getLevel(Skills.MAGIC) < bolts.getLevel()) {
|
||||
player.getPacketDispatch().sendMessage("You need a level of " + bolts.getLevel() + " to cast this spell.");
|
||||
return true;
|
||||
}
|
||||
for (Item item : bolts.getRunes()) {
|
||||
if (!player.getInventory().containsItem(item) && !usingStaff(player, item.getId())) {
|
||||
player.getPacketDispatch().sendMessage("You do not have enough runes to cast this spell.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final int amount = player.getInventory().getAmount(new Item(bolts.getBolt(), 1));
|
||||
if (amount < 1) {
|
||||
player.getPacketDispatch().sendMessage("You don't have any bolts to enchant.");
|
||||
return true;
|
||||
}
|
||||
final Item add = new Item(bolts.getEnchanted());
|
||||
if (amount > 10 && !player.getInventory().hasSpaceFor(add)) {
|
||||
player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
|
||||
return true;
|
||||
}
|
||||
player.graphics(GRAPHICS);
|
||||
player.animate(ANIMATION);
|
||||
player.getPulseManager().run(new Pulse(1) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
int enchant = amount;
|
||||
if (enchant > 10) {
|
||||
enchant = 10;
|
||||
}
|
||||
add.setAmount(enchant);
|
||||
player.getInventory().remove(new Item(bolts.getBolt(), enchant));
|
||||
player.getInventory().add(add);
|
||||
for (Item item : bolts.getRunes()) {
|
||||
boolean staff = usingStaff(player, item.getId());
|
||||
if (!player.getInventory().containsItem(item) && !staff) {
|
||||
player.getPacketDispatch().sendMessage("You do not have enough " + item.getName() + "s to cast this spell.");
|
||||
return true;
|
||||
}
|
||||
if (!staff) {
|
||||
player.getInventory().remove(item);
|
||||
}
|
||||
}
|
||||
player.getSkills().addExperience(Skills.MAGIC, bolts.getExp(), true);
|
||||
player.getPacketDispatch().sendMessage("The magic of the runes coaxes out the true nature of the gem tips.");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is holding the staff that will be used instead of
|
||||
* the rune.
|
||||
* @param p The player.
|
||||
* @param rune The rune item id.
|
||||
* @return {@code True} if the player is wearing the correct staff for this
|
||||
* rune.
|
||||
*/
|
||||
public boolean usingStaff(Player p, int rune) {
|
||||
Item weapon = p.getEquipment().get(3);
|
||||
if (weapon == null) {
|
||||
return false;
|
||||
}
|
||||
MagicStaff staff = MagicStaff.forId(rune);
|
||||
if (staff == null) {
|
||||
return false;
|
||||
}
|
||||
int[] staves = staff.getStaves();
|
||||
for (int id : staves) {
|
||||
if (weapon.getId() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the enumeration of bolts.
|
||||
* @author SonicForce41
|
||||
* @version 1
|
||||
*/
|
||||
public enum Bolts {
|
||||
OPAL(14, 879, 4, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.AIR_RUNE.getId(), 2) }, 9, 9236), SAPPHIRE(29, 9337, 7, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.MIND_RUNE.getId(), 1), new Item(Runes.WATER_RUNE.getId(), 1) }, 17, 9240), JADE(18, 9335, 14, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.EARTH_RUNE.getId(), 2) }, 19, 9237), PEARL(22, 880, 24, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.WATER_RUNE.getId(), 2) }, 29, 9238), EMERALD(32, 9338, 27, new Item[] { new Item(Runes.NATURE_RUNE.getId(), 1), new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.AIR_RUNE.getId(), 3) }, 37, 9241), RED_TOPAZ(26, 9336, 29, new Item[] { new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.FIRE_RUNE.getId(), 2) }, 33, 9239), RUBY(35, 9339, 49, new Item[] { new Item(Runes.BLOOD_RUNE.getId(), 1), new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.FIRE_RUNE.getId(), 5) }, 59, 9242), DIAMOND(38, 9340, 57, new Item[] { new Item(Runes.LAW_RUNE.getId(), 2), new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.EARTH_RUNE.getId(), 10) }, 67, 9243), DRAGONSTONE(41, 9341, 68, new Item[] { new Item(Runes.SOUL_RUNE.getId(), 1), new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.EARTH_RUNE.getId(), 15) }, 78, 9244), ONYX(44, 9342, 87, new Item[] { new Item(Runes.DEATH_RUNE.getId(), 1), new Item(Runes.COSMIC_RUNE.getId(), 1), new Item(Runes.FIRE_RUNE.getId(), 20) }, 97, 9245);
|
||||
|
||||
/**
|
||||
* The button
|
||||
*/
|
||||
private int button;
|
||||
|
||||
/**
|
||||
* The actual bolt
|
||||
*/
|
||||
private int bolt;
|
||||
|
||||
/**
|
||||
* The level
|
||||
*/
|
||||
private int level;
|
||||
|
||||
/**
|
||||
* The runes required
|
||||
*/
|
||||
private Item[] runes;
|
||||
|
||||
/**
|
||||
* The exp gained
|
||||
*/
|
||||
private double exp;
|
||||
|
||||
/**
|
||||
* The enchanted bolt
|
||||
*/
|
||||
private int enchanted;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BoltEnchantingInterface} {@code Object}.
|
||||
* @param button the button.
|
||||
* @param bolt the bolt.
|
||||
* @param level the level.
|
||||
* @param runes the runes.
|
||||
* @param exp the exp.
|
||||
* @param enchanted the enchanted.
|
||||
*/
|
||||
Bolts(int button, int bolt, int level, Item[] runes, double exp, int enchanted) {
|
||||
this.button = button;
|
||||
this.bolt = bolt;
|
||||
this.level = level;
|
||||
this.runes = runes;
|
||||
this.exp = exp;
|
||||
this.enchanted = enchanted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the button.
|
||||
* @return The button.
|
||||
*/
|
||||
public int getButton() {
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bolt.
|
||||
* @return The bolt.
|
||||
*/
|
||||
public int getBolt() {
|
||||
return bolt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return The level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the runes.
|
||||
* @return The runes.
|
||||
*/
|
||||
private Item[] getRunes() {
|
||||
return runes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exp.
|
||||
* @return The exp.
|
||||
*/
|
||||
public double getExp() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enchanted.
|
||||
* @return The enchanted.
|
||||
*/
|
||||
public int getEnchanted() {
|
||||
return enchanted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bolt by the id.
|
||||
* @param button the button.
|
||||
* @return the bolt.
|
||||
*/
|
||||
public static Bolts forId(int button) {
|
||||
for (Bolts bolts : Bolts.values()) {
|
||||
if (bolts.getButton() == button)
|
||||
return bolts;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import content.region.misc.tutisland.handlers.iface.CharacterDesign;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents a component plugin to handle the character design interface.
|
||||
* @author 'Vexia
|
||||
* @version 1.9
|
||||
*/
|
||||
@Initializable
|
||||
public final class CharacterDesignInterface extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.put(771, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
switch (opcode) {
|
||||
case 155:
|
||||
CharacterDesign.handleButtons(player, button);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package content.global.handlers.iface
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.component.ComponentDefinition
|
||||
import core.game.component.ComponentPlugin
|
||||
import core.game.node.entity.player.Player
|
||||
import core.plugin.Plugin
|
||||
|
||||
/**
|
||||
* I found a bunch of varps for this interface so I've documented them here.
|
||||
* to set, for example, COLD/HOT bar height, you need to send player.configmanager.set(GAUGE_VARP, (height shl COLD_OFFSET) or (height shl HOT_OFFSET))
|
||||
* bar gauges go up to 12
|
||||
* heat gauge at the top goes a full 360, though the edge is at roughly 160
|
||||
* @author Ceikry
|
||||
*/
|
||||
private const val GAUGE_UPDATE_SCRIPT = 894
|
||||
private const val COLD_OFFSET = 22
|
||||
private const val HOT_OFFSET = 18
|
||||
private const val GAUGE_OFFSET = 15
|
||||
private const val GAUGE_VARP = 1205
|
||||
private const val METER_VARP = 1201
|
||||
private const val BUTTON_ADD_COLD = 16
|
||||
private const val BUTTON_ADD_HOT = 18
|
||||
|
||||
class IncubationInterface : ComponentPlugin() {
|
||||
|
||||
override fun handle(player: Player?, component: Component?, opcode: Int, button: Int, slot: Int, itemId: Int): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun newInstance(arg: Any?): Plugin<Any> {
|
||||
ComponentDefinition.put(717, this)
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.RunScript;
|
||||
import core.game.system.communication.ClanRank;
|
||||
import core.game.system.communication.ClanRepository;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
import core.net.amsc.WorldCommunicator;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.StringUtils;
|
||||
import kotlin.Unit;
|
||||
|
||||
import static core.api.ContentAPIKt.sendInputDialogue;
|
||||
import static core.api.ContentAPIKt.setInterfaceText;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to handle the clan interfaces.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class ClanInterfacePlugin extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.put(590, this);
|
||||
ComponentDefinition.put(589, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
switch (component.getId()) {
|
||||
case 589:
|
||||
switch (button) {
|
||||
case 9:
|
||||
if (player.getInterfaceManager().getComponent(590) != null) {
|
||||
player.getPacketDispatch().sendMessage("Please close the interface you have open before using 'Clan Setup'");
|
||||
return true;
|
||||
}
|
||||
ClanRepository.openSettings(player);
|
||||
return true;
|
||||
case 14:
|
||||
player.getDetails().getCommunication().toggleLootshare(player);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 590:
|
||||
final ClanRepository clan = ClanRepository.get(player.getName(), true);
|
||||
switch (button) {
|
||||
case 23:
|
||||
if (opcode == 155) {
|
||||
clan.setJoinRequirement(ClanRank.NONE);
|
||||
} else {
|
||||
clan.setJoinRequirement(getRank(opcode));
|
||||
}
|
||||
player.getDetails().getCommunication().setJoinRequirement(clan.getJoinRequirement());
|
||||
MSPacketRepository.setClanSetting(player, 0, clan.getJoinRequirement());
|
||||
player.getPacketDispatch().sendString(clan.getJoinRequirement().getInfo(), 590, 23);
|
||||
break;
|
||||
case 24:
|
||||
clan.setMessageRequirement(getRank(opcode));
|
||||
player.getDetails().getCommunication().setMessageRequirement(clan.getMessageRequirement());
|
||||
MSPacketRepository.setClanSetting(player, 1, clan.getMessageRequirement());
|
||||
player.getPacketDispatch().sendString(clan.getMessageRequirement().getInfo(), 590, 24);
|
||||
break;
|
||||
case 25:
|
||||
clan.setKickRequirement(getRank(opcode));
|
||||
player.getDetails().getCommunication().setKickRequirement(clan.getKickRequirement());
|
||||
MSPacketRepository.setClanSetting(player, 2, clan.getKickRequirement());
|
||||
player.getPacketDispatch().sendString(clan.getKickRequirement().getInfo(), 590, 25);
|
||||
clan.update();
|
||||
break;
|
||||
case 26:
|
||||
if (opcode == 230) {
|
||||
clan.setLootRequirement(ClanRank.ADMINISTRATOR);
|
||||
} else {
|
||||
clan.setLootRequirement(getRank(opcode));
|
||||
}
|
||||
player.getDetails().getCommunication().setLootRequirement(clan.getLootRequirement());
|
||||
MSPacketRepository.setClanSetting(player, 3, clan.getLootRequirement());
|
||||
player.getPacketDispatch().sendString(clan.getLootRequirement().getInfo(), 590, 26);
|
||||
break;
|
||||
case 22:
|
||||
switch (opcode) {
|
||||
case 196:
|
||||
clan.setName("Chat disabled");
|
||||
player.getCommunication().setClanName("");
|
||||
player.getPacketDispatch().sendString(clan.getName(), 590, 22);
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendClanRename(player, "");
|
||||
break;
|
||||
}
|
||||
clan.clean(true);
|
||||
break;
|
||||
default:
|
||||
sendInputDialogue(player, false, "Enter clan prefix:", (value) -> {
|
||||
String name = StringUtils.formatDisplayName((String) value);
|
||||
setInterfaceText(player, name, 590, 22);
|
||||
if(WorldCommunicator.isEnabled()){
|
||||
MSPacketRepository.sendClanRename(player, name);
|
||||
clan.setName(name);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
if (clan.getName().equals("Chat disabled")) {
|
||||
player.getPacketDispatch().sendMessage("Your clan channel has now been enabled!");
|
||||
player.getPacketDispatch().sendMessage("Join your channel by clicking 'Join Chat' and typing: " + player.getUsername());
|
||||
}
|
||||
clan.setName(name);
|
||||
player.getCommunication().setClanName(name);
|
||||
clan.update();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value to set.
|
||||
* @param opcode the opcode.
|
||||
* @return the value.
|
||||
*/
|
||||
public static ClanRank getRank(int opcode) {
|
||||
switch (opcode) {
|
||||
case 155:
|
||||
return ClanRank.NONE;
|
||||
case 196:
|
||||
return ClanRank.FRIEND;
|
||||
case 124:
|
||||
return ClanRank.RECRUIT;
|
||||
case 199:
|
||||
return ClanRank.CORPORAL;
|
||||
case 234:
|
||||
return ClanRank.SERGEANT;
|
||||
case 168:
|
||||
return ClanRank.LIEUTENANT;
|
||||
case 166:
|
||||
return ClanRank.CAPTAIN;
|
||||
case 64:
|
||||
return ClanRank.GENERAL;
|
||||
case 53:
|
||||
return ClanRank.OWNER;
|
||||
}
|
||||
return ClanRank.NONE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package content.global.handlers.iface;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface.WeaponInterfaces;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the combat tab interface.
|
||||
* @author Emperor
|
||||
* @author Vexia'
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public class CombatTabInterface extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (WeaponInterfaces inter : WeaponInterfaces.values()) {
|
||||
ComponentDefinition.put(inter.getInterfaceId(), this);
|
||||
}
|
||||
ComponentDefinition.put(92, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player p, Component component, int opcode, int button, int slot, int itemId) {
|
||||
switch (button) {
|
||||
case 7:
|
||||
case 9:
|
||||
case 24:
|
||||
case 26:
|
||||
case 27:
|
||||
GameWorld.getPulser().submit(new Pulse(1, p) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
p.getSettings().toggleRetaliating();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 11:
|
||||
case 10:
|
||||
case 8:
|
||||
case 85:
|
||||
GameWorld.getPulser().submit(new Pulse(1, p) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
WeaponInterface inter = p.getExtension(WeaponInterface.class);
|
||||
if (inter != null && inter.isSpecialBar()) {
|
||||
p.getSettings().toggleSpecialBar();
|
||||
if (p.getSettings().isSpecialToggled()) {
|
||||
CombatSwingHandler handler;
|
||||
if ((handler = CombatStyle.MELEE.getSwingHandler().getSpecial(p.getEquipment().getNew(3).getId())) != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Plugin<Object> plugin = (Plugin<Object>) ((Object) handler);
|
||||
if (plugin.fireEvent("instant_spec", p) == Boolean.TRUE) {
|
||||
handleInstantSpec(p, handler, plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
WeaponInterface inter = p.getExtension(WeaponInterface.class);
|
||||
if (inter == null) {
|
||||
return false;
|
||||
}
|
||||
if (inter.setAttackStyle(button)) {
|
||||
if (button == 4 || button == 5) {
|
||||
inter.openAutocastSelect();
|
||||
} else if (p.getProperties().getAutocastSpell() != null) {
|
||||
inter.selectAutoSpell(-1, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to handle an instance special attack.
|
||||
* @param p the player.
|
||||
* @param handler the handler.
|
||||
* @param plugin the plugin.
|
||||
*/
|
||||
private static void handleInstantSpec(Player p, CombatSwingHandler handler, Plugin<Object> plugin) {
|
||||
handler.swing(p, p.getProperties().getCombatPulse().getVictim(), null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package content.global.handlers.iface
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.InterfaceListener
|
||||
|
||||
class CreditShopInterface : InterfaceListener {
|
||||
|
||||
val CREDIT_SHOP = Components.CREDIT_SHOP
|
||||
val TEXT_CHILD = 39
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
on(CREDIT_SHOP){player, component, opcode, buttonID, slot, itemID ->
|
||||
val item = getItem(buttonID)
|
||||
|
||||
if(opcode == 155){
|
||||
sendDialogue(player, "This item costs ${item.price} credits.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
if(buttonID == 14 || buttonID == 21){
|
||||
val specific = when(opcode){
|
||||
196 -> if(buttonID == 14) Items.RED_PARTYHAT_1038 else Items.RED_HWEEN_MASK_1057
|
||||
124 -> if(buttonID == 14) Items.GREEN_PARTYHAT_1044 else Items.GREEN_HWEEN_MASK_1053
|
||||
199 -> if(buttonID == 14) Items.BLUE_PARTYHAT_1042 else Items.BLUE_HWEEN_MASK_1055
|
||||
234 -> Items.YELLOW_PARTYHAT_1040
|
||||
168 -> Items.PURPLE_PARTYHAT_1046
|
||||
166 -> Items.WHITE_PARTYHAT_1048
|
||||
else -> Items.DWARF_WEED_SEED_5303
|
||||
}
|
||||
attemptPurchase(player,specific,item.price)
|
||||
} else {
|
||||
attemptPurchase(player,item.id,item.price)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(CREDIT_SHOP){player, component ->
|
||||
sendCredits(player)
|
||||
return@onOpen true
|
||||
}
|
||||
}
|
||||
|
||||
private fun getItem(buttonID: Int): ShopItem {
|
||||
return when(buttonID){
|
||||
14 -> ShopItem(Items.BLUE_PARTYHAT_1042,75)
|
||||
18 -> ShopItem(Items.SCYTHE_1419,100)
|
||||
20 -> ShopItem(Items.JANGLES_THE_MONKEY_14648,200)
|
||||
17 -> ShopItem(Items.CHRISTMAS_CRACKER_962,65)
|
||||
21 -> ShopItem(Items.BLUE_HWEEN_MASK_1055,65)
|
||||
16 -> ShopItem(Items.SANTA_HAT_1050,65)
|
||||
19 -> ShopItem(Items.BUNNY_EARS_1037,150)
|
||||
15 -> ShopItem(Items.EASTER_RING_7927,100)
|
||||
else -> ShopItem(0,0)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendCredits(player: Player){
|
||||
setInterfaceText(player, "You have ${player.details.credits} credits to spend.", CREDIT_SHOP, TEXT_CHILD)
|
||||
}
|
||||
|
||||
fun attemptPurchase(player: Player, item: Int, price: Int){
|
||||
if(player.details.credits < price){
|
||||
sendDialogue(player, "You don't have enough credits for that.")
|
||||
return
|
||||
}
|
||||
|
||||
if(player.inventory.add(Item(item))){
|
||||
player.details.credits -= price
|
||||
} else {
|
||||
sendDialogue(player, "You don't have enough inventory space for that.")
|
||||
}
|
||||
sendCredits(player)
|
||||
}
|
||||
|
||||
internal class ShopItem(val id: Int, val price: Int)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user