From 710f45e3dd92357b059079aae418778b346520c3 Mon Sep 17 00:00:00 2001 From: ThatGamerBlue Date: Sun, 2 Feb 2020 15:28:42 +0000 Subject: [PATCH] lol i fucked that other pr up royally --- .../net/runelite/api/geometry/Cuboid.java | 33 +++ .../freezetimersv2/FreezeTimersV2Config.java | 158 ++++++++++++ .../freezetimersv2/FreezeTimersV2Overlay.java | 182 ++++++++++++++ .../freezetimersv2/FreezeTimersV2Plugin.java | 226 ++++++++++++++++++ .../plugins/freezetimersv2/HeadIcons.java | 12 + .../freezetimersv2/PlayerSpellEffect.java | 67 ++++++ .../plugins/freezetimersv2/PrayerTracker.java | 85 +++++++ .../plugins/freezetimersv2/TimeMode.java | 45 ++++ .../client/plugins/freezetimersv2/Timer.java | 152 ++++++++++++ .../plugins/freezetimersv2/TimerManager.java | 84 +++++++ .../plugins/freezetimersv2/TimerType.java | 57 +++++ .../plugins/multiindicators/MapLocations.java | 39 ++- .../net/runelite/client/util/PvPUtil.java | 44 +++- .../client/plugins/freezetimersv2/freeze.png | Bin 0 -> 195 bytes .../plugins/freezetimersv2/freezeimmune.png | Bin 0 -> 492 bytes .../plugins/freezetimersv2/teleblock.png | Bin 0 -> 216 bytes .../freezetimersv2/teleblockimmune.png | Bin 0 -> 468 bytes .../client/plugins/freezetimersv2/veng.png | Bin 0 -> 251 bytes .../FreezeTimersV2OverlayTest.java | 56 +++++ 19 files changed, 1224 insertions(+), 16 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/geometry/Cuboid.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Config.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Overlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Plugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/HeadIcons.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PlayerSpellEffect.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PrayerTracker.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimeMode.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/Timer.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerManager.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerType.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/freeze.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/freezeimmune.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/teleblock.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/teleblockimmune.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/veng.png create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2OverlayTest.java diff --git a/runelite-api/src/main/java/net/runelite/api/geometry/Cuboid.java b/runelite-api/src/main/java/net/runelite/api/geometry/Cuboid.java new file mode 100644 index 0000000000..ad2075ee20 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/geometry/Cuboid.java @@ -0,0 +1,33 @@ +package net.runelite.api.geometry; + +import net.runelite.api.coords.WorldPoint; + +public class Cuboid +{ + private WorldPoint southWest; + private WorldPoint northEast; + + public Cuboid(int x1, int y1, int z1, int x2, int y2, int z2) + { + this(new WorldPoint(x1, y1, z1), new WorldPoint(x2, y2, z2)); + } + + public Cuboid(WorldPoint southWest, WorldPoint northEast) + { + this.southWest = southWest; + this.northEast = northEast; + } + + public boolean contains(WorldPoint worldPoint) + { + if (worldPoint.getPlane() < southWest.getPlane() || worldPoint.getPlane() > northEast.getPlane()) + { + return false; + } + if (worldPoint.getY() < southWest.getY() || worldPoint.getY() > northEast.getY()) + { + return false; + } + return worldPoint.getX() >= southWest.getX() && worldPoint.getX() <= northEast.getX(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Config.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Config.java new file mode 100644 index 0000000000..52af8c0fc9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Config.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Keybind; +import java.awt.Color; + +@ConfigGroup("freezetimersv2") +public interface FreezeTimersV2Config extends Config +{ + @ConfigItem( + name = "Show NPCs", + keyName = "showNpcs", + description = "Should we show the overlay on NPCs?", + position = 1 + ) + default boolean showNpcs() + { + return false; + } + + @ConfigItem( + name = "Show Players", + keyName = "showPlayers", + description = "Should we show the overlay on players?", + position = 2 + ) + default boolean showPlayers() + { + return true; + } + + @ConfigItem( + name = "Time Mode", + keyName = "timeMode", + description = "How should we display the time?", + position = 3 + ) + default TimeMode timeMode() + { + return TimeMode.TICKS; + } + + @ConfigItem( + name = "Timer Color", + keyName = "timerColor", + description = "Color for timers not on cooldown", + position = 4 + ) + default Color timerColor() + { + return Color.CYAN; + } + + @ConfigItem( + name = "Cooldown Color", + keyName = "cooldownColor", + description = "Color for timers on cooldown", + position = 5 + ) + default Color cooldownColor() + { + return Color.ORANGE; + } + + @ConfigItem( + name = "Freeze Timers", + keyName = "freezeTimers", + description = "Should we render freeze timers?", + position = 6 + ) + default boolean freezeTimers() + { + return true; + } + + @ConfigItem( + name = "Teleblock Timers", + keyName = "teleblockTimers", + description = "Should we render teleblock timers?", + position = 7 + ) + default boolean teleblockTimers() + { + return true; + } + + @ConfigItem( + name = "Vengeance Timers", + keyName = "vengTimers", + description = "Should we render vengeance timers?", + position = 8 + ) + default boolean vengTimers() + { + return true; + } + + @ConfigItem( + name = "Show Icons", + keyName = "showIcons", + description = "Should we render the icons? Note disabling this will override all colors", + position = 9 + ) + default boolean showIcons() + { + return true; + } + + @ConfigItem( + name = "Debug Keybind", + keyName = "debugKeybind", + description = "Don't press this unless you know what it does :)", + position = 10, + hidden = true + ) + default Keybind debugKeybind() + { + return Keybind.NOT_SET; + } + + @ConfigItem( + name = "Debug Integer", + keyName = "debugInteger", + description = "Related to the keybind in some way :)", + position = 11, + hidden = true + ) + default int debugInteger() + { + return -1; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Overlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Overlay.java new file mode 100644 index 0000000000..673748a5a7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Overlay.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import com.google.common.annotations.VisibleForTesting; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.Point; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayUtil; +import javax.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; + +public class FreezeTimersV2Overlay extends Overlay +{ + @Inject + private TimerManager timerManager; + @Inject + private Client client; + @Inject + private FreezeTimersV2Config config; + @Inject + private ConfigManager configManager; + private final Font timerFont = FontManager.getRunescapeBoldFont().deriveFont(14.0f); + + @Inject + public FreezeTimersV2Overlay() + { + super(); + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.UNDER_WIDGETS); + } + + @Override + public Dimension render(Graphics2D g) + { + Font oldFont = g.getFont(); + Color oldColor = g.getColor(); + g.setFont(timerFont); + + if (config.showNpcs()) + { + client.getNpcs().forEach((a) -> renderActor(g, a)); + } + + if (config.showPlayers()) + { + client.getPlayers().forEach((a) -> renderActor(g, a)); + } + + g.setFont(oldFont); + g.setColor(oldColor); + + return null; + } + + private void renderActor(Graphics2D g, Actor actor) + { + int offset = 0; + for (TimerType timerType : TimerType.values()) + { + if (timerType.shouldRender(configManager)) + { + if (timerManager.isTimerValid(actor, timerType) && timerManager.hasTimerActive(actor, timerType)) + { + if (renderTimer(g, actor, timerType, offset)) + { + offset++; + } + } + } + } + } + + private boolean renderTimer(Graphics2D g, Actor actor, TimerType timerType, int offset) + { + String text; + Timer timer = timerManager.getTimerFor(actor, timerType); + switch (config.timeMode()) + { + case SECONDS: + long millisRemaining = timer.getMillisForRender(); + if (millisRemaining == -1) + { + return false; // this shouldnt happen but just in case + } + text = formatTime(millisRemaining); + break; + case TICKS: + int tfr = timer.getTicksForRender(); + if (tfr == -1) + { + return false; + } + text = Integer.toString(tfr); + break; + default: + return false; + } + + Point canvasLocation = actor.getCanvasTextLocation(g, text, 0); + + if (canvasLocation == null) + { + return false; + } + + int yOffset = (offset * (g.getFontMetrics().getHeight() + 2)); + Rectangle rect = actor.getConvexHull().getBounds(); + int xOffset = (int) rect.getWidth(); + + BufferedImage image = timer.getIcon(); + Point actorCIL = actor.getCanvasImageLocation(image, 0); + Point textLocation = new Point(actorCIL.getX() + xOffset, actorCIL.getY() + yOffset); + + if (config.showIcons()) + { + g.drawImage(image, textLocation.getX(), textLocation.getY(), null); + xOffset = image.getWidth() + 1; + yOffset = (image.getHeight() - g.getFontMetrics().getHeight()); + textLocation = new Point(textLocation.getX() + xOffset, textLocation.getY() + image.getHeight() - yOffset); + } + + OverlayUtil.renderTextLocation(g, textLocation, text, timer.determineColor()); + + return true; + } + + @VisibleForTesting + public String formatTime(long time) + { + if (time > 59999) + { + return ((int) time / 60000) + ":" + formatSeconds(((int) (time % 60000) / 1000)); + } + else if (time > 9999) + { + return ((int) time / 1000) + ""; + } + else if (time > 999) + { + return ((int) time / 1000) + "." + ((int) (time % 1000) / 100); + } + return "0." + ((int) time / 100); + } + + private String formatSeconds(int seconds) + { + return String.format("%02d", seconds); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Plugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Plugin.java new file mode 100644 index 0000000000..f1f93cbdd3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2Plugin.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import com.google.inject.Provides; +import lombok.Getter; +import net.runelite.api.Actor; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.WorldType; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.PlayerDeath; +import net.runelite.api.events.SpotAnimationChanged; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.input.KeyManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.plugins.multiindicators.MapLocations; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.util.HotkeyListener; +import net.runelite.client.util.PvPUtil; +import org.apache.commons.lang3.ArrayUtils; +import javax.inject.Inject; +import java.util.EnumSet; + +@PluginDescriptor( + name = "Freeze Timers v2", + description = "Freeze/teleblock/veng timer overlay on players", + tags = {"freeze", "timers", "barrage", "teleblock", "pklite"}, + type = PluginType.PVP, + enabledByDefault = false +) +public class FreezeTimersV2Plugin extends Plugin +{ + private static final int VORKATH_REGION = 9023; + @Inject + @Getter + private Client client; + @Inject + private OverlayManager overlayManager; + @Inject + private PrayerTracker prayerTracker; + @Inject + private TimerManager timerManager; + @Inject + private FreezeTimersV2Overlay overlay; + @Inject + private FreezeTimersV2Config config; + @Inject + private KeyManager keyManager; + private int fakeSpotAnim = -1; + private HotkeyListener hotkeyListener = new HotkeyListener(() -> config.debugKeybind()) + { + public void hotkeyPressed() + { + fakeSpotAnim = config.debugInteger(); + } + }; + + public FreezeTimersV2Config getConfig() + { + return config; + } + + @Provides + public FreezeTimersV2Config getConfig(ConfigManager configManager) + { + return configManager.getConfig(FreezeTimersV2Config.class); + } + + @Override + public void startUp() + { + overlayManager.add(overlay); + keyManager.registerKeyListener(hotkeyListener); + } + + @Override + public void shutDown() + { + keyManager.unregisterKeyListener(hotkeyListener); + overlayManager.remove(overlay); + } + + @Subscribe + public void onGameTick(GameTick gameTick) + { + prayerTracker.gameTick(); + + if (fakeSpotAnim != -1) + { + SpotAnimationChanged event = new SpotAnimationChanged(); + event.setActor(client.getLocalPlayer()); + onSpotAnimChanged(event); + } + + EnumSet worldTypes = client.getWorldType(); + + for (Actor actor : client.getPlayers()) + { + if (!timerManager.hasTimerActive(actor, TimerType.TELEBLOCK)) + { + continue; + } + + WorldPoint actorLoc = actor.getWorldLocation(); + + if (!WorldType.isAllPvpWorld(worldTypes) && PvPUtil.getWildernessLevelFrom(actorLoc) <= 0) + { + timerManager.setTimerFor(actor, TimerType.TELEBLOCK, new Timer(this, null)); + } + else if (WorldType.isPvpWorld(worldTypes) && + MapLocations.getPvpSafeZones(actorLoc.getPlane()).contains(actorLoc.getX(), actorLoc.getY())) + { + timerManager.setTimerFor(actor, TimerType.TELEBLOCK, new Timer(this, null)); + } + else if (WorldType.isDeadmanWorld(worldTypes) && + MapLocations.getDeadmanSafeZones(actorLoc.getPlane()).contains(actorLoc.getX(), actorLoc.getY())) + { + timerManager.setTimerFor(actor, TimerType.TELEBLOCK, new Timer(this, null)); + } + } + } + + @Subscribe + public void onSpotAnimChanged(SpotAnimationChanged event) + { + Actor actor = event.getActor(); + int spotAnim = fakeSpotAnim == -1 ? actor.getSpotAnimation() : fakeSpotAnim; + fakeSpotAnim = -1; + if (spotAnim == prayerTracker.getSpotanimLastTick(event.getActor())) + { + return; + } + + PlayerSpellEffect effect = PlayerSpellEffect.getFromSpotAnim(spotAnim); + + if (effect == null) + { + return; + } + + if (timerManager.hasTimerActive(actor, effect.getType())) + { + return; + } + + timerManager.setTimerFor(actor, effect.getType(), new Timer(this, effect, effect.isHalvable() && prayerTracker.getPrayerIconLastTick(actor) == HeadIcons.MAGIC)); + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (event.getType() != ChatMessageType.GAMEMESSAGE + || !event.getMessage().contains("Your Tele Block has been removed")) + { + return; + } + + timerManager.jumpToCooldown(client.getLocalPlayer(), TimerType.TELEBLOCK); + } + + private boolean isAtVorkath() + { + return ArrayUtils.contains(client.getMapRegions(), VORKATH_REGION); + } + + @Subscribe + public void onNpcDespawned(NpcDespawned event) + { + if (!isAtVorkath()) + { + return; + } + + final NPC npc = event.getNpc(); + + if (npc.getName() == null) + { + return; + } + + if (npc.getName().contains("Zombified Spawn")) + { + // TODO: not sure if we're meant to jump to cooldown here or just remove the timer completely, doesn't mechanically make a difference though + timerManager.setTimerFor(client.getLocalPlayer(), TimerType.FREEZE, new Timer(this, null)); // empty timer + } + } + + @Subscribe + public void onPlayerDeath(PlayerDeath event) + { + for (TimerType type : TimerType.values()) + { + timerManager.setTimerFor(event.getPlayer(), type, new Timer(this, null)); + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/HeadIcons.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/HeadIcons.java new file mode 100644 index 0000000000..70316361c2 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/HeadIcons.java @@ -0,0 +1,12 @@ +package net.runelite.client.plugins.freezetimersv2; + +public class HeadIcons +{ + public static final int MELEE = 0; + public static final int RANGED = 1; + public static final int MAGIC = 2; + public static final int RETRIBUTION = 3; + public static final int SMITE = 4; + public static final int REDEMPTION = 5; + public static final int RANGE_MAGE = 6; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PlayerSpellEffect.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PlayerSpellEffect.java new file mode 100644 index 0000000000..1fc29eba9c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PlayerSpellEffect.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public enum PlayerSpellEffect +{ + BIND("Bind", 181, 8, false, TimerType.FREEZE), + SNARE("Snare", 180, 16, false, TimerType.FREEZE), + ENTANGLE("Entangle", 179, 24, false, TimerType.FREEZE), + RUSH("Ice Rush", 361, 8, false, TimerType.FREEZE), + BURST("Ice Burst", 363, 16, false, TimerType.FREEZE), + BLITZ("Ice Blitz", 367, 24, false, TimerType.FREEZE), + BARRAGE("Ice Barrage", 369, 32, false, TimerType.FREEZE), + TELEBLOCK("Teleblock", 345, 500, true, TimerType.TELEBLOCK), + VENG("Vengeance", 726, 50, false, TimerType.VENG), + VENG_OTHER("Vengeance Other", 725, 50, false, TimerType.VENG); + + @Getter(AccessLevel.PACKAGE) + private final String name; + @Getter(AccessLevel.PACKAGE) + private final int spotAnimId; + @Getter(AccessLevel.PACKAGE) + private final int timerLengthTicks; + @Getter(AccessLevel.PACKAGE) + private boolean halvable; + @Getter(AccessLevel.PACKAGE) + private final TimerType type; + + static PlayerSpellEffect getFromSpotAnim(int spotAnim) + { + for (PlayerSpellEffect effect : values()) + { + if (effect.getSpotAnimId() == spotAnim) + { + return effect; + } + } + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PrayerTracker.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PrayerTracker.java new file mode 100644 index 0000000000..20867cdc38 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/PrayerTracker.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Singleton +class PrayerTracker +{ + @Inject + private Client client; + private final Map> lastTick = new HashMap<>(); + private final Map> newTick = new HashMap<>(); + + public void gameTick() + { + lastTick.clear(); + lastTick.putAll(newTick); + newTick.clear(); + for (Player p : client.getPlayers()) + { + processActor(p); + } + for (NPC npc : client.getNpcs()) + { + processActor(npc); + } + } + + private void processActor(Actor actor) + { + if (!newTick.containsKey(actor)) + { + newTick.put(actor, new HashMap<>()); + } + if (actor instanceof Player) + { + newTick.get(actor).put("PrayerIcon", + ((Player) actor).getOverheadIcon() == null ? -1 : ((Player) actor).getOverheadIcon().ordinal()); + } + newTick.get(actor).put("SpotAnim", actor.getSpotAnimation()); + } + + int getPrayerIconLastTick(Actor p) + { + return lastTick.getOrDefault(p, new HashMap<>()).getOrDefault("PrayerIcon", -1337); + } + + int getSpotanimLastTick(Actor p) + { + return lastTick.getOrDefault(p, new HashMap<>()).getOrDefault("SpotAnim", -1337); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimeMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimeMode.java new file mode 100644 index 0000000000..0a68a8732a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimeMode.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +public enum TimeMode +{ + + TICKS("Ticks"), + SECONDS("MM:SS"); + + String human; + + TimeMode(String s) + { + this.human = s; + } + + public String toString() + { + return human; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/Timer.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/Timer.java new file mode 100644 index 0000000000..a6d1c2e167 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/Timer.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import lombok.EqualsAndHashCode; +import lombok.Setter; +import lombok.ToString; +import net.runelite.api.Client; +import java.awt.Color; +import java.awt.image.BufferedImage; + +@ToString +@EqualsAndHashCode +public class Timer +{ + private FreezeTimersV2Plugin plugin; + private Client client; + @Setter + private int ticksStart; + @Setter + private long startMillis; + @Setter + private int ticksLength; + private int cooldownLength; + private TimerType type; + private boolean shutdown = false; + + public Timer(FreezeTimersV2Plugin plugin, PlayerSpellEffect effect) + { + this(plugin, effect, false); + } + + public Timer(FreezeTimersV2Plugin plugin, PlayerSpellEffect effect, boolean half) + { + this.plugin = plugin; + this.client = plugin.getClient(); + this.ticksStart = client.getTickCount(); + this.startMillis = System.currentTimeMillis(); + this.ticksLength = effect == null ? 0 : half ? effect.getTimerLengthTicks() / 2 : effect.getTimerLengthTicks(); + this.cooldownLength = effect == null ? 0 : effect.getType().getImmunityLength(); + this.type = effect == null ? null : effect.getType(); + } + + public boolean isValid() + { + return type != null; + } + + public int getTicksElapsed() + { + return client.getTickCount() - ticksStart; + } + + public TimerState getTimerState() + { + int ticksElapsed = getTicksElapsed(); + if (ticksElapsed > ticksLength + cooldownLength) + { + return TimerState.INACTIVE; + } + else if (ticksElapsed > ticksLength) + { + return TimerState.COOLDOWN; + } + return TimerState.ACTIVE; + } + + public void setTimerTypeIfNull(TimerType set) + { + if (type == null) + { + type = set; + } + } + + public long getMillisForRender() + { + long millisElapsed = System.currentTimeMillis() - startMillis; + long millisRemaining = ((ticksLength * 600) + (cooldownLength * 600)) - millisElapsed; + switch (getTimerState()) + { + case ACTIVE: + return millisRemaining - (cooldownLength * 600); + case COOLDOWN: + return millisRemaining; + default: + return -1; + } + } + + public int getTicksForRender() + { + int ticksRemaining = (ticksLength + cooldownLength) - getTicksElapsed(); + ticksRemaining++; // so it renders nicely + switch (getTimerState()) + { + case ACTIVE: + return ticksRemaining - cooldownLength; + case COOLDOWN: + return ticksRemaining; + default: + return -1; + } + } + + public BufferedImage getIcon() + { + return getTimerState() == TimerState.COOLDOWN ? type.getCooldownIcon() : type.getIcon(); + } + + public Color determineColor() + { + if (plugin.getConfig().showIcons()) + { + return getTimerState() == TimerState.COOLDOWN ? plugin.getConfig().cooldownColor() : plugin.getConfig().timerColor(); + } + else + { + return getTimerState() == TimerState.COOLDOWN ? type.getDefaultColor().darker() : type.getDefaultColor(); + } + } + + public enum TimerState + { + ACTIVE, + COOLDOWN, + INACTIVE + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerManager.java new file mode 100644 index 0000000000..0d034749f9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerManager.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Actor; +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.HashMap; + +@Slf4j +@Singleton +public class TimerManager +{ + @Inject + private FreezeTimersV2Plugin plugin; + private HashMap> timerMap = new HashMap<>(); + + private HashMap getTimersFor(Actor actor) + { + if (!timerMap.containsKey(actor) || timerMap.get(actor) == null) + { + timerMap.put(actor, new HashMap<>()); + } + return timerMap.get(actor); + } + + public boolean isTimerValid(Actor actor, TimerType type) + { + return getTimerFor(actor, type).isValid(); + } + + public boolean hasTimerActive(Actor actor, TimerType type) + { + return getTimerFor(actor, type).getTimerState() != Timer.TimerState.INACTIVE; + } + + public Timer getTimerFor(Actor actor, TimerType type) + { + if (getTimersFor(actor).get(type) == null) + { + getTimersFor(actor).put(type, new Timer(plugin, null)); + } + return getTimersFor(actor).get(type); + } + + public void setTimerFor(Actor actor, TimerType type, Timer timer) + { + timer.setTimerTypeIfNull(type); + getTimersFor(actor).put(type, timer); + } + + // TODO: test me + public void jumpToCooldown(Actor actor, TimerType type) + { + Timer timer = getTimerFor(actor, type); + timer.setStartMillis(System.currentTimeMillis()); + timer.setTicksStart(plugin.getClient().getTickCount()); + timer.setTicksLength(0); + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerType.java b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerType.java new file mode 100644 index 0000000000..6fae0c8dc7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/freezetimersv2/TimerType.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 ThatGamerBlue + * 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.client.plugins.freezetimersv2; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.util.ImageUtil; +import java.awt.Color; +import java.awt.image.BufferedImage; + +@Getter +@RequiredArgsConstructor +public enum TimerType +{ + FREEZE(5, loadImage("freeze"), loadImage("freezeimmune"), "freezeTimers", Color.CYAN), // 3 seconds + TELEBLOCK(100, loadImage("teleblock"), loadImage("teleblockimmune"), "teleblockTimers", new Color(0x5254ae)), // this is 60 seconds, might be wrong + VENG(0, loadImage("veng"), null, "vengTimers", Color.RED.brighter()); + + private final int immunityLength; + private final BufferedImage icon; + private final BufferedImage cooldownIcon; + private final String renderConfig; + private final Color defaultColor; + + private static BufferedImage loadImage(String name) + { + return ImageUtil.getResourceStreamFromClass(FreezeTimersV2Plugin.class, name + ".png"); + } + + public boolean shouldRender(ConfigManager configManager) + { + return configManager.getConfiguration("freezetimersv2", renderConfig, Boolean.class); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java index be4008b8eb..e816d44c2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/multiindicators/MapLocations.java @@ -38,16 +38,21 @@ public class MapLocations { @SuppressWarnings("unchecked") private static final List[] MULTICOMBAT = new List[Constants.MAX_Z]; + private static Area[] MULTICOMBAT_CACHE = new Area[Constants.MAX_Z]; @SuppressWarnings("unchecked") private static final List[] NOT_MULTICOMBAT = new List[Constants.MAX_Z]; @SuppressWarnings("unchecked") private static final List[] ROUGH_WILDERNESS = new List[Constants.MAX_Z]; + private static Area[] ROUGH_WILDERNESS_CACHE = new Area[Constants.MAX_Z]; @SuppressWarnings("unchecked") private static final List[] WILDERNESS_LEVEL_LINES = new List[Constants.MAX_Z]; + private static Area[] WILDERNESS_LEVEL_LINES_CACHE = new Area[Constants.MAX_Z]; @SuppressWarnings("unchecked") private static final List[] DEADMAN_SAFE_ZONES = new List[Constants.MAX_Z]; + private static Area[] DEADMAN_SAFE_ZONES_CACHE = new Area[Constants.MAX_Z]; @SuppressWarnings("unchecked") private static final List[] PVP_WORLD_SAFE_ZONES = new List[Constants.MAX_Z]; + private static Area[] PVP_SAFE_ZONES_CACHE = new Area[Constants.MAX_Z]; private static Area getArea(List shapes) { @@ -74,9 +79,13 @@ public class MapLocations public static Area getMulticombat(int plane) { - Area area = getArea(MULTICOMBAT[plane]); - area.subtract(getArea(NOT_MULTICOMBAT[plane])); - return area; + if (MULTICOMBAT_CACHE[plane] == null) + { + Area area = getArea(MULTICOMBAT[plane]); + area.subtract(getArea(NOT_MULTICOMBAT[plane])); + MULTICOMBAT_CACHE[plane] = area; + } + return MULTICOMBAT_CACHE[plane]; } public static Area getMulticombat(Rectangle view, int plane) @@ -88,7 +97,11 @@ public class MapLocations public static Area getRoughWilderness(int plane) { - return getArea(ROUGH_WILDERNESS[plane]); + if (ROUGH_WILDERNESS_CACHE[plane] == null) + { + ROUGH_WILDERNESS_CACHE[plane] = getArea(ROUGH_WILDERNESS[plane]); + } + return ROUGH_WILDERNESS_CACHE[plane]; } public static Area getRoughWilderness(Rectangle view, int plane) @@ -98,7 +111,11 @@ public class MapLocations public static Area getWildernessLevelLines(int plane) { - return getArea(WILDERNESS_LEVEL_LINES[plane]); + if (WILDERNESS_LEVEL_LINES_CACHE[plane] == null) + { + WILDERNESS_LEVEL_LINES_CACHE[plane] = getArea(WILDERNESS_LEVEL_LINES[plane]); + } + return WILDERNESS_LEVEL_LINES_CACHE[plane]; } public static Area getWildernessLevelLines(Rectangle view, int plane) @@ -108,7 +125,11 @@ public class MapLocations public static Area getDeadmanSafeZones(int plane) { - return getArea(DEADMAN_SAFE_ZONES[plane]); + if (DEADMAN_SAFE_ZONES_CACHE[plane] == null) + { + DEADMAN_SAFE_ZONES_CACHE[plane] = getArea(DEADMAN_SAFE_ZONES[plane]); + } + return DEADMAN_SAFE_ZONES_CACHE[plane]; } public static Area getDeadmanSafeZones(Rectangle view, int plane) @@ -118,7 +139,11 @@ public class MapLocations public static Area getPvpSafeZones(int plane) { - return getArea(PVP_WORLD_SAFE_ZONES[plane]); + if (PVP_SAFE_ZONES_CACHE[plane] == null) + { + PVP_SAFE_ZONES_CACHE[plane] = getArea(PVP_WORLD_SAFE_ZONES[plane]); + } + return PVP_SAFE_ZONES_CACHE[plane]; } public static Area getPvpSafeZones(Rectangle view, int plane) diff --git a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java index 03c2a1a07c..de4968d476 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/PvPUtil.java @@ -6,12 +6,8 @@ * Written by PKLite(ST0NEWALL, others) , 2019 * */ - package net.runelite.client.util; -import java.util.Comparator; -import java.util.Objects; -import java.util.TreeMap; import net.runelite.api.Client; import net.runelite.api.InventoryID; import net.runelite.api.Item; @@ -20,29 +16,59 @@ import net.runelite.api.Player; import net.runelite.api.Varbits; import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.geometry.Cuboid; import net.runelite.client.game.ItemManager; import org.apache.commons.lang3.ArrayUtils; +import java.awt.Polygon; +import java.util.Comparator; +import java.util.Objects; +import java.util.TreeMap; /** * */ public class PvPUtil { + private static final Polygon NOT_WILDERNESS_BLACK_KNIGHTS = new Polygon( // this is black knights castle + new int[]{2994, 2995, 2996, 2996, 2994, 2994, 2997, 2998, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3005, + 3005, 3019, 3020, 3022, 3023, 3024, 3025, 3026, 3026, 3027, 3027, 3028, 3028, 3029, 3029, 3030, 3030, 3031, + 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3037}, + new int[]{3525, 3526, 3527, 3529, 3529, 3534, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, + 3545, 3545, 3546, 3546, 3545, 3544, 3543, 3543, 3542, 3541, 3540, 3539, 3537, 3536, 3535, 3534, 3533, 3532, + 3531, 3530, 3529, 3528, 3527, 3526, 3526, 3525}, + 43 + ); + private static final Cuboid MAIN_WILDERNESS_CUBOID = new Cuboid(2944, 3525, 0, 3391, 4351, 3); + private static final Cuboid GOD_WARS_WILDERNESS_CUBOID = new Cuboid(3008, 10112, 0, 3071, 10175, 3); + private static final Cuboid WILDERNESS_UNDERGROUND_CUBOID = new Cuboid(2944, 9920, 0, 3391, 10879, 3); /** * Gets the wilderness level based on a world point + * Java reimplementation of clientscript 384 [proc,wilderness_level] * * @param point the point in the world to get the wilderness level for * @return the int representing the wilderness level */ public static int getWildernessLevelFrom(WorldPoint point) { - int y = point.getY(); + if (MAIN_WILDERNESS_CUBOID.contains(point)) + { + if (NOT_WILDERNESS_BLACK_KNIGHTS.contains(point.getX(), point.getY())) + { + return 0; + } - int underLevel = ((y - 9920) / 8) + 1; - int upperLevel = ((y - 3520) / 8) + 1; - - return y > 6400 ? underLevel : upperLevel; + return ((point.getY() - 3520) / 8) + 1; // calc(((coordz(coord) - (55 * 64)) / 8) + 1) + } + else if (GOD_WARS_WILDERNESS_CUBOID.contains(point)) + { + return ((point.getY() - 9920) / 8) - 1; // calc(((coordz(coord) - (155 * 64)) / 8) - 1) + } + else if (WILDERNESS_UNDERGROUND_CUBOID.contains(point)) + { + return ((point.getY() - 9920) / 8) + 1; // calc(((coordz(coord) - (155 * 64)) / 8) + 1) + } + return 0; } /** diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/freeze.png b/runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/freeze.png new file mode 100644 index 0000000000000000000000000000000000000000..12b692890010bdbb825d299199f27e822311f9c6 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;js(W8VM(0bNN%K~y+Tt&%ZI13?glcg+=79Hg<(N{ZO3K=KtX7`GJ}q$tUXQigQrOepJy93^T=3TGQEQ@- z1@3l^=wa__tmL)R5pPhyvh+C^&}EWjM!txBST`N39H~G60000FVdQ&MBb@ E0Dy!@A^-pY literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/teleblockimmune.png b/runelite-client/src/main/resources/net/runelite/client/plugins/freezetimersv2/teleblockimmune.png new file mode 100644 index 0000000000000000000000000000000000000000..79514a7d3c2fac18f09843508014abaccff58f82 GIT binary patch literal 468 zcmV;_0W1EAP)pF7<5HgbW?9;ba!ELWdLwtX>N2bZe?^J zG%heMHvEiZ-v9ssQb|NXR5(wCQ?W_|K@i;o72zU+36c*;X&J#%8^KmA6jRs-1UUkU zMUqDB{egUdV7@?7`T-XCgnUGb^}XGh+qqnb1CQIAeecc8?Vj5mnU}@xm^gP2tbsYu zh}q1)6yGqYn}E}!MqbN=7c7C!?cJ9@?>+}`O(WzRz^CxmB9CD zfHcCE*!6-XVuWH$P-BlZ15O=l*npqS-bl87?I#LR>ErYBC#s+WdUFz(jXq1 zjU~wxSp(s*OIzqd4Q7&90H(F=KNL7DNKH!Y;1l8sr2iU$WX_8+EN5f%vJu(g#M4*8_RX94y$tHU44O=8o~u(& zfmD?Q`2{mLJiCzwtL-|W~`yvsL5cd$#+Di<&87YLIzJ)KbLh*2~7arF-toD literal 0 HcmV?d00001 diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2OverlayTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2OverlayTest.java new file mode 100644 index 0000000000..448c93978f --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/freezetimersv2/FreezeTimersV2OverlayTest.java @@ -0,0 +1,56 @@ +package net.runelite.client.plugins.freezetimersv2; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import net.runelite.api.Client; +import net.runelite.client.config.OpenOSRSConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import javax.inject.Inject; +import java.util.concurrent.ScheduledExecutorService; +import static org.junit.Assert.assertEquals; + +@RunWith(MockitoJUnitRunner.class) +public class FreezeTimersV2OverlayTest +{ + @Mock + @Bind + private ScheduledExecutorService scheduledExecutorService; + + @Mock + @Bind + private OpenOSRSConfig openOSRSConfig; + + @Mock + @Bind + private Client client; + + @Mock + @Bind + private FreezeTimersV2Config config; + + @Inject + private FreezeTimersV2Overlay timersOverlay; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testTimeHandler() + { + assertEquals("6.0", timersOverlay.formatTime(6000)); + assertEquals("0.7", timersOverlay.formatTime(744)); + assertEquals("14", timersOverlay.formatTime(14265)); + assertEquals("5:00", timersOverlay.formatTime(300000)); + assertEquals("37", timersOverlay.formatTime(37845)); + assertEquals("1.3", timersOverlay.formatTime(1345)); + } + +}