Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class AgilityScript extends Script
final MicroAgilityConfig config;

WorldPoint startPoint = null;
int lastAgilityXp = 0;
long lastTimeoutWarning = 0; // For throttled timeout warnings

@Inject
public AgilityScript(MicroAgilityPlugin plugin, MicroAgilityConfig config)
Expand All @@ -58,6 +60,7 @@ public boolean run()
Rs2Antiban.resetAntibanSettings();
Rs2Antiban.antibanSetupTemplates.applyAgilitySetup();
startPoint = plugin.getCourseHandler().getStartPoint();
lastAgilityXp = Microbot.getClient().getSkillExperience(Skill.AGILITY);
mainScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
try
{
Expand Down Expand Up @@ -87,6 +90,7 @@ public boolean run()
}

final WorldPoint playerWorldLocation = Microbot.getClient().getLocalPlayer().getWorldLocation();
final int currentAgilityXp = Microbot.getClient().getSkillExperience(Skill.AGILITY);

if (handleFood())
{
Expand All @@ -97,63 +101,14 @@ public boolean run()
return;
}

if (plugin.getCourseHandler().getCurrentObstacleIndex() > 0)
{
if (Rs2Player.isMoving() || Rs2Player.isAnimating())
{
return;
}
}

if (lootMarksOfGrace())
{
return;
}

if (config.alchemy())
{
getAlchItem().ifPresent(item -> Rs2Magic.alch(item, 50, 75));
}

if (plugin.getCourseHandler() instanceof PrifddinasCourse)
{
PrifddinasCourse course = (PrifddinasCourse) plugin.getCourseHandler();
if (course.handlePortal())
{
return;
}

if (course.handleWalkToStart(playerWorldLocation))
{
return;
}
}
else if(plugin.getCourseHandler() instanceof WerewolfCourse)
{
WerewolfCourse course = (WerewolfCourse) plugin.getCourseHandler();
if(course.handleFirstSteppingStone(playerWorldLocation))
{
return;
}
if(course.handleStickPickup(playerWorldLocation))
{
return;
}
else if(course.handleSlide())
{
return;
}
else if(course.handleStickReturn(playerWorldLocation))
{
return;
}
}
else if (!(plugin.getCourseHandler() instanceof GnomeStrongholdCourse))
if (handleCourseSpecificActions(playerWorldLocation))
{
if (plugin.getCourseHandler().handleWalkToStart(playerWorldLocation))
{
return;
}
return;
}

final int agilityExp = Microbot.getClient().getSkillExperience(Skill.AGILITY);
Expand All @@ -171,11 +126,86 @@ else if (!(plugin.getCourseHandler() instanceof GnomeStrongholdCourse))
Rs2Walker.walkMiniMap(gameObject.getWorldLocation());
}

if (Rs2GameObject.interact(gameObject))
// Check if we should click (handles animation/XP logic)
if (!plugin.getCourseHandler().shouldClickObstacle(currentAgilityXp, lastAgilityXp))
{
return; // Not ready to click yet
}

// Update XP if we got it while animating
if (currentAgilityXp > lastAgilityXp)
{
plugin.getCourseHandler().waitForCompletion(agilityExp, Microbot.getClient().getLocalPlayer().getWorldLocation().getPlane());
Rs2Antiban.actionCooldown();
Rs2Antiban.takeMicroBreakByChance();
lastAgilityXp = currentAgilityXp;
}

// Handle alchemy if enabled
if (shouldPerformAlch())
{
Optional<String> alchItem = getAlchItem();
if (alchItem.isPresent())
{
// Check if we should skip inefficient alchs
if (config.skipInefficient())
{
// Only alch if obstacle is far enough for efficient alching
if (gameObject.getWorldLocation().distanceTo(playerWorldLocation) >= 5)
{
if (config.efficientAlching())
{
if (performEfficientAlch(gameObject, alchItem.get(), agilityExp))
{
return;
}
}
else
{
// Still do normal alch if far enough but efficient alching is disabled
performNormalAlch(alchItem.get());
}
}
// Skip alching if obstacle is too close
}
else
{
// Normal behavior when skipInefficient is disabled
if (config.efficientAlching())
{
if (performEfficientAlch(gameObject, alchItem.get(), agilityExp))
{
return;
}
}
// Fall back to normal alching
performNormalAlch(alchItem.get());
}
}
}

// Normal obstacle interaction
if (Rs2GameObject.interact(gameObject)) {
// Wait for completion - this now returns quickly on XP drop
boolean completed = plugin.getCourseHandler().waitForCompletion(agilityExp,
Microbot.getClient().getLocalPlayer().getWorldLocation().getPlane());

if (!completed) {
// Timeout occurred - log warning (throttled to once per 30 seconds)
long now = System.currentTimeMillis();
if (now - lastTimeoutWarning > 30000) {
Microbot.log("Obstacle completion timed out - retrying on next iteration");
lastTimeoutWarning = now;
}
return; // Bail early to avoid acting on stale state
}

// XP tracking is already updated before clicking (line 137)
// Don't update here to avoid losing early action state

// If we're still animating after XP, don't add delays - proceed immediately
if (!Rs2Player.isAnimating() && !Rs2Player.isMoving()) {
// Only add delays if we're not animating
Rs2Antiban.actionCooldown();
Rs2Antiban.takeMicroBreakByChance();
}
}
}
catch (Exception ex)
Expand All @@ -191,7 +221,7 @@ private Optional<String> getAlchItem()
String itemsInput = config.itemsToAlch().trim();
if (itemsInput.isEmpty())
{
Microbot.log("No items specified for alching or none available.");
// Microbot.log("No items specified for alching or none available.");
return Optional.empty();
}

Expand All @@ -203,7 +233,7 @@ private Optional<String> getAlchItem()

if (itemsToAlch.isEmpty())
{
Microbot.log("No valid items specified for alching.");
// Microbot.log("No valid items specified for alching.");
return Optional.empty();
}

Expand Down Expand Up @@ -292,4 +322,82 @@ private boolean handleSummerPies()
}
return true;
}

private boolean shouldPerformAlch()
{
if (!config.alchemy())
{
return false;
}

// Check if we should skip alching based on configured chance
if (Math.random() * 100 < config.alchSkipChance())
{
return false;
}

return true;
}

private boolean performEfficientAlch(TileObject gameObject, String alchItem, int agilityExp)
{
WorldPoint playerLocation = Microbot.getClient().getLocalPlayer().getWorldLocation();

if (gameObject.getWorldLocation().distanceTo(playerLocation) >= 5)
{
// Efficient alching: click, alch, click
if (Rs2GameObject.interact(gameObject))
{
sleep(100, 200);
Rs2Magic.alch(alchItem, 50, 75);
Rs2GameObject.interact(gameObject);
boolean completed = plugin.getCourseHandler().waitForCompletion(agilityExp,
Microbot.getClient().getLocalPlayer().getWorldLocation().getPlane());

if (!completed) {
// Timeout during efficient alching - log warning
long now = System.currentTimeMillis();
if (now - lastTimeoutWarning > 30000) {
Microbot.log("Obstacle completion timed out during efficient alching");
lastTimeoutWarning = now;
}
return false; // Return false to indicate alch sequence failed
}

Rs2Antiban.actionCooldown();
Rs2Antiban.takeMicroBreakByChance();
lastAgilityXp = Microbot.getClient().getSkillExperience(Skill.AGILITY);
return true;
}
}
return false;
}

private void performNormalAlch(String alchItem)
{
// Simple alch - waitForCompletion handles all timing
Rs2Magic.alch(alchItem, 50, 75);
}

private boolean handleCourseSpecificActions(WorldPoint playerWorldLocation)
{
if (plugin.getCourseHandler() instanceof PrifddinasCourse)
{
PrifddinasCourse course = (PrifddinasCourse) plugin.getCourseHandler();
return course.handlePortal() || course.handleWalkToStart(playerWorldLocation);
}
else if (plugin.getCourseHandler() instanceof WerewolfCourse)
{
WerewolfCourse course = (WerewolfCourse) plugin.getCourseHandler();
return course.handleFirstSteppingStone(playerWorldLocation)
|| course.handleStickPickup(playerWorldLocation)
|| course.handleSlide()
|| course.handleStickReturn(playerWorldLocation);
}
else if (!(plugin.getCourseHandler() instanceof GnomeStrongholdCourse))
{
return plugin.getCourseHandler().handleWalkToStart(playerWorldLocation);
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.runelite.client.config.ConfigInformation;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
import net.runelite.client.config.Range;
import net.runelite.client.plugins.microbot.agility.enums.AgilityCourse;

@ConfigGroup("MicroAgility")
Expand Down Expand Up @@ -77,4 +78,41 @@ default String itemsToAlch()
{
return "";
}

@ConfigItem(
keyName = "efficientAlching",
name = "Efficient Alching",
description = "Click obstacle first, then alch, then click again (for obstacles 5+ tiles away)",
position = 6,
section = generalSection
)
default boolean efficientAlching()
{
return false;
}

@ConfigItem(
keyName = "skipInefficient",
name = "Skip Inefficient",
description = "Only alch when obstacle is 5+ tiles away (skip inefficient alchs)",
position = 7,
section = generalSection
)
default boolean skipInefficient()
{
return false;
}

@ConfigItem(
keyName = "alchSkipChance",
name = "Alch Skip Chance",
description = "Percentage chance to skip alching on any obstacle (0-100)",
position = 8,
section = generalSection
)
@Range(min = 0, max = 100)
default int alchSkipChance()
{
return 5;
}
}
Loading