Fixed some error spam about a nullref in animateWoodcutting

Fixed a general script processing oversight that could cause error-throwing scripts to continue executing
Scripts being processed now automatically cancel if the interaction-target-node is no longer active (fixes object could not be replaced spam)
Fixed the stopExecuting() spam
Fixed a CME in the disconnection queue (only affected server shutdown)
Future-proofed the ground spawn parser to work with the format Zaros now outputs
Added in proper SKILLING global clock for use with the script system - addresses some quirks and brings us closer to authenticity
This commit is contained in:
Ceikry
2023-03-21 03:50:27 +00:00
committed by Ryan
parent 48805eea66
commit 7ec901297b
8 changed files with 159 additions and 107 deletions
@@ -19,33 +19,33 @@ class ConsumableListener : InteractionListener {
}
private fun handleConsumable(player: Player, node: Node) : Boolean {
val consumable = Consumables.getConsumableById(node.id) ?: return stopExecuting(player)
val consumable = Consumables.getConsumableById(node.id) ?: return true
val food = getUsedOption(player) == "eat"
val isIgnoreMainClock = consumable.isIgnoreMainClock
if (food) {
if (isIgnoreMainClock && player.clocks[Clocks.NEXT_CONSUME] < GameWorld.ticks) {
consumable.consumable.consume(node as? Item ?: return stopExecuting(player), player)
consumable.consumable.consume(node as? Item ?: return true, player)
player.clocks[Clocks.NEXT_CONSUME] = getWorldTicks() + 2
player.clocks[Clocks.NEXT_EAT] = getWorldTicks() + 2
delayAttack(player, 3)
} else if (player.clocks[Clocks.NEXT_CONSUME] < getWorldTicks() && player.clocks[Clocks.NEXT_EAT] < getWorldTicks()) {
consumable.consumable.consume(node as? Item ?: return stopExecuting(player), player)
consumable.consumable.consume(node as? Item ?: return true, player)
player.clocks[Clocks.NEXT_EAT] = getWorldTicks() + 2
delayAttack(player, 3)
}
} else {
if (isIgnoreMainClock && player.clocks[Clocks.NEXT_CONSUME] < getWorldTicks()) {
consumable.consumable.consume(node as? Item ?: return stopExecuting(player), player)
consumable.consumable.consume(node as? Item ?: return true, player)
player.clocks[Clocks.NEXT_CONSUME] = getWorldTicks() + 3
player.clocks[Clocks.NEXT_DRINK] = getWorldTicks() + 3
} else if (player.clocks[Clocks.NEXT_CONSUME] < getWorldTicks() && player.clocks[Clocks.NEXT_DRINK] < getWorldTicks()) {
consumable.consumable.consume(node as? Item ?: return stopExecuting(player), player)
consumable.consumable.consume(node as? Item ?: return true, player)
player.clocks[Clocks.NEXT_DRINK] = getWorldTicks() + 3
}
}
return stopExecuting(player)
return true
}
}
}
@@ -10,6 +10,7 @@ import core.api.*
import core.game.event.ResourceProducedEvent
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.Clocks
import core.game.node.Node
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
@@ -47,36 +48,40 @@ class FishingListener : InteractionListener{
return restartScript(player)
if (state == 0) {
sendMessage(player, "You attempt to catch some fish...")
}
if (state == 1) {
if (!checkRequirements(player, op, node))
return clearScripts(player)
forager?.let {
val dest = player.location.transform(player.direction)
Pathfinder.find(it, dest).walk(it)
}
sendMessage(player, "You attempt to catch some fish...")
}
anim(player, op)
forager?.handlePassiveAction()
if (clockReady(player, Clocks.SKILLING)) {
anim(player, op)
forager?.handlePassiveAction()
val fish = op.rollFish(player) ?: return delayScript(player, 5)
if (!hasSpaceFor(player, fish.item)) return restartScript(player)
if (!op.removeBait(player.inventory)) return restartScript(player)
player.dispatch(ResourceProducedEvent(fish.item.id, fish.item.amount, node))
val fish = op.rollFish(player) ?: return delayClock(player, Clocks.SKILLING, 5)
if (!hasSpaceFor(player, fish.item) || !op.removeBait(player.inventory)) {
return restartScript(player)
}
val item = fish.item
if (isActive(SkillcapePerks.GREAT_AIM, player) && RandomFunction.roll(20)) {
addItem(player, item.id, item.amount)
sendMessage(player, colorize("%RYour expert aim catches you a second fish."))
player.dispatch(ResourceProducedEvent(fish.item.id, fish.item.amount, node))
val item = fish.item
if (isActive(SkillcapePerks.GREAT_AIM, player) && RandomFunction.roll(20)) {
addItemOrDrop(player, item.id, item.amount)
sendMessage(player, colorize("%RYour expert aim catches you a second fish."))
}
addItemOrDrop(player, item.id, item.amount)
player.incrementAttribute("$STATS_BASE:$STATS_FISH")
rewardXP(player, Skills.FISHING, fish.experience)
delayClock(player, Clocks.SKILLING, 5)
if (!checkRequirements(player, op, node))
return clearScripts(player)
}
addItemOrDrop(player, item.id, item.amount)
player.incrementAttribute("$STATS_BASE:$STATS_FISH")
rewardXP(player, Skills.FISHING, fish.experience)
setCurrentScriptState(player, 1)
return keepRunning(player)
}
@@ -118,4 +123,4 @@ class FishingListener : InteractionListener{
}
return false
}
}
}
@@ -12,6 +12,7 @@ import core.game.container.impl.EquipmentContainer
import core.game.event.ResourceProducedEvent
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.Clocks
import core.game.node.Node
import core.game.node.entity.impl.Projectile
import core.game.node.entity.player.Player
@@ -56,79 +57,79 @@ class WoodcuttingListener : InteractionListener {
val tool = SkillingTool.getHatchet(player)
if (!finishedMoving(player))
return true
return restartScript(player)
if (state == 0) {
if (!checkWoodcuttingRequirements(player, resource, node)) {
return clearScripts(player)
}
sendMessage(player, "You swing your axe at the tree...")
}
if (state == 1) {
if (!checkWoodcuttingRequirements(player, resource, node)) {
player.scripts.reset()
return true
}
}
if (clockReady(player, Clocks.SKILLING)) {
animateWoodcutting(player)
if (!checkReward(player, resource, tool))
return delayClock(player, Clocks.SKILLING, 3)
animateWoodcutting(player)
if (!checkReward(player, resource, tool))
return delayScript(player, 3)
if (tool.id == Items.INFERNO_ADZE_13661 && RandomFunction.roll(4)) {
sendMessage(player, "You chop some logs. The heat of the inferno adze incinerates them.")
Projectile.create(
player, null,
1776,
35, 30,
20, 25
).transform(
player,
player.location.transform(2, 0, 0),
true,
25, 25
).send()
delayScript(player, 3)
return rollDepletion(player, node.asScenery(), resource)
}
val reward = resource.getReward()
val rewardAmount: Int
if (reward > 0) {
rewardAmount = calculateRewardAmount(player, reward) // calculate amount
SkillingPets.checkPetDrop(player, SkillingPets.BEAVER) // roll for pet
//add experience
val experience: Double = calculateExperience(player, resource, rewardAmount)
player.getSkills().addExperience(Skills.WOODCUTTING, experience, true)
//send the message for the resource reward
if (resource == WoodcuttingNode.DRAMEN_TREE) {
player.packetDispatch.sendMessage("You cut a branch from the Dramen tree.")
} else {
player.packetDispatch.sendMessage("You get some " + ItemDefinition.forId(reward).name.lowercase(Locale.getDefault()) + ".")
if (tool.id == Items.INFERNO_ADZE_13661 && RandomFunction.roll(4)) {
sendMessage(player, "You chop some logs. The heat of the inferno adze incinerates them.")
Projectile.create(
player, null,
1776,
35, 30,
20, 25
).transform(
player,
player.location.transform(2, 0, 0),
true,
25, 25
).send()
delayClock(player, Clocks.SKILLING, 3)
return rollDepletion(player, node.asScenery(), resource)
}
//give the reward
player.inventory.add(Item(reward, rewardAmount))
player.dispatch(ResourceProducedEvent(reward, rewardAmount, node, -1))
var cutLogs = player.getAttribute("$STATS_BASE:$STATS_LOGS", 0)
player.setAttribute("/save:$STATS_BASE:$STATS_LOGS", ++cutLogs)
val reward = resource.getReward()
val rewardAmount: Int
if (reward > 0) {
rewardAmount = calculateRewardAmount(player, reward) // calculate amount
SkillingPets.checkPetDrop(player, SkillingPets.BEAVER) // roll for pet
//calculate bonus bird nest for mining
val chance = 282
if (RandomFunction.random(chance) == chance / 2) {
if (isActive(SkillcapePerks.NEST_HUNTER, player)) {
if (!player.inventory.add(BirdNest.getRandomNest(false).nest)) {
//add experience
val experience: Double = calculateExperience(player, resource, rewardAmount)
player.getSkills().addExperience(Skills.WOODCUTTING, experience, true)
//send the message for the resource reward
if (resource == WoodcuttingNode.DRAMEN_TREE) {
player.packetDispatch.sendMessage("You cut a branch from the Dramen tree.")
} else {
player.packetDispatch.sendMessage("You get some " + ItemDefinition.forId(reward).name.lowercase(Locale.getDefault()) + ".")
}
//give the reward
player.inventory.add(Item(reward, rewardAmount))
player.dispatch(ResourceProducedEvent(reward, rewardAmount, node, -1))
var cutLogs = player.getAttribute("$STATS_BASE:$STATS_LOGS", 0)
player.setAttribute("/save:$STATS_BASE:$STATS_LOGS", ++cutLogs)
//calculate bonus bird nest for mining
val chance = 282
if (RandomFunction.random(chance) == chance / 2) {
if (isActive(SkillcapePerks.NEST_HUNTER, player)) {
if (!player.inventory.add(BirdNest.getRandomNest(false).nest)) {
BirdNest.drop(player)
}
} else {
BirdNest.drop(player)
}
} else {
BirdNest.drop(player)
}
}
}
delayScript(player, 3)
rollDepletion(player, node.asScenery(), resource)
setCurrentScriptState(player, 1)
delayClock(player, Clocks.SKILLING, 3)
rollDepletion(player, node.asScenery(), resource)
if (!checkWoodcuttingRequirements(player, resource, node)) {
return clearScripts(player)
}
}
return keepRunning(player)
}
@@ -244,4 +245,4 @@ class WoodcuttingListener : InteractionListener {
}
return experience * amount
}
}
}