Implement Authentic Interaction Subsystem

Implemented authentic script/interaction queues
This does now mean we have a total of 3 interaction systems, but this additional system is necessary to fix certain categories of bug and implement some authentic features
Converted mining to new system
Converted fishing to new system
Converted woodcutting to new system
Provided an example of soft-queued scripts with GrandTreePodListener
Implemented tick-eating (it is now possible to eat a shark, drink a potion, and eat a karambwan all on the same tick)
Can now eat and drop items while stunned
This commit is contained in:
Ceikry
2023-02-28 23:41:14 +00:00
committed by Ryan
parent 5206c99151
commit 124eeab893
61 changed files with 1466 additions and 293 deletions
+96
View File
@@ -53,6 +53,9 @@ import core.game.interaction.InteractionListeners
import content.global.handlers.iface.ge.StockMarket
import content.global.skill.slayer.SlayerManager
import core.game.activity.Cutscene
import core.game.interaction.Clocks
import core.game.interaction.QueueStrength
import core.game.interaction.QueuedScript
import core.game.node.entity.player.info.LogType
import core.game.node.entity.player.info.PlayerMonitor
import core.tools.SystemLogger
@@ -60,7 +63,9 @@ import core.game.system.config.ItemConfigParser
import core.game.system.config.ServerConfigParser
import core.game.world.GameWorld
import core.game.world.GameWorld.Pulser
import core.game.world.map.path.ProjectilePathfinder
import core.game.world.repository.Repository
import core.tools.tick
import kotlin.math.absoluteValue
/**
@@ -2261,6 +2266,97 @@ fun addDialogueAction(player: Player, action: core.game.dialogue.DialogueAction)
player.dialogueInterpreter.addAction(action)
}
/**
* Used by content handlers to check if the entity is done moving yet
*/
fun finishedMoving(entity: Entity) : Boolean {
return entity.clocks[Clocks.MOVEMENT] < GameWorld.ticks
}
/**
* Delay the execution of the currently running script
*/
fun delayScript(entity: Entity, ticks: Int): Boolean {
entity.scripts.getActiveScript()?.let { it.nextExecution = GameWorld.ticks + ticks }
return false
}
/**
* Set the global delay for the entity, pausing execution of all queues/scripts until passed.
*/
fun delayEntity(entity: Entity, ticks: Int) {
entity.scripts.delay = GameWorld.ticks + ticks
lock(entity, 5) //TODO: REMOVE WHEN EVERYTHING IMPORTANT USES PROPER QUEUES - THIS IS INCORRECT BEHAVIOR
}
fun apRange(entity: Entity, apRange: Int) {
entity.scripts.apRange = apRange
entity.scripts.apRangeCalled = true
}
fun hasLineOfSight(entity: Entity, target: Node) : Boolean {
return ProjectilePathfinder.find(entity, target).isSuccessful
}
fun animationFinished(entity: Entity) : Boolean {
return entity.clocks[Clocks.ANIMATION_END] < GameWorld.ticks
}
fun clearScripts(entity: Entity) : Boolean {
entity.scripts.reset()
return true
}
fun restartScript(entity: Entity) : Boolean {
if (entity.scripts.getActiveScript()?.persist != true) {
SystemLogger.logErr(entity.scripts.getActiveScript()!!::class.java, "Tried to call restartScript on a non-persistent script! Either use stopExecuting() or make the script persistent.")
return clearScripts(entity)
}
return true
}
fun keepRunning(entity: Entity) : Boolean {
entity.scripts.getActiveScript()?.nextExecution = getWorldTicks() + 1
return false
}
fun stopExecuting(entity: Entity) : Boolean {
if (entity.scripts.getActiveScript()?.persist == true) {
SystemLogger.logErr(entity.scripts.getActiveScript()!!::class.java, "Tried to call stopExecuting() on a persistent script! To halt execution of a persistent script, you MUST call clearScripts()!")
return clearScripts(entity)
}
return true
}
fun queueScript(entity: Entity, delay: Int = 1, strength: QueueStrength = QueueStrength.WEAK, persist: Boolean = false, script: (stage: Int) -> Boolean) {
val s = QueuedScript(script, strength, persist)
s.nextExecution = getWorldTicks() + delay
entity.scripts.addToQueue(s, strength)
}
fun delayAttack(entity: Entity, ticks: Int) {
entity.properties.combatPulse.delayNextAttack(3)
entity.clocks[Clocks.NEXT_ATTACK] = getWorldTicks() + ticks
}
fun stun(entity: Entity, ticks: Int) {
entity.walkingQueue.reset()
entity.pulseManager.clear()
entity.locks.lockMovement(ticks)
entity.clocks[Clocks.STUN] = getWorldTicks() + ticks
entity.graphics(Graphics(80, 96))
if (entity is Player) {
entity.audioManager.send(Audio(2727, 1, 0))
entity.animate(Animation(424, Animator.Priority.VERY_HIGH))
sendMessage(entity, "You have been stunned!")
}
}
fun isStunned(entity: Entity) : Boolean {
return entity.clocks[Clocks.STUN] >= getWorldTicks()
}
/**
* Modifies prayer points by value
* @param player the player to modify prayer points