Wilderness improvements
Added an extra option to the deep wilderness gate warning: "I wish to proceed, and don't ask me again" Reused the same warning, with appropriate changes, for the edge/ardy levers due to the pvp mechanics Removed the interface warning when crossing the ditch until doomsayer is implemented Removed the inauthentic threat revenant and restricted brawler/pvp drops to revenants and chaos elemental only Now require 100k risk to obtain the boosted deep-wildy drop rates Hid our inauthentic mechanics behind a new server config option enhanced_deep_wilderness
This commit is contained in:
+11
-4
@@ -1,5 +1,6 @@
|
||||
package content.region.kandarin.ardougne.handlers;
|
||||
|
||||
import core.ServerConstants;
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialogueInterpreter;
|
||||
@@ -8,7 +9,6 @@ import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.TeleportManager;
|
||||
import core.game.node.entity.player.link.audio.Audio;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.system.task.Pulse;
|
||||
@@ -20,10 +20,11 @@ import core.plugin.ClassScanner;
|
||||
import org.rs09.consts.Sounds;
|
||||
|
||||
import static core.api.ContentAPIKt.playAudio;
|
||||
import static content.region.wilderness.handlers.WildernessGateHandlerKt.enterDeepWilderness;
|
||||
|
||||
/**
|
||||
* Handles wilderness levers.
|
||||
* @author 'Vexia
|
||||
* @author 'Vexia, Player Name
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
@@ -279,7 +280,6 @@ public final class WildernessLeverPlugin extends OptionHandler {
|
||||
public Location[] getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +325,14 @@ public final class WildernessLeverPlugin extends OptionHandler {
|
||||
public boolean open(Object... args) {
|
||||
lever = (LeverSets) args[0];
|
||||
id = (int) args[1];
|
||||
interpreter.sendDialogue("Warning! Pulling the lever will teleport you deep into the wilderness.");
|
||||
if (ServerConstants.ENHANCED_DEEP_WILDERNESS) {
|
||||
enterDeepWilderness(player, (player) -> {
|
||||
lever.pull(player, lever.getIndex(id), true);
|
||||
return null;
|
||||
}, "Pulling the lever will teleport you into the deep wilderness.");
|
||||
} else {
|
||||
interpreter.sendDialogue("Warning! Pulling the lever will teleport you deep into the wilderness.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
package content.region.wilderness.handlers
|
||||
|
||||
import content.region.wilderness.handlers.revenants.RevenantController
|
||||
import content.region.wilderness.handlers.revenants.RevenantNPC
|
||||
import content.region.wilderness.handlers.revenants.RevenantType
|
||||
import core.api.*
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.combat.DeathTask
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.npc.NPCBehavior
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.system.timer.PersistTimer
|
||||
import core.game.system.timer.impl.Disease
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.map.zone.impl.WildernessZone
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.tools.RandomFunction
|
||||
import core.tools.colorize
|
||||
import org.json.simple.JSONObject
|
||||
|
||||
object DeepWildyThreat {
|
||||
@JvmStatic fun getThreat (player: Player) : Int {
|
||||
return getOrStartTimer<DWThreatTimer>(player).ticksLeft
|
||||
}
|
||||
|
||||
@JvmStatic fun adjustThreat (player: Player, amount: Int) {
|
||||
val timer = getOrStartTimer<DWThreatTimer>(player)
|
||||
timer.ticksLeft += amount
|
||||
if (timer.ticksLeft >= 2500 && timer.lastMessage < 2000) {
|
||||
sendMessage(player, colorize("%RYou sense a great wrath upon you."))
|
||||
timer.lastMessage = 2000
|
||||
} else if (timer.ticksLeft >= 1000 && timer.lastMessage < 1000) {
|
||||
sendMessage(player, colorize("%RYou sense watchful eyes upon you."))
|
||||
timer.lastMessage = 1000
|
||||
} else if (timer.ticksLeft >= 500 && timer.lastMessage < 500) {
|
||||
sendMessage(player, colorize("%RYou sense a dark presence."))
|
||||
timer.lastMessage = 500
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
|
||||
var ticksLeft = 0
|
||||
var lastMessage = 0
|
||||
var currentRev: NPC? = null
|
||||
var forceSpawn = false
|
||||
|
||||
override fun run(entity: Entity): Boolean {
|
||||
if (ticksLeft-- <= 0) return false
|
||||
if (ticksLeft > 3000) ticksLeft = 3000
|
||||
if (ticksLeft % 5 != 0) return true
|
||||
if (entity !is Player) return false
|
||||
if (!entity.skullManager.isWilderness) return true
|
||||
|
||||
val rollchance =
|
||||
if (ticksLeft >= 2500) 10
|
||||
else if (ticksLeft >= 2000) 200
|
||||
else if (ticksLeft >= 1500) 400
|
||||
else if (ticksLeft >= 1000) 800
|
||||
else if (ticksLeft >= 500) 1500
|
||||
else 2_000_000
|
||||
|
||||
if ((currentRev == null || DeathTask.isDead(currentRev) || !currentRev!!.isActive) && (forceSpawn || RandomFunction.roll(rollchance))) {
|
||||
forceSpawn = false
|
||||
val type = RevenantType.getClosestHigherOrEqual(entity.properties.currentCombatLevel)
|
||||
val npc = NPC.create(type.ids.random(), entity.location)
|
||||
npc.isRespawn = false
|
||||
npc.behavior = RevGuardianBehavior()
|
||||
npc.init()
|
||||
npc.setAttribute("dw-threat-target", entity)
|
||||
RevenantController.unregisterRevenant(npc as RevenantNPC, false)
|
||||
currentRev = npc
|
||||
} else if (currentRev != null && !currentRev!!.location.withinDistance(entity.location, 25) && currentRev!!.properties.teleportLocation == null) {
|
||||
poofClear(currentRev!!)
|
||||
currentRev = null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun save(root: JSONObject, entity: Entity) {
|
||||
root["threat-time-remaining"] = ticksLeft.toString()
|
||||
root["threat-forceSpawn"] = (currentRev != null).toString()
|
||||
}
|
||||
|
||||
override fun parse(root: JSONObject, entity: Entity) {
|
||||
ticksLeft = root["threat-time-remaining"]?.toString()?.toIntOrNull() ?: 0
|
||||
forceSpawn = root["threat-forceSpawn"]?.toString()?.toBoolean() ?: false
|
||||
}
|
||||
|
||||
override fun defineCommands() {
|
||||
define("dwthreat", Privilege.ADMIN, "", "") {player, _ ->
|
||||
val timer = getOrStartTimer<DWThreatTimer>(player)
|
||||
notify(player, "Current Threat: ${timer.ticksLeft}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RevGuardianBehavior : NPCBehavior() {
|
||||
val deathMessages = arrayOf("Curses upon thee!", "Rot in blight!", "Suffer my wrath!", "Nevermore!", "May ye be undone!")
|
||||
var chats = arrayOf("Leave this place!", "Suffer!", "Death to thee!", "Flee, coward!", "Leave my resting place!", "Let me rest in peace!", "Thou belongeth to me!")
|
||||
|
||||
override fun tick(self: NPC): Boolean {
|
||||
val target = getAttribute<Player?>(self, "dw-threat-target", null) ?: return true
|
||||
if (!target.isActive || DeathTask.isDead(target)) {
|
||||
self.clear()
|
||||
return true
|
||||
}
|
||||
if (target.properties.teleportLocation != null && self.properties.teleportLocation == null) {
|
||||
if (WildernessZone.isInZone(target.properties.teleportLocation))
|
||||
self.properties.teleportLocation = target.properties.teleportLocation
|
||||
}
|
||||
self.attack(target)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreation(self: NPC) {
|
||||
Graphics.send(Graphics(86), self.location)
|
||||
sendChat(self, chats.random())
|
||||
}
|
||||
|
||||
override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean {
|
||||
val target = getAttribute<Player?>(self, "dw-threat-target", null)
|
||||
if (attacker != target) {
|
||||
if (shouldSendMessage && attacker is Player)
|
||||
sendMessage(attacker, "This revenant is focused on someone else.")
|
||||
return false
|
||||
}
|
||||
return super.canBeAttackedBy(self, attacker, style, shouldSendMessage)
|
||||
}
|
||||
|
||||
override fun onDeathStarted(self: NPC, killer: Entity) {
|
||||
val target = getAttribute<Player?>(self, "dw-threat-target", null) ?: return
|
||||
sendChat(self, deathMessages.random())
|
||||
val disease = getOrStartTimer<Disease>(target, 25)
|
||||
disease.hitsLeft = 25
|
||||
}
|
||||
|
||||
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
|
||||
val target = getAttribute<Player?>(self, "dw-threat-target", null) ?: return
|
||||
if (killer != target) drops.clear()
|
||||
val timer = getOrStartTimer<DWThreatTimer>(target)
|
||||
timer.ticksLeft = 0
|
||||
}
|
||||
|
||||
override fun getPathfinderOverride(self: NPC): Pathfinder? {
|
||||
return Pathfinder.SMART
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,10 @@ public final class WildernessDitchPlugin extends OptionHandler {
|
||||
player.faceLocation(node.getLocation());
|
||||
Scenery ditch = (Scenery) node;
|
||||
player.setAttribute("wildy_ditch", ditch);
|
||||
/*
|
||||
|
||||
Comment out the annoying ditch warning until the doomsayer has been implemented so that players can disable it properly.
|
||||
|
||||
if(!player.isArtificial()) {
|
||||
if (ditch.getRotation() % 2 == 0) {
|
||||
if (player.getLocation().getY() <= node.getLocation().getY()) {
|
||||
@@ -65,6 +69,7 @@ public final class WildernessDitchPlugin extends OptionHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
WildernessInterfacePlugin.handleDitch(player);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package content.region.wilderness.handlers
|
||||
|
||||
import content.region.wilderness.handlers.WildernessGateHandler.GateDialogue
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.interaction.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.Node
|
||||
import core.game.global.action.DoorActionHandler
|
||||
import core.game.dialogue.*
|
||||
@@ -16,39 +17,57 @@ class WildernessGateHandler : InteractionListener {
|
||||
on (gates, IntType.SCENERY, "open", handler = ::handleGate)
|
||||
}
|
||||
|
||||
private fun handleGate (player: Player, node: Node) : Boolean {
|
||||
if (player.location.y > 3890) {
|
||||
val isEntering = !player.skullManager.isDeepWilderness()
|
||||
|
||||
if (isEntering)
|
||||
openDialogue(player, GateDialogue(node.asScenery()))
|
||||
else {
|
||||
if (player.properties.combatPulse.isInCombat)
|
||||
private fun handleGate(player: Player, node: Node) : Boolean {
|
||||
if (player.location.y > 3890 && ServerConstants.ENHANCED_DEEP_WILDERNESS) {
|
||||
val isEntering = !player.skullManager.isDeepWilderness
|
||||
if (isEntering) {
|
||||
fun enter(player: Player) {
|
||||
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
|
||||
player.skullManager.isDeepWilderness = true
|
||||
}
|
||||
enterDeepWilderness(player, ::enter, "Beyond this gate you enter the deep wilderness!")
|
||||
} else {
|
||||
if (player.properties.combatPulse.isInCombat) {
|
||||
sendMessage(player, "You cannot leave while you are under attack.")
|
||||
else {
|
||||
} else {
|
||||
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
|
||||
player.skullManager.isDeepWilderness = false
|
||||
}
|
||||
}
|
||||
} else DoorActionHandler.handleAutowalkDoor (player, node.asScenery())
|
||||
} else DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
class GateDialogue (val gate: Scenery) : DialogueFile() {
|
||||
class GateDialogue(val callback: (Player) -> Unit, val firstLine: String) : DialogueFile() {
|
||||
override fun handle (interfaceId: Int, buttonId: Int) {
|
||||
when (stage) {
|
||||
0 -> sendDialogueLines(player!!, "WARNING!", "Beyond this gate you enter the deep wilderness!", "Anyone will be able to attack you without consequence!", "You WILL NOT be able to leave during combat!").also { stage++ }
|
||||
1 -> showTopics (
|
||||
0 -> sendDialogueLines(player!!, "WARNING!", firstLine, "Anyone will be able to attack you without consequence!", "You WILL NOT be able to leave during combat!").also { stage++ }
|
||||
1 -> sendDialogueLines(player!!, "While you are there, you will be skulled:","you will lose all your items if you die!","The skull will go away when you leave the deep wilderness.").also { stage++ }
|
||||
2 -> sendDialogueLines(player!!, "If you are risking sufficient value, the skull will become red.","This increases your chances of receiving special loot from killing","revenants and the Chaos Elemental!").also { stage++ }
|
||||
3 -> showTopics(
|
||||
Topic(FacialExpression.NEUTRAL, "I wish to proceed.", 10, true),
|
||||
Topic(FacialExpression.NEUTRAL, "Nevermind.", END_DIALOGUE, true)
|
||||
Topic(FacialExpression.NEUTRAL, "I wish to proceed, and don't show this warning again.", 11, true),
|
||||
Topic(FacialExpression.NEUTRAL, "Never mind.", END_DIALOGUE, true)
|
||||
)
|
||||
10 -> {
|
||||
10 -> {
|
||||
end()
|
||||
DoorActionHandler.handleAutowalkDoor (player!!, gate)
|
||||
player!!.skullManager.isDeepWilderness = true
|
||||
callback(player!!)
|
||||
}
|
||||
11 -> {
|
||||
player!!.setAttribute("/save:skip-deep-wilderness-warning", true)
|
||||
end()
|
||||
callback(player!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun enterDeepWilderness(player: Player, callback: (Player) -> Unit, firstLine: String) {
|
||||
if (player.getAttribute("/save:skip-deep-wilderness-warning",false)) {
|
||||
callback(player)
|
||||
} else {
|
||||
openDialogue(player, GateDialogue(callback, firstLine))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user