diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 228d6355c9..d45f55f89d 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -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 getProjectiles(); + } diff --git a/runelite-api/src/main/java/net/runelite/api/Projectile.java b/runelite-api/src/main/java/net/runelite/api/Projectile.java index bad70f9717..2497dfe248 100644 --- a/runelite-api/src/main/java/net/runelite/api/Projectile.java +++ b/runelite-api/src/main/java/net/runelite/api/Projectile.java @@ -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(); } diff --git a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java index 986d02591e..efe93c1243 100644 --- a/runelite-api/src/main/java/net/runelite/api/ProjectileID.java +++ b/runelite-api/src/main/java/net/runelite/api/ProjectileID.java @@ -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; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java index 80996c92b3..c51f3481d1 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeProjectileInfo.java @@ -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 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); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningConfig.java index a5ed6004a7..d646a1b382 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningConfig.java @@ -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", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java index 6c868e86ab..2d7935b521 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/aoewarnings/AoeWarningPlugin.java @@ -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; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java index d4dc6d456f..56ba1f7c97 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsOverlay.java @@ -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 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; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java index 6324222b1b..cd8d125da8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java @@ -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); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java index b0eec3328e..0cfce00c9b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java @@ -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; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index cf8d8215ce..5d92f2f174 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -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()); diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index b30e4cca72..b29ea0fed8 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -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 getProjectiles() + { + List projectiles = new ArrayList(); + 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) diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSProjectileMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSProjectileMixin.java index 20113ddb2a..94e2a71d44 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSProjectileMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSProjectileMixin.java @@ -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); + } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index cd1204a89d..8ba50a7812 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -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") diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSProjectile.java b/runescape-api/src/main/java/net/runelite/rs/api/RSProjectile.java index 1a5e1f6e8f..db90a83067 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSProjectile.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSProjectile.java @@ -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(); }