Merge branch 'master' into NPC-UPDATE-0cbfb2e4d
This commit is contained in:
42
.github/workflows/build.yml
vendored
42
.github/workflows/build.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
||||
pr-lint:
|
||||
name: PR title
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
steps:
|
||||
- name: PR title lint
|
||||
if: github.event_name == 'pull_request'
|
||||
@@ -15,49 +15,55 @@ jobs:
|
||||
title-regex: '^([\w-/]+): \w+'
|
||||
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v1
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@master
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Assembling
|
||||
run: gradlew assemble --console=plain
|
||||
run: ./gradlew assemble --console=plain
|
||||
- name: Building
|
||||
run: gradlew build --stacktrace -x test -x checkstyleMain --console=plain
|
||||
run: ./gradlew build --stacktrace -x test -x checkstyleMain --console=plain
|
||||
|
||||
test:
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
name: Test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v1
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@master
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Assembling
|
||||
run: gradlew assemble --console=plain
|
||||
run: ./gradlew assemble --console=plain
|
||||
- name: Testing
|
||||
run: gradlew test --stacktrace --console=plain
|
||||
run: ./gradlew test --stacktrace --console=plain
|
||||
|
||||
checkstyle:
|
||||
name: Checkstyle
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v1
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@master
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Assembling
|
||||
run: gradlew assemble --console=plain
|
||||
run: ./gradlew assemble --console=plain
|
||||
- name: Checking code conventions
|
||||
run: gradlew checkstyleMain --console=plain
|
||||
run: ./gradlew checkstyleMain --console=plain
|
||||
|
||||
approve:
|
||||
name: Approve
|
||||
@@ -67,6 +73,6 @@ jobs:
|
||||
steps:
|
||||
- name: Approve pull request
|
||||
if: github.event_name == 'pull_request' && github.actor == 'OpenOSRS'
|
||||
uses: hmarr/auto-approve-action@master
|
||||
uses: hmarr/auto-approve-action@v2.0.0
|
||||
with:
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
30
.github/workflows/gradle.yml
vendored
30
.github/workflows/gradle.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v1
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Update Gradle Wrapper
|
||||
@@ -28,17 +28,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Update Gradle dependencies
|
||||
run: ./gradlew useLatestVersions --console=plain
|
||||
- name: Create Gradle dependencies update Pull Request
|
||||
uses: Owain94/create-pull-request@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.OpenOSRS }}
|
||||
PULL_REQUEST_BRANCH: GRADLE-DEPENDENCY-UPDATE
|
||||
PULL_REQUEST_TITLE: 'project: Update gradle dependencies'
|
||||
PULL_REQUEST_BODY: This is an auto-generated PR with an updated gradle dependencies versions
|
||||
COMMIT_MESSAGE: 'project: Update gradle dependencies'
|
||||
PULL_REQUEST_LABELS: automated pull request, gradle
|
||||
- uses: actions/checkout@v1
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
- name: Update Gradle dependencies
|
||||
run: ./gradlew useLatestVersions --console=plain
|
||||
- name: Create Gradle dependencies update Pull Request
|
||||
uses: Owain94/create-pull-request@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.OpenOSRS }}
|
||||
PULL_REQUEST_BRANCH: GRADLE-DEPENDENCY-UPDATE
|
||||
PULL_REQUEST_TITLE: 'project: Update gradle dependencies'
|
||||
PULL_REQUEST_BODY: This is an auto-generated PR with an updated gradle dependencies versions
|
||||
COMMIT_MESSAGE: 'project: Update gradle dependencies'
|
||||
PULL_REQUEST_LABELS: automated pull request, gradle
|
||||
6
.github/workflows/scraper.yml
vendored
6
.github/workflows/scraper.yml
vendored
@@ -9,9 +9,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@master
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Make gradlew executable
|
||||
@@ -36,4 +36,4 @@ jobs:
|
||||
PULL_REQUEST_TITLE: 'Client: Update NPC stats'
|
||||
PULL_REQUEST_BODY: This is an auto-generated PR with changes from the OSRS wiki
|
||||
COMMIT_MESSAGE: 'Client: Update NPC stats'
|
||||
PULL_REQUEST_LABELS: automated pull request, NPC stats
|
||||
PULL_REQUEST_LABELS: automated pull request, NPC stats
|
||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -19,4 +19,4 @@ jobs:
|
||||
exempt-issue-label: 'awaiting-approval'
|
||||
exempt-pr-label: 'awaiting-approval'
|
||||
days-before-stale: 60
|
||||
days-before-close: 30
|
||||
days-before-close: 30
|
||||
@@ -273,6 +273,7 @@ public final class AnimationID
|
||||
// INFERNO animations
|
||||
public static final int JAL_NIB = 7574;
|
||||
public static final int JAL_MEJRAH = 7578;
|
||||
public static final int JAL_MEJRAH_STAND = 7577;
|
||||
public static final int JAL_AK_RANGE_ATTACK = 7581;
|
||||
public static final int JAL_AK_MELEE_ATTACK = 7582;
|
||||
public static final int JAL_AK_MAGIC_ATTACK = 7583;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,7 @@ import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.client.game.SpriteManager;
|
||||
import net.runelite.client.plugins.inferno.displaymodes.InfernoPrayerDisplayMode;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
@@ -41,16 +42,19 @@ import net.runelite.client.ui.overlay.components.ImageComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
|
||||
@Singleton
|
||||
public class InfernoJadOverlay extends Overlay
|
||||
public class InfernoInfoBoxOverlay extends Overlay
|
||||
{
|
||||
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
|
||||
private final Client client;
|
||||
private final InfernoPlugin plugin;
|
||||
private final SpriteManager spriteManager;
|
||||
private final PanelComponent imagePanelComponent = new PanelComponent();
|
||||
private BufferedImage prayMeleeSprite;
|
||||
private BufferedImage prayRangedSprite;
|
||||
private BufferedImage prayMagicSprite;
|
||||
|
||||
@Inject
|
||||
private InfernoJadOverlay(final Client client, final InfernoPlugin plugin, final SpriteManager spriteManager)
|
||||
private InfernoInfoBoxOverlay(final Client client, final InfernoPlugin plugin, final SpriteManager spriteManager)
|
||||
{
|
||||
setPosition(OverlayPosition.BOTTOM_RIGHT);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
@@ -62,48 +66,56 @@ public class InfernoJadOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isShowPrayerHelp() || (plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTTOM_RIGHT
|
||||
&& plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTH))
|
||||
if (plugin.getPrayerDisplayMode() != InfernoPrayerDisplayMode.BOTTOM_RIGHT
|
||||
&& plugin.getPrayerDisplayMode() != InfernoPrayerDisplayMode.BOTH)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
InfernoJad.Attack attack = null;
|
||||
int leastTicks = 999;
|
||||
|
||||
for (InfernoJad jad : plugin.getJads())
|
||||
{
|
||||
if (jad.getNextAttack() == null || jad.getTicksTillNextAttack() < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jad.getTicksTillNextAttack() < leastTicks)
|
||||
{
|
||||
leastTicks = jad.getTicksTillNextAttack();
|
||||
attack = jad.getNextAttack();
|
||||
}
|
||||
}
|
||||
|
||||
if (attack == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final BufferedImage prayerImage = getPrayerImage(attack);
|
||||
|
||||
imagePanelComponent.getChildren().clear();
|
||||
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
|
||||
imagePanelComponent.setBackgroundColor(client.isPrayerActive(attack.getPrayer())
|
||||
? ComponentConstants.STANDARD_BACKGROUND_COLOR
|
||||
: NOT_ACTIVATED_BACKGROUND_COLOR);
|
||||
|
||||
if (plugin.getClosestAttack() != null)
|
||||
{
|
||||
final BufferedImage prayerImage = getPrayerImage(plugin.getClosestAttack());
|
||||
|
||||
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
|
||||
imagePanelComponent.setBackgroundColor(client.isPrayerActive(plugin.getClosestAttack().getPrayer())
|
||||
? ComponentConstants.STANDARD_BACKGROUND_COLOR
|
||||
: NOT_ACTIVATED_BACKGROUND_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
imagePanelComponent.setBackgroundColor(ComponentConstants.STANDARD_BACKGROUND_COLOR);
|
||||
}
|
||||
|
||||
return imagePanelComponent.render(graphics);
|
||||
}
|
||||
|
||||
private BufferedImage getPrayerImage(InfernoJad.Attack attack)
|
||||
private BufferedImage getPrayerImage(InfernoNPC.Attack attack)
|
||||
{
|
||||
final int prayerSpriteID = attack == InfernoJad.Attack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
|
||||
return spriteManager.getSprite(prayerSpriteID, 0);
|
||||
if (prayMeleeSprite == null)
|
||||
{
|
||||
prayMeleeSprite = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MELEE, 0);
|
||||
}
|
||||
if (prayRangedSprite == null)
|
||||
{
|
||||
prayRangedSprite = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
|
||||
}
|
||||
if (prayMagicSprite == null)
|
||||
{
|
||||
prayMagicSprite = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
|
||||
}
|
||||
|
||||
switch (attack)
|
||||
{
|
||||
case MELEE:
|
||||
return prayMeleeSprite;
|
||||
case RANGED:
|
||||
return prayRangedSprite;
|
||||
case MAGIC:
|
||||
return prayMagicSprite;
|
||||
}
|
||||
|
||||
return prayMagicSprite;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
|
||||
* 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.inferno;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Prayer;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
public class InfernoJad
|
||||
{
|
||||
private static final int TICKS_AFTER_ANIMATION = 4;
|
||||
|
||||
private NPC npc;
|
||||
private Attack nextAttack;
|
||||
private int ticksTillNextAttack;
|
||||
|
||||
InfernoJad(NPC npc)
|
||||
{
|
||||
this.npc = npc;
|
||||
nextAttack = null;
|
||||
ticksTillNextAttack = -1;
|
||||
}
|
||||
|
||||
void updateNextAttack(Attack nextAttack)
|
||||
{
|
||||
this.nextAttack = nextAttack;
|
||||
this.ticksTillNextAttack = TICKS_AFTER_ANIMATION;
|
||||
}
|
||||
|
||||
void gameTick()
|
||||
{
|
||||
if (ticksTillNextAttack < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ticksTillNextAttack--;
|
||||
|
||||
if (ticksTillNextAttack < 0)
|
||||
{
|
||||
nextAttack = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
enum Attack
|
||||
{
|
||||
MAGIC(AnimationID.JALTOK_JAD_MAGE_ATTACK, Prayer.PROTECT_FROM_MAGIC),
|
||||
RANGE(AnimationID.JALTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
|
||||
|
||||
private final int animation;
|
||||
private final Prayer prayer;
|
||||
|
||||
Attack(final int animation, final Prayer prayer)
|
||||
{
|
||||
this.animation = animation;
|
||||
this.prayer = prayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
|
||||
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
|
||||
* 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.
|
||||
* 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 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
|
||||
@@ -25,162 +25,376 @@
|
||||
package net.runelite.client.plugins.inferno;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
public class InfernoNPC
|
||||
{
|
||||
public enum Attackstyle
|
||||
{
|
||||
MAGE("Mage", Color.CYAN),
|
||||
RANGE("Range", Color.GREEN),
|
||||
MELEE("Melee", Color.WHITE),
|
||||
RANDOM("Random", Color.ORANGE);
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private String name;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Color color;
|
||||
|
||||
Attackstyle(String s, Color c)
|
||||
{
|
||||
this.name = s;
|
||||
this.color = c;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private NPC npc;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private String name;
|
||||
|
||||
private Type type;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private Attackstyle attackstyle;
|
||||
|
||||
private Attack nextAttack;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int attackTicks;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int priority;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int ticksTillAttack = -1;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean attacking = false;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int attackAnimation;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private boolean isMidAttack = false;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int distanceToPlayer = 0;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
int textLocHeight;
|
||||
private int ticksTillNextAttack;
|
||||
private int lastAnimation;
|
||||
private boolean lastCanAttack;
|
||||
//0 = not in LOS, 1 = in LOS after move, 2 = in LOS
|
||||
private final Map<WorldPoint, Integer> safeSpotCache;
|
||||
|
||||
InfernoNPC(NPC npc)
|
||||
{
|
||||
this.npc = npc;
|
||||
textLocHeight = npc.getLogicalHeight() + 40;
|
||||
switch (npc.getId())
|
||||
this.type = Type.typeFromId(npc.getId());
|
||||
this.nextAttack = type.getDefaultAttack();
|
||||
this.ticksTillNextAttack = 0;
|
||||
this.lastAnimation = -1;
|
||||
this.lastCanAttack = false;
|
||||
this.safeSpotCache = new HashMap();
|
||||
}
|
||||
|
||||
void updateNextAttack(Attack nextAttack, int ticksTillNextAttack)
|
||||
{
|
||||
this.nextAttack = nextAttack;
|
||||
this.ticksTillNextAttack = ticksTillNextAttack;
|
||||
}
|
||||
|
||||
private void updateNextAttack(Attack nextAttack)
|
||||
{
|
||||
this.nextAttack = nextAttack;
|
||||
}
|
||||
|
||||
boolean canAttack(Client client, WorldPoint target)
|
||||
{
|
||||
if (safeSpotCache.containsKey(target))
|
||||
{
|
||||
case NpcID.JALAKREKKET:
|
||||
attackTicks = 4;
|
||||
name = "lil mel";
|
||||
attackAnimation = 7582;
|
||||
attackstyle = Attackstyle.MELEE;
|
||||
priority = 7;
|
||||
break;
|
||||
return safeSpotCache.get(target) == 2;
|
||||
}
|
||||
|
||||
case NpcID.JALAKREKXIL:
|
||||
attackTicks = 4;
|
||||
name = "lil range";
|
||||
attackAnimation = 7583;
|
||||
attackstyle = Attackstyle.RANGE;
|
||||
priority = 6;
|
||||
break;
|
||||
boolean hasLos = new WorldArea(target, 1, 1).hasLineOfSightTo(client, this.getNpc().getWorldArea());
|
||||
boolean hasRange = this.getType().getDefaultAttack() == Attack.MELEE ? this.getNpc().getWorldArea().isInMeleeDistance(target)
|
||||
: this.getNpc().getWorldArea().distanceTo(target) <= this.getType().getRange();
|
||||
|
||||
case NpcID.JALAKREKMEJ:
|
||||
attackTicks = 4;
|
||||
name = "lil mage";
|
||||
attackAnimation = 7581;
|
||||
attackstyle = Attackstyle.MAGE;
|
||||
priority = 5;
|
||||
break;
|
||||
if (hasLos && hasRange)
|
||||
{
|
||||
safeSpotCache.put(target, 2);
|
||||
}
|
||||
|
||||
case NpcID.JALMEJRAH:
|
||||
attackTicks = 3;
|
||||
name = "bat";
|
||||
attackAnimation = 7578;
|
||||
attackstyle = Attackstyle.RANGE;
|
||||
priority = 4;
|
||||
break;
|
||||
return hasLos && hasRange;
|
||||
}
|
||||
|
||||
case NpcID.JALAK:
|
||||
attackTicks = 6;
|
||||
name = "blob";
|
||||
attackAnimation = 7583; // also 7581
|
||||
attackstyle = Attackstyle.RANDOM;
|
||||
priority = 3;
|
||||
break;
|
||||
boolean canMoveToAttack(Client client, WorldPoint target, List<WorldPoint> obstacles)
|
||||
{
|
||||
if (safeSpotCache.containsKey(target))
|
||||
{
|
||||
return safeSpotCache.get(target) == 1 || safeSpotCache.get(target) == 2;
|
||||
}
|
||||
|
||||
case NpcID.JALIMKOT:
|
||||
attackTicks = 4;
|
||||
name = "meleer";
|
||||
attackAnimation = 7597;
|
||||
attackstyle = Attackstyle.MELEE;
|
||||
priority = 2;
|
||||
break;
|
||||
final List<WorldPoint> realObstacles = new ArrayList<>();
|
||||
for (WorldPoint obstacle : obstacles)
|
||||
{
|
||||
if (this.getNpc().getWorldArea().toWorldPointList().contains(obstacle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
case NpcID.JALXIL:
|
||||
attackTicks = 4;
|
||||
name = "ranger";
|
||||
attackAnimation = 7605;
|
||||
attackstyle = Attackstyle.RANGE;
|
||||
priority = 1;
|
||||
break;
|
||||
realObstacles.add(obstacle);
|
||||
}
|
||||
|
||||
case NpcID.JALZEK:
|
||||
attackTicks = 4;
|
||||
name = "mager";
|
||||
attackAnimation = 7610;
|
||||
attackstyle = Attackstyle.MAGE;
|
||||
priority = 0;
|
||||
break;
|
||||
final WorldArea targetArea = new WorldArea(target, 1, 1);
|
||||
WorldArea currentWorldArea = this.getNpc().getWorldArea();
|
||||
|
||||
default:
|
||||
attackTicks = 0;
|
||||
int steps = 0;
|
||||
while (true)
|
||||
{
|
||||
// Prevent infinite loop in case of pathfinding failure
|
||||
steps++;
|
||||
if (steps > 30)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final WorldArea predictedWorldArea = currentWorldArea.calculateNextTravellingPoint(client, targetArea, true, x ->
|
||||
{
|
||||
for (WorldPoint obstacle : realObstacles)
|
||||
{
|
||||
if (new WorldArea(x, 1, 1).intersectsWith(new WorldArea(obstacle, 1, 1)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Will only happen when NPC is underneath player or moving out of scene (but this will never show on overlay)
|
||||
if (predictedWorldArea == null)
|
||||
{
|
||||
safeSpotCache.put(target, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (predictedWorldArea == currentWorldArea)
|
||||
{
|
||||
safeSpotCache.put(target, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasLos = new WorldArea(target, 1, 1).hasLineOfSightTo(client, predictedWorldArea);
|
||||
boolean hasRange = this.getType().getDefaultAttack() == Attack.MELEE ? predictedWorldArea.isInMeleeDistance(target)
|
||||
: predictedWorldArea.distanceTo(target) <= this.getType().getRange();
|
||||
|
||||
if (hasLos && hasRange)
|
||||
{
|
||||
safeSpotCache.put(target, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
currentWorldArea = predictedWorldArea;
|
||||
}
|
||||
}
|
||||
|
||||
public String info()
|
||||
private boolean couldAttackPrevTick(Client client, WorldPoint lastPlayerLocation)
|
||||
{
|
||||
String info = "";
|
||||
|
||||
if (attacking)
|
||||
{
|
||||
info += ticksTillAttack;
|
||||
}
|
||||
//info += " D: " + distanceToPlayer;
|
||||
|
||||
return info;
|
||||
return new WorldArea(lastPlayerLocation, 1, 1).hasLineOfSightTo(client, this.getNpc().getWorldArea());
|
||||
}
|
||||
|
||||
void attacked()
|
||||
void gameTick(Client client, WorldPoint lastPlayerLocation, boolean finalPhase)
|
||||
{
|
||||
ticksTillAttack = attackTicks;
|
||||
attacking = true;
|
||||
safeSpotCache.clear();
|
||||
|
||||
if (ticksTillNextAttack > 0)
|
||||
{
|
||||
this.ticksTillNextAttack--;
|
||||
}
|
||||
|
||||
//Jad animation detection
|
||||
if (this.getType() == Type.JAD && this.getNpc().getAnimation() != -1 && this.getNpc().getAnimation() != this.lastAnimation)
|
||||
{
|
||||
final InfernoNPC.Attack currentAttack = InfernoNPC.Attack.attackFromId(this.getNpc().getAnimation());
|
||||
|
||||
if (currentAttack != null && currentAttack != Attack.UNKNOWN)
|
||||
{
|
||||
this.updateNextAttack(currentAttack, this.getType().getTicksAfterAnimation());
|
||||
}
|
||||
}
|
||||
|
||||
if (ticksTillNextAttack <= 0)
|
||||
{
|
||||
switch (this.getType())
|
||||
{
|
||||
case ZUK:
|
||||
if (this.getNpc().getAnimation() == AnimationID.TZKAL_ZUK)
|
||||
{
|
||||
if (finalPhase)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), 10);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JAD:
|
||||
if (this.getNextAttack() != Attack.UNKNOWN)
|
||||
{
|
||||
// Jad's cycle continuous after his animation + attack but there's no animation to alert it
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), 8);
|
||||
}
|
||||
break;
|
||||
case BLOB:
|
||||
//RS pathfinding + LOS = hell, so if it can attack you the tick you were on previously, start attack cycle
|
||||
if (!this.lastCanAttack && this.couldAttackPrevTick(client, lastPlayerLocation))
|
||||
{
|
||||
this.updateNextAttack(Attack.UNKNOWN, 3);
|
||||
}
|
||||
//If there's no animation when coming out of the safespot, the blob is detecting prayer
|
||||
else if (!this.lastCanAttack && this.canAttack(client, client.getLocalPlayer().getWorldLocation()))
|
||||
{
|
||||
this.updateNextAttack(Attack.UNKNOWN, 4);
|
||||
}
|
||||
//This will activate another attack cycle
|
||||
else if (this.getNpc().getAnimation() != -1)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), this.getType().getTicksAfterAnimation());
|
||||
}
|
||||
break;
|
||||
case BAT:
|
||||
// Range + LOS check for bat because it suffers from the defense animation bug, also dont activate on "stand" animation
|
||||
if (this.canAttack(client, client.getLocalPlayer().getWorldLocation())
|
||||
&& this.getNpc().getAnimation() != AnimationID.JAL_MEJRAH_STAND && this.getNpc().getAnimation() != -1)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), this.getType().getTicksAfterAnimation());
|
||||
}
|
||||
break;
|
||||
case MELEE:
|
||||
case RANGER:
|
||||
case MAGE:
|
||||
// For the meleer, ranger and mage the attack animation is always prioritized so only check for those
|
||||
// Normal attack animation, doesnt suffer from defense animation bug. Activate usual attack cycle
|
||||
if (this.getNpc().getAnimation() == AnimationID.JAL_IMKOT
|
||||
|| this.getNpc().getAnimation() == AnimationID.JAL_XIL_RANGE_ATTACK || this.getNpc().getAnimation() == AnimationID.JAL_XIL_MELEE_ATTACK
|
||||
|| this.getNpc().getAnimation() == AnimationID.JAL_ZEK_MAGE_ATTACK || this.getNpc().getAnimation() == AnimationID.JAL_ZEK_MELEE_ATTACK)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), this.getType().getTicksAfterAnimation());
|
||||
}
|
||||
// Burrow into ground animation for meleer
|
||||
else if (this.getNpc().getAnimation() == 7600)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), 12);
|
||||
}
|
||||
// Respawn enemy animation for mage
|
||||
else if (this.getNpc().getAnimation() == 7611)
|
||||
{
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), 8);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.getNpc().getAnimation() != -1)
|
||||
{
|
||||
// This will activate another attack cycle
|
||||
this.updateNextAttack(this.getType().getDefaultAttack(), this.getType().getTicksAfterAnimation());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Blob prayer detection
|
||||
if (this.getType() == Type.BLOB && this.getTicksTillNextAttack() == 3
|
||||
&& client.getLocalPlayer().getWorldLocation().distanceTo(this.getNpc().getWorldArea()) <= Type.BLOB.getRange())
|
||||
{
|
||||
InfernoNPC.Attack nextBlobAttack = InfernoNPC.Attack.UNKNOWN;
|
||||
if (client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES))
|
||||
{
|
||||
nextBlobAttack = InfernoNPC.Attack.MAGIC;
|
||||
}
|
||||
else if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC))
|
||||
{
|
||||
nextBlobAttack = InfernoNPC.Attack.RANGED;
|
||||
}
|
||||
|
||||
this.updateNextAttack(nextBlobAttack);
|
||||
}
|
||||
|
||||
// This is for jad (jad's animation lasts till after the attack is launched, which fucks up the attack cycle)
|
||||
lastAnimation = this.getNpc().getAnimation();
|
||||
// This is for blob (to check if player just came out of safespot)
|
||||
lastCanAttack = this.canAttack(client, client.getLocalPlayer().getWorldLocation());
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
enum Attack
|
||||
{
|
||||
MELEE(Prayer.PROTECT_FROM_MELEE,
|
||||
Color.ORANGE,
|
||||
Color.RED,
|
||||
new int[]{
|
||||
AnimationID.JAL_NIB,
|
||||
AnimationID.JAL_AK_MELEE_ATTACK,
|
||||
AnimationID.JAL_IMKOT,
|
||||
AnimationID.JAL_XIL_MELEE_ATTACK,
|
||||
AnimationID.JAL_ZEK_MELEE_ATTACK, //TODO: Yt-HurKot attack animation
|
||||
}),
|
||||
RANGED(Prayer.PROTECT_FROM_MISSILES,
|
||||
Color.GREEN,
|
||||
new Color(0, 128, 0),
|
||||
new int[]{
|
||||
AnimationID.JAL_MEJRAH,
|
||||
AnimationID.JAL_AK_RANGE_ATTACK,
|
||||
AnimationID.JAL_XIL_RANGE_ATTACK,
|
||||
AnimationID.JALTOK_JAD_RANGE_ATTACK,
|
||||
}),
|
||||
MAGIC(Prayer.PROTECT_FROM_MAGIC,
|
||||
Color.CYAN,
|
||||
Color.BLUE,
|
||||
new int[]{
|
||||
AnimationID.JAL_AK_MAGIC_ATTACK,
|
||||
AnimationID.JAL_ZEK_MAGE_ATTACK,
|
||||
AnimationID.JALTOK_JAD_MAGE_ATTACK
|
||||
}),
|
||||
UNKNOWN(null, Color.WHITE, Color.GRAY, new int[]{});
|
||||
|
||||
private final Prayer prayer;
|
||||
private final Color normalColor;
|
||||
private final Color criticalColor;
|
||||
private final int[] animationIds;
|
||||
|
||||
Attack(Prayer prayer, Color normalColor, Color criticalColor, int[] animationIds)
|
||||
{
|
||||
this.prayer = prayer;
|
||||
this.normalColor = normalColor;
|
||||
this.criticalColor = criticalColor;
|
||||
this.animationIds = animationIds;
|
||||
}
|
||||
|
||||
static Attack attackFromId(int animationId)
|
||||
{
|
||||
for (Attack attack : Attack.values())
|
||||
{
|
||||
if (ArrayUtils.contains(attack.getAnimationIds(), animationId))
|
||||
{
|
||||
return attack;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
enum Type
|
||||
{
|
||||
NIBBLER(new int[]{NpcID.JALNIB}, Attack.MELEE, 4, 99, 100),
|
||||
BAT(new int[]{NpcID.JALMEJRAH}, Attack.RANGED, 3, 4, 7),
|
||||
BLOB(new int[]{NpcID.JALAK}, Attack.UNKNOWN, 6, 15, 4),
|
||||
MELEE(new int[]{NpcID.JALIMKOT}, Attack.MELEE, 4, 1, 3),
|
||||
RANGER(new int[]{NpcID.JALXIL, NpcID.JALXIL_7702}, Attack.RANGED, 4, 98, 2),
|
||||
MAGE(new int[]{NpcID.JALZEK, NpcID.JALZEK_7703}, Attack.MAGIC, 4, 98, 1),
|
||||
JAD(new int[]{NpcID.JALTOKJAD, NpcID.JALTOKJAD_7704}, Attack.UNKNOWN, 3, 99, 0),
|
||||
HEALER_JAD(new int[]{NpcID.YTHURKOT, NpcID.YTHURKOT_7701, NpcID.YTHURKOT_7705}, Attack.MELEE, 4, 1, 6),
|
||||
ZUK(new int[]{NpcID.TZKALZUK}, Attack.UNKNOWN, 10, 99, 99),
|
||||
HEALER_ZUK(new int[]{NpcID.JALMEJJAK}, Attack.UNKNOWN, -1, 99, 100);
|
||||
|
||||
private final int[] npcIds;
|
||||
private final Attack defaultAttack;
|
||||
private final int ticksAfterAnimation;
|
||||
private final int range;
|
||||
private final int priority;
|
||||
|
||||
Type(int[] npcIds, Attack defaultAttack, int ticksAfterAnimation, int range, int priority)
|
||||
{
|
||||
this.npcIds = npcIds;
|
||||
this.defaultAttack = defaultAttack;
|
||||
this.ticksAfterAnimation = ticksAfterAnimation;
|
||||
this.range = range;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
static Type typeFromId(int npcId)
|
||||
{
|
||||
for (Type type : Type.values())
|
||||
{
|
||||
if (ArrayUtils.contains(type.getNpcIds(), npcId))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
|
||||
* 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.inferno;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
@Singleton
|
||||
public class InfernoNibblerOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final InfernoPlugin plugin;
|
||||
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@Inject
|
||||
public InfernoNibblerOverlay(final Client client, final InfernoPlugin plugin)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isDisplayNibblerOverlay() || plugin.getNibblers().size() == 0 || client.getMapRegions()[0] != 9043)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
|
||||
tableComponent.addRow("Nibblers Left: ", Integer.toString(plugin.getNibblers().size()));
|
||||
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Jacky <liangj97@gmail.com>
|
||||
* 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.inferno;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.inferno.displaymodes.InfernoPrayerDisplayMode;
|
||||
import net.runelite.client.plugins.inferno.displaymodes.InfernoSafespotDisplayMode;
|
||||
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.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
@Singleton
|
||||
public class InfernoOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private static final int TICK_PIXEL_SIZE = 60;
|
||||
private static final int BOX_WIDTH = 10;
|
||||
private static final int BOX_HEIGHT = 5;
|
||||
|
||||
private final InfernoPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public InfernoOverlay(final Client client, final InfernoPlugin plugin)
|
||||
private InfernoOverlay(final Client client, final InfernoPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@@ -58,55 +48,426 @@ public class InfernoOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!client.isInInstancedRegion() || client.getMapRegions()[0] != 9043)
|
||||
final Widget meleePrayerWidget = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MELEE);
|
||||
final Widget rangePrayerWidget = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
|
||||
final Widget magicPrayerWidget = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC);
|
||||
|
||||
if (plugin.isIndicateObstacles())
|
||||
{
|
||||
return null;
|
||||
renderObstacles(graphics);
|
||||
}
|
||||
|
||||
for (InfernoNPC monster : plugin.getMonsters().values())
|
||||
if (plugin.getSafespotDisplayMode() == InfernoSafespotDisplayMode.AREA)
|
||||
{
|
||||
NPC npc = monster.getNpc();
|
||||
//if (npc == null || !config.showPrayer()) return;
|
||||
LocalPoint lp = npc.getLocalLocation();
|
||||
if (lp != null)
|
||||
renderAreaSafepots(graphics);
|
||||
}
|
||||
else if (plugin.getSafespotDisplayMode() == InfernoSafespotDisplayMode.INDIVIDUAL_TILES)
|
||||
{
|
||||
renderIndividualTilesSafespots(graphics);
|
||||
}
|
||||
|
||||
for (InfernoNPC infernoNPC : plugin.getInfernoNpcs())
|
||||
{
|
||||
if (infernoNPC.getNpc().getConvexHull() != null)
|
||||
{
|
||||
Point point = Perspective.localToCanvas(client, lp, client.getPlane(), npc.getLogicalHeight());
|
||||
if (point != null)
|
||||
if (plugin.isIndicateNonSafespotted() && plugin.isNormalSafespots(infernoNPC)
|
||||
&& infernoNPC.canAttack(client, client.getLocalPlayer().getWorldLocation()))
|
||||
{
|
||||
if (monster.getTicksTillAttack() == 1 || (monster.getName().equals("blob") && monster.getTicksTillAttack() <= 3))
|
||||
{
|
||||
renderTextLocation(graphics, monster, monster.info(), Color.GREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderTextLocation(graphics, monster, monster.info(), Color.RED);
|
||||
}
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.RED);
|
||||
}
|
||||
if (plugin.isIndicateTemporarySafespotted() && plugin.isNormalSafespots(infernoNPC)
|
||||
&& infernoNPC.canMoveToAttack(client, client.getLocalPlayer().getWorldLocation(), plugin.getObstacles()))
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.YELLOW);
|
||||
}
|
||||
if (plugin.isIndicateSafespotted() && plugin.isNormalSafespots(infernoNPC))
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.GREEN);
|
||||
}
|
||||
if (plugin.isIndicateNibblers() && infernoNPC.getType() == InfernoNPC.Type.NIBBLER
|
||||
&& (!plugin.isIndicateCentralNibbler() || plugin.getCentralNibbler() != infernoNPC))
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.CYAN);
|
||||
}
|
||||
if (plugin.isIndicateCentralNibbler() && infernoNPC.getType() == InfernoNPC.Type.NIBBLER
|
||||
&& plugin.getCentralNibbler() == infernoNPC)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.BLUE);
|
||||
}
|
||||
if (plugin.isIndicateActiveHealersJad() && infernoNPC.getType() == InfernoNPC.Type.HEALER_JAD
|
||||
&& infernoNPC.getNpc().getInteracting() != client.getLocalPlayer())
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.CYAN);
|
||||
}
|
||||
if (plugin.isIndicateActiveHealersZuk() && infernoNPC.getType() == InfernoNPC.Type.HEALER_ZUK
|
||||
&& infernoNPC.getNpc().getInteracting() != client.getLocalPlayer())
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, infernoNPC.getNpc().getConvexHull(), Color.CYAN);
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin.isIndicateNpcPosition(infernoNPC))
|
||||
{
|
||||
renderNpcLocation(graphics, infernoNPC);
|
||||
}
|
||||
|
||||
if (plugin.isTicksOnNpc(infernoNPC) && infernoNPC.getTicksTillNextAttack() > 0)
|
||||
{
|
||||
renderTicksOnNpc(graphics, infernoNPC);
|
||||
}
|
||||
}
|
||||
|
||||
if ((plugin.getPrayerDisplayMode() == InfernoPrayerDisplayMode.PRAYER_TAB
|
||||
|| plugin.getPrayerDisplayMode() == InfernoPrayerDisplayMode.BOTH)
|
||||
&& (meleePrayerWidget != null && !meleePrayerWidget.isHidden()
|
||||
&& rangePrayerWidget != null && !rangePrayerWidget.isHidden()
|
||||
&& magicPrayerWidget != null && !magicPrayerWidget.isHidden()))
|
||||
{
|
||||
renderPrayerIconOverlay(graphics);
|
||||
|
||||
if (plugin.isDescendingBoxes())
|
||||
{
|
||||
renderDescendingBoxes(graphics);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// renders text location
|
||||
private static void renderTextLocation(Graphics2D graphics, InfernoNPC actor, String text, Color color)
|
||||
private void renderObstacles(Graphics2D graphics)
|
||||
{
|
||||
graphics.setFont(new Font("Arial", Font.BOLD, 15));
|
||||
Point textLocation = actor.getNpc().getCanvasTextLocation(graphics, text, actor.textLocHeight + 40);
|
||||
if (Strings.isNullOrEmpty(text))
|
||||
for (WorldPoint worldPoint : plugin.getObstacles())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final LocalPoint localPoint = LocalPoint.fromWorld(client, worldPoint);
|
||||
|
||||
if (textLocation != null)
|
||||
{
|
||||
int x = textLocation.getX();
|
||||
int y = textLocation.getY();
|
||||
if (localPoint == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.drawString(text, x + 1, y + 1);
|
||||
final Polygon tilePoly = Perspective.getCanvasTilePoly(client, localPoint);
|
||||
|
||||
graphics.setColor(color);
|
||||
graphics.drawString(text, x, y);
|
||||
if (tilePoly == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, tilePoly, Color.BLUE);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAreaSafepots(Graphics2D graphics)
|
||||
{
|
||||
for (int safeSpotId : plugin.getSafeSpotAreas().keySet())
|
||||
{
|
||||
if (safeSpotId > 6)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color colorEdge1 = null;
|
||||
Color colorEdge2 = null;
|
||||
Color colorFill = null;
|
||||
|
||||
switch (safeSpotId)
|
||||
{
|
||||
case 0:
|
||||
colorEdge1 = Color.WHITE;
|
||||
colorFill = Color.WHITE;
|
||||
break;
|
||||
case 1:
|
||||
colorEdge1 = Color.RED;
|
||||
colorFill = Color.RED;
|
||||
break;
|
||||
case 2:
|
||||
colorEdge1 = Color.GREEN;
|
||||
colorFill = Color.GREEN;
|
||||
break;
|
||||
case 3:
|
||||
colorEdge1 = Color.BLUE;
|
||||
colorFill = Color.BLUE;
|
||||
break;
|
||||
case 4:
|
||||
colorEdge1 = Color.RED;
|
||||
colorEdge2 = Color.GREEN;
|
||||
colorFill = Color.YELLOW;
|
||||
break;
|
||||
case 5:
|
||||
colorEdge1 = Color.RED;
|
||||
colorEdge2 = Color.BLUE;
|
||||
colorFill = new Color(255, 0, 255);
|
||||
break;
|
||||
case 6:
|
||||
colorEdge1 = Color.GREEN;
|
||||
colorEdge2 = Color.BLUE;
|
||||
colorFill = new Color(0, 255, 255);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
//Add all edges, calculate average edgeSize and indicate tiles
|
||||
final List<int[][]> allEdges = new ArrayList<>();
|
||||
int edgeSizeSquared = 0;
|
||||
|
||||
for (WorldPoint worldPoint : plugin.getSafeSpotAreas().get(safeSpotId))
|
||||
{
|
||||
final LocalPoint localPoint = LocalPoint.fromWorld(client, worldPoint);
|
||||
|
||||
if (localPoint == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final Polygon tilePoly = Perspective.getCanvasTilePoly(client, localPoint);
|
||||
|
||||
if (tilePoly == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OverlayUtil.renderAreaTilePolygon(graphics, tilePoly, colorFill);
|
||||
|
||||
final int[][] edge1 = new int[][]{{tilePoly.xpoints[0], tilePoly.ypoints[0]}, {tilePoly.xpoints[1], tilePoly.ypoints[1]}};
|
||||
edgeSizeSquared += Math.pow(tilePoly.xpoints[0] - tilePoly.xpoints[1], 2) + Math.pow(tilePoly.ypoints[0] - tilePoly.ypoints[1], 2);
|
||||
allEdges.add(edge1);
|
||||
final int[][] edge2 = new int[][]{{tilePoly.xpoints[1], tilePoly.ypoints[1]}, {tilePoly.xpoints[2], tilePoly.ypoints[2]}};
|
||||
edgeSizeSquared += Math.pow(tilePoly.xpoints[1] - tilePoly.xpoints[2], 2) + Math.pow(tilePoly.ypoints[1] - tilePoly.ypoints[2], 2);
|
||||
allEdges.add(edge2);
|
||||
final int[][] edge3 = new int[][]{{tilePoly.xpoints[2], tilePoly.ypoints[2]}, {tilePoly.xpoints[3], tilePoly.ypoints[3]}};
|
||||
edgeSizeSquared += Math.pow(tilePoly.xpoints[2] - tilePoly.xpoints[3], 2) + Math.pow(tilePoly.ypoints[2] - tilePoly.ypoints[3], 2);
|
||||
allEdges.add(edge3);
|
||||
final int[][] edge4 = new int[][]{{tilePoly.xpoints[3], tilePoly.ypoints[3]}, {tilePoly.xpoints[0], tilePoly.ypoints[0]}};
|
||||
edgeSizeSquared += Math.pow(tilePoly.xpoints[3] - tilePoly.xpoints[0], 2) + Math.pow(tilePoly.ypoints[3] - tilePoly.ypoints[0], 2);
|
||||
allEdges.add(edge4);
|
||||
}
|
||||
|
||||
if (allEdges.size() <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
edgeSizeSquared /= allEdges.size();
|
||||
|
||||
//Find and indicate unique edges
|
||||
final int toleranceSquared = (int) Math.ceil(edgeSizeSquared / 6);
|
||||
|
||||
for (int i = 0; i < allEdges.size(); i++)
|
||||
{
|
||||
int[][] baseEdge = allEdges.get(i);
|
||||
|
||||
boolean duplicate = false;
|
||||
|
||||
for (int j = 0; j < allEdges.size(); j++)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int[][] checkEdge = allEdges.get(j);
|
||||
|
||||
if (edgeEqualsEdge(baseEdge, checkEdge, toleranceSquared))
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!duplicate)
|
||||
{
|
||||
OverlayUtil.renderFullLine(graphics, baseEdge, colorEdge1);
|
||||
|
||||
if (colorEdge2 != null)
|
||||
{
|
||||
OverlayUtil.renderDashedLine(graphics, baseEdge, colorEdge2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void renderIndividualTilesSafespots(Graphics2D graphics)
|
||||
{
|
||||
for (WorldPoint worldPoint : plugin.getSafeSpotMap().keySet())
|
||||
{
|
||||
final int safeSpotId = plugin.getSafeSpotMap().get(worldPoint);
|
||||
|
||||
if (safeSpotId > 6)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final LocalPoint localPoint = LocalPoint.fromWorld(client, worldPoint);
|
||||
|
||||
if (localPoint == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final Polygon tilePoly = Perspective.getCanvasTilePoly(client, localPoint);
|
||||
|
||||
if (tilePoly == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color color;
|
||||
switch (safeSpotId)
|
||||
{
|
||||
case 0:
|
||||
color = Color.WHITE;
|
||||
break;
|
||||
case 1:
|
||||
color = Color.RED;
|
||||
break;
|
||||
case 2:
|
||||
color = Color.GREEN;
|
||||
break;
|
||||
case 3:
|
||||
color = Color.BLUE;
|
||||
break;
|
||||
case 4:
|
||||
color = new Color(255, 255, 0);
|
||||
break;
|
||||
case 5:
|
||||
color = new Color(255, 0, 255);
|
||||
break;
|
||||
case 6:
|
||||
color = new Color(0, 255, 255);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, tilePoly, color);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderTicksOnNpc(Graphics2D graphics, InfernoNPC infernoNPC)
|
||||
{
|
||||
final Color color = (infernoNPC.getTicksTillNextAttack() == 1
|
||||
|| (infernoNPC.getType() == InfernoNPC.Type.BLOB && infernoNPC.getTicksTillNextAttack() == 4))
|
||||
? infernoNPC.getNextAttack().getCriticalColor() : infernoNPC.getNextAttack().getNormalColor();
|
||||
final Point canvasPoint = infernoNPC.getNpc().getCanvasTextLocation(
|
||||
graphics, String.valueOf(infernoNPC.getTicksTillNextAttack()), 0);
|
||||
OverlayUtil.renderTextLocation(graphics, String.valueOf(infernoNPC.getTicksTillNextAttack()),
|
||||
plugin.getTextSize(), plugin.getFontStyle().getFont(), color, canvasPoint, false, 0);
|
||||
}
|
||||
|
||||
private void renderNpcLocation(Graphics2D graphics, InfernoNPC infernoNPC)
|
||||
{
|
||||
final LocalPoint localPoint = LocalPoint.fromWorld(client, infernoNPC.getNpc().getWorldLocation());
|
||||
|
||||
if (localPoint != null)
|
||||
{
|
||||
final Polygon tilePolygon = Perspective.getCanvasTilePoly(client, localPoint);
|
||||
|
||||
if (tilePolygon != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, tilePolygon, Color.BLUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderDescendingBoxes(Graphics2D graphics)
|
||||
{
|
||||
for (Integer tick : plugin.getUpcomingAttacks().keySet())
|
||||
{
|
||||
final Map<InfernoNPC.Attack, Integer> attackPriority = plugin.getUpcomingAttacks().get(tick);
|
||||
int bestPriority = 999;
|
||||
InfernoNPC.Attack bestAttack = null;
|
||||
|
||||
for (Map.Entry<InfernoNPC.Attack, Integer> attackEntry : attackPriority.entrySet())
|
||||
{
|
||||
if (attackEntry.getValue() < bestPriority)
|
||||
{
|
||||
bestAttack = attackEntry.getKey();
|
||||
bestPriority = attackEntry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
for (InfernoNPC.Attack currentAttack : attackPriority.keySet())
|
||||
{
|
||||
//TODO: Config values for these colors
|
||||
final Color color = (tick == 1 && currentAttack == bestAttack) ? Color.RED : Color.ORANGE;
|
||||
final Widget prayerWidget = client.getWidget(currentAttack.getPrayer().getWidgetInfo());
|
||||
|
||||
int baseX = (int) prayerWidget.getBounds().getX();
|
||||
baseX += prayerWidget.getBounds().getWidth() / 2;
|
||||
baseX -= BOX_WIDTH / 2;
|
||||
|
||||
int baseY = (int) prayerWidget.getBounds().getY() - tick * TICK_PIXEL_SIZE - BOX_HEIGHT;
|
||||
baseY += TICK_PIXEL_SIZE - ((plugin.getLastTick() + 600 - System.currentTimeMillis()) / 600.0 * TICK_PIXEL_SIZE);
|
||||
|
||||
final Rectangle boxRectangle = new Rectangle(BOX_WIDTH, BOX_HEIGHT);
|
||||
boxRectangle.translate(baseX, baseY);
|
||||
|
||||
if (currentAttack == bestAttack)
|
||||
{
|
||||
OverlayUtil.renderFilledPolygon(graphics, boxRectangle, color);
|
||||
}
|
||||
else if (plugin.isIndicateNonPriorityDescendingBoxes())
|
||||
{
|
||||
OverlayUtil.renderOutlinePolygon(graphics, boxRectangle, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPrayerIconOverlay(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getClosestAttack() != null)
|
||||
{
|
||||
// Prayer indicator in prayer tab
|
||||
InfernoNPC.Attack prayerForAttack = null;
|
||||
if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC))
|
||||
{
|
||||
prayerForAttack = InfernoNPC.Attack.MAGIC;
|
||||
}
|
||||
else if (client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES))
|
||||
{
|
||||
prayerForAttack = InfernoNPC.Attack.RANGED;
|
||||
}
|
||||
else if (client.isPrayerActive(Prayer.PROTECT_FROM_MELEE))
|
||||
{
|
||||
prayerForAttack = InfernoNPC.Attack.MELEE;
|
||||
}
|
||||
|
||||
if (plugin.getClosestAttack() != prayerForAttack || plugin.isIndicateWhenPrayingCorrectly())
|
||||
{
|
||||
final Widget prayerWidget = client.getWidget(plugin.getClosestAttack().getPrayer().getWidgetInfo());
|
||||
final Rectangle prayerRectangle = new Rectangle((int) prayerWidget.getBounds().getWidth(),
|
||||
(int) prayerWidget.getBounds().getHeight());
|
||||
prayerRectangle.translate((int) prayerWidget.getBounds().getX(), (int) prayerWidget.getBounds().getY());
|
||||
|
||||
//TODO: Config values for these colors
|
||||
Color prayerColor;
|
||||
if (plugin.getClosestAttack() == prayerForAttack)
|
||||
{
|
||||
prayerColor = Color.GREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
prayerColor = Color.RED;
|
||||
}
|
||||
|
||||
OverlayUtil.renderOutlinePolygon(graphics, prayerRectangle, prayerColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean edgeEqualsEdge(int[][] edge1, int[][] edge2, int toleranceSquared)
|
||||
{
|
||||
return (pointEqualsPoint(edge1[0], edge2[0], toleranceSquared) && pointEqualsPoint(edge1[1], edge2[1], toleranceSquared))
|
||||
|| (pointEqualsPoint(edge1[0], edge2[1], toleranceSquared) && pointEqualsPoint(edge1[1], edge2[0], toleranceSquared));
|
||||
}
|
||||
|
||||
private boolean pointEqualsPoint(int[] point1, int[] point2, int toleranceSquared)
|
||||
{
|
||||
double distanceSquared = Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2);
|
||||
|
||||
return distanceSquared <= toleranceSquared;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,138 +0,0 @@
|
||||
package net.runelite.client.plugins.inferno;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
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.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class InfernoPrayerOverlay extends Overlay
|
||||
{
|
||||
private static final int TICK_PIXEL_SIZE = 60;
|
||||
private static final int BLOB_WIDTH = 10;
|
||||
private static final int BLOB_HEIGHT = 5;
|
||||
|
||||
private final InfernoPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
private InfernoPrayerOverlay(final Client client, final InfernoPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC).isHidden()
|
||||
|| client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES).isHidden())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
InfernoJad.Attack prayerForAttack = null;
|
||||
|
||||
if (client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC))
|
||||
{
|
||||
prayerForAttack = InfernoJad.Attack.MAGIC;
|
||||
}
|
||||
else if (client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES))
|
||||
{
|
||||
prayerForAttack = InfernoJad.Attack.RANGE;
|
||||
}
|
||||
|
||||
InfernoJad.Attack closestAttack = null;
|
||||
int leastTicks = 999;
|
||||
|
||||
for (InfernoJad jad : plugin.getJads())
|
||||
{
|
||||
if (jad.getNextAttack() == null || jad.getTicksTillNextAttack() < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jad.getTicksTillNextAttack() < leastTicks)
|
||||
{
|
||||
leastTicks = jad.getTicksTillNextAttack();
|
||||
closestAttack = jad.getNextAttack();
|
||||
}
|
||||
|
||||
if (!plugin.isDescendingBoxes() || !plugin.isShowPrayerHelp()
|
||||
|| (plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.PRAYER_TAB
|
||||
&& plugin.getPrayerOverlayMode() != InfernoPrayerOverlayMode.BOTH))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final Widget prayerWidget = jad.getNextAttack() == InfernoJad.Attack.MAGIC
|
||||
? client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC) : client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
|
||||
int baseX = (int) prayerWidget.getBounds().getX();
|
||||
baseX += prayerWidget.getBounds().getWidth() / 2;
|
||||
baseX -= BLOB_WIDTH / 2;
|
||||
|
||||
int baseY = (int) prayerWidget.getBounds().getY() - jad.getTicksTillNextAttack() * TICK_PIXEL_SIZE - BLOB_HEIGHT;
|
||||
baseY += TICK_PIXEL_SIZE - ((plugin.getLastTick() + 600 - System.currentTimeMillis()) / 600.0 * TICK_PIXEL_SIZE);
|
||||
|
||||
final Polygon blob = new Polygon(new int[]{0, BLOB_WIDTH, BLOB_WIDTH, 0}, new int[]{0, 0, BLOB_HEIGHT, BLOB_HEIGHT}, 4);
|
||||
blob.translate(baseX, baseY);
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, blob, Color.ORANGE);
|
||||
}
|
||||
|
||||
if (plugin.isShowPrayerHelp() && closestAttack != null
|
||||
&& (closestAttack != prayerForAttack || plugin.isIndicateWhenPrayingCorrectly())
|
||||
&& (plugin.getPrayerOverlayMode() == InfernoPrayerOverlayMode.PRAYER_TAB
|
||||
|| plugin.getPrayerOverlayMode() == InfernoPrayerOverlayMode.BOTH))
|
||||
{
|
||||
final Widget prayerWidget = closestAttack == InfernoJad.Attack.MAGIC
|
||||
? client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC) : client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
|
||||
final Polygon prayer = new Polygon(
|
||||
new int[]{0, (int) prayerWidget.getBounds().getWidth(), (int) prayerWidget.getBounds().getWidth(), 0},
|
||||
new int[]{0, 0, (int) prayerWidget.getBounds().getHeight(), (int) prayerWidget.getBounds().getHeight()},
|
||||
4);
|
||||
prayer.translate((int) prayerWidget.getBounds().getX(), (int) prayerWidget.getBounds().getY());
|
||||
|
||||
Color prayerColor;
|
||||
if (closestAttack == prayerForAttack)
|
||||
{
|
||||
prayerColor = Color.GREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
prayerColor = Color.RED;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, prayer, prayerColor);
|
||||
}
|
||||
|
||||
if (plugin.isIndicateActiveHealers())
|
||||
{
|
||||
for (NPC healer : plugin.getActiveHealers())
|
||||
{
|
||||
if (healer.getConvexHull() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, healer.getConvexHull(), Color.CYAN);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package net.runelite.client.plugins.inferno;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum InfernoPrayerOverlayMode
|
||||
{
|
||||
PRAYER_TAB("Prayer Tab"),
|
||||
BOTTOM_RIGHT("Bottom Right"),
|
||||
BOTH("Both");
|
||||
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Kyleeld <https://github.com/kyleeld>
|
||||
* Copyright (c) 2019, openosrs <https://openosrs.com>
|
||||
* Copyright (c) 2019, RuneLitePlus <https://runelitepl.us>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -28,18 +28,21 @@ package net.runelite.client.plugins.inferno;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.awt.Color;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.plugins.inferno.displaymodes.InfernoNamingDisplayMode;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
class InfernoWaveMappings
|
||||
{
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private static final ImmutableMap<Integer, int[]> waveMapping;
|
||||
|
||||
private static final Map<Integer, int[]> waveMapping;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private static final ImmutableMap<Integer, String> npcNameMapping;
|
||||
private static final Map<Integer, String> npcNameMappingComplex;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private static final Map<Integer, String> npcNameMappingSimple;
|
||||
|
||||
static
|
||||
{
|
||||
@@ -108,30 +111,43 @@ class InfernoWaveMappings
|
||||
waveMapBuilder.put(61, new int[]{32, 32, 32, 85, 165, 240, 370, 490});
|
||||
waveMapBuilder.put(62, new int[]{32, 32, 32, 85, 85, 165, 240, 370, 490});
|
||||
waveMapBuilder.put(63, new int[]{32, 32, 32, 165, 165, 240, 370, 490});
|
||||
waveMapBuilder.put(64, new int[]{32, 32, 32, 85, 240, 240, 370, 490});
|
||||
waveMapBuilder.put(65, new int[]{32, 32, 32, 85, 370, 370, 490});
|
||||
waveMapBuilder.put(66, new int[]{32, 32, 32, 85, 490, 490});
|
||||
waveMapBuilder.put(64, new int[]{32, 32, 32, 240, 240, 370, 490});
|
||||
waveMapBuilder.put(65, new int[]{32, 32, 32, 370, 370, 490});
|
||||
waveMapBuilder.put(66, new int[]{32, 32, 32, 490, 490});
|
||||
waveMapBuilder.put(67, new int[]{900});
|
||||
waveMapBuilder.put(68, new int[]{900, 900, 900});
|
||||
waveMapBuilder.put(69, new int[]{1400});
|
||||
|
||||
waveMapping = waveMapBuilder.build();
|
||||
|
||||
ImmutableMap.Builder<Integer, String> nameMapBuilder = new ImmutableMap.Builder<>();
|
||||
ImmutableMap.Builder<Integer, String> nameMapBuilderSimple = new ImmutableMap.Builder<>();
|
||||
|
||||
nameMapBuilder.put(32, "Jal-Nib - Level 32");
|
||||
nameMapBuilder.put(85, "Jal-MejRah - Level 85");
|
||||
nameMapBuilder.put(165, "Jal-Ak - Level 165");
|
||||
nameMapBuilder.put(240, "Jal-ImKot - Level 240");
|
||||
nameMapBuilder.put(370, "Jal-Xil - Level 370");
|
||||
nameMapBuilder.put(490, "Jal-Zek - Level 490");
|
||||
nameMapBuilder.put(900, "JalTok-Jad - Level 900");
|
||||
nameMapBuilder.put(1400, "TzKal-Zuk - Level 1400");
|
||||
nameMapBuilderSimple.put(32, "Nibbler");
|
||||
nameMapBuilderSimple.put(85, "Bat");
|
||||
nameMapBuilderSimple.put(165, "Blob");
|
||||
nameMapBuilderSimple.put(240, "Meleer");
|
||||
nameMapBuilderSimple.put(370, "Ranger");
|
||||
nameMapBuilderSimple.put(490, "Mage");
|
||||
nameMapBuilderSimple.put(900, "Jad");
|
||||
nameMapBuilderSimple.put(1400, "Zuk");
|
||||
|
||||
npcNameMapping = nameMapBuilder.build();
|
||||
npcNameMappingSimple = nameMapBuilderSimple.build();
|
||||
|
||||
ImmutableMap.Builder<Integer, String> nameMapBuilderComplex = new ImmutableMap.Builder<>();
|
||||
|
||||
nameMapBuilderComplex.put(32, "Jal-Nib");
|
||||
nameMapBuilderComplex.put(85, "Jal-MejRah");
|
||||
nameMapBuilderComplex.put(165, "Jal-Ak");
|
||||
nameMapBuilderComplex.put(240, "Jal-ImKot");
|
||||
nameMapBuilderComplex.put(370, "Jal-Xil");
|
||||
nameMapBuilderComplex.put(490, "Jal-Zek");
|
||||
nameMapBuilderComplex.put(900, "JalTok-Jad");
|
||||
nameMapBuilderComplex.put(1400, "TzKal-Zuk");
|
||||
|
||||
npcNameMappingComplex = nameMapBuilderComplex.build();
|
||||
}
|
||||
|
||||
static void addWaveComponent(PanelComponent panelComponent, String header, int wave, Color titleColor, Color color)
|
||||
static void addWaveComponent(InfernoPlugin plugin, PanelComponent panelComponent, String header, int wave, Color titleColor, Color color)
|
||||
{
|
||||
int[] monsters = waveMapping.get(wave);
|
||||
|
||||
@@ -160,7 +176,23 @@ class InfernoWaveMappings
|
||||
|
||||
TitleComponent.TitleComponentBuilder builder = TitleComponent.builder();
|
||||
|
||||
builder.text(count + "x " + npcNameMapping.get(monsterType));
|
||||
String npcNameText = "";
|
||||
|
||||
if (plugin.getNpcNaming() == InfernoNamingDisplayMode.SIMPLE)
|
||||
{
|
||||
npcNameText += npcNameMappingSimple.get(monsterType);
|
||||
}
|
||||
else
|
||||
{
|
||||
npcNameText += npcNameMappingComplex.get(monsterType);
|
||||
}
|
||||
|
||||
if (plugin.isNpcLevels())
|
||||
{
|
||||
npcNameText += " (" + monsterType + ")";
|
||||
}
|
||||
|
||||
builder.text(count + "x " + npcNameText);
|
||||
builder.color(color);
|
||||
|
||||
panelComponent.getChildren().add(builder.build());
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.awt.Graphics2D;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Setter;
|
||||
import static net.runelite.client.plugins.inferno.InfernoWaveMappings.addWaveComponent;
|
||||
import net.runelite.client.plugins.inferno.displaymodes.InfernoWaveDisplayMode;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
@@ -47,6 +48,7 @@ public class InfernoWaveOverlay extends Overlay
|
||||
displayMode == InfernoWaveDisplayMode.BOTH)
|
||||
{
|
||||
addWaveComponent(
|
||||
plugin,
|
||||
panelComponent,
|
||||
"Current Wave (Wave " + plugin.getCurrentWaveNumber() + ")",
|
||||
plugin.getCurrentWaveNumber(),
|
||||
@@ -59,6 +61,7 @@ public class InfernoWaveOverlay extends Overlay
|
||||
displayMode == InfernoWaveDisplayMode.BOTH)
|
||||
{
|
||||
addWaveComponent(
|
||||
plugin,
|
||||
panelComponent,
|
||||
"Next Wave (Wave " + plugin.getNextWaveNumber() + ")",
|
||||
plugin.getNextWaveNumber(),
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.runelite.client.plugins.inferno.displaymodes;
|
||||
|
||||
public enum InfernoNamingDisplayMode
|
||||
{
|
||||
SIMPLE,
|
||||
COMPLEX
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.runelite.client.plugins.inferno.displaymodes;
|
||||
|
||||
public enum InfernoPrayerDisplayMode
|
||||
{
|
||||
PRAYER_TAB,
|
||||
BOTTOM_RIGHT,
|
||||
BOTH
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.runelite.client.plugins.inferno.displaymodes;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
public enum InfernoSafespotDisplayMode
|
||||
{
|
||||
OFF("Off"),
|
||||
INDIVIDUAL_TILES("Individual tiles"),
|
||||
AREA("Area (lower fps)");
|
||||
|
||||
final private String name;
|
||||
|
||||
InfernoSafespotDisplayMode(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
* (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.inferno;
|
||||
package net.runelite.client.plugins.inferno.displaymodes;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.runelite.client.plugins.inferno.displaymodes;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
public enum InfernoZukShieldDisplayMode
|
||||
{
|
||||
OFF("Off"),
|
||||
LIVE("Live (follow shield)"),
|
||||
PREDICT("Predict (NOT WORKING YET)");
|
||||
|
||||
final private String name;
|
||||
|
||||
InfernoZukShieldDisplayMode(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,49 @@ public class OverlayUtil
|
||||
graphics.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public static void renderOutlinePolygon(Graphics2D graphics, Shape poly, Color color)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
final Stroke originalStroke = graphics.getStroke();
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(poly);
|
||||
graphics.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public static void renderFilledPolygon(Graphics2D graphics, Shape poly, Color color)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
final Stroke originalStroke = graphics.getStroke();
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(poly);
|
||||
graphics.fill(poly);
|
||||
graphics.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public static void renderAreaTilePolygon(Graphics2D graphics, Shape poly, Color color)
|
||||
{
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 10));
|
||||
graphics.fill(poly);
|
||||
}
|
||||
|
||||
public static void renderFullLine(Graphics2D graphics, int[][] line, Color color)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
final Stroke originalStroke = graphics.getStroke();
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawLine(line[0][0], line[0][1], line[1][0], line[1][1]);
|
||||
graphics.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public static void renderDashedLine(Graphics2D graphics, int[][] line, Color color)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
final Stroke originalStroke = graphics.getStroke();
|
||||
graphics.setStroke(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0));
|
||||
graphics.drawLine(line[0][0], line[0][1], line[1][0], line[1][1]);
|
||||
graphics.setStroke(originalStroke);
|
||||
}
|
||||
|
||||
public static void renderPolygonThin(Graphics2D graphics, Polygon poly, Color color)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
|
||||
Reference in New Issue
Block a user