423 lines
14 KiB
Java
423 lines
14 KiB
Java
/*
|
|
* THIS SOFTWARE WRITTEN BY A KEYBOARD-WIELDING MONKEY BOI
|
|
* No rights reserved. Use, redistribute, and modify at your own discretion,
|
|
* and in accordance with Yagex and RuneLite guidelines.
|
|
* However, aforementioned monkey would prefer if you don't sell this plugin for profit.
|
|
* Good luck on your raids!
|
|
*/
|
|
|
|
package net.runelite.client.plugins.gauntlet;
|
|
|
|
import com.google.inject.Provides;
|
|
import lombok.AccessLevel;
|
|
import lombok.Getter;
|
|
import net.runelite.api.Actor;
|
|
import net.runelite.api.Client;
|
|
import net.runelite.api.GameObject;
|
|
import net.runelite.api.GameState;
|
|
import net.runelite.api.HeadIcon;
|
|
import net.runelite.api.NPC;
|
|
import net.runelite.api.NPCComposition;
|
|
import net.runelite.api.Player;
|
|
import net.runelite.api.Projectile;
|
|
import net.runelite.api.Skill;
|
|
import net.runelite.api.SoundEffectID;
|
|
import net.runelite.api.Tile;
|
|
import net.runelite.api.events.AnimationChanged;
|
|
import net.runelite.api.events.ConfigChanged;
|
|
import net.runelite.api.events.GameObjectChanged;
|
|
import net.runelite.api.events.GameObjectDespawned;
|
|
import net.runelite.api.events.GameObjectSpawned;
|
|
import net.runelite.api.events.GameStateChanged;
|
|
import net.runelite.api.events.GameTick;
|
|
import net.runelite.api.events.NpcDespawned;
|
|
import net.runelite.api.events.NpcSpawned;
|
|
import net.runelite.api.events.VarbitChanged;
|
|
import net.runelite.client.config.ConfigManager;
|
|
import net.runelite.client.eventbus.Subscribe;
|
|
import net.runelite.client.game.SkillIconManager;
|
|
import net.runelite.client.plugins.Plugin;
|
|
import net.runelite.client.plugins.PluginDescriptor;
|
|
import net.runelite.client.ui.overlay.OverlayManager;
|
|
import net.runelite.client.util.ImageUtil;
|
|
|
|
import javax.inject.Inject;
|
|
import java.awt.image.BufferedImage;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
@PluginDescriptor(
|
|
name = "Gauntlet",
|
|
description = "All-in-one plugin for the Gauntlet.",
|
|
tags = {"Gauntlet"},
|
|
enabledByDefault = false
|
|
)
|
|
|
|
public class GauntletPlugin extends Plugin {
|
|
|
|
public BufferedImage imageCrystalDeposit;
|
|
public BufferedImage imagePhrenRoots;
|
|
public BufferedImage imageFishingSpot;
|
|
public BufferedImage imageGrymRoot;
|
|
public BufferedImage imageLinumTirinum;
|
|
|
|
public BufferedImage imageAttackRange;
|
|
public BufferedImage imageAttackMage;
|
|
public BufferedImage imageAttackPrayer;
|
|
|
|
public final Map<GameObject, Tile> resources = new HashMap<>();
|
|
|
|
public Set<Projectile> projectiles = new HashSet<>();
|
|
|
|
public int bossCounter = 0; // Attacks until the boss changes attack styles.
|
|
public BossAttackPhase currentPhase = BossAttackPhase.UNKNOWN;
|
|
|
|
public int playerCounter = 6; // Attacks until the boss changes prayer.
|
|
|
|
public enum BossAttackPhase {
|
|
MAGIC, RANGE, UNKNOWN;
|
|
}
|
|
|
|
public enum BossAttack {
|
|
MAGIC, RANGE, PRAYER, LIGHTNING;
|
|
}
|
|
|
|
@Inject
|
|
private Client client;
|
|
|
|
@Getter(AccessLevel.PUBLIC)
|
|
@Inject
|
|
private OverlayManager overlayManager;
|
|
|
|
@Inject
|
|
private GauntletOverlay overlay;
|
|
|
|
@Inject
|
|
private SkillIconManager iconManager;
|
|
|
|
@Inject
|
|
private GauntletConfig config;
|
|
|
|
@Provides
|
|
GauntletConfig getConfig(ConfigManager configManager) {
|
|
return configManager.getConfig(GauntletConfig.class);
|
|
}
|
|
|
|
@Inject
|
|
private GauntletTimer timer;
|
|
|
|
private boolean timerVisible = true;
|
|
|
|
public boolean tornadoesActive = false;
|
|
public int tornadoTicks = GauntletUtils.TORNADO_TICKS;
|
|
|
|
@Override
|
|
protected void startUp() {
|
|
loadImages(config.iconSize());
|
|
|
|
resetCounters();
|
|
|
|
timerVisible = config.displayTimerWidget();
|
|
timer.resetStates();
|
|
timer.initStates();
|
|
|
|
if (timerVisible) {
|
|
overlayManager.add(timer);
|
|
}
|
|
|
|
overlayManager.add(overlay);
|
|
}
|
|
|
|
@Override
|
|
protected void shutDown() {
|
|
resetCounters();
|
|
timer.resetStates();
|
|
|
|
if (timerVisible) {
|
|
overlayManager.remove(timer);
|
|
timerVisible = false;
|
|
}
|
|
|
|
overlayManager.remove(overlay);
|
|
}
|
|
|
|
/**
|
|
* Called when images need to be resized.
|
|
*/
|
|
private void loadImages(int imageSize) {
|
|
imageCrystalDeposit = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.MINING, true), imageSize, imageSize);
|
|
imagePhrenRoots = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.WOODCUTTING, true), imageSize, imageSize);
|
|
imageFishingSpot = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.FISHING, true), imageSize, imageSize);
|
|
imageGrymRoot = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.HERBLORE, true), imageSize, imageSize);
|
|
imageLinumTirinum = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.FARMING, true), imageSize, imageSize);
|
|
|
|
imageAttackMage = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.MAGIC, true), imageSize, imageSize);
|
|
imageAttackRange = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.RANGED, true), imageSize, imageSize);
|
|
imageAttackPrayer = ImageUtil.resizeImage(iconManager.getSkillImage(Skill.PRAYER, true), imageSize, imageSize);
|
|
}
|
|
|
|
@Subscribe
|
|
public void onConfigChanged(ConfigChanged event) {
|
|
if (event.getGroup() == null || event.getKey() == null || !event.getGroup().equals("Gauntlet"))
|
|
return;
|
|
|
|
if (event.getKey().equals("displayTimerWidget")) {
|
|
if (config.displayTimerWidget() && !timerVisible) {
|
|
overlayManager.add(timer);
|
|
timerVisible = true;
|
|
} else if (!config.displayTimerWidget() && timerVisible) {
|
|
overlayManager.remove(timer);
|
|
timerVisible = false;
|
|
}
|
|
} else if (event.getKey().equals("iconSize")) {
|
|
loadImages(config.iconSize());
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void onVarbitChanged(VarbitChanged event) {
|
|
// This handles the timer based on varp states.
|
|
timer.checkStates(true);
|
|
}
|
|
|
|
@Subscribe
|
|
public void onNpcSpawned(NpcSpawned event) {
|
|
NPC npc = event.getNpc();
|
|
if (GauntletUtils.isBoss(npc))
|
|
resetCounters();
|
|
}
|
|
|
|
@Subscribe
|
|
public void onNpcDespawned(NpcDespawned event) {
|
|
NPC npc = event.getNpc();
|
|
if (GauntletUtils.isBoss(npc))
|
|
resetCounters();
|
|
}
|
|
|
|
/**
|
|
* Reset all boss and player related counter resources.
|
|
*/
|
|
private void resetCounters() {
|
|
bossCounter = 0;
|
|
currentPhase = BossAttackPhase.UNKNOWN;
|
|
|
|
playerCounter = 6;
|
|
|
|
tornadoesActive = false;
|
|
tornadoTicks = GauntletUtils.TORNADO_TICKS;
|
|
|
|
projectiles.clear();
|
|
}
|
|
|
|
/**
|
|
* Method is called when an attack is performed by the boss.
|
|
*
|
|
* @param style BossAttack ; the attack performed by the boss
|
|
*/
|
|
public void doAttack(BossAttack style) {
|
|
// Prayer attacks are magic related. We only care if it's prayer to play the unique sound.
|
|
// This section will change all PRAYER attacks to MAGIC.
|
|
if (style == BossAttack.PRAYER) {
|
|
if (config.uniquePrayerAudio()) {
|
|
client.playSoundEffect(SoundEffectID.MAGIC_SPLASH_BOING);
|
|
}
|
|
|
|
style = BossAttack.MAGIC;
|
|
}
|
|
|
|
// This section will decrement the boss attack counter by 1.
|
|
if (style == BossAttack.LIGHTNING) {
|
|
bossCounter--;
|
|
} else if (style == BossAttack.RANGE) {
|
|
if (currentPhase != BossAttackPhase.RANGE) {
|
|
currentPhase = BossAttackPhase.RANGE;
|
|
bossCounter = 3;
|
|
} else {
|
|
bossCounter--;
|
|
}
|
|
} else if (style == BossAttack.MAGIC) {
|
|
if (currentPhase != BossAttackPhase.MAGIC) {
|
|
currentPhase = BossAttackPhase.MAGIC;
|
|
bossCounter = 3;
|
|
} else {
|
|
bossCounter--;
|
|
}
|
|
}
|
|
|
|
// This section will reset the boss attack counter if necessary.
|
|
if (bossCounter <= 0) {
|
|
BossAttackPhase nextPhase;
|
|
|
|
switch (currentPhase) {
|
|
case MAGIC:
|
|
bossCounter = 4;
|
|
nextPhase = BossAttackPhase.RANGE;
|
|
break;
|
|
case RANGE:
|
|
bossCounter = 4;
|
|
nextPhase = BossAttackPhase.MAGIC;
|
|
break;
|
|
default:
|
|
bossCounter = 0;
|
|
nextPhase = BossAttackPhase.UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
currentPhase = nextPhase;
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void onAnimationChanged(AnimationChanged event) {
|
|
Actor actor = event.getActor();
|
|
|
|
// This section handles the player counter.
|
|
if (actor instanceof Player && GauntletUtils.inBoss(client)) {
|
|
Player p = (Player) actor;
|
|
if (p.getName().equals(client.getLocalPlayer().getName())) {
|
|
int id = p.getAnimation();
|
|
if (id != -1) {
|
|
// Detect the overhead prayer that the boss is using and determine the list of animations that the boss is currently immune to.
|
|
int[] wrong_style = new int[]{};
|
|
|
|
for (NPC npc : this.client.getNpcs()) {
|
|
if (GauntletUtils.isBoss(npc)) {
|
|
NPCComposition comp = npc.getComposition();
|
|
if (comp != null) {
|
|
HeadIcon prayer = comp.getOverheadIcon();
|
|
if (prayer != null) {
|
|
switch (prayer) {
|
|
case MELEE:
|
|
wrong_style = GauntletUtils.MELEE_ANIMATIONS;
|
|
break;
|
|
case RANGED:
|
|
wrong_style = GauntletUtils.RANGE_ANIMATIONS;
|
|
break;
|
|
case MAGIC:
|
|
wrong_style = GauntletUtils.MAGE_ANIMATIONS;
|
|
break;
|
|
default:
|
|
wrong_style = new int[]{};
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check that the player performed an attack animation that the boss isn't immune to.
|
|
if (GauntletUtils.arrayContainsInteger(GauntletUtils.PLAYER_ANIMATIONS, id) && !GauntletUtils.arrayContainsInteger(wrong_style, id)) {
|
|
// Attack is valid. Decrement the player attack counter and reset it if necessary.
|
|
playerCounter--;
|
|
if (playerCounter <= 0) {
|
|
playerCounter = 6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// This section handles the boss attack counter if they perform a lightning attack.
|
|
if (actor instanceof NPC) {
|
|
NPC npc = (NPC) actor;
|
|
if (GauntletUtils.isBoss(npc)) {
|
|
int id = npc.getAnimation();
|
|
if (id == GauntletUtils.BOSS_ANIMATION_LIGHTNING) {
|
|
this.doAttack(BossAttack.LIGHTNING);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void onGameTick(GameTick event) {
|
|
// This handles the timer based on player health.
|
|
timer.checkStates(false);
|
|
|
|
// This section handles the boss attack counter if they perform a projectile attack.
|
|
Set<Projectile> newProjectiles = new HashSet<>();
|
|
|
|
for (Projectile projectile : client.getProjectiles()) {
|
|
newProjectiles.add(projectile);
|
|
|
|
if (!projectiles.contains(projectile)) {
|
|
int id = projectile.getId();
|
|
if (GauntletUtils.arrayContainsInteger(GauntletUtils.PROJECTILE_MAGIC, id)) {
|
|
this.doAttack(BossAttack.MAGIC);
|
|
} else if (GauntletUtils.arrayContainsInteger(GauntletUtils.PROJECTILE_PRAYER, id)) {
|
|
this.doAttack(BossAttack.PRAYER);
|
|
} else if (GauntletUtils.arrayContainsInteger(GauntletUtils.PROJECTILE_RANGE, id)) {
|
|
this.doAttack(BossAttack.RANGE);
|
|
}
|
|
}
|
|
}
|
|
|
|
projectiles.clear();
|
|
projectiles = newProjectiles;
|
|
|
|
// This section handles lightning decay.
|
|
if (!this.tornadoesActive) {
|
|
for (NPC npc : client.getNpcs()) {
|
|
if (GauntletUtils.isTornado(npc)) {
|
|
tornadoesActive = true;
|
|
tornadoTicks = GauntletUtils.TORNADO_TICKS;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
tornadoTicks--;
|
|
if (tornadoTicks <= 0) {
|
|
tornadoesActive = false;
|
|
tornadoTicks = GauntletUtils.TORNADO_TICKS;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void onGameObjectSpawned(GameObjectSpawned event) {
|
|
onGameObject(event.getTile(), null, event.getGameObject());
|
|
}
|
|
|
|
@Subscribe
|
|
public void onGameObjectChanged(GameObjectChanged event) {
|
|
onGameObject(event.getTile(), event.getPrevious(), event.getGameObject());
|
|
}
|
|
|
|
@Subscribe
|
|
public void onGameObjectDespawned(GameObjectDespawned event) {
|
|
onGameObject(event.getTile(), event.getGameObject(), null);
|
|
}
|
|
|
|
@Subscribe
|
|
public void onGameStateChanged(GameStateChanged event) {
|
|
if (event.getGameState() == GameState.LOADING) {
|
|
resources.clear();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when a GameObject spawns, changes, or despawns.
|
|
*
|
|
* @param tile Tile
|
|
* @param oldObject TileObject
|
|
* @param newObject TileObject
|
|
*/
|
|
private void onGameObject(Tile tile, GameObject oldObject, GameObject newObject) {
|
|
resources.remove(oldObject);
|
|
|
|
if (newObject == null) {
|
|
return;
|
|
}
|
|
|
|
int id = newObject.getId();
|
|
|
|
if (GauntletUtils.arrayContainsInteger(GauntletUtils.RESOURCE_IDS, id)) {
|
|
resources.put(newObject, tile);
|
|
}
|
|
}
|
|
}
|