mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -07:00
Deep wilderness threat balancing
Killing the hostile event now removes all built up threat Hostile event can now follow the player up/down stairs, through cave entrances, etc. Hostile event now applies disease status for 25 hits when killed Reduced the threat gained by killing NPCs by 5x Increased the threat gained by brawlers drops by 3.75x PvP gear drops now award maximum threat (30 minutes to return to zero) In summary, the hostile event will trigger less often but will be more dangerous
This commit is contained in:
parent
1be9335815
commit
6a3e91f13c
7 changed files with 84 additions and 21 deletions
|
|
@ -1,13 +1,19 @@
|
|||
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.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.zone.impl.WildernessZone
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.tools.RandomFunction
|
||||
import core.tools.colorize
|
||||
|
|
@ -38,7 +44,6 @@ class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
|
|||
var ticksLeft = 0
|
||||
var lastMessage = 0
|
||||
var currentRev: NPC? = null
|
||||
var chats = arrayOf("Leave this place!", "Suffer!", "Death to you!", "Flee, coward!", "Leave my resting place!", "Let me rest in peace!", "You belong to me!")
|
||||
|
||||
override fun run(entity: Entity): Boolean {
|
||||
if (ticksLeft-- <= 0) return false
|
||||
|
|
@ -59,13 +64,12 @@ class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
|
|||
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.attack(entity)
|
||||
Graphics.send(Graphics(86), npc.location)
|
||||
ticksLeft -= 500
|
||||
sendChat(npc, chats.random())
|
||||
npc.setAttribute("dw-threat-target", entity)
|
||||
RevenantController.unregisterRevenant(npc as RevenantNPC, false)
|
||||
currentRev = npc
|
||||
} else if (currentRev != null && !currentRev!!.location.withinDistance(entity.location, 25)) {
|
||||
} else if (currentRev != null && !currentRev!!.location.withinDistance(entity.location, 25) && currentRev!!.properties.teleportLocation == null) {
|
||||
poofClear(currentRev!!)
|
||||
currentRev = null
|
||||
}
|
||||
|
|
@ -74,11 +78,11 @@ class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
|
|||
}
|
||||
|
||||
override fun save(root: JSONObject, entity: Entity) {
|
||||
root["threat-time-remaining"] = ticksLeft
|
||||
root["threat-time-remaining"] = ticksLeft.toString()
|
||||
}
|
||||
|
||||
override fun parse(root: JSONObject, entity: Entity) {
|
||||
ticksLeft = root.getOrDefault("threat-time-remaining", 3000) as? Int ?: 3000
|
||||
ticksLeft = root["threat-time-remaining"]?.toString()?.toIntOrNull() ?: 0
|
||||
}
|
||||
|
||||
override fun defineCommands() {
|
||||
|
|
@ -87,4 +91,42 @@ class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
|
|||
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) {
|
||||
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
|
||||
}
|
||||
sendChat(self, "ticking")
|
||||
self.attack(target)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreation(self: NPC) {
|
||||
Graphics.send(Graphics(86), self.location)
|
||||
sendChat(self, chats.random())
|
||||
}
|
||||
|
||||
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
|
||||
val timer = getOrStartTimer<DWThreatTimer>(target)
|
||||
timer.ticksLeft = 0
|
||||
}
|
||||
}
|
||||
|
|
@ -35,11 +35,12 @@ class RevenantController : TickListener, Commands {
|
|||
Repository.RENDERABLE_NPCS.add(revenantNPC)
|
||||
}
|
||||
|
||||
@JvmStatic fun unregisterRevenant(revenantNPC: RevenantNPC) {
|
||||
@JvmStatic fun unregisterRevenant(revenantNPC: RevenantNPC, removeRender: Boolean = true) {
|
||||
trackedRevenants.remove(revenantNPC)
|
||||
taskTimeRemaining.remove(revenantNPC)
|
||||
currentTask.remove(revenantNPC)
|
||||
Repository.RENDERABLE_NPCS.remove(revenantNPC)
|
||||
if (removeRender)
|
||||
Repository.RENDERABLE_NPCS.remove(revenantNPC)
|
||||
}
|
||||
|
||||
val routes = listOf(
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public class RevenantNPC extends AbstractNPC {
|
|||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
RevenantController.unregisterRevenant(this);
|
||||
RevenantController.unregisterRevenant(this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -125,6 +125,7 @@ public class RevenantNPC extends AbstractNPC {
|
|||
}
|
||||
setAttribute("eat-delay", GameWorld.getTicks() + 6);
|
||||
}
|
||||
behavior.tick(this);
|
||||
if (aggressiveHandler != null && aggressiveHandler.selectTarget()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ package content.region.wilderness.handlers.revenants;
|
|||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A revenant type.
|
||||
* @author Vexia
|
||||
|
|
@ -66,6 +69,14 @@ public enum RevenantType {
|
|||
NPCDefinition def = NPCDefinition.forId(t.ids[0]);
|
||||
if (def.getCombatLevel() >= combatLevel) return t;
|
||||
}
|
||||
return null;
|
||||
return RevenantType.DRAGON;
|
||||
}
|
||||
|
||||
public static List<Integer> getAllIds() {
|
||||
ArrayList<Integer> ids = new ArrayList<>();
|
||||
for (RevenantType t : values()) {
|
||||
for (int id : t.ids) ids.add(id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ class Frozen : PersistTimer (1, "frozen") {
|
|||
|
||||
override fun getTimer (vararg args: Any) : RSTimer {
|
||||
val inst = Frozen()
|
||||
println(args)
|
||||
inst.runInterval = args.getOrNull(0) as? Int ?: 10
|
||||
inst.shouldApplyImmunity = args.getOrNull(1) as? Boolean ?: false
|
||||
return inst
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ public final class WildernessZone extends MapZone {
|
|||
boolean isValidTarget = e instanceof NPC && (isDeepWildy || e.asNpc().getName().contains("Revenant") || e.getId() == NPCs.CHAOS_ELEMENTAL_3200);
|
||||
|
||||
if (isDeepWildy) {
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 250);
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 50);
|
||||
}
|
||||
|
||||
if (!isValidTarget) return;
|
||||
|
||||
int cEleGloveRate = isDeepWildy ? 50 : 150;
|
||||
int normalGloveRate = isDeepWildy ? 75 : 150;
|
||||
int normalGloveRate = isDeepWildy ? 100 : 150;
|
||||
|
||||
int pvpGearRate = getNewDropRate(e.asNpc().getDefinition().getCombatLevel());
|
||||
if (isDeepWildy)
|
||||
|
|
@ -114,7 +114,8 @@ public final class WildernessZone extends MapZone {
|
|||
Item reward = new Item(BrawlingGloves.forIndicator(glove).getId());
|
||||
GroundItemManager.create(reward, e.asNpc().getDropLocation(), killer.asPlayer());
|
||||
Repository.sendNews(killer.getUsername() + " has received " + reward.getName().toLowerCase() + " from a " + e.asNpc().getName() + "!");
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 200);
|
||||
if (isDeepWildy)
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 750);
|
||||
}
|
||||
|
||||
for (int j : PVP_GEAR) {
|
||||
|
|
@ -128,7 +129,8 @@ public final class WildernessZone extends MapZone {
|
|||
}
|
||||
Repository.sendNews(killer.asPlayer().getUsername() + " has received a " + reward.getName() + " from a " + e.asNpc().getName() + "!");
|
||||
GroundItemManager.create(reward, ((NPC) e).getDropLocation(), killer.asPlayer());
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 1000);
|
||||
if (isDeepWildy)
|
||||
DeepWildyThreat.adjustThreat((Player) killer, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -307,6 +309,13 @@ public final class WildernessZone extends MapZone {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean isInZone (Location l) {
|
||||
for (ZoneBorders z : INSTANCE.borders) {
|
||||
if (z.insideBorder(l)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The wilderness level.
|
||||
* @return the level.
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ class UpdateSequence
|
|||
playersList = renderablePlayers
|
||||
npcList = Repository.renderableNpcs
|
||||
lobbyList!!.map{ PacketRepository.send(ClearMinimapFlag::class.java, PlayerContext(it)) }
|
||||
|
||||
var playerTickStart = System.currentTimeMillis()
|
||||
renderablePlayers.forEach(Player::tick)
|
||||
Grafana.playerTickTime = (System.currentTimeMillis() - playerTickStart).toInt()
|
||||
|
||||
var npcTickStart = System.currentTimeMillis()
|
||||
npcList!!.forEach(NPC::tick)
|
||||
Grafana.npcTickTime = (System.currentTimeMillis() - npcTickStart).toInt()
|
||||
|
||||
var playerTickStart = System.currentTimeMillis()
|
||||
renderablePlayers.forEach(Player::tick)
|
||||
Grafana.playerTickTime = (System.currentTimeMillis() - playerTickStart).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue