diff --git a/Server/src/main/java/rs09/game/ai/general/scriptrepository/Script.java b/Server/src/main/java/rs09/game/ai/general/scriptrepository/Script.java index 4342dfa4b..7e725eafd 100644 --- a/Server/src/main/java/rs09/game/ai/general/scriptrepository/Script.java +++ b/Server/src/main/java/rs09/game/ai/general/scriptrepository/Script.java @@ -39,6 +39,11 @@ public abstract class Script { } } + @Override + public String toString() { + return bot.getName() + " is a " + this.getClass().getSimpleName() + " at location " + bot.getLocation().toString() + " Current pulse: " + bot.getPulseManager().getCurrent(); + } + public abstract void tick(); public void setLevel(int skill, int level) { diff --git a/Server/src/main/kotlin/rs09/game/ai/general/ScriptAPI.kt b/Server/src/main/kotlin/rs09/game/ai/general/ScriptAPI.kt index bdfbd287b..92b755ff1 100644 --- a/Server/src/main/kotlin/rs09/game/ai/general/ScriptAPI.kt +++ b/Server/src/main/kotlin/rs09/game/ai/general/ScriptAPI.kt @@ -353,12 +353,39 @@ class ScriptAPI(private val bot: Player) { } } + /** + * Function to iteratively walk an array of Locations to get over complex obstacles. + * @param steps the array of locations to walk to. + * @author dginovker + */ + fun walkArray(steps: Array){ + bot.pulseManager.run(object : Pulse(){ + var stepIndex = 0 + override fun pulse(): Boolean { + // If the stepIndex is out of bounds, we're done + if(stepIndex >= steps.size) return true + // If we're near the last step, we're done + if (bot.location.withinDistance(steps[steps.size - 1], 2)) { + return true + } + // If we're not near the next step, walk to it + if (!bot.location.withinDistance(steps[stepIndex], 5)) { + walkTo(steps[stepIndex]) + return false + } + // If we're near the next step, increment the step index + stepIndex++ + + return false + } + }) + } + /** * @param loc the location to walk to. * @param radius tiles around the location the bot could walk to. * @author Kermit */ - fun randomWalkTo(loc: Location, radius: Int) { if(!bot.walkingQueue.isMoving) { GlobalScope.launch { @@ -383,8 +410,6 @@ class ScriptAPI(private val bot: Player) { diffY /= 2 } GameWorld.Pulser.submit(object : MovementPulse(bot, bot.location.transform(diffX, diffY, 0), Pathfinder.SMART) { - - override fun pulse(): Boolean { return true } diff --git a/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/Adventurer.kt b/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/Adventurer.kt index 98b6d3b76..935caf877 100644 --- a/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/Adventurer.kt +++ b/Server/src/main/kotlin/rs09/game/ai/general/scriptrepository/Adventurer.kt @@ -4,7 +4,6 @@ import core.game.interaction.DestinationFlag import core.game.interaction.MovementPulse import core.game.node.scenery.Scenery import core.game.node.entity.combat.CombatStyle -import rs09.game.node.entity.combat.CombatSwingHandler import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.game.system.task.Pulse @@ -12,12 +11,7 @@ import rs09.game.world.GameWorld import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.zone.ZoneBorders -import rs09.game.world.repository.Repository.sendNews import core.game.world.update.flag.* -import core.game.world.update.flag.context.Animation -import core.game.world.update.flag.context.ChatMessage -import core.game.world.update.flag.context.Graphics -import core.game.world.update.flag.player.ChatFlag import core.tools.RandomFunction import org.json.simple.JSONArray import org.json.simple.JSONObject @@ -78,6 +72,10 @@ class Adventurer(val style: CombatStyle): Script() { skills[Skills.SLAYER] = 90 } + override fun toString(): String { + return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city" + } + private var state = State.START fun getRandomCity(): Location{ @@ -156,10 +154,10 @@ class Adventurer(val style: CombatStyle): Script() { // zoneborder checker if(ticks % 30 == 0){ - for(border in common_stuck_locations){ - if(border.insideBorder(bot)){ - refresh() - ticks = 0 + for((zone, resolution) in common_stuck_locations){ + if(zone.insideBorder(bot)){ + resolution(this) + return } } } @@ -551,9 +549,50 @@ class Adventurer(val style: CombatStyle): Script() { magics,gemrocks,chaosnpc,chaosnpc, chaosnpc2,taverly) - val common_stuck_locations = arrayListOf( - ZoneBorders(2861,3425,2869,3440), - ZoneBorders(2937,3356,2936,3353) + private val whiteWolfMountainTop = Location(2850, 3496, 0) + private val catherbyToTopOfWhiteWolf = arrayOf(Location(2856, 3442, 0), Location(2848, 3455, 0), Location(2848, 3471, 0), Location(2848, 3487, 0)) + private val tavleryToTopOfWhiteWolf = arrayOf(Location(2872, 3425, 0), Location(2863, 3440, 0), Location(2863, 3459, 0), Location(2854, 3475, 0), Location(2859, 3488, 0)) + val common_stuck_locations = mapOf( + // South of Tavlery dungeon + ZoneBorders(2878, 3386, 2884, 3395) to { it: Adventurer -> + it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray()) + }, + // West of Tavlery dungeon + ZoneBorders(2874, 3390, 2880, 3401) to { it: Adventurer -> + it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray()) + }, + // South of White Wolf Mountain in Tavlery + ZoneBorders(2865,3408,2874,3423) to { it: Adventurer -> + it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray()) + }, + // On beginning of White Wolf Mountain in Tavlery + ZoneBorders(2855, 3454, 2852, 3450) to { it: Adventurer -> + it.scriptAPI.walkArray(tavleryToTopOfWhiteWolf + whiteWolfMountainTop + catherbyToTopOfWhiteWolf.reversedArray()) + }, + // South of White Wolf Mountain in Catherby + ZoneBorders(2861,3425,2867, 3432) to { it: Adventurer -> + it.scriptAPI.walkArray(catherbyToTopOfWhiteWolf + whiteWolfMountainTop + tavleryToTopOfWhiteWolf.reversedArray()) + }, + // On beginning of White Wolf Mountain in Catherby + ZoneBorders(2863, 3441, 2859, 3438) to { it: Adventurer -> + it.scriptAPI.walkArray(catherbyToTopOfWhiteWolf + whiteWolfMountainTop + tavleryToTopOfWhiteWolf.reversedArray()) + }, + // At the Crumbling Wall in Falador + ZoneBorders(2937,3356,2936,3353) to { it: Adventurer -> + // Interact with the Crumbling Wall + val wall = it.scriptAPI.getNearestNode("Crumbling wall", true); + if (wall == null) { + it.refresh() + it.ticks = 0 + return@to + } + it.scriptAPI.interact(it.bot, wall, "Climb-over") + }, + // Northwest corner of Draynor Bank + ZoneBorders(3092, 3246, 3091, 3247) to { it: Adventurer -> + // Walk into Draynor Bank + it.scriptAPI.walkTo(Location(3093, 3243, 0)) + }, ) val dialogue: JSONObject diff --git a/Server/src/main/kotlin/rs09/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/kotlin/rs09/game/system/command/sets/MiscCommandSet.kt index f4c3b7580..8b82f8809 100644 --- a/Server/src/main/kotlin/rs09/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/kotlin/rs09/game/system/command/sets/MiscCommandSet.kt @@ -21,6 +21,8 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.rs09.consts.Components import rs09.ServerConstants +import rs09.game.ai.AIPlayer +import rs09.game.ai.AIRepository import rs09.game.camerautils.PlayerCamera import rs09.game.content.activity.fishingtrawler.TrawlerLoot import rs09.game.content.ame.RandomEventManager @@ -191,10 +193,23 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ player.packetDispatch.sendString(red + "" + p.username + if(rights > 0) " [ip=" + p.details.ipAddress + ", name=" + p.details.compName + "]" else "",275,lineStart++) } } - /** - * =================================================================================== - */ + /** + * Lists information about a bot + */ + define("botinfo", Privilege.MODERATOR, "::botinfo botname", "Prints debug information about a bot"){ player, args -> + val scriptInstances = AIRepository.PulseRepository + + // Find the bot with the given name (non-case sensitive) + val bot = scriptInstances.find { it.botScript.bot.username.equals(args[1], true) } + if (bot == null) { + reject(player, "No bot with that name found.") + return@define + } + val botInfo = bot.botScript.toString() + // Print the bot's information, max 80chars per line + botInfo.chunked(80).forEach { notify(player, it) } + } /** * Opens the credit/voting shop