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"
}
private var state = State.START
var state = State.START
fun getRandomCity(): Location{
return cities.random()
@@ -7,6 +7,7 @@ import core.game.node.entity.player.link.request.RequestType
import core.plugin.Initializable
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.bots.*
/**
* Represents the plugin used to handle the player option interacting.
@@ -22,8 +23,10 @@ class RequestOption : InteractionListener {
return@on true
}
on(_P_ASSIST.name, IntType.PLAYER) { player, node ->
if (node is AIPlayer)
AIRepository.sendBotInfo(player, node)
player.requestManager.request((node as Player), RequestType.ASSIST)
return@on true
}
}
}
}
@@ -3,6 +3,7 @@ package core.game.bots
import core.game.node.entity.player.Player
import core.game.node.item.GroundItem
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.
@@ -49,5 +50,20 @@ class AIRepository {
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 core.tools.SystemLogger;
import static core.api.ContentAPIKt.getWorldTicks;
import static core.api.ContentAPIKt.log;
import core.tools.Log;
import java.util.Deque;
/**
@@ -80,6 +84,9 @@ public abstract class MovementPulse extends Pulse {
private Location previousLoc;
private Location previousMoverLoc;
private int previousMoveTime;
/**
* Constructs a new {@code MovementPulse} {@code Object}.
*
@@ -182,7 +189,8 @@ public abstract class MovementPulse extends Pulse {
public boolean update() {
mover.face(null);
if (mover == null || destination == null || mover.getViewport().getRegion() == null) {
return false;
stop();
return true;
}
if (hasInactiveNode() || !mover.getViewport().getRegion().isActive()) {
@@ -194,6 +202,23 @@ public abstract class MovementPulse extends Pulse {
}
findPath();
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.
int radius = destination instanceof Entity && ((Entity)destination).getWalkingQueue().hasPath() ? 1 : 0;
if (interactLocation == null)
@@ -265,7 +290,7 @@ public abstract class MovementPulse extends Pulse {
else if (inside) {
loc = findBorderLocation();
}
} else if (loc == previousLoc) return;
} else if (loc == previousLoc && interactLocation != null && mover.getWalkingQueue().hasPath()) return;
if (destination == null) {
return;
@@ -332,8 +357,8 @@ public abstract class MovementPulse extends Pulse {
mover.face(null);
}
}
previousLoc = loc;
}
previousLoc = loc;
}
last = destination.getLocation();
}
@@ -10,6 +10,7 @@ import core.game.node.scenery.Scenery
import core.game.world.GameWorld
import core.game.world.map.Location
import core.game.world.map.path.Pathfinder
import core.game.bots.AIPlayer
import core.tools.Log
import core.tools.SystemLogger
import java.lang.Integer.max
@@ -39,18 +40,18 @@ class ScriptProcessor(val entity: Entity) {
if (entity.delayed()) return
var canProcess = !entity.delayed()
if (entity is Player)
if (entity is Player && entity !is AIPlayer)
canProcess = canProcess && !entity.hasModalOpen()
if (entity !is Player) return
if (!entity.delayed() && canProcess && interactTarget != null) {
if (opScript != null && inOperableDistance()) {
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return)
processInteractScript(opScript ?: return)
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return reset())
processInteractScript(opScript ?: return reset())
}
else if (apScript != null && inApproachDistance(apScript ?: return)) {
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return)
processInteractScript(apScript ?: return)
else if (apScript != null && inApproachDistance(apScript ?: return reset())) {
face(entity, interactTarget?.getFaceLocation(entity.location) ?: return reset())
processInteractScript(apScript ?: return reset())
}
else if (apScript == null && opScript == null && inOperableDistance()) {
sendMessage(entity, "Nothing interesting happens.")
@@ -62,18 +63,18 @@ class ScriptProcessor(val entity: Entity) {
if (didMove)
entity.clocks[Clocks.MOVEMENT] = GameWorld.ticks + if (entity.walkingQueue.isRunning) 0 else 1
var canProcess = !entity.delayed()
if (entity is Player)
if (entity is Player && entity !is AIPlayer)
canProcess = canProcess && !entity.interfaceManager.isOpened && !entity.interfaceManager.hasChatbox()
if (entity !is Player) return
if (!entity.delayed() && canProcess && interactTarget != null && !interacted) {
if (opScript != null && inOperableDistance()) {
face(entity, interactTarget?.centerLocation ?: return)
processInteractScript(opScript ?: return)
face(entity, interactTarget?.centerLocation ?: return reset())
processInteractScript(opScript ?: return reset())
}
else if (apScript != null && inApproachDistance(apScript ?: return)) {
face(entity, interactTarget?.centerLocation ?: return)
processInteractScript(apScript ?: return)
else if (apScript != null && inApproachDistance(apScript ?: return reset())) {
face(entity, interactTarget?.centerLocation ?: return reset())
processInteractScript(apScript ?: return reset())
}
else if (apScript == null && opScript == null && inOperableDistance()) {
sendMessage(entity, "Nothing interesting happens.")
@@ -246,6 +247,7 @@ class ScriptProcessor(val entity: Entity) {
fun reset() {
apScript = null
opScript = null
currentScript = null
apRangeCalled = false
interacted = false
apRange = 10