@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Hexagon <hexagon@fking.work>
|
||||||
|
* 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.specialcounter;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
class PlayerInfoDrop
|
||||||
|
{
|
||||||
|
private final int startCycle;
|
||||||
|
private final int endCycle;
|
||||||
|
private final int playerIdx;
|
||||||
|
private final String text;
|
||||||
|
private final int startHeightOffset;
|
||||||
|
private final int endHeightOffset;
|
||||||
|
private final Font font;
|
||||||
|
private final Color color;
|
||||||
|
private final BufferedImage image;
|
||||||
|
|
||||||
|
public static Builder builder(int startCycle, int endCycle, int playerIdx, String text)
|
||||||
|
{
|
||||||
|
return new Builder(startCycle, endCycle, playerIdx, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Accessors(fluent = true)
|
||||||
|
@Setter
|
||||||
|
static class Builder
|
||||||
|
{
|
||||||
|
private final int startCycle;
|
||||||
|
private final int endCycle;
|
||||||
|
private final int playerIdx;
|
||||||
|
private final String text;
|
||||||
|
private int startHeightOffset = 0;
|
||||||
|
private int endHeightOffset = 200;
|
||||||
|
private Font font = FontManager.getRunescapeBoldFont();
|
||||||
|
private Color color = Color.WHITE;
|
||||||
|
private BufferedImage image;
|
||||||
|
|
||||||
|
public PlayerInfoDrop build()
|
||||||
|
{
|
||||||
|
if (startCycle > endCycle)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("endCycle must be after startCycle");
|
||||||
|
}
|
||||||
|
if (playerIdx < 0 || playerIdx > 2047)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("playerIdx must be between 0-2047");
|
||||||
|
}
|
||||||
|
return new PlayerInfoDrop(startCycle, endCycle, playerIdx, text, startHeightOffset, endHeightOffset, font, color, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Hexagon <hexagon@fking.work>
|
||||||
|
* 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.specialcounter;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.Player;
|
||||||
|
import net.runelite.api.Point;
|
||||||
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||||
|
import net.runelite.client.util.ColorUtil;
|
||||||
|
import net.runelite.client.util.ImageUtil;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class PlayerInfoDropOverlay extends Overlay
|
||||||
|
{
|
||||||
|
private final SpecialCounterPlugin plugin;
|
||||||
|
private final SpecialCounterConfig config;
|
||||||
|
private final Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PlayerInfoDropOverlay(SpecialCounterPlugin plugin, SpecialCounterConfig config, Client client)
|
||||||
|
{
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.config = config;
|
||||||
|
this.client = client;
|
||||||
|
setPosition(OverlayPosition.DYNAMIC);
|
||||||
|
setPriority(OverlayPriority.MED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension render(Graphics2D graphics)
|
||||||
|
{
|
||||||
|
final List<PlayerInfoDrop> infoDrops = plugin.getPlayerInfoDrops();
|
||||||
|
if (infoDrops.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int cycle = client.getGameCycle();
|
||||||
|
for (Iterator<PlayerInfoDrop> iterator = infoDrops.iterator(); iterator.hasNext();)
|
||||||
|
{
|
||||||
|
PlayerInfoDrop infoDrop = iterator.next();
|
||||||
|
|
||||||
|
if (cycle < infoDrop.getStartCycle())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cycle > infoDrop.getEndCycle())
|
||||||
|
{
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.specDrops())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = client.getCachedPlayers()[infoDrop.getPlayerIdx()];
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int elapsed = cycle - infoDrop.getStartCycle();
|
||||||
|
int percent = elapsed * 100 / (infoDrop.getEndCycle() - infoDrop.getStartCycle());
|
||||||
|
int currentHeight = infoDrop.getEndHeightOffset() * percent / 100;
|
||||||
|
String text = infoDrop.getText();
|
||||||
|
|
||||||
|
graphics.setFont(infoDrop.getFont());
|
||||||
|
Point textLocation = player.getCanvasTextLocation(graphics, text, player.getLogicalHeight() + infoDrop.getStartHeightOffset() + currentHeight);
|
||||||
|
if (textLocation == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int alpha = 255 - (255 * percent / 100);
|
||||||
|
BufferedImage image = infoDrop.getImage();
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
int textHeight = graphics.getFontMetrics().getHeight() - graphics.getFontMetrics().getMaxDescent();
|
||||||
|
int textMargin = image.getWidth() / 2;
|
||||||
|
int x = textLocation.getX() - textMargin - 1;
|
||||||
|
int y = textLocation.getY() - textHeight / 2 - image.getHeight() / 2;
|
||||||
|
Point imageLocation = new Point(x, y);
|
||||||
|
|
||||||
|
textLocation = new Point(textLocation.getX() + textMargin, textLocation.getY());
|
||||||
|
|
||||||
|
OverlayUtil.renderImageLocation(graphics, imageLocation, ImageUtil.alphaOffset(image, alpha - 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawText(graphics, textLocation, text, infoDrop.getColor(), alpha);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawText(Graphics2D g, Point point, String text, Color color, int colorAlpha)
|
||||||
|
{
|
||||||
|
g.setColor(ColorUtil.colorWithAlpha(Color.BLACK, colorAlpha));
|
||||||
|
g.drawString(text, point.getX() + 1, point.getY() + 1);
|
||||||
|
g.setColor(ColorUtil.colorWithAlpha(color, colorAlpha));
|
||||||
|
g.drawString(text, point.getX(), point.getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.specialcounter;
|
package net.runelite.client.plugins.specialcounter;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import net.runelite.client.config.Config;
|
import net.runelite.client.config.Config;
|
||||||
import net.runelite.client.config.ConfigGroup;
|
import net.runelite.client.config.ConfigGroup;
|
||||||
import net.runelite.client.config.ConfigItem;
|
import net.runelite.client.config.ConfigItem;
|
||||||
@@ -45,6 +46,28 @@ public interface SpecialCounterConfig extends Config
|
|||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
position = 1,
|
position = 1,
|
||||||
|
keyName = "specDrops",
|
||||||
|
name = "Spec Drops",
|
||||||
|
description = "Draws an overlay over the player when a special attack hits"
|
||||||
|
)
|
||||||
|
default boolean specDrops()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
position = 2,
|
||||||
|
keyName = "specDropColor",
|
||||||
|
name = "Spec Drop Color",
|
||||||
|
description = "Text color for spec drops"
|
||||||
|
)
|
||||||
|
default Color specDropColor()
|
||||||
|
{
|
||||||
|
return Color.WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
position = 10,
|
||||||
keyName = "dragonWarhammerThreshold",
|
keyName = "dragonWarhammerThreshold",
|
||||||
name = "Dragon Warhammer",
|
name = "Dragon Warhammer",
|
||||||
description = "Threshold for Dragon Warhammer (0 to disable)"
|
description = "Threshold for Dragon Warhammer (0 to disable)"
|
||||||
@@ -55,7 +78,7 @@ public interface SpecialCounterConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
position = 2,
|
position = 20,
|
||||||
keyName = "arclightThreshold",
|
keyName = "arclightThreshold",
|
||||||
name = "Arclight",
|
name = "Arclight",
|
||||||
description = "Threshold for Arclight (0 to disable)"
|
description = "Threshold for Arclight (0 to disable)"
|
||||||
@@ -66,7 +89,7 @@ public interface SpecialCounterConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
position = 3,
|
position = 30,
|
||||||
keyName = "darklightThreshold",
|
keyName = "darklightThreshold",
|
||||||
name = "Darklight",
|
name = "Darklight",
|
||||||
description = "Threshold for Darklight (0 to disable)"
|
description = "Threshold for Darklight (0 to disable)"
|
||||||
@@ -77,7 +100,7 @@ public interface SpecialCounterConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
position = 4,
|
position = 40,
|
||||||
keyName = "bandosGodswordThreshold",
|
keyName = "bandosGodswordThreshold",
|
||||||
name = "Bandos Godsword",
|
name = "Bandos Godsword",
|
||||||
description = "Threshold for Bandos Godsword (0 to disable)"
|
description = "Threshold for Bandos Godsword (0 to disable)"
|
||||||
@@ -88,7 +111,7 @@ public interface SpecialCounterConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
position = 5,
|
position = 50,
|
||||||
keyName = "bulwarkThreshold",
|
keyName = "bulwarkThreshold",
|
||||||
name = "Dinh's Bulwark",
|
name = "Dinh's Bulwark",
|
||||||
description = "Threshold for Dinh's Bulwark (0 to disable)"
|
description = "Threshold for Dinh's Bulwark (0 to disable)"
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ package net.runelite.client.plugins.specialcounter;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Actor;
|
import net.runelite.api.Actor;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -44,6 +49,7 @@ import net.runelite.api.NPC;
|
|||||||
import net.runelite.api.NpcID;
|
import net.runelite.api.NpcID;
|
||||||
import net.runelite.api.VarPlayer;
|
import net.runelite.api.VarPlayer;
|
||||||
import net.runelite.api.coords.WorldPoint;
|
import net.runelite.api.coords.WorldPoint;
|
||||||
|
import net.runelite.api.events.CommandExecuted;
|
||||||
import net.runelite.api.events.GameStateChanged;
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.GameTick;
|
import net.runelite.api.events.GameTick;
|
||||||
import net.runelite.api.events.HitsplatApplied;
|
import net.runelite.api.events.HitsplatApplied;
|
||||||
@@ -57,7 +63,9 @@ import net.runelite.client.eventbus.Subscribe;
|
|||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||||
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.client.ws.PartyService;
|
import net.runelite.client.ws.PartyService;
|
||||||
import net.runelite.client.ws.WSClient;
|
import net.runelite.client.ws.WSClient;
|
||||||
|
|
||||||
@@ -95,6 +103,9 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
private final Set<Integer> interactedNpcIds = new HashSet<>();
|
private final Set<Integer> interactedNpcIds = new HashSet<>();
|
||||||
private final SpecialCounter[] specialCounter = new SpecialCounter[SpecialWeapon.values().length];
|
private final SpecialCounter[] specialCounter = new SpecialCounter[SpecialWeapon.values().length];
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private final List<PlayerInfoDrop> playerInfoDrops = new ArrayList<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
@@ -119,6 +130,12 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
@Inject
|
@Inject
|
||||||
private SpecialCounterConfig config;
|
private SpecialCounterConfig config;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private OverlayManager overlayManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PlayerInfoDropOverlay playerInfoDropOverlay;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
SpecialCounterConfig getConfig(ConfigManager configManager)
|
SpecialCounterConfig getConfig(ConfigManager configManager)
|
||||||
{
|
{
|
||||||
@@ -128,6 +145,7 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
@Override
|
@Override
|
||||||
protected void startUp()
|
protected void startUp()
|
||||||
{
|
{
|
||||||
|
overlayManager.add(playerInfoDropOverlay);
|
||||||
wsClient.registerMessage(SpecialCounterUpdate.class);
|
wsClient.registerMessage(SpecialCounterUpdate.class);
|
||||||
currentWorld = -1;
|
currentWorld = -1;
|
||||||
specialPercentage = -1;
|
specialPercentage = -1;
|
||||||
@@ -140,6 +158,7 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
protected void shutDown()
|
protected void shutDown()
|
||||||
{
|
{
|
||||||
removeCounters();
|
removeCounters();
|
||||||
|
overlayManager.remove(playerInfoDropOverlay);
|
||||||
wsClient.unregisterMessage(SpecialCounterUpdate.class);
|
wsClient.unregisterMessage(SpecialCounterUpdate.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,15 +286,18 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
if (wasSpec && specialWeapon != null && hitsplat.getAmount() > 0)
|
if (wasSpec && specialWeapon != null && hitsplat.getAmount() > 0)
|
||||||
{
|
{
|
||||||
int hit = getHit(specialWeapon, hitsplat);
|
int hit = getHit(specialWeapon, hitsplat);
|
||||||
|
int localPlayerId = client.getLocalPlayer().getId();
|
||||||
|
|
||||||
updateCounter(specialWeapon, null, hit);
|
updateCounter(specialWeapon, null, hit);
|
||||||
|
|
||||||
if (!party.getMembers().isEmpty())
|
if (!party.getMembers().isEmpty())
|
||||||
{
|
{
|
||||||
final SpecialCounterUpdate specialCounterUpdate = new SpecialCounterUpdate(interactingId, specialWeapon, hit);
|
final SpecialCounterUpdate specialCounterUpdate = new SpecialCounterUpdate(interactingId, specialWeapon, hit, client.getWorld(), localPlayerId);
|
||||||
specialCounterUpdate.setMemberId(party.getLocalMember().getMemberId());
|
specialCounterUpdate.setMemberId(party.getLocalMember().getMemberId());
|
||||||
wsClient.send(specialCounterUpdate);
|
wsClient.send(specialCounterUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playerInfoDrops.add(createSpecInfoDrop(specialWeapon, hit, localPlayerId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,9 +356,23 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
updateCounter(event.getWeapon(), name, event.getHit());
|
updateCounter(event.getWeapon(), name, event.getHit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.getWorld() == client.getWorld())
|
||||||
|
{
|
||||||
|
playerInfoDrops.add(createSpecInfoDrop(event.getWeapon(), event.getHit(), event.getPlayerId()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onCommandExecuted(CommandExecuted commandExecuted)
|
||||||
|
{
|
||||||
|
if (commandExecuted.getCommand().equals("spec"))
|
||||||
|
{
|
||||||
|
playerInfoDrops.add(createSpecInfoDrop(SpecialWeapon.BANDOS_GODSWORD, 42, client.getLocalPlayer().getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private SpecialWeapon usedSpecialWeapon()
|
private SpecialWeapon usedSpecialWeapon()
|
||||||
{
|
{
|
||||||
ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
|
ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
|
||||||
@@ -424,4 +460,17 @@ public class SpecialCounterPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
return specialWeapon.isDamage() ? hitsplat.getAmount() : 1;
|
return specialWeapon.isDamage() ? hitsplat.getAmount() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PlayerInfoDrop createSpecInfoDrop(SpecialWeapon weapon, int hit, int playerId)
|
||||||
|
{
|
||||||
|
int cycle = client.getGameCycle();
|
||||||
|
BufferedImage image = ImageUtil.resizeImage(itemManager.getImage(weapon.getItemID()[0]), 24, 24);
|
||||||
|
|
||||||
|
return PlayerInfoDrop.builder(cycle, cycle + 100, playerId, Integer.toString(hit))
|
||||||
|
.color(config.specDropColor())
|
||||||
|
.startHeightOffset(100)
|
||||||
|
.endHeightOffset(400)
|
||||||
|
.image(image)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -35,4 +35,6 @@ public class SpecialCounterUpdate extends PartyMemberMessage
|
|||||||
private final int npcId;
|
private final int npcId;
|
||||||
private final SpecialWeapon weapon;
|
private final SpecialWeapon weapon;
|
||||||
private final int hit;
|
private final int hit;
|
||||||
|
private final int world;
|
||||||
|
private final int playerId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.google.inject.Guice;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.testing.fieldbinder.Bind;
|
import com.google.inject.testing.fieldbinder.Bind;
|
||||||
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import net.runelite.api.Actor;
|
import net.runelite.api.Actor;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.EquipmentInventorySlot;
|
import net.runelite.api.EquipmentInventorySlot;
|
||||||
@@ -44,13 +45,16 @@ import net.runelite.api.events.InteractingChanged;
|
|||||||
import net.runelite.api.events.VarbitChanged;
|
import net.runelite.api.events.VarbitChanged;
|
||||||
import net.runelite.client.Notifier;
|
import net.runelite.client.Notifier;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||||
|
import net.runelite.client.util.AsyncBufferedImage;
|
||||||
import net.runelite.client.ws.PartyService;
|
import net.runelite.client.ws.PartyService;
|
||||||
import net.runelite.client.ws.WSClient;
|
import net.runelite.client.ws.WSClient;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.lenient;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -90,6 +94,14 @@ public class SpecialCounterPluginTest
|
|||||||
@Bind
|
@Bind
|
||||||
private SpecialCounterConfig specialCounterConfig;
|
private SpecialCounterConfig specialCounterConfig;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
@Bind
|
||||||
|
private OverlayManager overlayManager;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
@Bind
|
||||||
|
private PlayerInfoDropOverlay playerInfoDropOverlay;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SpecialCounterPlugin specialCounterPlugin;
|
private SpecialCounterPlugin specialCounterPlugin;
|
||||||
|
|
||||||
@@ -107,6 +119,8 @@ public class SpecialCounterPluginTest
|
|||||||
when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(100);
|
when(client.getVar(VarPlayer.SPECIAL_ATTACK_PERCENT)).thenReturn(100);
|
||||||
specialCounterPlugin.onVarbitChanged(new VarbitChanged());
|
specialCounterPlugin.onVarbitChanged(new VarbitChanged());
|
||||||
|
|
||||||
|
// Set up item image for spec info drop
|
||||||
|
when(itemManager.getImage(anyInt())).thenReturn(new AsyncBufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HitsplatApplied hitsplat(Actor target, Hitsplat.HitsplatType type)
|
private static HitsplatApplied hitsplat(Actor target, Hitsplat.HitsplatType type)
|
||||||
|
|||||||
Reference in New Issue
Block a user