diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index b9cb1faf4a..17dd82f7bc 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1602,4 +1602,6 @@ public interface Client extends GameEngine EnumComposition getEnum(int id); void draw2010Menu(); + + NodeCache getHealthBarCache(); } diff --git a/runelite-api/src/main/java/net/runelite/api/HealthBar.java b/runelite-api/src/main/java/net/runelite/api/HealthBar.java new file mode 100644 index 0000000000..2ffeedca28 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/HealthBar.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +public interface HealthBar +{ + SpritePixels getHealthBarFrontSprite(); + + SpritePixels getHealthBarBackSprite(); + + void setPadding(int padding); +} diff --git a/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java b/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java new file mode 100644 index 0000000000..01085f05bb --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/events/PostHealthBar.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.events; + +import lombok.Data; +import net.runelite.api.HealthBar; + +@Data +public class PostHealthBar +{ + private HealthBar healthBar; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/InterfaceStylesPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/InterfaceStylesPlugin.java index 3be1e31cee..d39203863a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/InterfaceStylesPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/interfacestyles/InterfaceStylesPlugin.java @@ -31,11 +31,14 @@ import java.awt.image.BufferedImage; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.HealthBar; import net.runelite.api.HealthBarOverride; +import net.runelite.api.NodeCache; import net.runelite.api.SpriteID; import net.runelite.api.SpritePixels; import net.runelite.api.events.BeforeMenuRender; import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.PostHealthBar; import net.runelite.api.events.WidgetPositioned; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; @@ -68,6 +71,8 @@ public class InterfaceStylesPlugin extends Plugin @Inject private SpriteManager spriteManager; + private HealthBarOverride healthBarOverride; + @Provides InterfaceStylesConfig provideConfig(ConfigManager configManager) { @@ -87,6 +92,7 @@ public class InterfaceStylesPlugin extends Plugin { restoreWidgetDimensions(); removeGameframe(); + healthBarOverride = null; client.setHealthBarOverride(null); }); } @@ -106,6 +112,25 @@ public class InterfaceStylesPlugin extends Plugin adjustWidgetDimensions(); } + @Subscribe + public void onPostHealthBar(PostHealthBar postHealthBar) + { + if (healthBarOverride == null || !config.hdHealthBars()) + { + return; + } + + HealthBar healthBar = postHealthBar.getHealthBar(); + SpritePixels frontSprite = healthBar.getHealthBarFrontSprite(); + + // Check if this is the health bar we are replacing + if (frontSprite == healthBarOverride.getFrontSprite() || frontSprite == healthBarOverride.getFrontSpriteLarge()) + { + // Increase padding to show some more green at very low hp percentages + healthBar.setPadding(1); + } + } + private void updateAllOverrides() { removeGameframe(); @@ -245,6 +270,10 @@ public class InterfaceStylesPlugin extends Plugin private void overrideHealthBars() { + // Reset health bar cache to reset applied padding + NodeCache healthBarCache = client.getHealthBarCache(); + healthBarCache.reset(); + if (config.hdHealthBars()) { String fileBase = Skin.AROUND_2010.toString() + "/healthbar/"; @@ -256,10 +285,12 @@ public class InterfaceStylesPlugin extends Plugin SpritePixels backSpriteLarge = getFileSpritePixels(fileBase + "back_large.png"); HealthBarOverride override = new HealthBarOverride(frontSprite, backSprite, frontSpriteLarge, backSpriteLarge); + healthBarOverride = override; client.setHealthBarOverride(override); } else { + healthBarOverride = null; client.setHealthBarOverride(null); } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSHealthBarMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSHealthBarMixin.java index 2a25c1a2a1..4e35a52c49 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSHealthBarMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSHealthBarMixin.java @@ -25,10 +25,15 @@ package net.runelite.mixins; import net.runelite.api.HealthBarOverride; +import net.runelite.api.events.PostHealthBar; import net.runelite.api.mixins.Copy; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.MethodHook; import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSBuffer; +import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSHealthBar; import net.runelite.rs.api.RSSpritePixels; @@ -38,6 +43,9 @@ public abstract class RSHealthBarMixin implements RSHealthBar // Larger values are used for bosses like Corporeal Beast private static final int DEFAULT_HEALTH_SCALE = 30; + @Shadow("clientInstance") + private static RSClient client; + @Shadow("healthBarOverride") private static HealthBarOverride healthBarOverride; @@ -93,4 +101,13 @@ public abstract class RSHealthBarMixin implements RSHealthBar ? (RSSpritePixels) healthBarOverride.frontSprite : (RSSpritePixels) healthBarOverride.frontSpriteLarge; } + + @MethodHook(value = "read", end = true) + @Inject + public void onRead(RSBuffer buffer) + { + PostHealthBar postHealthBar = new PostHealthBar(); + postHealthBar.setHealthBar(this); + client.getCallbacks().post(postHealthBar); + } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index b51376bb1a..77836e550f 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -965,4 +965,8 @@ public interface RSClient extends RSGameEngine, Client @Import("drawCircle") void RasterizerDrawCircle(int x, int y, int r, int rgb); + + @Import("healthbarCache") + @Override + RSNodeCache getHealthBarCache(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSHealthBar.java b/runescape-api/src/main/java/net/runelite/rs/api/RSHealthBar.java index 66997d990d..758bf8cb83 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSHealthBar.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSHealthBar.java @@ -24,10 +24,23 @@ */ package net.runelite.rs.api; +import net.runelite.api.HealthBar; import net.runelite.mapping.Import; -public interface RSHealthBar +public interface RSHealthBar extends RSCacheableNode, HealthBar { @Import("healthScale") int getHealthScale(); + + @Import("getHealthBarFrontSprite") + @Override + RSSpritePixels getHealthBarFrontSprite(); + + @Import("getHealthBarBackSprite") + @Override + RSSpritePixels getHealthBarBackSprite(); + + @Import("healthBarPadding") + @Override + void setPadding(int padding); }