diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt index 24f1feb..e857ef1 100644 --- a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt +++ b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.kt @@ -1,12 +1,34 @@ -package XPDropPlugin; - +package XPDropPlugin + +import KondoKit.Exposed import plugin.Plugin -import plugin.annotations.PluginMeta -import plugin.api.* +import plugin.api.API +import plugin.api.API.* +import plugin.api.FontColor.fromColor +import plugin.api.FontType +import plugin.api.TextModifier +import plugin.api.WindowMode +import rt4.Sprite +import rt4.client import java.awt.Color +import java.awt.image.BufferedImage +import java.io.InputStream +import javax.imageio.ImageIO import kotlin.math.ceil + class plugin : Plugin() { + + enum class Theme { + DEFAULT, RUNELITE + } + + @Exposed + private var theme = Theme.DEFAULT + + @Exposed + private var alwaysShow = false + private val displayTimeout = 10000L // 10 seconds private val drawStart = 175 private val drawPadding = 25 @@ -15,41 +37,50 @@ class plugin : Plugin() { private var totalXp = 0 private val activeGains = ArrayList() private var lastGain = 0L + private val IN_GAME = 30 + + private val spriteCache = HashMap() + + override fun Init() { + val themeIndex = (GetData("xp-drop-theme") as? String) ?: "DEFAULT" + theme = Theme.valueOf(themeIndex) + alwaysShow = (GetData("xp-drop-alwaysShow") as? Boolean) ?: false + } override fun Draw(deltaTime: Long) { - if (System.currentTimeMillis() - lastGain >= displayTimeout && activeGains.isEmpty()) - return + if (shouldSkipDrawing()) return drawTotalXPBox() - val removeList = ArrayList() - var posX = API.GetWindowDimensions().width / 2 - if (API.GetWindowMode() == WindowMode.FIXED) - posX += 60 + val movementSpeedFactor = deltaTime / 16.666 // 60 FPS - for(gain in activeGains) { - gain.currentPos -= ceil(deltaTime / 20.0).toInt() + for (gain in activeGains) { + gain.currentPos -= ceil(movementSpeedFactor).toInt() // Adjust movement based on deltaTime if (gain.currentPos <= drawClear) { removeList.add(gain) totalXp += gain.xp - } else if (gain.currentPos <= drawStart){ - val sprite = XPSprites.getSpriteForSkill(skillId = gain.skill) - sprite?.render(posX - 25, gain.currentPos - 20) - API.DrawText( - FontType.SMALL, - FontColor.fromColor(Color.WHITE), - TextModifier.LEFT, - addCommas(gain.xp.toString()), - posX, - gain.currentPos - ) + } else if (gain.currentPos <= drawStart) { + drawXPDrops(gain) } } activeGains.removeAll(removeList.toSet()) } + private fun shouldSkipDrawing(): Boolean { + return client.gameState < IN_GAME || (!alwaysShow && isDisplayTimeoutExpired() && activeGains.isEmpty()) + } + + fun OnKondoValueUpdated() { + StoreData("xp-drop-theme",theme.toString()) + StoreData("xp-drop-alwaysShow",alwaysShow) + } + + private fun isDisplayTimeoutExpired(): Boolean { + return System.currentTimeMillis() - lastGain >= displayTimeout + } + override fun OnXPUpdate(skill: Int, xp: Int) { if (xp == lastXp[skill]) return @@ -81,6 +112,54 @@ class plugin : Plugin() { } private fun drawTotalXPBox() { + when (theme) { + Theme.DEFAULT -> drawDefaultXPBox() + Theme.RUNELITE -> drawRuneliteXPBox() + } + } + + private fun drawXPDrops(gain : XPGain) { + when (theme) { + Theme.DEFAULT -> drawDefaultXPDrop(gain) + Theme.RUNELITE -> drawRuneliteXPDrops(gain) + } + } + + private fun drawDefaultXPDrop(gain: XPGain) { + var posX = API.GetWindowDimensions().width / 2 + if (API.GetWindowMode() == WindowMode.FIXED) + posX += 60 + val sprite = spriteCache.getOrPut(gain.skill) { XPSprites.getSpriteForSkill(skillId = gain.skill) } + sprite?.render(posX - 25, gain.currentPos - 20) + DrawText( + FontType.SMALL, + fromColor(Color.WHITE), + TextModifier.LEFT, + addCommas(gain.xp.toString()), + posX, + gain.currentPos + ) + } + + private fun drawRuneliteXPDrops(gain: XPGain) { + val w = API.GetWindowDimensions().width + val offset = if(API.GetWindowMode() == WindowMode.FIXED) 251 else 225 + val extra = 2; + val posX = w - (offset + extra) + + val str = addCommas(gain.xp.toString()) + val fontCharWidth = 4 + val displace = str.length*fontCharWidth + 30 + + // should be scaled https://github.com/runelite/runelite/blob/0500906f8de9cd20875c168a7a59e5e066ed5058/runelite-client/src/main/java/net/runelite/client/game/SkillIconManager.java#L50 + // but for now this is good enough + + val sprite = spriteCache.getOrPut(gain.skill) { XPSprites.getSpriteForSkill(skillId = gain.skill) } + sprite?.render(posX - displace, gain.currentPos - 20) + drawTextWithDropShadow(posX, gain.currentPos, Color.WHITE, addCommas(gain.xp.toString())) + } + + private fun drawDefaultXPBox() { var posX = API.GetWindowDimensions().width / 2 val posY = API.GetWindowDimensions().height / 4 @@ -89,13 +168,13 @@ class plugin : Plugin() { API.ClipRect(0, 0, posX * 2, posY * 4) - val horizontal = API.GetSprite(822) - val horizontalTop = API.GetSprite(820) - val tlCorner = API.GetSprite(824) - val blCorner = API.GetSprite(826) - val trCorner = API.GetSprite(825) - val brCorner = API.GetSprite(827) - val bg = API.GetSprite(657) + val horizontal = spriteCache.getOrPut(822) { API.GetSprite(822) } + val horizontalTop = spriteCache.getOrPut(820) { API.GetSprite(820) } + val tlCorner = spriteCache.getOrPut(824) { API.GetSprite(824) } + val blCorner = spriteCache.getOrPut(826) { API.GetSprite(826) } + val trCorner = spriteCache.getOrPut(825) { API.GetSprite(825) } + val brCorner = spriteCache.getOrPut(827) { API.GetSprite(827) } + val bg = spriteCache.getOrPut(657) { API.GetSprite(657) } bg?.render(posX - 77, 10) API.FillRect(posX - 75, 5, 140, 30, 0, 64) @@ -112,26 +191,58 @@ class plugin : Plugin() { horizontalTop?.render(posX + 9, -8) horizontal?.render(posX + 9, 22) - API.DrawText( - FontType.SMALL, - FontColor.fromColor(Color.WHITE), - TextModifier.LEFT, - "Total Xp: ${addCommas(totalXp.toString())}", - posX - 65, - 28 + DrawText( + FontType.SMALL, + fromColor(Color.WHITE), + TextModifier.LEFT, + "Total Xp: ${addCommas(totalXp.toString())}", + posX - 65, + 28 ) } + private fun drawRuneliteXPBox() { + val boxHeight = 29 + val boxWidth = 119 + val posX = API.GetWindowDimensions().width + + val innerBorderColor = Color(90, 82, 69).rgb + val outerBorderColor = Color(56,48,35).rgb + + val offset = if(API.GetWindowMode() == WindowMode.FIXED) 251 else 225 + val boxStart = posX - (offset + boxWidth) + val yOffset = if(API.GetWindowMode() == WindowMode.FIXED) 4 else 0 + + val lvlIcon = 898; + val sprite = spriteCache.getOrPut(lvlIcon){ + val imageStream: InputStream = plugin::class.java.getResourceAsStream("res/rl-lvls.png") + imageStream.use { imageStream -> + val image: BufferedImage = ImageIO.read(imageStream) + API.GetSpriteFromPNG(image) + } + } + + // Draw a simple rectangle instead of the default box design + API.FillRect(boxStart, yOffset, boxWidth, boxHeight, innerBorderColor, 150) + drawTextWithDropShadow(boxStart+boxWidth-4, 18+yOffset, Color.WHITE, addCommas(totalXp.toString())) + + // Inner Border + API.DrawRect(boxStart+1, 1+yOffset, boxWidth-2, boxHeight-2, innerBorderColor) + // redraw around the border + API.DrawRect(boxStart, yOffset, boxWidth, boxHeight, outerBorderColor) + sprite?.render(boxStart + 3, 3+yOffset) + } + data class XPGain(val skill: Int, val xp: Int, var currentPos: Int) - fun addCommas(num: String): String{ + fun addCommas(num: String): String { var newString = "" - if(num.length > 9){ + if (num.length > 9) { return "Lots!" } var counter = 1 num.reversed().forEach { - if(counter % 3 == 0 && counter != num.length){ + if (counter % 3 == 0 && counter != num.length) { newString += "$it," } else { newString += it @@ -140,4 +251,10 @@ class plugin : Plugin() { } return newString.reversed() } + + private fun drawTextWithDropShadow(x: Int, y: Int, color: Color, text: String, mod : TextModifier = TextModifier.RIGHT) { + DrawText(FontType.SMALL, fromColor(Color(0)), mod, text, x + 1, y + 1) + DrawText(FontType.SMALL, fromColor(color), mod, text, x, y) + } } + diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties index 35027ea..53b820f 100644 --- a/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties +++ b/plugin-playground/src/main/kotlin/XPDropPlugin/plugin.properties @@ -1,3 +1,3 @@ AUTHOR='Ceikry' DESCRIPTION='Draws nice and clean experience drops onto the screen.' -VERSION=1.2 +VERSION=1.3 diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/res/rl-lvls.png b/plugin-playground/src/main/kotlin/XPDropPlugin/res/rl-lvls.png new file mode 100644 index 0000000..c840a49 Binary files /dev/null and b/plugin-playground/src/main/kotlin/XPDropPlugin/res/rl-lvls.png differ diff --git a/plugin-playground/src/main/kotlin/XPDropPlugin/res/xpIco.png b/plugin-playground/src/main/kotlin/XPDropPlugin/res/xpIco.png new file mode 100644 index 0000000..c68a872 Binary files /dev/null and b/plugin-playground/src/main/kotlin/XPDropPlugin/res/xpIco.png differ