You can significantly shorten some of the methods used while allowing for any other spells you wish to add in the future much more streamlined.
For instance,
private boolean canAttack() throws InterruptedException {
if(spell.toString().toLowerCase().equals("firestrike")) {
return canUseFireStrike();
}
if(spell.toString().toLowerCase().equals("earthstrike")) {
return canUseEarthStrike();
}
if(spell.toString().toLowerCase().equals("waterstrike")) {
return canUseWaterStrike();
}
if(spell.toString().toLowerCase().equals("airstrike")) {
return canUseAirStrike();
}
return false;
}
Can be shortened if you initialize spell to a MagicSpell:
private boolean canAttack() throws InterruptedException {
return getMagic().canCast(spell, false);
}
This
private void selectSpell() throws InterruptedException {
if (spell.toString().toLowerCase().equals("firestrike")) {
RS2Widget w = widgets.get(201, 1, 4);
if (w != null && w.isVisible()) {
w.interact("Fire Strike");
}
Sleep.sleepUntil(() -> widgets.isVisible(593), 5000);
}
if (spell.toString().toLowerCase().equals("earthstrike")) {
RS2Widget w = widgets.get(201, 1, 3);
if (w != null && w.isVisible()) {
w.interact("Earth Strike");
}
Sleep.sleepUntil(() -> widgets.isVisible(593), 5000);
}
if (spell.toString().toLowerCase().equals("waterstrike")) {
RS2Widget w = widgets.get(201, 1, 2);
if (w != null && w.isVisible()) {
w.interact("Water Strike");
}
Sleep.sleepUntil(() -> widgets.isVisible(593), 5000);
}
if (spell.toString().toLowerCase().equals("airstrike")) {
RS2Widget w = widgets.get(201, 1, 1);
if (w != null && w.isVisible()) {
w.interact("Wind Strike");
}
Sleep.sleepUntil(() -> widgets.isVisible(593), 5000);
}
}
Can be shortened to
private void selectSpell() throws InterruptedException {
RS2Widget spellWidget = getWidgets().getWidgetContainingSprite(201, spell.getSpriteIndex());
if (spellWidget != null && spellWidget.isVisible()) {
spellWidget.interact();
}
Sleep.sleepUntil(() -> widgets.isVisible(593), 5000);
}
I would move some of the logic implementation in the loop to its own method for readability, so something like this:
@Override
public int onLoop() throws InterruptedException {
dismissDialogue();
if (!canAttack()) {
this.stop();
log("[Error] Out of runes.");
}
if (shouldAttack()) {
if (shouldRotateScreen()) {
rotateCameraToLesserDemon();
} else {
attack();
}
}
return (random(600, 900)); // time before loop starts over
}