lol i fucked that other pr up royally

This commit is contained in:
ThatGamerBlue
2020-02-02 15:28:42 +00:00
parent 6ece2b5f2f
commit 710f45e3dd
19 changed files with 1224 additions and 16 deletions

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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<WorldType> 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));
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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<Actor, HashMap<String, Integer>> lastTick = new HashMap<>();
private final Map<Actor, HashMap<String, Integer>> 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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
}
}

View File

@@ -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<Actor, HashMap<TimerType, Timer>> timerMap = new HashMap<>();
private HashMap<TimerType, Timer> 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);
}
}

View File

@@ -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);
}
}

View File

@@ -38,16 +38,21 @@ public class MapLocations
{
@SuppressWarnings("unchecked")
private static final List<Shape>[] MULTICOMBAT = new List[Constants.MAX_Z];
private static Area[] MULTICOMBAT_CACHE = new Area[Constants.MAX_Z];
@SuppressWarnings("unchecked")
private static final List<Shape>[] NOT_MULTICOMBAT = new List[Constants.MAX_Z];
@SuppressWarnings("unchecked")
private static final List<Shape>[] ROUGH_WILDERNESS = new List[Constants.MAX_Z];
private static Area[] ROUGH_WILDERNESS_CACHE = new Area[Constants.MAX_Z];
@SuppressWarnings("unchecked")
private static final List<Shape>[] 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<Shape>[] 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<Shape>[] 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<Shape> 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)

View File

@@ -6,12 +6,8 @@
* Written by PKLite(ST0NEWALL, others) <stonewall@thots.cc.usa>, 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;
}
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

View File

@@ -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));
}
}