diff --git a/README.md b/README.md index ee556c8..2c4d981 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ A RuneLite plugin to help solve random events by displaying solutions for each r - Displays the correct coffin solution for all the graves via color-coded highlights - Swaps "Use" to be the first option on a coffin +- View either skill icons or item icons related to the grave ### [Mime](https://oldschool.runescape.wiki/w/Mime_(Random_Event))
diff --git a/src/main/java/randomeventhelper/RandomEventHelperConfig.java b/src/main/java/randomeventhelper/RandomEventHelperConfig.java index 004f9af..c6f5dab 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperConfig.java +++ b/src/main/java/randomeventhelper/RandomEventHelperConfig.java @@ -42,28 +42,70 @@ default boolean isDrillDemonEnabled() return true; } + @ConfigSection( + name = "Freaky Forester", + description = "Freaky Forester random event options", + position = 3, + closedByDefault = true + ) + String SECTION_FREAKY_FORESTER = "sectionFreakyForester"; + @ConfigItem( keyName = "isFreakyForesterEnabled", name = "Freaky Forester", description = "Helps highlight the correct pheasant to kill for the Freaky Forester random event.", - position = 3 + section = SECTION_FREAKY_FORESTER, + position = 0 ) default boolean isFreakyForesterEnabled() { return true; } + @ConfigItem( + keyName = "pheasantHighlightMode", + name = "Pheasant Highlight Mode", + description = "Configures how to highlight the pheasant(s) for the Freaky Forester random event.", + section = SECTION_FREAKY_FORESTER, + position = 1 + ) + default PheasantMode pheasantHighlightMode() + { + return PheasantMode.SPECIFIC; + } + + @ConfigSection( + name = "Gravedigger", + description = "Gravedigger random event options", + position = 4, + closedByDefault = true + ) + String SECTION_GRAVEDIGGER = "sectionGravedigger"; + @ConfigItem( keyName = "isGravediggerEnabled", name = "Gravedigger", description = "Helps highlight where each coffin belongs to each grave for the Gravedigger random event.", - position = 4 + section = SECTION_GRAVEDIGGER, + position = 0 ) default boolean isGravediggerEnabled() { return true; } + @ConfigItem( + keyName = "gravediggerUseSkillIcons", + name = "Use skill icons instead of item icons", + description = "Use the associated skill icons instead of item icons for gravestones and coffins in the Gravedigger random event.", + section = SECTION_GRAVEDIGGER, + position = 1 + ) + default boolean gravediggerUseSkillIcons() + { + return true; + } + @ConfigItem( keyName = "isMazeEnabled", name = "Maze", @@ -129,24 +171,4 @@ default boolean isQuizMasterEnabled() { return true; } - - @ConfigSection( - name = "Options", - description = "Further configure various options", - position = 11, - closedByDefault = true - ) - String SECTION_OPTIONS = "sectionOptions"; - - @ConfigItem( - keyName = "pheasantHighlightMode", - name = "Pheasant Highlight Mode", - description = "Configures how to highlight the pheasant(s) for the Freaky Forester random event.", - section = SECTION_OPTIONS, - position = 0 - ) - default PheasantMode pheasantHighlightMode() - { - return PheasantMode.SPECIFIC; - } } diff --git a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java index f21fb02..f9e56e5 100644 --- a/src/main/java/randomeventhelper/RandomEventHelperPlugin.java +++ b/src/main/java/randomeventhelper/RandomEventHelperPlugin.java @@ -34,6 +34,7 @@ import randomeventhelper.randomevents.drilldemon.DrillDemonHelper; import randomeventhelper.randomevents.freakyforester.FreakyForesterHelper; import randomeventhelper.randomevents.gravedigger.GravediggerHelper; +import randomeventhelper.randomevents.gravedigger.GravediggerOverlay; import randomeventhelper.randomevents.maze.MazeHelper; import randomeventhelper.randomevents.mime.MimeHelper; import randomeventhelper.randomevents.pinball.PinballHelper; @@ -87,6 +88,9 @@ public class RandomEventHelperPlugin extends Plugin @Inject private GravediggerHelper gravediggerHelper; + @Inject + private GravediggerOverlay gravediggerOverlay; + @Inject private MimeHelper mimeHelper; @@ -129,7 +133,7 @@ protected void startUp() throws Exception } if (config.isGravediggerEnabled()) { - gravediggerHelper.startUp(); + gravediggerHelper.startUp(gravediggerOverlay); } if (config.isMimeEnabled()) { @@ -236,7 +240,7 @@ else if (configChanged.getKey().equals("isGravediggerEnabled")) { if (config.isGravediggerEnabled()) { - gravediggerHelper.startUp(); + gravediggerHelper.startUp(gravediggerOverlay); } else { diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/Coffin.java b/src/main/java/randomeventhelper/randomevents/gravedigger/Coffin.java index bef3474..26435bb 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/Coffin.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/Coffin.java @@ -8,23 +8,26 @@ import lombok.AllArgsConstructor; import lombok.Getter; import net.runelite.api.gameval.ItemID; +import net.runelite.api.gameval.SpriteID; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; @Getter @AllArgsConstructor public enum Coffin { - CRAFTING(0, ItemID.MACRO_DIGGER_COFFIN_OBJECT_1, ItemID.POT_EMPTY, new Color(88, 58, 12)), - MINING(1, ItemID.MACRO_DIGGER_COFFIN_OBJECT_2, ItemID.BRONZE_PICKAXE, Color.LIGHT_GRAY), - COOKING(2, ItemID.MACRO_DIGGER_COFFIN_OBJECT_3, ItemID.CHEFS_HAT, Color.ORANGE), - FARMING(3, ItemID.MACRO_DIGGER_COFFIN_OBJECT_4, ItemID.DIBBER, Color.BLUE), - WOODCUTTING(4, ItemID.MACRO_DIGGER_COFFIN_OBJECT_5, ItemID.BRONZE_AXE, Color.GREEN), - EMPTY(5, -1, -1, Color.BLACK); // No item ID for empty coffin + CRAFTING(0, ItemID.MACRO_DIGGER_COFFIN_OBJECT_1, ItemID.POT_EMPTY, SpriteID.Staticons.CRAFTING, new Color(88, 58, 12)), + MINING(1, ItemID.MACRO_DIGGER_COFFIN_OBJECT_2, ItemID.BRONZE_PICKAXE, SpriteID.Staticons.MINING, Color.LIGHT_GRAY), + COOKING(2, ItemID.MACRO_DIGGER_COFFIN_OBJECT_3, ItemID.CHEFS_HAT, SpriteID.Staticons.COOKING, Color.ORANGE), + FARMING(3, ItemID.MACRO_DIGGER_COFFIN_OBJECT_4, ItemID.DIBBER, SpriteID.Staticons2.FARMING, Color.BLUE), + WOODCUTTING(4, ItemID.MACRO_DIGGER_COFFIN_OBJECT_5, ItemID.BRONZE_AXE, SpriteID.Staticons.WOODCUTTING, Color.GREEN), + EMPTY(5, -1, -1, -1, Color.BLACK); // No item ID for empty coffin private final int varbitValue; // Value for both MACRO_DIGGER_GRAVE and MACRO_DIGGER_COFFIN - private final int itemID; // Item ID of the coffin item - private final int associatedItemID; // An item ID associated with the coffin - private final Color color; + private final int itemID; // Item ID of the coffin item itself + private final int associatedItemID; // An item ID associated with the coffin's contents + private final int associatedSkillSpriteID; // Skill sprite ID associated with the coffin's contents + private final Color color; // A color associated with the coffin and the skill it represents based on its contents private static final Map VARBIT_COFFIN_MAP; private static final Map ITEMID_COFFIN_MAP; @@ -54,4 +57,13 @@ public BufferedImage getItemImage(ItemManager itemManager) } return itemManager.getImage(this.associatedItemID); } + + public BufferedImage getSkillIconImage(SpriteManager spriteManager) + { + if (this.associatedSkillSpriteID == -1) + { + return null; + } + return spriteManager.getSprite(this.associatedSkillSpriteID, 0); + } } diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java index cc1ba71..2aa2d4a 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerHelper.java @@ -19,6 +19,7 @@ import net.runelite.api.GameObject; import net.runelite.api.Item; import net.runelite.api.NPC; +import net.runelite.api.Tile; import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameTick; import net.runelite.api.events.ItemContainerChanged; @@ -32,6 +33,7 @@ import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.overlay.OverlayManager; import randomeventhelper.RandomEventHelperPlugin; @@ -49,9 +51,11 @@ public class GravediggerHelper private ItemManager itemManager; @Inject - private OverlayManager overlayManager; + private SpriteManager spriteManager; @Inject + private OverlayManager overlayManager; + private GravediggerOverlay gravediggerOverlay; @Inject @@ -66,21 +70,25 @@ public class GravediggerHelper @Getter private Map coffinItemImageMap; + @Getter + private Map coffinSkillImageMap; + private Multiset previousInventory; private Multiset currentInventoryItems; @Getter private Set coffinsInInventory; - - public void startUp() + public void startUp(GravediggerOverlay gravediggerOverlay) { + this.gravediggerOverlay = gravediggerOverlay; this.eventBus.register(this); - this.overlayManager.add(gravediggerOverlay); + this.overlayManager.add(this.gravediggerOverlay); this.overlayManager.add(gravediggerItemOverlay); - this.initiallyEnteredGraveDiggerArea = false; + this.initiallyEnteredGraveDiggerArea = true; this.graveMap = Maps.newHashMapWithExpectedSize(5); this.coffinItemImageMap = Maps.newHashMapWithExpectedSize(5); + this.coffinSkillImageMap = Maps.newHashMapWithExpectedSize(5); this.previousInventory = HashMultiset.create(); this.currentInventoryItems = HashMultiset.create(); this.coffinsInInventory = Sets.newHashSetWithExpectedSize(5); @@ -89,11 +97,16 @@ public void startUp() public void shutDown() { this.eventBus.unregister(this); - this.overlayManager.remove(gravediggerOverlay); + if (this.gravediggerOverlay != null) + { + this.overlayManager.remove(gravediggerOverlay); + this.gravediggerOverlay = null; + } this.overlayManager.remove(gravediggerItemOverlay); - this.initiallyEnteredGraveDiggerArea = false; + this.initiallyEnteredGraveDiggerArea = true; this.graveMap = null; this.coffinItemImageMap = null; + this.coffinSkillImageMap = null; this.previousInventory = null; this.currentInventoryItems = null; this.coffinsInInventory = null; @@ -107,6 +120,39 @@ public void onGameTick(GameTick gameTick) // And by using a separate variable to make sure not to run this constantly every game tick if (this.initiallyEnteredGraveDiggerArea) { + if (this.currentInventoryItems.isEmpty()) + { + ItemContainerChanged itemContainerChangedEvent = new ItemContainerChanged(InventoryID.INV, this.client.getItemContainer(InventoryID.INV)); + this.onItemContainerChanged(itemContainerChangedEvent); + } + + if (this.graveMap.isEmpty()) + { + Tile[][][] sceneTiles = this.client.getTopLevelWorldView().getScene().getTiles(); // [Plane][x][y] + Tile[][] tilesInZ = sceneTiles[this.client.getTopLevelWorldView().getPlane()]; // Tiles at [z] + + for (Tile[] tilesInZX : tilesInZ) // Tiles at [z][x] + { + for (Tile tile : tilesInZX) // Tiles at [z][x][y] + { + if (tile != null && tile.getGameObjects() != null) + { + for (GameObject gameObject : tile.getGameObjects()) + { + // There seemed to be some case where the game object was null + if (gameObject == null) + { + continue; + } + GameObjectSpawned gameObjectSpawnedEvent = new GameObjectSpawned(); + gameObjectSpawnedEvent.setGameObject(gameObject); + this.onGameObjectSpawned(gameObjectSpawnedEvent); + } + } + } + } + } + for (GraveNumber graveNumber : GraveNumber.values()) { VarbitChanged graveTypeVarbitChangedEvent = new VarbitChanged(); @@ -117,8 +163,25 @@ public void onGameTick(GameTick gameTick) placedCoffinVarbitChangedEvent.setValue(this.client.getVarbitValue(graveNumber.getPlacedCoffinVarbitID())); this.onVarbitChanged(graveTypeVarbitChangedEvent); this.onVarbitChanged(placedCoffinVarbitChangedEvent); - this.initiallyEnteredGraveDiggerArea = false; } + + if (this.coffinItemImageMap.isEmpty()) + { + for (Coffin coffin : Coffin.values()) + { + this.coffinItemImageMap.put(coffin, coffin.getItemImage(this.itemManager)); + } + } + + if (this.coffinSkillImageMap.isEmpty()) + { + for (Coffin coffin : Coffin.values()) + { + this.coffinSkillImageMap.put(coffin, coffin.getSkillIconImage(this.spriteManager)); + } + } + + this.initiallyEnteredGraveDiggerArea = false; } } @@ -243,11 +306,6 @@ public void onNpcSpawned(NpcSpawned npcSpawned) { log.debug("Grave Digger Leo NPC spawned in grave digger random event area."); this.initiallyEnteredGraveDiggerArea = true; - // Take this opportunity to initialize the BufferedImage for the coffin items - for (Coffin coffin : Coffin.values()) - { - coffinItemImageMap.put(coffin, coffin.getItemImage(this.itemManager)); - } } } } diff --git a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java index afd5abd..303a4ad 100644 --- a/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java +++ b/src/main/java/randomeventhelper/randomevents/gravedigger/GravediggerOverlay.java @@ -20,23 +20,26 @@ import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayUtil; +import randomeventhelper.RandomEventHelperConfig; @Slf4j @Singleton public class GravediggerOverlay extends Overlay { private final Client client; + private final RandomEventHelperConfig config; + private final GravediggerHelper gravediggerHelper; private final SpriteManager spriteManager; - private final GravediggerHelper plugin; private BufferedImage checkBufferedImage; private BufferedImage crossBufferedImage; @Inject - public GravediggerOverlay(Client client, GravediggerHelper plugin, SpriteManager spriteManager) + public GravediggerOverlay(Client client, RandomEventHelperConfig config, GravediggerHelper gravediggerHelper, SpriteManager spriteManager) { this.client = client; + this.config = config; this.spriteManager = spriteManager; - this.plugin = plugin; + this.gravediggerHelper = gravediggerHelper; setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_SCENE); } @@ -44,7 +47,7 @@ public GravediggerOverlay(Client client, GravediggerHelper plugin, SpriteManager @Override public Dimension render(Graphics2D graphics2D) { - if (plugin.getGraveMap() != null && !plugin.getGraveMap().isEmpty()) + if (this.gravediggerHelper.getGraveMap() != null && !this.gravediggerHelper.getGraveMap().isEmpty()) { if (checkBufferedImage == null) { @@ -54,13 +57,13 @@ public Dimension render(Graphics2D graphics2D) { this.crossBufferedImage = this.spriteManager.getSprite(SpriteID.OptionsRadioButtons.CROSS_RED, 0); } - for (Map.Entry graveEntry : plugin.getGraveMap().entrySet()) + for (Map.Entry graveEntry : this.gravediggerHelper.getGraveMap().entrySet()) { GraveNumber graveNumber = graveEntry.getKey(); Grave grave = graveEntry.getValue(); if (grave != null) { - BufferedImage coffinImage = plugin.getCoffinItemImageMap().get(grave.getRequiredCoffin()); + BufferedImage coffinImage = this.config.gravediggerUseSkillIcons() ? this.gravediggerHelper.getCoffinSkillImageMap().get(grave.getRequiredCoffin()) : this.gravediggerHelper.getCoffinItemImageMap().get(grave.getRequiredCoffin()); Coffin requiredCoffin = grave.getRequiredCoffin(); Coffin placedCoffin = grave.getPlacedCoffin(); if (requiredCoffin == null || placedCoffin == null) @@ -75,52 +78,18 @@ public Dimension render(Graphics2D graphics2D) { continue; } - if (grave.getGraveStone() != null) - { - Point location = grave.getGraveStone().getCanvasLocation(); - LocalPoint localPoint = grave.getGraveStone().getLocalLocation(); - if (location != null) - { - OverlayUtil.renderImageLocation(client, graphics2D, localPoint, coffinImage, 50); - } - // Also outline the gravestone - Shape graveStoneHull = grave.getGraveStone().getConvexHull(); - if (graveStoneHull != null) - { - OverlayUtil.renderPolygon(graphics2D, graveStoneHull, requiredCoffinColor); - } - } + + renderGravestoneIcon(graphics2D, grave, coffinImage, requiredCoffinColor); + renderHighlightGravestone(graphics2D, grave, coffinImage, requiredCoffinColor); + // If the grave is empty, then highlight it according to if (placedCoffin == Coffin.EMPTY) { - Shape emptyGraveHull = grave.getEmptyGrave().getConvexHull(); - if (emptyGraveHull != null) - { - OverlayUtil.renderPolygon(graphics2D, emptyGraveHull, requiredCoffinColor, requiredCoffinTransparentColor, new BasicStroke(2)); - } + renderHighlightEmptyGrave(graphics2D, grave, requiredCoffinColor, requiredCoffinTransparentColor, 2); } else { - Shape filledGraveHull = grave.getFilledGrave().getConvexHull(); - if (filledGraveHull != null) - { - OverlayUtil.renderPolygon(graphics2D, filledGraveHull, placedCoffinColor, placedCoffinTransparentColor, new BasicStroke(2)); - Point centeredSpritePoint = Perspective.getCanvasImageLocation(client, grave.getFilledGrave().getLocalLocation(), checkBufferedImage, 0); - if (placedCoffin != requiredCoffin) - { - if (centeredSpritePoint != null) - { - OverlayUtil.renderImageLocation(graphics2D, centeredSpritePoint, crossBufferedImage); - } - } - else - { - if (centeredSpritePoint != null) - { - OverlayUtil.renderImageLocation(graphics2D, centeredSpritePoint, checkBufferedImage); - } - } - } + renderHighlightFilledGrave(graphics2D, grave, placedCoffinColor, placedCoffinTransparentColor, placedCoffin, requiredCoffin, 2); } } } @@ -128,6 +97,67 @@ public Dimension render(Graphics2D graphics2D) return null; } + private void renderGravestoneIcon(Graphics2D graphics2D, Grave grave, BufferedImage coffinImage, Color requiredCoffinColor) + { + if (grave.getGraveStone() != null) + { + Point location = grave.getGraveStone().getCanvasLocation(); + LocalPoint localPoint = grave.getGraveStone().getLocalLocation(); + if (location != null) + { + OverlayUtil.renderImageLocation(client, graphics2D, localPoint, coffinImage, 50); + } + } + } + + private void renderHighlightGravestone(Graphics2D graphics2D, Grave grave, BufferedImage coffinImage, Color requiredCoffinColor) + { + if (grave.getGraveStone() != null) + { + Shape graveStoneHull = grave.getGraveStone().getConvexHull(); + if (graveStoneHull != null) + { + OverlayUtil.renderPolygon(graphics2D, graveStoneHull, requiredCoffinColor); + } + } + } + + private void renderHighlightEmptyGrave(Graphics2D graphics2D, Grave grave, Color requiredCoffinColor, Color requiredCoffinTransparentColor, int strokeWidth) + { + if (grave.getEmptyGrave() != null) + { + Shape emptyGraveHull = grave.getEmptyGrave().getConvexHull(); + if (emptyGraveHull != null) + { + OverlayUtil.renderPolygon(graphics2D, emptyGraveHull, requiredCoffinColor, requiredCoffinTransparentColor, new BasicStroke(strokeWidth)); + } + } + } + + private void renderHighlightFilledGrave(Graphics2D graphics2D, Grave grave, Color placedCoffinColor, Color placedCoffinTransparentColor, Coffin placedCoffin, Coffin requiredCoffin, int strokeWidth) + { + if (grave.getFilledGrave() != null) + { + Shape filledGraveHull = grave.getFilledGrave().getConvexHull(); + if (filledGraveHull != null) + { + OverlayUtil.renderPolygon(graphics2D, filledGraveHull, placedCoffinColor, placedCoffinTransparentColor, new BasicStroke(strokeWidth)); + Point centeredSpritePoint = Perspective.getCanvasImageLocation(client, grave.getFilledGrave().getLocalLocation(), checkBufferedImage, 0); + if (centeredSpritePoint != null) + { + if (placedCoffin != requiredCoffin) + { + OverlayUtil.renderImageLocation(graphics2D, centeredSpritePoint, crossBufferedImage); + } + else + { + OverlayUtil.renderImageLocation(graphics2D, centeredSpritePoint, checkBufferedImage); + } + } + } + } + } + private Color getTransparentColor(Color color, int alpha) { return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);