Added some bot debugging support via the "Request Assist" option on bots

Found and fixed the issue causing bots to get stuck or only interact with one thing
Added some additional safety checks in the script processor
This commit is contained in:
Ceikry
2023-05-25 04:33:27 +00:00
committed by Ryan
parent b995436ea4
commit 6eed461162
5 changed files with 63 additions and 17 deletions
@@ -77,7 +77,7 @@ class Adventurer(val style: CombatStyle): Script() {
return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city" return "${bot.name} is an Adventurer bot at ${bot.location}! State: $state - City: $city"
} }
private var state = State.START var state = State.START
fun getRandomCity(): Location{ fun getRandomCity(): Location{
return cities.random() return cities.random()
@@ -7,6 +7,7 @@ import core.game.node.entity.player.link.request.RequestType
import core.plugin.Initializable import core.plugin.Initializable
import core.game.interaction.IntType import core.game.interaction.IntType
import core.game.interaction.InteractionListener import core.game.interaction.InteractionListener
import core.game.bots.*
/** /**
* Represents the plugin used to handle the player option interacting. * Represents the plugin used to handle the player option interacting.
@@ -22,8 +23,10 @@ class RequestOption : InteractionListener {
return@on true return@on true
} }
on(_P_ASSIST.name, IntType.PLAYER) { player, node -> on(_P_ASSIST.name, IntType.PLAYER) { player, node ->
if (node is AIPlayer)
AIRepository.sendBotInfo(player, node)
player.requestManager.request((node as Player), RequestType.ASSIST) player.requestManager.request((node as Player), RequestType.ASSIST)
return@on true return@on true
} }
} }
} }
@@ -3,6 +3,7 @@ package core.game.bots
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.item.GroundItem import core.game.node.item.GroundItem
import core.game.ge.GrandExchangeOffer import core.game.ge.GrandExchangeOffer
import content.global.bots.*
/** /**
* A repository for bots to make use of that can contain any info that might be useful to them. * A repository for bots to make use of that can contain any info that might be useful to them.
@@ -49,5 +50,20 @@ class AIRepository {
AIPlayer.deregister((it.botScript.bot as AIPlayer).uid) AIPlayer.deregister((it.botScript.bot as AIPlayer).uid)
} }
} }
@JvmStatic fun sendBotInfo (player: Player, bot: AIPlayer) {
val pulse = PulseRepository[bot.username.lowercase()] ?: return
bot.setAttribute("tracked", true)
player.debug("[Bot: ${bot.username}][${pulse.botScript::class.simpleName}]=================")
player.debug("PM Pulse Running? ${if(bot.pulseManager.hasPulseRunning()) bot.pulseManager.getCurrent()::class.java.name else "No"}")
player.debug("Interaction Running? ${bot.scripts.getActiveScript() != null} ${bot.scripts.getActiveScript()?.let { " : " + it.execution!!::class.java.name } ?: ""}")
player.debug("Botscript Running? ${pulse.botScript.running}")
player.debug("Random Delay? ${pulse.randomDelay}")
player.debug("Delayed? ${bot.scripts.delay}")
if (pulse.botScript is Adventurer) {
player.debug("State: ${pulse.botScript.state.name}")
}
player.debug("==========================================")
}
} }
} }
@@ -17,6 +17,10 @@ import core.net.packet.out.ClearMinimapFlag;
import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function2;
import core.tools.SystemLogger; import core.tools.SystemLogger;
import static core.api.ContentAPIKt.getWorldTicks;
import static core.api.ContentAPIKt.log;
import core.tools.Log;
import java.util.Deque; import java.util.Deque;
/** /**
@@ -80,6 +84,9 @@ public abstract class MovementPulse extends Pulse {
private Location previousLoc; private Location previousLoc;
private Location previousMoverLoc;
private int previousMoveTime;
/** /**
* Constructs a new {@code MovementPulse} {@code Object}. * Constructs a new {@code MovementPulse} {@code Object}.
* *
@@ -182,7 +189,8 @@ public abstract class MovementPulse extends Pulse {
public boolean update() { public boolean update() {
mover.face(null); mover.face(null);
if (mover == null || destination == null || mover.getViewport().getRegion() == null) { if (mover == null || destination == null || mover.getViewport().getRegion() == null) {
return false; stop();
return true;
} }
if (hasInactiveNode() || !mover.getViewport().getRegion().isActive()) { if (hasInactiveNode() || !mover.getViewport().getRegion().isActive()) {
@@ -194,6 +202,23 @@ public abstract class MovementPulse extends Pulse {
} }
findPath(); findPath();
Location ml = mover.getLocation(); Location ml = mover.getLocation();
if (previousMoverLoc == null || !previousMoverLoc.equals(ml)) {
previousMoverLoc = Location.create(ml);
previousMoveTime = getWorldTicks();
}
else if (getWorldTicks() - previousMoveTime >= 25) {
if (mover instanceof Player) {
((Player) mover).getPacketDispatch().sendMessage("I can't reach that.");
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext((Player) mover));
}
log(this.getClass(), Log.FINE, mover.getName() + " was trying to move to " + interactLocation + " from " + ml + " but hasn't changed location in 25 ticks. More info follows:");
log(this.getClass(), Log.FINE, " -> Locked? " + mover.getLocks().isMovementLocked());
log(this.getClass(), Log.FINE, " -> Has path? " + mover.getWalkingQueue().hasPath());
stop();
return true;
}
// Allow being within 1 square of moving entities to interact with them. // Allow being within 1 square of moving entities to interact with them.
int radius = destination instanceof Entity && ((Entity)destination).getWalkingQueue().hasPath() ? 1 : 0; int radius = destination instanceof Entity && ((Entity)destination).getWalkingQueue().hasPath() ? 1 : 0;
if (interactLocation == null) if (interactLocation == null)
@@ -265,7 +290,7 @@ public abstract class MovementPulse extends Pulse {
else if (inside) { else if (inside) {
loc = findBorderLocation(); loc = findBorderLocation();
} }
} else if (loc == previousLoc) return; } else if (loc == previousLoc && interactLocation != null && mover.getWalkingQueue().hasPath()) return;
if (destination == null) { if (destination == null) {
return; return;
@@ -332,8 +357,8 @@ public abstract class MovementPulse extends Pulse {
mover.face(null); mover.face(null);
} }
} }
previousLoc = loc;
} }
previousLoc = loc;
} }
last = destination.getLocation(); last = destination.getLocation();
} }
@@ -10,6 +10,7 @@ import core.game.node.scenery.Scenery
import core.game.world.GameWorld import core.game.world.GameWorld
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.path.Pathfinder import core.game.world.map.path.Pathfinder
import core.game.bots.AIPlayer
import core.tools.Log import core.tools.Log
import core.tools.SystemLogger import core.tools.SystemLogger
import java.lang.Integer.max import java.lang.Integer.max
@@ -39,18 +40,18 @@ class ScriptProcessor(val entity: Entity) {
if (entity.delayed()) return if (entity.delayed()) return
var canProcess = !entity.delayed() var canProcess = !entity.delayed()
if (entity is Player) if (entity is Player && entity !is AIPlayer)
canProcess = canProcess && !entity.hasModalOpen() canProcess = canProcess && !entity.hasModalOpen()
if (entity !is Player) return if (entity !is Player) return
if (!entity.delayed() && canProcess && interactTarget != null) { if (!entity.delayed() && canProcess && interactTarget != null) {
if (opScript != null && inOperableDistance()) { if (opScript != null && inOperableDistance()) {
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return) face(entity, interactTarget?.getFaceLocation(entity.location) ?: return reset())
processInteractScript(opScript ?: return) processInteractScript(opScript ?: return reset())
} }
else if (apScript != null && inApproachDistance(apScript ?: return)) { else if (apScript != null && inApproachDistance(apScript ?: return reset())) {
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return) face(entity, interactTarget?.getFaceLocation(entity.location) ?: return reset())
processInteractScript(apScript ?: return) processInteractScript(apScript ?: return reset())
} }
else if (apScript == null && opScript == null && inOperableDistance()) { else if (apScript == null && opScript == null && inOperableDistance()) {
sendMessage(entity, "Nothing interesting happens.") sendMessage(entity, "Nothing interesting happens.")
@@ -62,18 +63,18 @@ class ScriptProcessor(val entity: Entity) {
if (didMove) if (didMove)
entity.clocks[Clocks.MOVEMENT] = GameWorld.ticks + if (entity.walkingQueue.isRunning) 0 else 1 entity.clocks[Clocks.MOVEMENT] = GameWorld.ticks + if (entity.walkingQueue.isRunning) 0 else 1
var canProcess = !entity.delayed() var canProcess = !entity.delayed()
if (entity is Player) if (entity is Player && entity !is AIPlayer)
canProcess = canProcess && !entity.interfaceManager.isOpened && !entity.interfaceManager.hasChatbox() canProcess = canProcess && !entity.interfaceManager.isOpened && !entity.interfaceManager.hasChatbox()
if (entity !is Player) return if (entity !is Player) return
if (!entity.delayed() && canProcess && interactTarget != null && !interacted) { if (!entity.delayed() && canProcess && interactTarget != null && !interacted) {
if (opScript != null && inOperableDistance()) { if (opScript != null && inOperableDistance()) {
face(entity, interactTarget?.centerLocation ?: return) face(entity, interactTarget?.centerLocation ?: return reset())
processInteractScript(opScript ?: return) processInteractScript(opScript ?: return reset())
} }
else if (apScript != null && inApproachDistance(apScript ?: return)) { else if (apScript != null && inApproachDistance(apScript ?: return reset())) {
face(entity, interactTarget?.centerLocation ?: return) face(entity, interactTarget?.centerLocation ?: return reset())
processInteractScript(apScript ?: return) processInteractScript(apScript ?: return reset())
} }
else if (apScript == null && opScript == null && inOperableDistance()) { else if (apScript == null && opScript == null && inOperableDistance()) {
sendMessage(entity, "Nothing interesting happens.") sendMessage(entity, "Nothing interesting happens.")
@@ -246,6 +247,7 @@ class ScriptProcessor(val entity: Entity) {
fun reset() { fun reset() {
apScript = null apScript = null
opScript = null opScript = null
currentScript = null
apRangeCalled = false apRangeCalled = false
interacted = false interacted = false
apRange = 10 apRange = 10