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:
Ceikry 2023-08-11 00:09:07 +00:00 committed by Ryan
parent 1be9335815
commit 6a3e91f13c
7 changed files with 84 additions and 21 deletions

View file

@ -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() {
@ -88,3 +92,41 @@ class DWThreatTimer : PersistTimer(1, "dw-threat"), Commands {
}
}
}
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
}
}

View file

@ -35,10 +35,11 @@ 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)
if (removeRender)
Repository.RENDERABLE_NPCS.remove(revenantNPC)
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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.

View file

@ -34,13 +34,13 @@ class UpdateSequence
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()
}
/**