diff --git a/Server/src/main/content/global/bots/Adventurer.kt b/Server/src/main/content/global/bots/Adventurer.kt index d47e23145..543046192 100644 --- a/Server/src/main/content/global/bots/Adventurer.kt +++ b/Server/src/main/content/global/bots/Adventurer.kt @@ -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() diff --git a/Server/src/main/content/global/handlers/player/RequestOption.kt b/Server/src/main/content/global/handlers/player/RequestOption.kt index aecf7515b..33707b358 100644 --- a/Server/src/main/content/global/handlers/player/RequestOption.kt +++ b/Server/src/main/content/global/handlers/player/RequestOption.kt @@ -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 } } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/bots/AIRepository.kt b/Server/src/main/core/game/bots/AIRepository.kt index 113a565f7..83f5e4ae2 100644 --- a/Server/src/main/core/game/bots/AIRepository.kt +++ b/Server/src/main/core/game/bots/AIRepository.kt @@ -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("==========================================") + } } } diff --git a/Server/src/main/core/game/interaction/MovementPulse.java b/Server/src/main/core/game/interaction/MovementPulse.java index 11f727dd9..67caf8676 100644 --- a/Server/src/main/core/game/interaction/MovementPulse.java +++ b/Server/src/main/core/game/interaction/MovementPulse.java @@ -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(); } diff --git a/Server/src/main/core/game/interaction/ScriptProcessor.kt b/Server/src/main/core/game/interaction/ScriptProcessor.kt index dd8e4792c..5ccd0e446 100644 --- a/Server/src/main/core/game/interaction/ScriptProcessor.kt +++ b/Server/src/main/core/game/interaction/ScriptProcessor.kt @@ -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