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,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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user