Merge pull request #376 from Dreyri/projectiles

Projectiles Dev Tool and Additions to the AoE plugin
This commit is contained in:
Adam
2018-01-14 09:56:14 -05:00
committed by GitHub
14 changed files with 521 additions and 18 deletions

View File

@@ -154,6 +154,8 @@ public interface Client
IndexedSprite[] getMapScene();
int getGameCycle();
SpritePixels[] getMapIcons();
IndexedSprite[] getModIcons();
@@ -169,4 +171,7 @@ public interface Client
boolean isClanMember(String name);
Point getSceneDestinationLocation();
List<Projectile> getProjectiles();
}

View File

@@ -24,9 +24,55 @@
*/
package net.runelite.api;
public interface Projectile
import java.time.Duration;
public interface Projectile extends Renderable
{
int getId();
Actor getInteracting();
Point getTarget();
int getTargetZ();
int getX1();
int getY1();
int getFloor();
int getHeight();
int getEndHeight();
int getStartMovementCycle();
int getSpawnCycle();
int getCycleLength();
Duration getLength();
int getEndCycle();
int getRemainingCycles();
int getSlope();
int getStartHeight();
double getX();
double getY();
double getZ();
double getScalar();
double getVelocityX();
double getVelocityY();
double getVelocityZ();
}

View File

@@ -33,4 +33,36 @@ public class ProjectileID
public static final int VASA_AWAKEN_AOE = 1327;
public static final int VASA_RANGED_AOE = 1329;
public static final int TEKTON_METEOR_AOE = 660;
public static final int OLM_FALLING_CRYSTAL_AOE = -1; //please help
public static final int OLM_BURNING_AOE = -1;
public static final int VORKATH_BOMB_AOE = 1481;
public static final int VORKATH_POISON_POOL_AOE = 1483;
public static final int VORKATH_TICK_FIRE_AOE = 1482;
public static final int VORKATH_SPAWN_AOE = 1484;
public static final int GALVEK_MINE = 1495;
public static final int GALVEK_BOMB = 1491;
public static final int VETION_LIGHTNING = 280;
public static final int CHAOS_FANATIC_AOE = 551; //for lack of a better word
public static final int CORPOREAL_BEAST_AOE = 315;
public static final int CORPOREAL_BEAST_DARK_CORE_AOE = 319;
/**
* missing: marble gargoyle, superior dark beast
*/
/**
* non AOE, regular projectiles
*/
public static final int VORKATH_DRAGONBREATH = 393;
public static final int VORKATH_RANGED = 1477;
public static final int VORKATH_MAGIC = 1479;
public static final int VORKATH_PRAYER_DISABLE = 1471;
public static final int VORKATH_VENOM = 1470;
public static final int VORKATH_ICE = 350;
}

View File

@@ -25,6 +25,8 @@
package net.runelite.client.plugins.aoewarnings;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import net.runelite.api.ProjectileID;
public enum AoeProjectileInfo
@@ -41,7 +43,46 @@ public enum AoeProjectileInfo
*/
VASA_AWAKEN_AOE(ProjectileID.VASA_AWAKEN_AOE, 4500, 3),
VASA_RANGED_AOE(ProjectileID.VASA_RANGED_AOE, 3000, 3),
TEKTON_METEOR_AOE(ProjectileID.TEKTON_METEOR_AOE, 4000, 3);
TEKTON_METEOR_AOE(ProjectileID.TEKTON_METEOR_AOE, 4000, 3),
/**
* The AOEs of Vorkath
*/
VORKATH_BOMB(ProjectileID.VORKATH_BOMB_AOE, 2400, 3),
VORKATH_POISON_POOL(ProjectileID.VORKATH_POISON_POOL_AOE, 1800, 1),
VORKATH_SPAWN(ProjectileID.VORKATH_SPAWN_AOE, 3000, 1), //extra tick because hard to see otherwise
VORKATH_TICK_FIRE(ProjectileID.VORKATH_TICK_FIRE_AOE, 600, 1),
/**
* the AOEs of Galvek
*/
GALVEK_MINE(ProjectileID.GALVEK_MINE, 3600, 3),
GALVEK_BOMB(ProjectileID.GALVEK_BOMB, 2400, 3),
/**
* the AOE of Vet'ion
*/
VETION_LIGHTNING(ProjectileID.VETION_LIGHTNING, 3000, 1),
/**
* the AOE of Chaos Fanatic
*/
CHAOS_FANATIC(ProjectileID.CHAOS_FANATIC_AOE, 3000, 1),
/**
* the AOE of the Corporeal Beast
*/
CORPOREAL_BEAST(ProjectileID.CORPOREAL_BEAST_AOE, 3000, 1),
CORPOREAL_BEAST_DARK_CORE(ProjectileID.CORPOREAL_BEAST_DARK_CORE_AOE, 3000, 3),
/**
* the AOEs of The Great Olm
* missing ids and length, please help
*/
OLM_FALLING_CRYSTAL(ProjectileID.OLM_FALLING_CRYSTAL_AOE, 2400, 3),
OLM_BURNING(ProjectileID.OLM_BURNING_AOE, 2400, 3);
/**
* The id of the projectile to trigger this AoE warning
@@ -61,6 +102,16 @@ public enum AoeProjectileInfo
*/
private final int aoeSize;
private static final Map<Integer, AoeProjectileInfo> map = new HashMap<>();
static
{
for (AoeProjectileInfo aoe : values())
{
map.put(aoe.id, aoe);
}
}
AoeProjectileInfo(int id, int lifeTimeMillis, int aoeSize)
{
this.id = id;
@@ -85,13 +136,6 @@ public enum AoeProjectileInfo
public static AoeProjectileInfo getById(int id)
{
for (AoeProjectileInfo aoeProjectileInfo : values())
{
if (id == aoeProjectileInfo.getId())
{
return aoeProjectileInfo;
}
}
return null;
return map.get(id);
}
}

View File

@@ -95,6 +95,66 @@ public interface AoeWarningConfig extends Config
return true;
}
@ConfigItem(
keyName = "vorkath",
name = "Vorkath",
description = "Configures whether or not AoE Projectile Warnings for Vorkath are displayed"
)
default boolean isVorkathEnabled()
{
return true;
}
@ConfigItem(
keyName = "galvek",
name = "Galvek",
description = "Configures whether or not AoE Projectile Warnings for Galvek are displayed"
)
default boolean isGalvekEnabled()
{
return true;
}
@ConfigItem(
keyName = "vetion",
name = "Vet'ion",
description = "Configures whether or not AoE Projectile Warnings for Vet'ion are displayed"
)
default boolean isVetionEnabled()
{
return true;
}
@ConfigItem(
keyName = "chaosfanatic",
name = "Chaos Fanatic",
description = "Configures whether or not AoE Projectile Warnings for Chaos Fanatic are displayed"
)
default boolean isChaosFanaticEnabled()
{
return true;
}
@ConfigItem(
keyName = "olm",
name = "Great Olm",
description = "Configures whether or not AoE Projectile Warnings for The Great Olm are displayed"
)
default boolean isOlmEnabled()
{
return true;
}
@ConfigItem(
keyName = "corp",
name = "Corporeal Beast",
description = "Configures whether or not AoE Projectile Warnings for the Corporeal Beast are displayed"
)
default boolean isCorpEnabled()
{
return true;
}
@ConfigItem(
keyName = "outline",
name = "Display Outline",

View File

@@ -125,6 +125,24 @@ public class AoeWarningPlugin extends Plugin
return config.isVasaEnabled();
case TEKTON_METEOR_AOE:
return config.isTektonEnabled();
case VORKATH_BOMB:
case VORKATH_POISON_POOL:
case VORKATH_SPAWN:
case VORKATH_TICK_FIRE:
return config.isVorkathEnabled();
case VETION_LIGHTNING:
return config.isVetionEnabled();
case CHAOS_FANATIC:
return config.isChaosFanaticEnabled();
case GALVEK_BOMB:
case GALVEK_MINE:
return config.isGalvekEnabled();
case OLM_FALLING_CRYSTAL:
case OLM_BURNING:
return config.isOlmEnabled();
case CORPOREAL_BEAST:
case CORPOREAL_BEAST_DARK_CORE:
return config.isCorpEnabled();
}
return false;

View File

@@ -25,6 +25,7 @@
*/
package net.runelite.client.plugins.devtools;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
@@ -37,6 +38,7 @@ import java.awt.geom.Rectangle2D;
import java.util.List;
import javax.annotation.Nullable;
import javax.inject.Inject;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject;
@@ -45,7 +47,9 @@ import net.runelite.api.Item;
import net.runelite.api.ItemLayer;
import net.runelite.api.NPC;
import net.runelite.api.Node;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Projectile;
import net.runelite.api.Region;
import net.runelite.api.Tile;
import net.runelite.api.WallObject;
@@ -117,6 +121,11 @@ public class DevToolsOverlay extends Overlay
renderInventory(graphics);
}
if (plugin.isToggleProjectiles())
{
renderProjectiles(graphics);
}
renderWidgets(graphics);
return null;
@@ -325,6 +334,64 @@ public class DevToolsOverlay extends Overlay
}
}
private void renderProjectiles(Graphics2D graphics)
{
List<Projectile> projectiles = client.getProjectiles();
for (Projectile projectile : projectiles)
{
int originX = projectile.getX1();
int originY = projectile.getY1();
net.runelite.api.Point tilePoint = new net.runelite.api.Point(originX, originY);
Polygon poly = Perspective.getCanvasTilePoly(client, tilePoint);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, Color.RED);
}
long projectileLength = projectile.getLength().toMillis();
int projectileId = projectile.getId();
Actor projectileInteracting = projectile.getInteracting();
String infoString = "";
if (projectileInteracting == null)
{
infoString += "AoE";
}
else
{
infoString += "Targeted (T: " + projectileInteracting.getName() + ")";
}
infoString += " (ID: " + projectileId + ") (L: " + projectileLength + "ms)";
if (projectileInteracting != null)
{
OverlayUtil.renderActorOverlay(graphics, projectile.getInteracting(), infoString, Color.RED);
}
else
{
net.runelite.api.Point targetPoint = projectile.getTarget();
OverlayUtil.renderTilePointOverlay(graphics, client, targetPoint, infoString, Color.RED);
}
}
}
public void renderProjectileOrigin(Graphics2D graphics, Projectile projectile, int floor, net.runelite.api.Point origin)
{
Polygon poly = Perspective.getCanvasTilePoly(client, origin);
graphics.setColor(Color.RED);
graphics.setStroke(new BasicStroke(2));
graphics.drawPolygon(poly);
graphics.setColor(Color.RED);
graphics.fillPolygon(poly);
}
public void renderWidgets(Graphics2D graphics)
{
Widget widget = plugin.currentWidget;

View File

@@ -60,6 +60,7 @@ public class DevToolsPanel extends PluginPanel
private JButton renderWallsBtn = new JButton();
private JButton renderDecorBtn = new JButton();
private JButton renderInventoryBtn = new JButton();
private JButton renderProjectilesBtn = new JButton();
private JLabel textLbl = new JLabel();
private JLabel textColorLbl = new JLabel();
@@ -92,7 +93,7 @@ public class DevToolsPanel extends PluginPanel
private JPanel createOptionsPanel()
{
JPanel container = new JPanel();
container.setLayout(new GridLayout(5, 2, 3, 3));
container.setLayout(new GridLayout(6, 2, 3, 3));
renderPlayersBtn = new JButton("Players");
renderPlayersBtn.addActionListener(e ->
@@ -158,6 +159,14 @@ public class DevToolsPanel extends PluginPanel
});
container.add(renderInventoryBtn);
renderProjectilesBtn = new JButton("Projectiles");
renderProjectilesBtn.addActionListener(e ->
{
highlightButton(renderProjectilesBtn);
plugin.toggleProjectiles();
});
container.add(renderProjectilesBtn);
JButton settingsSnapshotBtn = new JButton("Get Settings");
settingsSnapshotBtn.addActionListener(settingsTracker::snapshot);
container.add(settingsSnapshotBtn);

View File

@@ -56,6 +56,7 @@ public class DevToolsPlugin extends Plugin
private boolean toggleWalls;
private boolean toggleDecor;
private boolean toggleInventory;
private boolean toggleProjectiles;
Widget currentWidget;
int itemIndex = -1;
@@ -135,6 +136,11 @@ public class DevToolsPlugin extends Plugin
toggleInventory = !toggleInventory;
}
void toggleProjectiles()
{
toggleProjectiles = !toggleProjectiles;
}
boolean isTogglePlayers()
{
return togglePlayers;
@@ -175,4 +181,8 @@ public class DevToolsPlugin extends Plugin
return toggleInventory;
}
boolean isToggleProjectiles()
{
return toggleProjectiles;
}
}

View File

@@ -38,6 +38,8 @@ import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.SpritePixels;
import net.runelite.api.TileObject;
@@ -318,6 +320,28 @@ public class OverlayUtil
}
}
public static void renderTilePointOverlay(Graphics2D graphics, Client client, Point point, String text, Color color)
{
Polygon poly = Perspective.getCanvasTilePoly(client, point);
if (poly != null)
{
renderPolygon(graphics, poly, color);
}
Point minimapLocation = Perspective.worldToMiniMap(client, point.getX(), point.getY());
if (minimapLocation != null)
{
renderMinimapLocation(graphics, minimapLocation, color);
}
Point textLocation = Perspective.getCanvasTextLocation(client, graphics, point, text, 0);
if (textLocation != null)
{
renderTextLocation(graphics, textLocation, text, color);
}
}
public static void setGraphicProperties(Graphics2D graphics)
{
graphics.setFont(FontManager.getRunescapeFont());

View File

@@ -32,17 +32,13 @@ import net.runelite.api.IndexedSprite;
import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
import net.runelite.api.NPC;
import net.runelite.api.Node;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.Projectile;
import net.runelite.api.Skill;
import net.runelite.api.Varbits;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.events.ClanMembersChanged;
import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameStateChanged;
@@ -50,8 +46,15 @@ import net.runelite.api.events.MapRegionChanged;
import net.runelite.api.events.PlayerMenuOptionsChanged;
import net.runelite.api.events.ResizeableChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import static net.runelite.client.callback.Hooks.eventBus;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSDeque;
import net.runelite.rs.api.RSIndexedSprite;
import net.runelite.rs.api.RSWidget;
@@ -331,6 +334,33 @@ public abstract class RSClientMixin implements RSClient
setMenuOptionCount(count);
}
@Inject
@Override
public List<Projectile> getProjectiles()
{
List<Projectile> projectiles = new ArrayList<Projectile>();
RSDeque projectileDeque = this.getProjectilesDeque();
Node head = projectileDeque.getHead();
Node current = head;
while (current != null)
{
if (current instanceof Projectile)
{
projectiles.add((Projectile) current);
}
current = current.getNext();
if (current == head)
{
break;
}
}
return projectiles;
}
@Inject
@Override
public void setModIcons(IndexedSprite[] modIcons)

View File

@@ -24,9 +24,13 @@
*/
package net.runelite.mixins;
import java.time.Duration;
import net.runelite.api.Actor;
import net.runelite.api.Point;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSNPC;
@@ -39,6 +43,74 @@ public abstract class RSProjectileMixin implements RSProjectile
@Shadow("clientInstance")
private static RSClient client;
@Inject
private int targetX;
@Inject
private int targetY;
@Inject
private int targetZ;
@Inject
Integer spawnCycle;
@Inject
@Override
public Point getTarget()
{
if (targetX == -1 || targetY == -1)
{
return null;
}
return new Point(targetX, targetY);
}
@Inject
@Override
public int getTargetZ()
{
return targetZ;
}
@Inject
@Override
public int getSpawnCycle()
{
return spawnCycle == null ? -1 : spawnCycle;
}
/**
* the cycles returned are for the amount of time moving this works
* better with the projectile movement event as it only gets called
* after the projectile starts moving
*
* @return total time projectile will move for in gamecycles
*/
@Inject
@Override
public int getCycleLength()
{
return getEndCycle() - getSpawnCycle();
}
@Inject
@Override
public Duration getLength()
{
return Duration.ofMillis(getCycleLength() * 20);
}
@Inject
@Override
public int getRemainingCycles()
{
int currentGameCycle = client.getGameCycle();
return getEndCycle() - currentGameCycle;
}
@Inject
@Override
public Actor getInteracting()
@@ -68,4 +140,22 @@ public abstract class RSProjectileMixin implements RSProjectile
return players[idx];
}
}
@Copy("moveProjectile")
abstract void moveProjectile(int targetX, int targetY, int targetZ, int gameCycle);
@Replace("moveProjectile")
public void rl$moveProjectile(int targetX, int targetY, int targetZ, int gameCycle)
{
this.targetX = targetX;
this.targetY = targetY;
this.targetZ = targetZ;
if (spawnCycle == null)
{
spawnCycle = client.getGameCycle();
}
moveProjectile(targetX, targetY, targetZ, gameCycle);
}
}

View File

@@ -146,6 +146,9 @@ public interface RSClient extends RSGameEngine, Client
@Import("groundItemDeque")
RSDeque[][][] getGroundItemDeque();
@Import("projectiles")
RSDeque getProjectilesDeque();
@Import("username")
@Override
String getUsername();
@@ -266,6 +269,7 @@ public interface RSClient extends RSGameEngine, Client
boolean isMenuOpen();
@Import("gameCycle")
@Override
int getGameCycle();
@Import("packetHandler")

View File

@@ -27,7 +27,7 @@ package net.runelite.rs.api;
import net.runelite.api.Projectile;
import net.runelite.mapping.Import;
public interface RSProjectile extends Projectile
public interface RSProjectile extends RSRenderable, Projectile
{
@Import("id")
@Override
@@ -35,4 +35,68 @@ public interface RSProjectile extends Projectile
@Import("interacting")
int getRsInteracting();
@Import("height")
@Override
int getHeight();
@Import("endHeight")
@Override
int getEndHeight();
@Import("x1")
@Override
int getX1();
@Import("y1")
@Override
int getY1();
@Import("floor")
@Override
int getFloor();
@Import("startMovementCycle")
@Override
int getStartMovementCycle();
@Import("endCycle")
@Override
int getEndCycle();
@Import("slope")
@Override
int getSlope();
@Import("startHeight")
@Override
int getStartHeight();
@Import("x")
@Override
double getX();
@Import("y")
@Override
double getY();
@Import("z")
@Override
double getZ();
@Import("scalar")
@Override
double getScalar();
@Import("velocityX")
@Override
double getVelocityX();
@Import("velocityY")
@Override
double getVelocityY();
@Import("velocityZ")
@Override
double getVelocityZ();
}