Me diga como esta funcionando a logica do uso da ...
Criado em: 9 de março de 2025
Criado em: 9 de março de 2025
Me diga como esta funcionando a logica do uso da spell de teleporte do script a seguir, esta a todo momento tentanto utilizar a spell de teleporte para lumbridge mesmo ja estando me lumbdrige, e de forma repetitiva.
package com.runemate.party;
import com.runemate.pathfinder.path.MateWebPath;
import com.runemate.pathfinder.Pathfinder;
import com.runemate.pathfinder.path.;
import com.runemate.pathfinder.;
import com.runemate.pathfinder.model.;
import com.runemate.pathfinder.io.;
import com.runemate.pathfinder.path.transport.;
import com.runemate.pathfinder.path.teleport.;
import com.runemate.pathfinder.model.requirement.;
import com.runemate.pathfinder.model.dto.;
import com.runemate.pathfinder.data.;
import com.runemate.pathfinder.context.;
import com.runemate.pathfinder.api.;
import com.runemate.pathfinder.algo.;
import com.runemate.game.api.script.framework.LoopingBot;
import com.runemate.game.api.hybrid.entities.Npc;
import com.runemate.game.api.hybrid.input.Mouse;
import com.runemate.game.api.hybrid.local.Camera;
import com.runemate.game.api.hybrid.local.Skill;
import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
import com.runemate.game.api.hybrid.location.Area;
import com.runemate.game.api.hybrid.location.Coordinate;
import com.runemate.game.api.hybrid.location.navigation.Path;
import com.runemate.game.api.hybrid.region.Npcs;
import com.runemate.game.api.hybrid.region.Players;
import com.runemate.game.api.script.Execution;
import com.runemate.game.api.script.framework.listeners.InventoryListener;
import com.runemate.game.api.script.framework.listeners.events.ItemEvent;
import com.runemate.ui.setting.annotation.open.SettingsProvider;
import com.runemate.ui.setting.open.Settings;
import com.runemate.game.api.hybrid.entities.GameObject;
import com.runemate.game.api.hybrid.input.Keyboard;
import com.runemate.game.api.hybrid.local.hud.interfaces.*;
import com.runemate.game.api.hybrid.location.navigation.cognizant.ScenePath;
import com.runemate.game.api.hybrid.location.navigation.web.Web;
import com.runemate.game.api.hybrid.location.navigation.web.WebPath;
import com.runemate.game.api.hybrid.location.navigation.web.WebPathBuilder;
import com.runemate.game.api.hybrid.region.GameObjects;
import com.runemate.game.api.hybrid.region.GroundItems;
import com.runemate.game.events.osrs.OSRSLoginHandler;
import com.runemate.game.internal.events.GameEventControllerImpl;
import com.runemate.game.api.hybrid.local.hud.interfaces.Chatbox;
import com.runemate.game.api.hybrid.region.Npcs;
import com.runemate.game.api.hybrid.region.Players;
import com.runemate.game.api.hybrid.region.Region;
import com.runemate.game.api.hybrid.util.calculations.Random;
import com.runemate.game.api.script.framework.tree.BranchTask;
import com.runemate.game.api.script.framework.tree.LeafTask;
import com.runemate.game.api.script.framework.tree.TreeBot;
import com.runemate.game.api.script.framework.tree.TreeTask;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
Exemplo de bot que treina Fish+Cook e Woodcut+Firemake até atingir total level >= 100 no OSRS,
agora com correções para abrir portas se o personagem estiver em local fechado,
e garantir locomoção para o WOODCUT_CENTER mesmo à longas distâncias.
Nesta versão, adicionamos logs super detalhados para análise minuciosa do fluxo de execução,
e também corrigimos o problema de tentar acender a fogueira infinitamente quando o jogo
mostra "You can't light a fire in here" (local inapropriado).
*/
public class totallevel100 extends TreeBot {
// =============================================================================
// CONFIG / COORDENADAS
// =============================================================================
private static final Coordinate SAFE_SPOT = new Coordinate(3215, 3222, 0);
private static final Coordinate FISHING_SPOT = new Coordinate(3243, 3152);
// Cozinha
private static final Coordinate KITCHEN = new Coordinate(3231, 3197);
private static final Coordinate DOOR_OUTSIDE = new Coordinate(3235, 3199);
private static final Coordinate DOOR_INSIDE = new Coordinate(3235, 3198);
// Área para Woodcutting
private static final Coordinate WOODCUT_CENTER = new Coordinate(3184, 3245, 0);
private static final int WOODCUT_RADIUS = 120; // Para considerar "chegou" perto do centro
// Raio para procurar árvores ao redor do jogador
private static final int TREE_SEARCH_RADIUS = 50;
/**
// Pathfinder
private Pathfinder pathfinder;
@Override
public void onStart(String... args) {
System.out.println("[onStart] Inicializando o bot. Argumentos recebidos: ");
if (args != null && args.length > 0) {
for (int i = 0; i < args.length; i++) {
System.out.println(" -> Arg["+i+"]: " + args[i]);
}
} else {
System.out.println(" -> Nenhum argumento adicional fornecido.");
}
System.out.println("[onStart] Criando instância do Pathfinder...");
pathfinder = Pathfinder.create(this);
System.out.println("[onStart] Pathfinder criado com sucesso.");
}
@Override
public TreeTask createRootTask() {
System.out.println("[createRootTask] Criando a root task principal (CheckIfReachedTotal).");
return new CheckIfReachedTotal();
}
// =============================================================================
// ========================= CHECA SE ATINGIMOS TOTAL ==========================
// =============================================================================
private class CheckIfReachedTotal extends BranchTask {
text@Override public boolean validate() { System.out.println("[CheckIfReachedTotal:validate] Iniciando validação para ver se atingimos total >= 100..."); int fish = getLevel(Skill.FISHING); int cook = getLevel(Skill.COOKING); int wc = getLevel(Skill.WOODCUTTING); int fm = getLevel(Skill.FIREMAKING); int soma = fish + cook + wc + fm; System.out.println("[CheckIfReachedTotal:validate] Níveis atuais => Fishing=" + fish + ", Cooking=" + cook + ", Woodcutting=" + wc + ", Firemaking=" + fm + ". Soma (fish+cook+wc+fm)=" + soma); boolean reached = (soma >= 100); System.out.println("[CheckIfReachedTotal:validate] reached=" + reached + " (>=100?)"); return reached; } @Override public TreeTask successTask() { System.out.println("[CheckIfReachedTotal:successTask] -> Soma >= 100. Encaminhando para EndTask()."); return new EndTask(); } @Override public TreeTask failureTask() { System.out.println("[CheckIfReachedTotal:failureTask] -> Soma < 100. Encaminhando para RootTask()."); return new RootTask(); }
}
// =============================================================================
// =========================== 1) ROOT TASK ===================================
// =============================================================================
private class RootTask extends BranchTask {
@Override
public boolean validate() {
System.out.println("[RootTask:validate] Verificando se o jogador está sob ataque (healthGauge != null)...");
boolean underAttack = isUnderAttack();
System.out.println("[RootTask:validate] underAttack=" + underAttack);
return underAttack;
}
text@Override public TreeTask successTask() { System.out.println("[RootTask:successTask] Jogador está sob ataque => GoSafeAreaTask."); return new GoSafeAreaTask(); } @Override public TreeTask failureTask() { System.out.println("[RootTask:failureTask] Jogador NÃO está sob ataque => ChoosePairBranch."); return new ChoosePairBranch(); } private boolean isUnderAttack() { if (Players.getLocal() == null) { System.out.println("[RootTask:isUnderAttack] Jogador local é nulo => não deve estar sob ataque."); return false; } return (Players.getLocal().getHealthGauge() != null); }
}
private class GoSafeAreaTask extends LeafTask {
@Override
public void execute() {
System.out.println("[GoSafeAreaTask:execute] Fomos atacados! Iniciando deslocamento para área segura...");
walkTo(SAFE_SPOT, 2);
System.out.println("[GoSafeAreaTask:execute] Aguardando de 2..5s antes de retomar...");
Execution.delay(Random.nextInt(2000, 5000));
System.out.println("[GoSafeAreaTask:execute] Finalizando GoSafeAreaTask e retornando para o fluxo na RootTask.");
}
}
// =============================================================================
// ====================== 2) ESCOLHER QUAL PAR TREINAR ========================
// =============================================================================
private class ChoosePairBranch extends BranchTask {
textprivate boolean chooseFishCook; @Override public boolean validate() { System.out.println("[ChoosePairBranch:validate] Verificando soma de níveis Fish+Cook e Wc+Fm..."); int fish = getLevel(Skill.FISHING); int cook = getLevel(Skill.COOKING); int wc = getLevel(Skill.WOODCUTTING); int fm = getLevel(Skill.FIREMAKING); int sumFishCook = fish + cook; int sumWcFm = wc + fm; System.out.println("[ChoosePairBranch:validate] sumFishCook=" + sumFishCook + ", sumWcFm=" + sumWcFm); // Se Fish+Cook >= 35 e Wc+Fm >= 35 => ambos completos => forçamos Wc/Fm if (sumFishCook >= 35 && sumWcFm >= 35) { chooseFishCook = false; System.out.println("[ChoosePairBranch:validate] Ambos >= 35. Mesmo assim forçaremos FishCook no 'if' => (mas log diz forçando Wc/Fm?)."); System.out.println(" - Nota: O código retornará 'true', mas no successTask iremos para FishCookRoot (veja a logica)."); return chooseFishCook; } // Se fish+cook >= 35 mas wc+fm não => vamos Wc+Fm if (sumFishCook >= 35 && sumWcFm < 35) { chooseFishCook = false; System.out.println("[ChoosePairBranch:validate] Fish+Cook >= 35 e Wc+Fm < 35 => Vamos Wc+Fm."); return chooseFishCook; } // Se wc+fm >= 35 mas fish+cook não => vamos Fish+Cook if (sumWcFm >= 35 && sumFishCook < 35) { chooseFishCook = true; System.out.println("[ChoosePairBranch:validate] Wc+Fm >= 35 e Fish+Cook < 35 => Vamos Fish+Cook."); return chooseFishCook; } // Caso final => escolhemos com base na diferença ou aleatório int diffFishCook = 35 - sumFishCook; int diffWcFm = 35 - sumWcFm; System.out.println("[ChoosePairBranch:validate] diffFishCook=" + diffFishCook + ", diffWcFm=" + diffWcFm); if (diffFishCook == diffWcFm) { // aleatório chooseFishCook = ThreadLocalRandom.current().nextBoolean(); System.out.println("[ChoosePairBranch:validate] Diffs iguais => escolha aleatória => chooseFishCook=" + chooseFishCook); } else { chooseFishCook = (diffFishCook < diffWcFm); System.out.println("[ChoosePairBranch:validate] Diffs diferentes => chooseFishCook=" + chooseFishCook); } return chooseFishCook; } @Override public TreeTask successTask() { System.out.println("[ChoosePairBranch:successTask] => FishCookRoot"); return new FishCookRoot(); } @Override public TreeTask failureTask() { System.out.println("[ChoosePairBranch:failureTask] => WoodcutFiremakeRoot"); return new WoodcutFiremakeRoot(); }
}
// =============================================================================
// =================== 3) FISH/COOK ROOT (sem parada) =========================
// =============================================================================
private class FishCookRoot extends BranchTask {
@Override
public boolean validate() {
System.out.println("[FishCookRoot:validate] Verificando se o inventário está cheio...");
boolean full = Inventory.isFull();
System.out.println("[FishCookRoot:validate] Inventory.isFull()=" + full);
return full;
}
text@Override public TreeTask successTask() { System.out.println("[FishCookRoot:successTask] -> Inventário cheio, chamando CookingTask()"); return new CookingTask(); } @Override public TreeTask failureTask() { System.out.println("[FishCookRoot:failureTask] -> Inventário não está cheio, chamando FishingTask()"); return new FishingTask(); }
}
// ------------------- COOKING TASK --------------------------------------------
private class CookingTask extends LeafTask {
@Override
public void execute() {
System.out.println("[CookingTask:execute] ** Iniciando rotina de cozinhar (Cooking) **");
text// 1) Tentar abrir a porta para entrar na cozinha System.out.println("[CookingTask:execute] 1) handleDoorRoutine(true) => Entrar na cozinha..."); handleDoorRoutine(true); // 2) Caminha até a cozinha System.out.println("[CookingTask:execute] 2) Caminhando até KITCHEN..."); walkTo(KITCHEN, 3); // 3) Tenta cozinhar System.out.println("[CookingTask:execute] 3) Chamando cookFish()..."); cookFish(); // 4) Abre a porta para sair e voltar a pescar System.out.println("[CookingTask:execute] 4) handleDoorRoutine(false) => Sair da cozinha..."); handleDoorRoutine(false); System.out.println("[CookingTask:execute] Finalizando rotina de cozinhar (CookingTask)."); } private void cookFish() { System.out.println("[CookingTask:cookFish] Verificando se existe peixe cru no inventário (Raw shrimps ou Raw anchovies)..."); if (!Inventory.contains("Raw shrimps") && !Inventory.contains("Raw anchovies")) { System.out.println("[CookingTask:cookFish] Não há peixe cru para cozinhar. Encerrando método cookFish()."); return; } System.out.println("[CookingTask:cookFish] Tentando encontrar o objeto Range na área da cozinha..."); GameObject cookRange = encontrarRange(); if (cookRange == null) { System.out.println("[CookingTask:cookFish] Não foi possível encontrar o Range. Abortando."); return; } double distRange = Players.getLocal().distanceTo(cookRange); System.out.println("[CookingTask:cookFish] Distância até o Range=" + distRange); if (distRange > 2) { System.out.println("[CookingTask:cookFish] Distância > 2. Caminhando até o Range para aproximar..."); walkTo(cookRange.getPosition(), 1); } // Atualiza cookRange após o walkTo cookRange = encontrarRange(); if (cookRange == null) { System.out.println("[CookingTask:cookFish] Range sumiu após tentarmos andar até lá. Abortando."); return; } System.out.println("[CookingTask:cookFish] Tentando interagir com Range via 'Cook'..."); if (cookRange.isVisible() && cookRange.interact("Cook")) { System.out.println("[CookingTask:cookFish] Interagimos com 'Cook'. Dando pequena espera..."); Execution.delay(800, 1500); handlePopUps(); pressSpaceSafely(); Execution.delay(300, 600); long startTime = System.currentTimeMillis(); long maxTime = 180_000; // 3 minutos System.out.println("[CookingTask:cookFish] Iniciando loop para cozinhar enquanto houver peixe cru e não excedermos " + maxTime + "ms."); while (temPeixeCru() && (System.currentTimeMillis() - startTime) < maxTime) { handlePopUps(); if (!isPlayerCooking() && temPeixeCru()) { System.out.println("[CookingTask:cookFish] Detecção de quebra na animação. Reabrindo interface de cozimento..."); reabrirInterfaceDeCozinhar(cookRange); } Execution.delay(800, 1200); } System.out.println("[CookingTask:cookFish] Loop de cozimento finalizado. Chamando descartarPeixes()..."); descartarPeixes(); } else { System.out.println("[CookingTask:cookFish] Falhou ao interagir com Range usando 'Cook'. Fallback => usarItemNoRange(cookRange)."); usarItemNoRange(cookRange); } } private void reabrirInterfaceDeCozinhar(GameObject cookRange) { System.out.println("[CookingTask:reabrirInterfaceDeCozinhar] Tentando Use em Raw fish novamente..."); SpriteItem rawFish = Inventory.getItems("Raw shrimps", "Raw anchovies").first(); if (rawFish != null && rawFish.interact("Use")) { System.out.println("[CookingTask:reabrirInterfaceDeCozinhar] Interagimos com peixe cru (Use). Esperando..."); Execution.delay(300, 600); handlePopUps(); if (cookRange.interact("Use")) { System.out.println("[CookingTask:reabrirInterfaceDeCozinhar] Interagimos com Range (Use). Pressionando espaço para abrir interface de cozimento..."); Execution.delay(600, 1200); handlePopUps(); pressSpaceSafely(); Execution.delay(300, 600); } } else { System.out.println("[CookingTask:reabrirInterfaceDeCozinhar] Nenhum peixe cru encontrado para reabrir interface."); } } private void usarItemNoRange(GameObject cookRange) { System.out.println("[CookingTask:usarItemNoRange] Início do método fallback para cozinhar usando 'Use' (Raw fish -> Range)."); SpriteItem rawFish = Inventory.getItems("Raw shrimps", "Raw anchovies").first(); if (rawFish != null && rawFish.interact("Use")) { System.out.println("[CookingTask:usarItemNoRange] Interagimos com o item (Use). Delay curto..."); Execution.delay(300, 600); handlePopUps(); if (cookRange.interact("Use")) { System.out.println("[CookingTask:usarItemNoRange] Usando peixe cru no Range. Aguardando abertura da interface..."); Execution.delay(600, 1200); handlePopUps(); pressSpaceSafely(); Execution.delay(300, 600); long startTime = System.currentTimeMillis(); long maxTime = 180_000; System.out.println("[CookingTask:usarItemNoRange] Iniciando loop de cozimento (fallback). Máximo de " + maxTime + "ms..."); while (temPeixeCru() && (System.currentTimeMillis() - startTime) < maxTime) { handlePopUps(); if (!isPlayerCooking() && temPeixeCru()) { System.out.println("[CookingTask:usarItemNoRange] Detecção de quebra na animação. Chamando reabrirInterfaceDeCozinhar(cookRange)..."); reabrirInterfaceDeCozinhar(cookRange); } Execution.delay(800, 1200); } System.out.println("[CookingTask:usarItemNoRange] Loop de cozimento (fallback) finalizado. Chamando descartarPeixes()..."); descartarPeixes(); } else { System.out.println("[CookingTask:usarItemNoRange] Falhou ao interagir com Range via 'Use'."); } } else { System.out.println("[CookingTask:usarItemNoRange] Nenhum peixe cru encontrado para usar com Range. Abortando."); } } private boolean temPeixeCru() { boolean shrimps = Inventory.contains("Raw shrimps"); boolean anch = Inventory.contains("Raw anchovies"); boolean tem = shrimps || anch; System.out.println("[CookingTask:temPeixeCru] shrimps=" + shrimps + ", anch=" + anch + " => " + tem); return tem; } private boolean isPlayerCooking() { if (Players.getLocal() == null) { System.out.println("[CookingTask:isPlayerCooking] Players.getLocal() == null => false"); return false; } int anim = Players.getLocal().getAnimationId(); boolean cooking = (anim != -1); return cooking; } private GameObject encontrarRange() { System.out.println("[CookingTask:encontrarRange] Buscando por 'Range' num raio de 10 tiles da KITCHEN..."); return GameObjects.newQuery() .names("Range") .within(new Area.Circular(KITCHEN, 10)) .results() .nearest(); } private void descartarPeixes() { System.out.println("[CookingTask:descartarPeixes] Descartando peixes cozidos e queimados do inventário..."); String[] itemsToDiscard = {"Shrimps", "Burnt shrimp", "Burnt fish", "Anchovies"}; for (String itemName : itemsToDiscard) { while (Inventory.contains(itemName)) { SpriteItem itemToDrop = Inventory.getItems(itemName).first(); if (itemToDrop != null && itemToDrop.interact("Drop")) { System.out.println("[CookingTask:descartarPeixes] Dropamos: " + itemName); Execution.delay(200, 400); handlePopUps(); } else { System.out.println("[CookingTask:descartarPeixes] Falhou ao dropper item ou itemToDrop é nulo. Tentando novamente..."); Execution.delay(400, 800); } } } System.out.println("[CookingTask:descartarPeixes] Fim do método descartarPeixes()."); }
}
// ---------------------- FISHING TASK -----------------------------------------
private class FishingTask extends LeafTask {
@Override
public void execute() {
System.out.println("[FishingTask:execute] ** Iniciando rotina de pesca (Fishing). **");
textif (isPlayerFishing()) { System.out.println("[FishingTask:execute] Já estamos pescando (animação ativa). handlePopUps()..."); handlePopUps(); return; } double distSpot = Players.getLocal().distanceTo(FISHING_SPOT); System.out.println("[FishingTask:execute] Distância até FISHING_SPOT=" + distSpot); if (distSpot > 5) { System.out.println("[FishingTask:execute] Distância > 5 => andando até FISHING_SPOT..."); walkTo(FISHING_SPOT, 3); } else { System.out.println("[FishingTask:execute] Distância <= 5 => iniciar pesca com startFishing()..."); startFishing(); } System.out.println("[FishingTask:execute] Finalizando rotina de pesca."); } private void startFishing() { System.out.println("[FishingTask:startFishing] Buscando Npc 'Fishing spot' num raio de 10 tiles..."); Npc fishingSpot = Npcs.newQuery() .names("Fishing spot") .within(new Area.Circular(FISHING_SPOT, 10)) .results() .nearest(); if (fishingSpot != null) { System.out.println("[FishingTask:startFishing] Encontramos fishingSpot. Interagindo com 'Net'..."); if (fishingSpot.interact("Net")) { System.out.println("[FishingTask:startFishing] Interagimos com 'Net'. Aguardando animação iniciar..."); Execution.delayUntil(this::isPlayerFishing, 2000); } else { System.out.println("[FishingTask:startFishing] Falha ao interagir com Fishing spot (Net)."); } } else { System.out.println("[FishingTask:startFishing] Nenhum 'Fishing spot' encontrado próximo."); } Execution.delay(Random.nextInt(500, 2000)); } private boolean isPlayerFishing() { if (Players.getLocal() == null) { System.out.println("[FishingTask:isPlayerFishing] Players.getLocal() == null => false"); return false; } int anim = Players.getLocal().getAnimationId(); boolean isFishing = (anim != -1); return isFishing; }
}
// =============================================================================
// =========== 4) WOODCUT/FIREMAKE ROOT COM PASSO PRÉVIO DE IR À COORD =========
// =============================================================================
private class WoodcutFiremakeRoot extends BranchTask {
@Override
public boolean validate() {
System.out.println("[WoodcutFiremakeRoot:validate] Verificando se estamos na área de Woodcutting...");
boolean inArea = isInWoodcutArea();
System.out.println("[WoodcutFiremakeRoot:validate] isInWoodcutArea()=" + inArea);
return inArea;
}
text@Override public TreeTask successTask() { System.out.println("[WoodcutFiremakeRoot:successTask] -> Estamos na área => FiremakingOrWoodcutBranch."); return new FiremakingOrWoodcutBranch(); } @Override public TreeTask failureTask() { System.out.println("[WoodcutFiremakeRoot:failureTask] -> Não estamos na área => GoWoodcutAreaTask."); return new GoWoodcutAreaTask(); } private boolean isInWoodcutArea() { if (Players.getLocal() == null) { System.out.println("[WoodcutFiremakeRoot:isInWoodcutArea] Players.getLocal() == null => false."); return false; } double dist = Players.getLocal().distanceTo(WOODCUT_CENTER); System.out.println("[WoodcutFiremakeRoot:isInWoodcutArea] Distância até WOODCUT_CENTER=" + dist + ", comparado com WOODCUT_RADIUS=" + WOODCUT_RADIUS); return dist <= WOODCUT_RADIUS; }
}
private class GoWoodcutAreaTask extends LeafTask {
@Override
public void execute() {
System.out.println("[GoWoodcutAreaTask:execute] Andando até WOODCUT_CENTER pois não estamos na área de Woodcutting...");
walkTo(WOODCUT_CENTER, WOODCUT_RADIUS);
}
}
/**
Branch que decide se vamos Firemaking ou Woodcutting.
continuamos Firemaking.
@Override
public boolean validate() {
System.out.println("[FiremakingOrWoodcutBranch:validate] Checando condições para Firemaking vs Woodcutting...");
textboolean inventoryFull = Inventory.isFull(); boolean haveLogs = Inventory.contains("Logs"); System.out.println(" -> inventoryFull=" + inventoryFull + ", haveLogs=" + haveLogs + ", firemakingMode=" + firemakingMode); if (firemakingMode && haveLogs) { System.out.println("[FiremakingOrWoodcutBranch:validate] Continuamos Firemaking => firemakingMode=true + haveLogs=true."); return true; } if (inventoryFull && haveLogs) { System.out.println("[FiremakingOrWoodcutBranch:validate] Inventário cheio + logs => Ativando modo Firemaking..."); firemakingMode = true; return true; } firemakingMode = false; System.out.println("[FiremakingOrWoodcutBranch:validate] Modo Firemaking desligado => iremos cortar madeira (Woodcutting)."); return false;
}
@Override
public TreeTask successTask() {
System.out.println("[FiremakingOrWoodcutBranch:successTask] => FiremakingTask()");
return new FiremakingTask();
}
@Override
public TreeTask failureTask() {
System.out.println("[FiremakingOrWoodcutBranch:failureTask] => WoodcuttingTask()");
return new WoodcuttingTask();
}
}
// ----------------------------- WOODCUTTING -----------------------------------
private class WoodcuttingTask extends LeafTask {
textprivate GameObject currentTree = null; private long lastChopStart = 0; @Override public void execute() { System.out.println("[WoodcuttingTask:execute] ** Iniciando rotina de corte de árvores **"); handlePopUps(); // Verifica se estamos cortando alguma árvore if (isPlayerWoodcutting()) { System.out.println("[WoodcuttingTask:execute] Jogador já está em animação de woodcutting..."); // Check for timeout long sinceStart = System.currentTimeMillis() - lastChopStart; System.out.println("[WoodcuttingTask:execute] Tempo desde início do corte atual: " + sinceStart + "ms (limite 30000ms)."); if (sinceStart > 30000) { System.out.println("[WoodcuttingTask:execute] Timeout de 30s excedido => resetando árvore atual (buscando nova)."); currentTree = null; return; } // Se a árvore sumiu (stump), achar outra if (currentTree == null || !currentTree.isValid()) { System.out.println("[WoodcuttingTask:execute] currentTree é nula ou inválida => Procurar nova árvore."); currentTree = findNearestTree(); if (currentTree != null && tryChopTree(currentTree)) { lastChopStart = System.currentTimeMillis(); } } else { System.out.println("[WoodcuttingTask:execute] Árvore atual ainda é válida => Apenas aguardando continuar o corte."); } return; } // Não está em animação => procurar outra árvore System.out.println("[WoodcuttingTask:execute] Jogador não está cortando => findNearestTree()."); currentTree = findNearestTree(); if (currentTree != null) { System.out.println("[WoodcuttingTask:execute] currentTree != null => tentaremos cortar..."); if (tryChopTree(currentTree)) { lastChopStart = System.currentTimeMillis(); } else { System.out.println("[WoodcuttingTask:execute] Falha ao tentar cortar a árvore => walkTo(WOODCUT_CENTER, 3)."); walkTo(WOODCUT_CENTER, 3); } } else { // Nenhuma árvore disponível System.out.println("[WoodcuttingTask:execute] Nenhuma árvore disponível => voltar ao centro e aguardar."); walkTo(WOODCUT_CENTER, 3); } } private GameObject findNearestTree() { System.out.println("[WoodcuttingTask:findNearestTree] Buscando por objetos 'Tree' com action 'Chop down' dentro de " + TREE_SEARCH_RADIUS + " tiles."); return GameObjects.newQuery() .names("Tree") .actions("Chop down") .within(new Area.Circular(Players.getLocal().getPosition(), TREE_SEARCH_RADIUS)) .results() .nearest(); } private boolean tryChopTree(GameObject tree) { if (tree == null) { System.out.println("[WoodcuttingTask:tryChopTree] Recebemos uma árvore nula => retorno false."); return false; } double dist = Players.getLocal().distanceTo(tree); System.out.println("[WoodcuttingTask:tryChopTree] Distância até árvore=" + dist); if (dist > 10) { System.out.println("[WoodcuttingTask:tryChopTree] Distância > 10 => walkTo(tree.getPosition(), 3) para aproximar."); walkTo(tree.getPosition(), 3); } if (tree.isValid() && tree.isVisible()) { System.out.println("[WoodcuttingTask:tryChopTree] Árvore válida e visível => interagindo com 'Chop down'..."); if (tree.interact("Chop down")) { System.out.println("[WoodcuttingTask:tryChopTree] Aguardando animação iniciar até 3000ms..."); Execution.delayUntil(this::isPlayerWoodcutting, 3000); return true; } else { System.out.println("[WoodcuttingTask:tryChopTree] Interação com a árvore falhou (Chop down)."); } } else { System.out.println("[WoodcuttingTask:tryChopTree] Árvore inválida ou não visível => false."); } return false; } private boolean isPlayerWoodcutting() { if (Players.getLocal() == null) { System.out.println("[WoodcuttingTask:isPlayerWoodcutting] Players.getLocal()==null => false."); return false; } int anim = Players.getLocal().getAnimationId(); boolean wcut = (anim != -1); return wcut; }
}
// ----------------------------- FIREMAKING ------------------------------------
private class FiremakingTask extends LeafTask {
text@Override public void execute() { System.out.println("[FiremakingTask:execute] ** Iniciando rotina de Firemaking... **"); handlePopUps(); boolean hasLogs = Inventory.contains("Logs"); boolean hasTinder = Inventory.contains("Tinderbox"); System.out.println("[FiremakingTask:execute] Checando inventário => hasLogs=" + hasLogs + ", hasTinder=" + hasTinder); if (!hasLogs || !hasTinder) { System.out.println("[FiremakingTask:execute] Faltam Logs ou Tinderbox => desativando firemakingMode e saindo."); firemakingMode = false; return; } if (isPlayerFiremaking()) { System.out.println("[FiremakingTask:execute] Jogador já está em animação de Firemaking => apenas retornar."); return; } // 1) Verifica se a tile atual está livre Coordinate myPos = Players.getLocal().getPosition(); System.out.println("[FiremakingTask:execute] Posição atual do jogador => " + myPos); if (isTileBlocked(myPos)) { System.out.println("[FiremakingTask:execute] Tile atual está bloqueada => moveToEmptyTile(2)..."); if (moveToEmptyTile(2)) { System.out.println("[FiremakingTask:execute] Tile livre encontrada => Aguardando breve delay..."); Execution.delay(600, 1200); } else { System.out.println("[FiremakingTask:execute] moveToEmptyTile(2) falhou em encontrar tile => prosseguimos mesmo assim."); } } // 2) Tenta acender SpriteItem logs = Inventory.newQuery().names("Logs").results().first(); if (logs == null) { System.out.println("[FiremakingTask:execute] Não achamos 'Logs' no inventário => firemakingMode = false."); firemakingMode = false; return; } System.out.println("[FiremakingTask:execute] Tentando interagir com Logs (Light)..."); if (logs.interact("Light")) { System.out.println("[FiremakingTask:execute] Interagimos com 'Light'. Esperando animação de Firemaking iniciar..."); Execution.delay(600, 1200); // NOVO CHECK: Se o jogo indicar "You can't light a fire in here", vamos nos mover if (checkCantLightFireMessage()) { System.out.println("[FiremakingTask:execute] Detectada mensagem: 'You can't light a fire in here' => movendo para tile vazia e retornando."); moveToEmptyTile(4); return; } Execution.delayUntil(this::isPlayerFiremaking, 2000); if (!isPlayerFiremaking()) { System.out.println("[FiremakingTask:execute] Após o delay, ainda não estamos em animação => fallback usarTinderboxNosLogs()."); usarTinderboxNosLogs(); } } else { System.out.println("[FiremakingTask:execute] Falha em 'Light'. Fallback => usarTinderboxNosLogs()."); usarTinderboxNosLogs(); } // Se após um tempinho ainda não estiver em animação, tenta de novo Execution.delay(500, 800); if (!isPlayerFiremaking()) { System.out.println("[FiremakingTask:execute] Ainda não em animação => walkTo(WOODCUT_CENTER, WOODCUT_RADIUS)."); walkTo(WOODCUT_CENTER, WOODCUT_RADIUS); } } /** * Novo método para verificar a mensagem no chat: * "You can't light a fire in here" (ou algo equivalente). */ private boolean checkCantLightFireMessage() { // Procuramos mensagens recentes de tipo "GAME" que contenham a string. // Se sua versão do RuneMate usa outra forma de capturar, adapte conforme necessário. return com.runemate.game.api.hybrid.local.hud.interfaces.Chatbox.getMessages(com.runemate.game.api.hybrid.local.hud.interfaces.Chatbox.Message.Type.SERVER) .stream() .anyMatch(m -> { String txt = m.getMessage().toLowerCase(); return txt.contains("you can't light a fire in here.") || txt.contains("you can't light a fire in this area.") || txt.contains("you can't light a fire here.") || txt.contains("you cannot light a fire in this area."); }); } private boolean isTileBlocked(Coordinate tile) { if (tile == null) { System.out.println("[FiremakingTask:isTileBlocked] tile=null => retornando true (bloqueada)."); return true; } if (!tile.isReachable()) { System.out.println("[FiremakingTask:isTileBlocked] tile.isReachable() => false => retornando true (bloqueada)."); return true; } GameObject blockingObj = GameObjects.newQuery() .on(tile) .names("Fire", "Ashes") .results() .first(); boolean blocked = (blockingObj != null); System.out.println("[FiremakingTask:isTileBlocked] blockingObj=" + blockingObj + ", blocked=" + blocked); return blocked; } private boolean moveToEmptyTile(int maxRadius) { System.out.println("[FiremakingTask:moveToEmptyTile] maxRadius=" + maxRadius + ". Gerando lista de tiles candidatas livres..."); if (Players.getLocal() == null) { System.out.println("[FiremakingTask:moveToEmptyTile] Jogador local nulo => false."); return false; } Coordinate myPos = Players.getLocal().getPosition(); List<Coordinate> candidates = new ArrayList<>(); for (int dx = -maxRadius; dx <= maxRadius; dx++) { for (int dy = -maxRadius; dy <= maxRadius; dy++) { if (Math.abs(dx) + Math.abs(dy) > maxRadius) continue; Coordinate candidate = new Coordinate(myPos.getX() + dx, myPos.getY() + dy, myPos.getPlane()); if (!isTileBlocked(candidate)) { candidates.add(candidate); } } } System.out.println("[FiremakingTask:moveToEmptyTile] Tiles livres encontradas=" + candidates.size()); if (candidates.isEmpty()) { System.out.println("[FiremakingTask:moveToEmptyTile] Nenhuma tile livre no raio => false."); return false; } // Escolhe uma aleatória Coordinate chosen = candidates.get(Random.nextInt(0, candidates.size())); System.out.println("[FiremakingTask:moveToEmptyTile] Tile escolhida: " + chosen + ". Chamando walkTo(chosen, 1)..."); walkTo(chosen, 1); return true; } private void usarTinderboxNosLogs() { System.out.println("[FiremakingTask:usarTinderboxNosLogs] Início do fallback Tinderbox->Logs."); SpriteItem tinder = Inventory.getItems("Tinderbox").first(); SpriteItem logs = Inventory.getItems("Logs").first(); if (tinder == null || logs == null) { System.out.println("[FiremakingTask:usarTinderboxNosLogs] Falta Tinderbox ou Logs => firemakingMode=false."); firemakingMode = false; return; } System.out.println("[FiremakingTask:usarTinderboxNosLogs] Interagindo com Tinderbox (Use)..."); if (tinder.interact("Use")) { Execution.delay(300, 600); handlePopUps(); System.out.println("[FiremakingTask:usarTinderboxNosLogs] Agora interagindo com Logs (Use)..."); if (logs.interact("Use")) { System.out.println("[FiremakingTask:usarTinderboxNosLogs] Aguarda animação de Firemaking até 2000ms..."); Execution.delay(600, 1200); // Checamos se apareceu mensagem "You can't light a fire..." if (checkCantLightFireMessage()) { System.out.println("[FiremakingTask:usarTinderboxNosLogs] 'You can't light a fire in here' detectado => move away e return."); moveToEmptyTile(4); return; } Execution.delayUntil(this::isPlayerFiremaking, 2000); } else { System.out.println("[FiremakingTask:usarTinderboxNosLogs] Falha ao usar Logs com Tinderbox."); } } else { System.out.println("[FiremakingTask:usarTinderboxNosLogs] Falha ao interagir com Tinderbox (Use)."); } } private boolean isPlayerFiremaking() { if (Players.getLocal() == null) { System.out.println("[FiremakingTask:isPlayerFiremaking] Players.getLocal()==null => false."); return false; } int anim = Players.getLocal().getAnimationId(); boolean isFm = (anim != -1); return isFm; }
}
// =============================================================================
// ======================== MÉTODOS UTILITÁRIOS =================================
// =============================================================================
/**
Caminha usando o Pathfinder para navegação.
Para quando estiver <= 'radius' de distância de 'destination'.
*/
private void walkTo(Coordinate destination, int radius) {
System.out.println("[walkTo] => Início do método. Destination=" + destination + ", radius=" + radius);
if (Players.getLocal() == null) {
System.out.println("[walkTo] Jogador local nulo => não podemos andar. Retornando.");
return;
}
// Primeiro tenta usar ScenePath (mais eficiente para distâncias curtas)
System.out.println("[walkTo] Tentando ScenePath.buildTo(" + destination + ")...");
Path path = ScenePath.buildTo(destination);
if (path != null) {
System.out.println("[walkTo] ScenePath foi construído com sucesso. Usaremos ScenePath.");
} else {
System.out.println("[walkTo] ScenePath falhou => tentando utilizar pathfinder para criar path...");
textif (pathfinder.getLastPath() != null && pathfinder.getLastPath().isValid()) { System.out.println("[walkTo] Usando lastPath do pathfinder que ainda é válido."); path = pathfinder.getLastPath(); } else { System.out.println("[walkTo] lastPath é nulo ou inválido => criando novo path via pathfinder.pathBuilder()."); path = pathfinder.pathBuilder() .preferAccuracy() .enableMinigameTeleports(false) .poh(POH.builder() .mountedGlory(true) .mountedXericsTalisman(true) .jewelleryBoxTier(JewelleryBox.Tier.ORNATE) .nexusPortal(Portal.BARROWS) .build()) .destination(destination) .findPath(); }
}
int tries = 0;
while (Players.getLocal().distanceTo(destination) > radius && tries < 8) {
System.out.println("[walkTo] Loop de movimento, tentativas=" + (tries + 1) +
" | Distância atual=" + Players.getLocal().distanceTo(destination));
closeBlockingInterfaces();
textif (path != null) { System.out.println("[walkTo] path != null => path.step()..."); path.step(); handlePopUps(); closeBlockingInterfaces(); openAnyCloseDoor(); // Abre portas caso existam próximas Execution.delay(300, 600); if (!Players.getLocal().isMoving()) { System.out.println("[walkTo] Player não está se movendo => tentamos novamente abrir portas e pequeno delay..."); Execution.delay(400, 800); openAnyCloseDoor(); } } else { System.out.println("[walkTo] path==null => não conseguimos criar caminho. Encerrando loop."); break; } Execution.delay(300, 600); tries++; double distAfter = Players.getLocal().distanceTo(destination); System.out.println("[walkTo] Distância após step => " + distAfter); if (distAfter <= radius) { System.out.println("[walkTo] Chegamos dentro do radius => break loop."); break; } else { System.out.println("[walkTo] Ainda fora do radius. Continuando caso possamos..."); openAnyCloseDoor(); if (tries % 3 == 0) { System.out.println("[walkTo] Recriando path com pathfinder após " + tries + " tentativas..."); path = pathfinder.pathBuilder() .preferAccuracy() .enableMinigameTeleports(false) .poh(POH.builder() .mountedGlory(true) .mountedXericsTalisman(true) .jewelleryBoxTier(JewelleryBox.Tier.ORNATE) .nexusPortal(Portal.BARROWS) .build()) .destination(destination) .findPath(); } }
}
System.out.println("[walkTo] Fim do método walkTo().");
}
/**
Tenta abrir quaisquer portas próximas com action "Open" (ou "Gate"/"Large door" etc.)
para ajudar a liberar o caminho.
*/
private void openAnyCloseDoor() {
System.out.println("[openAnyCloseDoor] Verificando se há portas/gates próximos para abrir...");
String[] possibleDoorNames = {"Door", "Gate", "Large door"};
GameObject door = GameObjects.newQuery()
.names(possibleDoorNames)
.actions("Open")
.within(new Area.Circular(Players.getLocal().getPosition(), 3))
.results()
.nearest();
if (door != null) {
System.out.println("[openAnyCloseDoor] Achamos um objeto => " + door.getDefinition().getName() +
" em " + door.getPosition() + ". Tentando interagir com 'Open'...");
if (door.isVisible() && door.interact("Open")) {
System.out.println("[openAnyCloseDoor] Interagimos com a porta/gate. Aguarda 1..2s...");
Execution.delay(1000, 2000);
} else {
System.out.println("[openAnyCloseDoor] Porta/gate não é visível ou falha na interação. Verificar câmera/posição.");
}
}
}
/**
Fecha interfaces que possam bloquear a tela (por ex. World Map aberta).
*/
private void closeBlockingInterfaces() {
// Exemplo: Tenta identificar interface de WorldMap
// Caso seu script precise fechar outras interfaces, expandir aqui.
InterfaceComponent worldMap = Interfaces.newQuery()
.texts("World Map", "You are now looking at the World Map")
.visible()
.results()
.first();
if (worldMap != null) {
System.out.println("[closeBlockingInterfaces] Detectamos o mapa aberto. Fechando via ESC...");
Keyboard.pressKey(KeyEvent.VK_ESCAPE);
Execution.delay(500, 1000);
}
}
/**
Lógica para abrir/fechar a porta da cozinha, se necessário.
*/
private void handleDoorRoutine(boolean isEntering) {
System.out.println("[handleDoorRoutine] isEntering=" + isEntering + ". Definindo doorPosition...");
Coordinate doorPosition = isEntering ? DOOR_OUTSIDE : DOOR_INSIDE;
System.out.println("[handleDoorRoutine] doorPosition=" + doorPosition);
if (Players.getLocal() == null) {
System.out.println("[handleDoorRoutine] Jogador local nulo => abortando.");
return;
}
System.out.println("[handleDoorRoutine] walkTo(doorPosition, 3) para aproximar-se da porta...");
walkTo(doorPosition, 3);
// Tentar até 3x abrir
for (int attempt = 0; attempt < 3; attempt++) {
System.out.println("[handleDoorRoutine] Tentativa de abrir porta => " + (attempt+1));
GameObject door = GameObjects.newQuery()
.names("Door")
.actions("Open")
.within(new Area.Circular(doorPosition, 3))
.results()
.nearest();
textif (door != null) { if (!door.isVisible()) { System.out.println("[handleDoorRoutine] Porta encontrada, mas não está visível. Talvez precisemos ajustar câmera."); } System.out.println("[handleDoorRoutine] Interagindo com porta (Open)..."); if (door.interact("Open")) { System.out.println("[handleDoorRoutine] Esperando 1..2s para confirmar abertura..."); Execution.delay(1000, 2000); GameObject maybeClosed = GameObjects.newQuery() .names("Door") .actions("Close") .within(new Area.Circular(doorPosition, 3)) .results() .nearest(); if (maybeClosed != null) { System.out.println("[handleDoorRoutine] Detectamos porta com action 'Close' => significa que abrimos com sucesso!"); break; } else { System.out.println("[handleDoorRoutine] Não encontramos porta com action 'Close'. Pode estar bugado ou já aberto."); } } else { System.out.println("[handleDoorRoutine] Falha ao interagir com 'Open'. Tentando novamente."); } } else { System.out.println("[handleDoorRoutine] Porta não encontrada ou já aberta. (door==null)."); } Execution.delay(800, 1200);
}
System.out.println("[handleDoorRoutine] Fim do método. (isEntering=" + isEntering + ")");
}
/**
Tenta identificar pop-ups (level-up, diálogos etc.) e fecha se encontrar.
*/
private void handlePopUps() {
System.out.println("[handlePopUps] Verificando possíveis pop-ups (Level up, diálogos etc.)...");
// Exemplo: Tenta identificar interface de Level-up
InterfaceComponent levelUp = Interfaces.newQuery()
.containers(233)
.types(InterfaceComponent.Type.CONTAINER)
.visible()
.results()
.first();
if (levelUp != null) {
System.out.println("[handlePopUps] Encontrado container de Level-Up. Pressionando SPACE...");
pressSpaceSafely();
Execution.delay(300, 600);
}
// Diálogo "Click here to continue"
InterfaceComponent clickToContinue = Interfaces.newQuery()
.texts("Click here to continue")
.visible()
.results()
.first();
if (clickToContinue != null) {
System.out.println("[handlePopUps] Encontrado diálogo 'Click here to continue'. Pressionando SPACE...");
pressSpaceSafely();
Execution.delay(300, 600);
}
}
/**
/**
// =============================================================================
// ========================= TAREFA FINAL (ENCERRAR) ===========================
// =============================================================================
private class EndTask extends LeafTask {
@Override
public void execute() {
System.out.println("[EndTask:execute] ** PARABÉNS! Total level >= 100. ENCERRANDO SCRIPT AGORA. **");
totallevel100.this.stop("Total level 100 atingido");
}
}
}
O que está acontecendo é que o Pathfinder (o sistema de caminho que você está usando) está configurado para tentar teletransportar o personagem quando julga que “precisa” se deslocar até determinado ponto, e ele não reconhece corretamente que o seu personagem já está em Lumbridge. Como resultado, ele fica invocando a mesma rota/teleporte repetidamente (geralmente o “Teleport to Lumbridge”), mesmo você estando lá.
Em outras palavras, a “lógica de teleporte” não está explícita no seu código (você não chama LumbridgeTeleport()
em lugar nenhum), porém a biblioteca do pathfinder, por padrão, inclui rotas de teleporte quando acha necessário — a não ser que você desative todas elas. Você até desativou enableMinigameTeleports(false)
, mas há outros tipos de teleporte (padrão, jóias, etc.) que ainda podem estar ativos.
A causa usual desse problema é:
.preferAccuracy()
), ele vê no banco de dados interno que “uma forma garantida” de chegar a tal coordenada é usando o Teleport to Lumbridge (ou outro teleporte).No seu código, isso ocorre dentro do método walkTo(...)
, porque lá você:
ScenePath.buildTo(destination)
. Se der null
, você cai no trecho do pathfinder.pathBuilder()... .findPath()
.while (distance > radius && tries < 8)
, você chama repetidamente path.step()
, e a cada poucas tentativas (cada 3 loops), refaz o path = pathfinder.pathBuilder()...findPath()
.Em muitos web-walkers e pathfinders, o “Lumbridge Teleport” é um teleporte-padrão que o script pode usar para voltar a um “hub” ou “ponto de referência”, principalmente em free-to-play ou ao redor de Lumbridge, então é comum ele aparecer como rota de fallback.
Desative completamente teleports (caso não queira teleporte automático)
Normalmente há algo como pathBuilder.disableAllTeleports()
ou .enableStandardTeleports(false)
dependendo da API usada. Veja se existe um método parecido na sua biblioteca e chame-o antes de findPath()
.
Verificar se já estamos “no destino” antes de chamar o path
if (Players.getLocal().distanceTo(destino) <= radius)
e só chame pathfinder
se de fato estiver longe. Assim você evita que ele faça um path (e eventualmente um teleporte) se a distância for mínima.Ajustar o “radius” ou ver se a coordenada exata do destino está correta
plane
errado (por exemplo, o plane = 1 se estiver num andar superior, etc.), levando o pathfinder a achar que você ainda precisa se mover para “chegar lá”.Coordinate
que você passou é de fato a exata do “chão”. Se tiver altitude/plano diferente, o pathfinder entende que você não chegou.Verificar se a Web interna do pathfinder não está falhando na rota “a pé”
walkTo(...)
o jogador já não esteja dentro do destino, evitando que o pathfinder sequer entre em ação desnecessariamente.desative o uso de feitiço de teleporte no pathfinder. encontrei essas informações sobre uso de spell teleport na documentação do pathfinder, package com.runemate.pathfinder.data;
import com.runemate.game.api.hybrid.location.;
import com.runemate.pathfinder.api.;
import com.runemate.pathfinder.context.;
import lombok.;
@AllArgsConstructor
@Getter
public enum TeleportSpell {
LUMBRIDGE_HOME_TELEPORT(SpellBook.Standard.HOME_TELEPORT, new Coordinate(3225, 3219, 0)),
TELEPORT_TO_HOUSE(SpellBook.Standard.TELEPORT_TO_HOUSE, MovementConstants.HOUSE_POINT),
VARROCK_TELEPORT(SpellBook.Standard.VARROCK_TELEPORT, new Coordinate(3212, 3424, 0)),
LUMBRIDGE_TELEPORT(SpellBook.Standard.LUMBRIDGE_TELEPORT, new Coordinate(3225, 3219, 0)),
FALADOR_TELEPORT(SpellBook.Standard.FALADOR_TELEPORT, new Coordinate(2966, 3379, 0)),
CAMELOT_TELEPORT(SpellBook.Standard.CAMELOT_TELEPORT, new Coordinate(2757, 3479, 0)),
ARDOUGNE_TELEPORT(SpellBook.Standard.ARDOUGNE_TELEPORT, new Coordinate(2661, 3300, 0)),
CIVITAS_ILLA_FORTIS_TELEPORT(SpellBook.Standard.CIVITAS_ILLA_FORTIS_TELEPORT, new Coordinate(1680, 3133, 0)),
WATCHTOWER_TELEPORT(SpellBook.Standard.WATCHTOWER_TELEPORT, new Coordinate(2931, 4717, 2)),
TROLLHEIM_TELEPORT(SpellBook.Standard.TROLLHEIM_TELEPORT, new Coordinate(2888, 3678, 0)),
TELEPORT_TO_KOUREND(SpellBook.Standard.TELEPORT_TO_KOUREND, new Coordinate(1643, 3673, 0)),
TELEPORT_TO_APE_ATOLL(SpellBook.Standard.TELEPORT_TO_APE_ATOLL, new Coordinate(2796, 2791, 0)),
text// ANCIENT TELEPORTS EDGEVILLE_HOME_TELEPORT(SpellBook.Ancient.EDGEVILLE_HOME_TELEPORT, new Coordinate(3087, 3496, 0)), PADDEWWA_TELEPORT(SpellBook.Ancient.PADDEWWA_TELEPORT, new Coordinate(3098, 9883, 0)), SENNTISTEN_TELEPORT(SpellBook.Ancient.SENNTISTEN_TELEPORT, new Coordinate(3321, 3335, 0)), KHARYRLL_TELEPORT(SpellBook.Ancient.KHARYRLL_TELEPORT, new Coordinate(3493, 3474, 0)), LASSAR_TELEPORT(SpellBook.Ancient.LASSAR_TELEPORT, new Coordinate(3004, 3468, 0)), DAREEYAK_TELEPORT(SpellBook.Ancient.DAREEYAK_TELEPORT, new Coordinate(2969, 3695, 0)), CARRALLANGER_TELEPORT(SpellBook.Ancient.CARRALLANGER_TELEPORT, new Coordinate(3157, 3667, 0)), ANNAKARL_TELEPORT(SpellBook.Ancient.ANNAKARL_TELEPORT, new Coordinate(3288, 3888, 0)), GHORROCK_TELEPORT(SpellBook.Ancient.GHORROCK_TELEPORT, new Coordinate(2977, 3872, 0)), // LUNAR TELEPORTS LUNAR_HOME_TELEPORT(SpellBook.Lunar.LUNAR_HOME_TELEPORT, new Coordinate(2094, 3914, 0)), MOONCLAN_TELEPORT(SpellBook.Lunar.MOONCLAN_TELEPORT, new Coordinate(2113, 3917, 0)), OURANIA_TELEPORT(SpellBook.Lunar.OURANIA_TELEPORT, new Coordinate(2470, 3247, 0)), WATERBIRTH_TELEPORT(SpellBook.Lunar.WATERBIRTH_TELEPORT, new Coordinate(2548, 3758, 0)), BARBARIAN_TELEPORT(SpellBook.Lunar.BARBARIAN_TELEPORT, new Coordinate(2545, 3571, 0)), KHAZARD_TELEPORT(SpellBook.Lunar.KHAZARD_TELEPORT, new Coordinate(2637, 3168, 0)), FISHING_GUILD_TELEPORT(SpellBook.Lunar.FISHING_GUILD_TELEPORT, new Coordinate(2610, 3389, 0)), CATHERBY_TELEPORT(SpellBook.Lunar.CATHERBY_TELEPORT, new Coordinate(2802, 3449, 0)), ICE_PLATEAU_TELEPORT(SpellBook.Lunar.ICE_PLATEAU_TELEPORT, new Coordinate(2973, 3939, 0)), // NECROMANCY TELEPORTS ARCEUUS_HOME_TELEPORT(SpellBook.Necromancy.ARCEUUS_HOME_TELEPORT, new Coordinate(1699, 3882, 0)), ARCEUUS_LIBRARY_TELEPORT(SpellBook.Necromancy.ARCEUUS_LIBRARY_TELEPORT, new Coordinate(1634, 3836, 0)), DRAYNOR_MANOR_TELEPORT(SpellBook.Necromancy.DRAYNOR_MANOR_TELEPORT, new Coordinate(3109, 3352, 0)), BATTLEFRONT_TELEPORT(SpellBook.Necromancy.BATTLEFRONT_TELEPORT, new Coordinate(1350, 3740, 0)), MIND_ALTAR_TELEPORT(SpellBook.Necromancy.MIND_ALTAR_TELEPORT, new Coordinate(2978, 3508, 0)),
// RESPAWN_TELEPORT(SpellBook.Necromancy.RESPAWN_TELEPORT, new Coordinate(3262, 6074, 0)),
SALVE_GRAVEYARD_TELEPORT(SpellBook.Necromancy.SALVE_GRAVEYARD_TELEPORT, new Coordinate(3431, 3460, 0)),
FENKENSTRAINS_CASTLE_TELEPORT(SpellBook.Necromancy.FENKENSTRAINS_CASTLE_TELEPORT, new Coordinate(3546, 3528, 0)),
WEST_ARDOUGNE_TELEPORT(SpellBook.Necromancy.WEST_ARDOUGNE_TELEPORT, new Coordinate(2502, 3291, 0)),
HARMONY_ISLAND_TELEPORT(SpellBook.Necromancy.HARMONY_ISLAND_TELEPORT, new Coordinate(3799, 2867, 0)),
CEMETERY_TELEPORT(SpellBook.Necromancy.CEMETERY_TELEPORT, new Coordinate(2978, 3763, 0)),
BARROWS_TELEPORT(SpellBook.Necromancy.BARROWS_TELEPORT, new Coordinate(3563, 3313, 0)),
APE_ATOLL_TELEPORT(SpellBook.Necromancy.APE_ATOLL_TELEPORT, new Coordinate(2769, 9100, 0)),
;
textprivate final Castable spell; private final Coordinate point; public boolean canCast(GraphContext context) { return spell.canCast(context); } public boolean isHomeTeleport() { return this == ARCEUUS_HOME_TELEPORT || this == EDGEVILLE_HOME_TELEPORT || this == LUNAR_HOME_TELEPORT || this == LUMBRIDGE_HOME_TELEPORT; }
}
O Pathfinder expõe internamente diversos “transportes” (teleportes, jóias, minigames etc.) como passos de rota possíveis. Então, mesmo que você não esteja chamando explicitamente o feitiço de teleporte no código, o pathfinder acaba “optando” pelo Lumbridge Teleport quando julga necessário.
Para desativar esses teleports de feitiço (inclusive o Lumbridge Teleport) no pathbuilder, você normalmente precisa chamar algo como:
javapath = pathfinder.pathBuilder() .preferAccuracy() // Desativa cada tipo de teleporte que a sua versão da API disponibiliza .enableStandardTeleports(false) .enableAncientTeleports(false) .enableLunarTeleports(false) .enableArceuusTeleports(false) .enableMinigameTeleports(false) .poh(POH.builder() // Se você também não quer POH nem Joias, pode deixar desativado, // senão basta configurar o que você quer aqui. .mountedGlory(true) .mountedXericsTalisman(true) .jewelleryBoxTier(JewelleryBox.Tier.ORNATE) .nexusPortal(Portal.BARROWS) .build()) .destination(destination) .findPath();
Ou seja, além do enableMinigameTeleports(false)
que você já estava usando, também precisa chamar enableStandardTeleports(false)
, enableAncientTeleports(false)
, etc., de acordo com todas as spellbooks que você não quer usar. Assim o pathfinder ignora aqueles feitiços (como o Lumbridge Teleport) na hora de montar a rota.
Observação: Alguns nomes de método podem variar ligeiramente, dependendo da versão/branch do pathfinder que você tem. Mas a ideia é sempre “desligar” explicitamente cada categoria de teleporte que não queira que o script use. Se a sua API tiver algo como
.disableAllTeleports()
ou.allowTeleports(false)
, também resolve de uma vez.