Fixed deadlock regression in bots

Added some runecrafting player scripts
This commit is contained in:
Pine Stone 2023-07-29 05:02:38 +00:00 committed by Ryan
parent 661390e66f
commit 421c419f69
6 changed files with 599 additions and 8 deletions

View file

@ -0,0 +1,181 @@
package content.global.bots
import content.global.skill.runecrafting.MysteriousRuin
import core.cache.def.impl.SceneryDefinition
import core.game.bots.*
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.world.map.Location
import core.game.world.map.RegionManager
import core.game.world.map.zone.ZoneBorders
import core.net.packet.PacketProcessor
import org.rs09.consts.Items
@PlayerCompatible
@ScriptName("Cosmic Rune Crafter")
@ScriptDescription("Crafts cosmic runes. Start in Zanaris w/ cosmic tiara.")
@ScriptIdentifier("cosmic_crafter")
class CosmicCrafter : Script() {
var state = State.INIT
var runeCounter = 0
var overlay: ScriptAPI.BottingOverlay? = null
var startLocation = Location(0,0,0)
var timer = 0
var bank_deposit = true
var bank = Location(2384, 4457)
var squeezeZone = ZoneBorders(2413, 4400, 2416, 4406)
var endZone = ZoneBorders(2405, 4392, 2410, 4397)
var agility_part = 0
var ruinsZone = ZoneBorders(2400, 4370, 2410, 4385)
var cosmicZone = ZoneBorders(2160, 4830, 2170, 4840)
var ruinPoint = Location(2407, 4379, 0)
var agility2ExitPoint = Location(2408, 4394, 0)
var agility2EntryPoint = Location(2408, 4396, 0)
var agility1ExitPoint = Location(2415, 4401, 0)
var agility1EntryPoint = Location(2415, 4403, 0)
override fun tick() {
if (timer-- > 0) {
return
}
if (bot.settings.runEnergy > 10.0) {
bot.settings.isRunToggled = true
}
when(state){
State.INIT -> {
if (!bot.equipment.containsAtLeastOneItem(Items.COSMIC_TIARA_5539)) {
bot.sendMessage("Please equip a cosmic tiara first.")
state = State.INVALID
} else {
overlay = scriptAPI.getOverlay()
overlay!!.init()
overlay!!.setTitle("Cosmic Runes")
overlay!!.setTaskLabel("Runes Crafted:")
overlay!!.setAmount(0)
startLocation = bot.location
state = State.BANKING
}
}
State.BANKING -> {
if(bot.location != bank) {
scriptAPI.walkTo(bank)
return
}
val runes = bot.inventory.getAmount(Item(Items.COSMIC_RUNE_564))
if (runes > 0) {
runeCounter += runes
overlay!!.setAmount(runeCounter)
bot.sendMessage("You have crafted a total of: $runeCounter runes.")
scriptAPI.bankItem(Items.COSMIC_RUNE_564)
} else {
scriptAPI.withdraw(Items.PURE_ESSENCE_7936, 28)
state = State.FIRST_AGILITY
}
}
State.FIRST_AGILITY -> {
val squeezeWall = scriptAPI.getNearestNode(12127, true)
if (agility_part == 0) {
if (!squeezeZone.insideBorder(bot))
scriptAPI.walkTo(agility1EntryPoint)
else {
scriptAPI.interact(bot, squeezeWall, "squeeze-past")
agility_part = 1
timer = 6
}
} else if (agility_part == 1) {
if (!endZone.insideBorder(bot))
scriptAPI.walkTo(agility2EntryPoint)
else {
scriptAPI.interact(bot, squeezeWall, "squeeze-past")
state = State.RUNNING_TO_ALTER
timer = 6
}
}
}
State.RUNNING_TO_ALTER -> {
if (cosmicZone.insideBorder(bot))
state = State.CRAFTING
val ruins = scriptAPI.getNearestNode(2458,true)
if (!ruinsZone.insideBorder(bot)) {
scriptAPI.walkTo(ruinPoint)
} else if (ruins != null && ruins.location.withinDistance(bot.location, 20)) {
if (!bot.equipment.containsAtLeastOneItem(Items.COSMIC_TIARA_5539)) {
bot.sendMessage("Please equip a cosmic tiara first.")
state = State.INVALID
} else {
val ruinsChild = (ruins as Scenery).getChild(bot)
scriptAPI.interact(bot, ruinsChild, "enter")
timer = 4
}
}
}
State.CRAFTING -> {
val alter = scriptAPI.getNearestNode(2484,true)
scriptAPI.interact(bot, alter, "craft-rune")
if(bot.inventory.containsAtLeastOneItem(Item(Items.COSMIC_RUNE_564)))
state = State.LEAVING_ALTER
}
State.LEAVING_ALTER -> {
var portalOut = scriptAPI.getNearestNode(2471, true)
scriptAPI.interact(bot, portalOut, "use")
if (ruinsZone.insideBorder(bot)) {
state = State.RETURN_AGILITY
timer = 2
}
}
State.RETURN_AGILITY -> {
val squeezeWall = scriptAPI.getNearestNode(12127, true)
if (agility_part == 1) {
if (!endZone.insideBorder(bot))
scriptAPI.walkTo(agility2ExitPoint)
else {
scriptAPI.interact(bot, squeezeWall, "squeeze-past")
agility_part = 0
timer = 6
}
} else if (agility_part == 0) {
if (!squeezeZone.insideBorder(bot))
scriptAPI.walkTo(agility1ExitPoint)
else {
scriptAPI.interact(bot, squeezeWall, "squeeze-past")
state = State.BANKING
timer = 6
}
}
}
State.INVALID -> {
timer = 25
state = State.INIT
}
}
}
override fun newInstance(): Script {
return this
}
enum class State {
INIT,
BANKING,
FIRST_AGILITY,
RETURN_AGILITY,
RUNNING_TO_ALTER,
CRAFTING,
LEAVING_ALTER,
INVALID
}
}

View file

@ -0,0 +1,210 @@
package content.global.bots
import content.global.travel.ship.Ships
import core.cache.def.impl.ItemDefinition
import core.game.bots.*
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
@PlayerCompatible
@ScriptName("Law Rune Crafter")
@ScriptDescription("Crafts law runes. Start near Draynor bank w/ law tiara.")
@ScriptIdentifier("law_crafter")
class LawCrafter : Script() {
var state = State.INIT
var runeCounter = 0
var overlay: ScriptAPI.BottingOverlay? = null
var startLocation = Location(0,0,0)
var timer = 0
var bank = ZoneBorders(3092, 3242, 3092, 3245)
var boatNPC = Location(3047, 3234, 0)
var ruinsZone = ZoneBorders(2850, 3375, 2860, 3382)
var ruinPoint = Location(2857, 3380, 0)
var onBoat = ZoneBorders(2824, 3328, 2840, 3333)
var offBoat = ZoneBorders(2827, 3335, 2836, 3336)
var lawLocation = Location(2464, 4830, 0)
var lawZone = ZoneBorders(2439, 4808, 2488, 4855)
var returnNPC = Location(2835, 3335, 0)
var halfBank = Location(3069, 3275, 0)
override fun tick() {
if (timer-- > 0) {
return
}
if (bot.settings.runEnergy > 10.0) {
bot.settings.isRunToggled = true
}
when(state){
State.INIT -> {
if (!bot.equipment.containsAtLeastOneItem(Items.LAW_TIARA_5545) || !ItemDefinition.canEnterEntrana(bot)) {
bot.sendMessage("Please equip a law tiara first.")
bot.sendMessage("AND REMOVE ALL WEAPONS AND ARMOR.")
state = State.INVALID
} else {
overlay = scriptAPI.getOverlay()
overlay!!.init()
overlay!!.setTitle("Law Runes")
overlay!!.setTaskLabel("Runes Crafted:")
overlay!!.setAmount(0)
startLocation = bot.location
state = State.BANKING
}
}
State.BANKING -> {
endDialogue = true
bot.interfaceManager.closeChatbox()
bot.interfaceManager.openChatbox(137)
bot.interfaceManager.closeChatbox()
bot.dialogueInterpreter.close()
if(!bank.insideBorder(bot)) {
scriptAPI.walkTo(bank.randomLoc)
return
}
val runes = bot.inventory.getAmount(Item(Items.LAW_RUNE_563))
if (runes > 0) {
runeCounter += runes
overlay!!.setAmount(runeCounter)
bot.sendMessage("You have crafted a total of: $runeCounter runes.")
scriptAPI.bankItem(Items.LAW_RUNE_563)
} else {
scriptAPI.withdraw(Items.PURE_ESSENCE_7936, 28)
state = State.HALF_BANK
}
}
State.TO_BOAT_GUY -> {
var boatGuy = scriptAPI.getNearestNode(2729, false)
if (boatGuy != null){
if (boatGuy.location.withinDistance(bot.location,2)) {
if (ItemDefinition.canEnterEntrana(bot)) {
endDialogue = false
Ships.PORT_SARIM_TO_ENTRANA.sail(bot)
state = State.CROSS_GANGPLANK
} else {
state = State.INVALID
}
} else {
scriptAPI.walkTo(boatGuy.location)
}
} else {
scriptAPI.walkTo(boatNPC)
}
}
State.CROSS_GANGPLANK -> {
if (onBoat.insideBorder(bot)) {
var gangplank = scriptAPI.getNearestNode(2415, true)
if (gangplank != null) {
scriptAPI.interact(bot, gangplank, "cross")
}
} else if (offBoat.insideBorder(bot)) {
state = State.RUNNING_TO_ALTER
endDialogue = true
}
}
State.RUNNING_TO_ALTER -> {
if (lawZone.insideBorder(bot))
state = State.CRAFTING
val ruins = scriptAPI.getNearestNode(2459,true)
if (!ruinsZone.insideBorder(bot)) {
scriptAPI.walkTo(ruinPoint)
} else if (ruins != null && ruins.location.withinDistance(bot.location, 20)) {
val ruinsChild = (ruins as Scenery).getChild(bot)
scriptAPI.interact(bot, ruinsChild, "enter")
timer = 4
}
}
State.CRAFTING -> {
if (!lawZone.insideBorder(bot)) {
return
}
if (bot.location != lawLocation) {
scriptAPI.walkTo(lawLocation)
}
val alter = scriptAPI.getNearestNode(2485,true)
scriptAPI.interact(bot, alter, "craft-rune")
if(bot.inventory.containsAtLeastOneItem(Item(Items.LAW_RUNE_563)))
state = State.LEAVING_ALTER
}
State.LEAVING_ALTER -> {
var portalOut = scriptAPI.getNearestNode(2472, true)
scriptAPI.interact(bot, portalOut, "use")
if (ruinsZone.insideBorder(bot)) {
state = State.RETURN_TO_BOAT_GUY
timer = 2
}
}
State.RETURN_TO_BOAT_GUY -> {
var boatGuy = scriptAPI.getNearestNode(2730, false)
if (boatGuy != null){
if (boatGuy.location.withinDistance(bot.location,2)) {
endDialogue = false
Ships.ENTRANA_TO_PORT_SARIM.sail(bot)
state = State.HALF_BANK
} else {
scriptAPI.walkTo(boatGuy.location)
}
} else {
scriptAPI.walkTo(returnNPC)
}
}
// Splits up the journey into two parts.
// This is because the dialogue can't be ended until you are safely on the
// mainland side. But new chunks won't load while dialogue is still displayed.
State.HALF_BANK -> {
if (bot.inventory.containsAtLeastOneItem(Items.PURE_ESSENCE_7936)) {
if ( (bot.location.x - 2) > halfBank.x) {
scriptAPI.walkTo(halfBank)
} else {
state = State.TO_BOAT_GUY
}
} else {
if ( (bot.location.x + 2) < halfBank.x) {
scriptAPI.walkTo(halfBank)
} else {
state = State.BANKING
}
}
}
State.INVALID -> {
timer = 25
state = State.INIT
}
}
}
override fun newInstance(): Script {
return this
}
enum class State {
INIT,
BANKING,
TO_BOAT_GUY,
CROSS_GANGPLANK,
RUNNING_TO_ALTER,
CRAFTING,
LEAVING_ALTER,
RETURN_TO_BOAT_GUY,
HALF_BANK,
INVALID
}
}

View file

@ -0,0 +1,173 @@
package content.global.bots
import content.global.skill.runecrafting.MysteriousRuin
import core.api.teleport
import core.game.bots.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListeners
import core.game.node.entity.player.link.TeleportManager
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
@PlayerCompatible
@ScriptName("Nature Rune Crafter")
@ScriptDescription("Crafts nat runes. Start in Zanaris w/ dramen staff + Nat tiara.")
@ScriptIdentifier("nature_crafter")
class NatureCrafter : Script() {
var state = State.INIT
var runeCounter = 0
var overlay: ScriptAPI.BottingOverlay? = null
var startLocation = Location(0,0,0)
var timer = 0
var teleWaitTime = 16 // 18 ticks needed to rotate the clocks, 2 to teleport
var bank = Location(2384, 4457)
var ruinsZone = ZoneBorders(2866, 3017, 2873, 3022)
var faeRingDestination = Location(2412, 4435, 0) // You don't walk to the fae rings
// you can only walk next to them. so path to the nearest point that isn't in the ring.
var faeRingCenter = Location(2412, 4434, 0)
var karamjaRingDestination = Location(2801, 3002, 0)
var karamjaRingCenter = Location(2801, 3003, 0)
var natureZone = ZoneBorders(2387, 4828, 2416, 4856)
override fun tick() {
if (timer-- > 0) {
return
}
if (bot.settings.runEnergy > 10.0) {
bot.settings.isRunToggled = true
}
when(state){
State.INIT -> {
if (checkValid()) {
overlay = scriptAPI.getOverlay()
overlay!!.init()
overlay!!.setTitle("Nature Runes")
overlay!!.setTaskLabel("Runes Crafted:")
overlay!!.setAmount(0)
startLocation = bot.location
state = State.BANKING
}
}
State.BANKING -> {
if(bot.location != bank) {
scriptAPI.walkTo(bank)
return
}
val runes = bot.inventory.getAmount(Item(Items.NATURE_RUNE_561))
if (runes > 0) {
runeCounter += runes
overlay!!.setAmount(runeCounter)
bot.sendMessage("You have crafted a total of: $runeCounter runes.")
scriptAPI.bankItem(Items.NATURE_RUNE_561)
} else {
scriptAPI.withdraw(Items.PURE_ESSENCE_7936, 28)
state = State.RUNNING_TO_TELE
}
}
State.RUNNING_TO_TELE -> {
if (bot.location != faeRingDestination) {
scriptAPI.walkTo(faeRingDestination)
} else {
if (checkValid()) {
timer = teleWaitTime
state = State.TELE_WAIT
bot.sendMessage("Entering Fairy Ring Codes. Please wait...")
}
}
}
State.TELE_WAIT -> {
teleport(bot, karamjaRingCenter, TeleportManager.TeleportType.FAIRY_RING)
state = State.RUNNING_TO_ALTER
// tele takes 4 ticks so wait that long.
timer = 4
}
State.RETURN_WAIT -> {
teleport(bot, faeRingCenter, TeleportManager.TeleportType.FAIRY_RING)
state = State.BANKING
}
State.RUNNING_TO_ALTER -> {
val ruins = scriptAPI.getNearestNode(2460,true)
if (natureZone.insideBorder(bot))
state = State.CRAFTING
if (!ruinsZone.insideBorder(bot)) {
scriptAPI.walkTo(ruinsZone.randomLoc)
} else if (ruins != null && ruins.location.withinDistance(bot.location, 20) && checkValid()) {
val ruinsChild = (ruins as Scenery).getChild(bot)
scriptAPI.interact(bot, ruinsChild, "enter")
timer = 4
}
}
State.CRAFTING -> {
val alter = scriptAPI.getNearestNode(2486,true)
scriptAPI.interact(bot, alter, "craft-rune")
if(bot.inventory.containsAtLeastOneItem(Item(Items.NATURE_RUNE_561)))
state = State.LEAVING_ALTER
}
State.LEAVING_ALTER -> {
var portalOut = scriptAPI.getNearestNode(2473, true)
scriptAPI.interact(bot, portalOut, "use")
if (ruinsZone.insideBorder(bot))
state = State.RETURNING_TO_TELE
}
State.RETURNING_TO_TELE -> {
if (bot.location != karamjaRingDestination) {
scriptAPI.walkTo(karamjaRingDestination)
} else {
if (checkValid()) {
var portalOut = scriptAPI.getNearestNode(14130, true)
portalOut?.interaction?.handle(bot, portalOut.interaction[0])
timer = 4
state = State.RETURN_WAIT
}
}
}
State.INVALID -> {
timer = 25
state = State.INIT
}
}
}
// Terminates if you have invalid inventory to avoid cheating
private fun checkValid(): Boolean {
if (!bot.equipment.containsAtLeastOneItem(Items.DRAMEN_STAFF_772) or !bot.equipment.containsAtLeastOneItem(Items.NATURE_TIARA_5541)) {
bot.sendMessage("Please equip a dramen staff and nature tiara first.")
state = State.INVALID
return false
}
return true
}
override fun newInstance(): Script {
return this
}
enum class State {
INIT,
BANKING,
RUNNING_TO_TELE,
TELE_WAIT,
RUNNING_TO_ALTER,
CRAFTING,
LEAVING_ALTER,
RETURNING_TO_TELE,
RETURN_WAIT,
INVALID
}
}

View file

@ -2,12 +2,12 @@ package content.global.bots
import core.game.bots.* import core.game.bots.*
import core.game.interaction.DestinationFlag import core.game.interaction.DestinationFlag
import core.game.interaction.IntType
import core.game.interaction.InteractionListeners
import core.game.interaction.MovementPulse import core.game.interaction.MovementPulse
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items import org.rs09.consts.Items
import core.game.interaction.IntType
import core.game.interaction.InteractionListeners
@PlayerCompatible @PlayerCompatible
@ScriptDescription("Start in varrock bank with rune mysteries complete and a pickaxe equipped/in inventory") @ScriptDescription("Start in varrock bank with rune mysteries complete and a pickaxe equipped/in inventory")
@ -18,6 +18,7 @@ class VarrockEssenceMiner : Script(){
var state = State.TO_ESSENCE var state = State.TO_ESSENCE
val auburyZone = ZoneBorders(3252, 3398, 3254, 3402) val auburyZone = ZoneBorders(3252, 3398, 3254, 3402)
val bankZone = ZoneBorders(3251, 3420,3254, 3422) val bankZone = ZoneBorders(3251, 3420,3254, 3422)
// Used for automatic failure prevention eg from levelup
override fun tick() { override fun tick() {
when(state){ when(state){
@ -49,10 +50,13 @@ class VarrockEssenceMiner : Script(){
} }
State.MINING -> { State.MINING -> {
if(bot.inventory.isFull) {
state = State.TO_BANK
}
else {
val essence = scriptAPI.getNearestNode(2491,true) val essence = scriptAPI.getNearestNode(2491,true)
essence?.let { InteractionListeners.run(essence.id, IntType.SCENERY,"mine",bot,essence) } essence?.let { InteractionListeners.run(essence.id, IntType.SCENERY,"mine",bot,essence) }
if(bot.inventory.isFull) }
state = State.TO_BANK
} }
State.TO_BANK -> { State.TO_BANK -> {

View file

@ -1,12 +1,12 @@
package core.game.bots package core.game.bots
import content.global.bots.Idler
import core.Server
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.GameWorld import core.game.world.GameWorld
import core.game.world.map.Location import core.game.world.map.Location
import core.tools.RandomFunction import core.tools.RandomFunction
import core.Server
import content.global.bots.Idler
class GeneralBotCreator { class GeneralBotCreator {
//org/crandor/net/packet/in/InteractionPacket.java <<< This is a very useful class for learning to code bots //org/crandor/net/packet/in/InteractionPacket.java <<< This is a very useful class for learning to code bots
@ -40,6 +40,28 @@ class GeneralBotCreator {
randomDelay -= 1 randomDelay -= 1
return false return false
} }
/*
* Chatboxes and interfaces will cause the authentic interaction subsystem
* to pause any currently running authentically-implemented interactions.
*
* When this happens, if the interfaces are not handled by the script and closed,
* execution will remain paused as the game believes the bot is still doing something
* (because they still have an authentic interaction in the queue, that is not advancing
* because it is paused) and so the script does not execute, but the pulse is waiting on botscript input.
*
* This deadlock can be worked around by just closing these.
*
* Set endDialogue to FALSE if you want
* to avoid automatic dialogue termination (useful for, for example, boat travel)
*/
if (botScript.bot.scripts.getActiveScript() != null && botScript.bot.hasModalOpen() && botScript.endDialogue) {
botScript.bot.interfaceManager.closeChatbox()
botScript.bot.interfaceManager.openChatbox(137)
botScript.bot.interfaceManager.close()
botScript.bot.dialogueInterpreter.close()
}
if (!botScript.bot.pulseManager.hasPulseRunning() && botScript.bot.scripts.getActiveScript() == null) { if (!botScript.bot.pulseManager.hasPulseRunning() && botScript.bot.scripts.getActiveScript() == null) {
/*if (ticks++ >= RandomFunction.random(90000,120000)) { /*if (ticks++ >= RandomFunction.random(90000,120000)) {

View file

@ -19,6 +19,7 @@ public abstract class Script {
public Player bot; public Player bot;
public boolean running = true; public boolean running = true;
public boolean endDialogue = true;
public void init(boolean isPlayer) public void init(boolean isPlayer)
{ {