# Conflicts:
#	runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java
This commit is contained in:
James Munson
2019-04-19 22:17:09 -07:00
168 changed files with 21537 additions and 507 deletions

4
.gitignore vendored
View File

@@ -8,3 +8,7 @@ project.properties
.project
.settings/
.classpath
runelite-client/src/main/resources/META-INF/MANIFEST.MF
git
classes/artifacts/client_jar/run.bat
classes/artifacts/client_jar/client.jar

View File

@@ -38,6 +38,7 @@ import net.runelite.api.coords.WorldPoint;
*/
public interface Actor extends Renderable
{
/**
* Gets the combat level of the actor.
*
@@ -246,4 +247,10 @@ public interface Actor extends Renderable
* @param overheadText the overhead text
*/
void setOverheadText(String overheadText);
/**
* Used by the "Tick Counter Plugin
*/
int getActionFrame();
int getActionFrameCycle();
}

View File

@@ -154,10 +154,26 @@ public final class AnimationID
public static final int PISCARILIUS_CRANE_REPAIR = 7199;
public static final int HOME_MAKE_TABLET = 4067;
//block animations for players and perhaps npcs as well?
public static final int BLOCK_DEFENDER = 4177;
public static final int BLOCK_NO_SHIELD = 420;
public static final int BLOCK_SHIELD = 1156;
public static final int BLOCK_SWORD = 388;
public static final int BLOCK_UNARMED = 424;
// NPC animations
public static final int TZTOK_JAD_MAGIC_ATTACK = 2656;
public static final int TZTOK_JAD_RANGE_ATTACK = 2652;
public static final int HELLHOUND_DEFENCE = 6566;
public static final int VORKATH_WAKE_UP = 7950;
public static final int VORKATH_DEATH = 7949;
public static final int VORKATH_SLASH_ATTACK = 7951;
public static final int VORKATH_ATTACK = 7952;
public static final int VORKATH_FIRE_BOMB_ATTACK = 7960;
public static final int VORKATH_ACID_ATTACK = 7957;
public static final int BLACKJACK_KO = 838;
public static final int VETION_EARTHQUAKE = 5507;
public static final int ZULRAH_DEATH = 5804;
// Farming
public static final int FARMING_HARVEST_FRUIT_TREE = 2280;
@@ -194,4 +210,7 @@ public final class AnimationID
// POH Animations
public static final int INCENSE_BURNER = 3687;
public static final int LOW_LEVEL_MAGIC_ATTACK = 1162;
public static final int HIGH_LEVEL_MAGIC_ATTACK = 1167;
public static final int BLOWPIPE_ATTACK = 5061;
}

View File

@@ -53,6 +53,7 @@ public enum VarPlayer
NMZ_REWARD_POINTS(1060),
ATTACKING_PLAYER(1075),
/**
* -1 : Poison immune
* Normal poison damage is ceil( this / 5.0f )

View File

@@ -480,7 +480,16 @@ public enum Varbits
/**
* The active tab within the quest interface
*/
QUEST_TAB(8168);
QUEST_TAB(8168),
/**
* Temple Trekking
*/
TREK_POINTS(1955),
TREK_STARTED(1956),
TREK_EVENT(1958),
TREK_STATUS(6719);
/**
* The raw varbit ID.

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019, Davis Cook <https://github.com/daviscook477>
* 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.api.events;
/**
* an event posted when a cannonball is fired
*/
public class CannonballFired
{
}

View File

@@ -36,6 +36,7 @@ import net.runelite.api.PlayerComposition;
*/
public enum KitType
{
HELMET(0),
CAPE(1),
AMULET(2),
WEAPON(3),
@@ -45,7 +46,9 @@ public enum KitType
HEAD(8),
HANDS(9),
BOOTS(10),
JAW(11);
JAW(11),
RING(12),
AMMUNITION(13);
/**
* Raw equipment index.

View File

@@ -129,6 +129,7 @@ public class WidgetID
public static final int SKILLS_GROUP_ID = 320;
public static final int QUESTTAB_GROUP_ID = 629;
public static final int MUSIC_GROUP_ID = 239;
public static final int MUSICTAB_GROUP_ID = 239;
public static final int BARROWS_PUZZLE_GROUP_ID = 25;
static class WorldMap
@@ -701,16 +702,152 @@ public class WidgetID
static class StandardSpellBook
{
static final int LUMBRIDGE_HOME_TELEPORT = 4;
static final int WIND_STRIKE = 5;
static final int CONFUSE = 6;
static final int ENCHANT_CROSSBOW_BOLT = 7;
static final int WATER_STRIKE = 8;
static final int LVL_1_ENCHANT = 9;
static final int EARTH_STRIKE = 10;
static final int WEAKEN = 11;
static final int FIRE_STRIKE = 12;
static final int BONES_TO_BANANAS = 13;
static final int WIND_BOLT = 14;
static final int CURSE = 15;
static final int BIND = 16;
static final int LOW_LEVEL_ALCHEMY = 17;
static final int WATER_BOLT = 18;
static final int VARROCK_TELEPORT = 19;
static final int LVL_2_ENCHANT = 20;
static final int EARTH_BOLT = 21;
static final int LUMBRIDGE_TELEPORT = 22;
static final int TELEKINETIC_GRAB = 23;
static final int FIRE_BOLT = 24;
static final int FALADOR_TELEPORT = 25;
static final int CRUMBLE_UNDEAD = 26;
static final int TELEPORT_TO_HOUSE = 27;
static final int WIND_BLAST = 28;
static final int SUPERHEAT_ITEM = 29;
static final int CAMELOT_TELEPORT = 30;
static final int WATER_BLAST = 31;
static final int LVL_3_ENCHANT = 32;
static final int IBAN_BLAST = 33;
static final int SNARE = 34;
static final int MAGIC_DART = 35;
static final int ARDOUGNE_TELEPORT = 36;
static final int EARTH_BLAST = 37;
static final int HIGH_LEVEL_ALCHEMY = 38;
static final int CHARGE_WATER_ORB = 39;
static final int LVL_4_ENCHANT = 40;
static final int WATCHTOWER_TELEPORT = 41;
static final int FIRE_BLAST = 42;
static final int CHARGE_EARTH_ORB = 43;
static final int BONES_TO_PEACHES = 44;
static final int SARADOMIN_STRIKE = 45;
static final int CLAWS_OF_GUTHIX = 46;
static final int FLAMES_OF_ZAMORAK = 47;
static final int TROLLHEIM_TELEPORT = 48;
static final int WIND_WAVE = 49;
static final int HARGE_FIRE_ORB = 50;
static final int TELEPORT_TO_APE_ATOLL = 51;
static final int WATER_WAVE = 52;
static final int CHARGE_AIR_ORB = 53;
static final int VULNERABILITY = 54;
static final int LVL_5_ENCHANT = 55;
static final int TELEPORT_TO_KOUREND = 56;
static final int EARTH_WAVE = 57;
static final int ENFEEBLE = 58;
static final int TELEOTHER_LUMBRIDGE = 59;
static final int FIRE_WAVE = 60;
static final int ENTANGLE = 61;
static final int STUN = 62;
static final int CHARGE = 63;
static final int WIND_SURGE = 64;
static final int TELEOTHER_FALADOR = 65;
static final int WATER_SURGE = 66;
static final int TELE_BLOCK = 67;
static final int BOUNTY_TARGET_TELEPORT = 68;
static final int LVL_6_ENCHANT = 69;
static final int TELEOTHER_CAMELOT = 70;
static final int EARTH_SURGE = 71;
static final int LVL_7_ENCHANT = 72;
static final int FIRE_SURGE = 73;
}
static class AncientSpellBook
{
static class AncientSpellBook {
static final int BOUNTY_TARGET_TELEPORT = 68;
static final int ICE_RUSH = 74;
static final int ICE_BLITZ = 75;
static final int ICE_BURST = 76;
static final int ICE_BARRAGE = 77;
static final int BLOOD_RUSH = 78;
static final int BLOOD_BLITZ = 79;
static final int BLOOD_BURST = 80;
static final int BLOOD_BARRAGE = 81;
static final int SMOKE_RUSH = 82;
static final int SMOKE_BLITZ = 83;
static final int SMOKE_BURST = 84;
static final int SMOKE_BARRAGE = 85;
static final int SHADOW_RUSH = 86;
static final int SHADOW_BLITZ = 87;
static final int SHADOW_BURST = 88;
static final int SHADOW_BARRAGE = 89;
static final int PADDEWWA_TELEPORT = 90;
static final int SENNTISTEN_TELEPORT = 91;
static final int KHARYRLL_TELEPORT = 92;
static final int LASSAR_TELEPORT = 93;
static final int DAREEYAK_TELEPORT = 94;
static final int CARRALLANGER_TELEPORT = 95;
static final int ANNAKARL_TELEPORT = 96;
static final int GHORROCK_TELEPORT = 97;
static final int EDGEVILLE_HOME_TELEPORT = 98;
}
static class LunarSpellBook
{
static class LunarSpellBook {
static final int BOUNTY_TARGET_TELEPORT = 68;
static final int LUNAR_HOME_TELEPORT = 99;
static final int BAKE_PIE = 100;
static final int CURE_PLANT = 101;
static final int MONSTER_EXAMINE = 102;
static final int NPC_CONTACT = 103;
static final int CURE_OTHER = 104;
static final int HUMIDIFY = 105;
static final int MOONCLAN_TELEPORT = 106;
static final int TELE_GROUP_MOONCLAN = 107;
static final int CURE_ME = 108;
static final int HUNTER_KIT = 109;
static final int WATERBIRTH_TELEPORT = 110;
static final int TELE_GROUP_WATERBIRTH = 111;
static final int CURE_GROUP = 112;
static final int STAT_SPY = 113;
static final int BARBARIAN_TELEPORT = 114;
static final int TELE_GROUP_BARBARIAN = 115;
static final int SUPERGLASS_MAKE = 116;
static final int TAN_LEATHER = 117;
static final int KHAZARD_TELEPORT = 118;
static final int TELE_GROUP_KHAZARD = 119;
static final int DREAM = 120;
static final int STRING_JEWELLERY = 121;
static final int STAT_RESTORE_POT_SHARE = 122;
static final int MAGIC_IMBUE = 123;
static final int FERTILE_SOIL = 124;
static final int BOOST_POTION_SHARE = 125;
static final int FISHING_GUILD_TELEPORT = 126;
static final int TELE_GROUP_FISHING_GUILD = 127;
static final int PLANK_MAKE = 128;
static final int CATHERBY_TELEPORT = 129;
static final int TELE_GROUP_CATHERBY = 130;
static final int RECHARGE_DRAGONSTONE = 131;
static final int ICE_PLATEAU_TELEPORT = 132;
static final int TELE_GROUP_ICE_PLATEAU = 133;
static final int ENERGY_TRANSFER = 134;
static final int HEAL_OTHER = 135;
static final int VENGEANCE_OTHER = 136;
static final int VENGEANCE = 137;
static final int HEAL_GROUP = 138;
static final int SPELLBOOK_SWAP = 139;
static final int GEOMANCY = 140;
static final int SPIN_FLAX = 141;
static final int OURANIA_TELEPORT = 142;
}
static class ArceuusSpellBook

View File

@@ -450,10 +450,56 @@ public enum WidgetInfo
MINIGAME_TELEPORT_BUTTON(WidgetID.MINIGAME_TAB_ID, WidgetID.Minigames.TELEPORT_BUTTON),
/* STANDARD SPELL BOOK WIDGETS*/
SPELL_LUMBRIDGE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.LUMBRIDGE_HOME_TELEPORT),
SPELL_EDGEVILLE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.EDGEVILLE_HOME_TELEPORT),
SPELL_BIND(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.BIND),
SPELL_SNARE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.SNARE),
SPELL_ENTANGLE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.ENTANGLE),
SPELL_TELE_BLOCK(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.TELE_BLOCK),
SPELL_FIRE_SURGE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.FIRE_SURGE),
SPELL_BOUNTY_TARGET_TELEPORT2(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.StandardSpellBook.BOUNTY_TARGET_TELEPORT),
/* END OF STANDARD SPELL BOOK WIDGETS*/
/* LUNAR SPELL BOOK WIDGETS*/
SPELL_LUNAR_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.LunarSpellBook.LUNAR_HOME_TELEPORT),
SPELL_VENGEANCE_OTHER(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.LunarSpellBook.VENGEANCE_OTHER),
SPELL_VENGEANCE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.LunarSpellBook.VENGEANCE),
SPELL_BOUNTY_TARGET_TELEPORT3(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.LunarSpellBook.BOUNTY_TARGET_TELEPORT),
/* LUNA SPELL BOOK WIDGETS*/
/* ARCEUUS SPELL BOOK WIDGETS*/
SPELL_ARCEUUS_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.ArceuusSpellBook.ARCEUUS_HOME_TELEPORT),
/* END OF ARCEUUS SPELL BOOK WIDGETS*/
/* ANCIENT SPELL BOOK WIDGETS*/
SPELL_ICE_RUSH(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.ICE_RUSH),
SPELL_ICE_BLITZ(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.ICE_BLITZ),
SPELL_ICE_BURST(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.ICE_BURST),
SPELL_ICE_BARRAGE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.ICE_BARRAGE),
SPELL_BLOOD_RUSH(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.BLOOD_RUSH),
SPELL_BLOOD_BLITZ(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.BLOOD_BLITZ),
SPELL_BLOOD_BURST(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.BLOOD_BURST),
SPELL_BLOOD_BARRAGE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.BLOOD_BARRAGE),
SPELL_SMOKE_RUSH(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SMOKE_RUSH),
SPELL_SMOKE_BLITZ(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SMOKE_BLITZ),
SPELL_SMOKE_BURST(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SMOKE_BURST),
SPELL_SMOKE_BARRAGE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SMOKE_BARRAGE),
SPELL_SHADOW_RUSH(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SHADOW_RUSH),
SPELL_SHADOW_BLITZ(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SHADOW_BLITZ),
SPELL_SHADOW_BURST(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SHADOW_BURST),
SPELL_SHADOW_BARRAGE(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SHADOW_BARRAGE),
SPELL_PADDEWWA_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.PADDEWWA_TELEPORT),
SPELL_SENNTISTEN_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.SENNTISTEN_TELEPORT),
SPELL_KHARYRLL_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.KHARYRLL_TELEPORT),
SPELL_LASSAR_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.LASSAR_TELEPORT),
SPELL_DAREEYAK_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.DAREEYAK_TELEPORT),
SPELL_CARRALLANGER_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.CARRALLANGER_TELEPORT),
SPELL_ANNAKARL_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.ANNAKARL_TELEPORT),
SPELL_GHORROCK_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.GHORROCK_TELEPORT),
SPELL_EDGEVILLE_HOME_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.EDGEVILLE_HOME_TELEPORT),
SPELL_BOUNTY_TARGET_TELEPORT(WidgetID.SPELLBOOK_GROUP_ID, WidgetID.AncientSpellBook.BOUNTY_TARGET_TELEPORT),
/* END OF ANCIENT SPELL BOOK WIDGETS*/
PVP_SKULL_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL_CONTAINER),
PVP_WORLD_SAFE_ZONE(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SAFE_ZONE),
@@ -478,6 +524,20 @@ public enum WidgetInfo
QUESTLIST_MEMBERS_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MEMBERS_CONTAINER),
QUESTLIST_MINIQUEST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.MINIQUEST_CONTAINER),
MUSICTAB_INTERFACE(WidgetID.MUSICTAB_GROUP_ID, 1),
MUSICTAB_SONG_BOX(WidgetID.MUSICTAB_GROUP_ID, 2),
MUSICTAB_ALL_SONGS(WidgetID.MUSICTAB_GROUP_ID, 3),
MUSICTAB_SCROLLBAR(WidgetID.MUSICTAB_GROUP_ID, 4),
MUSICTAB_PLAYING(WidgetID.MUSICTAB_GROUP_ID, 5),
MUSICTAB_CURRENT_SONG_NAME(WidgetID.MUSICTAB_GROUP_ID, 6),
MUSICTAB_AUTO_BUTTON_LISTENER(WidgetID.MUSICTAB_GROUP_ID, 7),
MUSICTAB_AUTO_BUTTON(WidgetID.MUSICTAB_GROUP_ID, 8),
MUSICTAB_MANUAL_BUTTON_LISTENER(WidgetID.MUSICTAB_GROUP_ID, 9),
MUSICTAB_MANUAL_BUTTON(WidgetID.MUSICTAB_GROUP_ID, 10),
MUSICTAB_LOOP_BUTTON_LISTENER(WidgetID.MUSICTAB_GROUP_ID, 11),
MUSICTAB_LOOP_BUTTON(WidgetID.MUSICTAB_GROUP_ID, 12),
MUSICTAB_UNLOCKED_SONGS(WidgetID.MUSICTAB_GROUP_ID, 13),
QUESTTAB_QUEST_TAB(WidgetID.QUESTTAB_GROUP_ID, WidgetID.QuestTab.QUEST_TAB);
private final int groupId;

View File

@@ -26,6 +26,7 @@ package net.runelite.api.widgets;
import java.awt.Rectangle;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import net.runelite.api.Point;
@@ -34,55 +35,34 @@ import net.runelite.api.Point;
*/
@AllArgsConstructor
@ToString
@Getter
public class WidgetItem
{
private final int id;
private final int quantity;
private final int index;
private final Rectangle canvasBounds;
/**
* Gets the ID of the item represented.
* The ID of the item represented.
*
* @return the items ID
* @see net.runelite.api.ItemID
*/
public int getId()
{
return id;
}
private final int id;
/**
* Gets the quantity of the represented item.
*
* @return the items quantity
* The quantity of the represented item.
*/
public int getQuantity()
{
return quantity;
}
private final int quantity;
/**
* Gets the index position of this WidgetItem inside its parents
* The index position of this WidgetItem inside its parents
* WidgetItem array.
*
* @return the index in the parent widget
* @see Widget#getWidgetItems()
*/
public int getIndex()
{
return index;
}
private final int index;
/**
* Gets the area where the widget is drawn on the canvas.
*
* @return the occupied area of the widget
* The area where the widget is drawn on the canvas.
*/
public Rectangle getCanvasBounds()
{
return canvasBounds;
}
private final Rectangle canvasBounds;
/**
* The widget which contains this item.
*/
private final Widget widget;
/**
* Gets the upper-left coordinate of where the widget is being drawn

View File

@@ -254,6 +254,11 @@
<artifactId>jcl-core</artifactId>
<version>2.8</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>17.0.0</version>
</dependency>
</dependencies>
<build>

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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.aoewarnings;
import net.runelite.api.coords.LocalPoint;
import java.time.Instant;
public class AoeProjectile
{
private final Instant startTime;
private final LocalPoint targetPoint;
private final AoeProjectileInfo aoeProjectileInfo;
public AoeProjectile(Instant startTime, LocalPoint targetPoint, AoeProjectileInfo aoeProjectileInfo)
{
this.startTime = startTime;
this.targetPoint = targetPoint;
this.aoeProjectileInfo = aoeProjectileInfo;
}
public Instant getStartTime()
{
return startTime;
}
public LocalPoint getTargetPoint()
{
return targetPoint;
}
public AoeProjectileInfo getAoeProjectileInfo()
{
return aoeProjectileInfo;
}
}

View File

@@ -0,0 +1,128 @@
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
{
LIZARDMAN_SHAMAN_AOE(ProjectileID.LIZARDMAN_SHAMAN_AOE, 3000, 3),
CRAZY_ARCHAEOLOGIST_AOE(ProjectileID.CRAZY_ARCHAEOLOGIST_AOE, 3000, 3),
ICE_DEMON_RANGED_AOE(ProjectileID.ICE_DEMON_RANGED_AOE, 3000, 3),
/**
* When you don't have pray range on ice demon does an ice barrage
*/
ICE_DEMON_ICE_BARRAGE_AOE(ProjectileID.ICE_DEMON_ICE_BARRAGE_AOE, 3000, 3),
/**
* The AOE when vasa first starts
*/
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),
/**
* 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),
DAWN_FREEZE(ProjectileID.DAWN_FREEZE, 3000, 3),
DUSK_CEILING(ProjectileID.DUSK_CEILING, 3000, 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(1357, 3000, 3),
OLM_BURNING(1349, 2400, 1),
OLM_FALLING_CRYSTAL_TRAIL(1352, 2400, 1),
OLM_ACID_TRAIL(1354, 2400, 1),
OLM_FIRE_LINE(1347, 2400, 1),
/**
* the AOE of the Wintertodt snow that falls
*/
WINTERTODT_SNOW_FALL(1310, 4000, 3);
/**
* The id of the projectile to trigger this AoE warning
*/
private final int id;
/**
* How long the indicator should last for this AoE warning This might
* need to be a bit longer than the projectile actually takes to land as
* there is a fade effect on the warning
*/
private final Duration lifeTime;
/**
* The size of the splash radius of the AoE warning Ex. Lizardman shaman
* AoE is a 3x3, so aoeSize = 3
*/
private final int aoeSize;
private static final Map<Integer, AoeProjectileInfo> map = new HashMap<>();
static
{
for (AoeProjectileInfo aoe : values())
{
map.put(aoe.id, aoe);
}
}
AoeProjectileInfo(int id, int lifeTimeMillis, int aoeSize)
{
this.id = id;
this.lifeTime = Duration.ofMillis(lifeTimeMillis);
this.aoeSize = aoeSize;
}
public Duration getLifeTime()
{
return lifeTime;
}
public int getId()
{
return id;
}
public int getAoeSize()
{
return aoeSize;
}
public static AoeProjectileInfo getById(int id)
{
return map.get(id);
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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.aoewarnings;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("aoe")
public interface AoeWarningConfig extends Config
{
@ConfigItem(
keyName = "enabled",
name = "AoE Warnings Enabled",
description = "Configures whether or not AoE Projectile Warnings plugin is displayed"
)
default boolean enabled()
{
return true;
}
@ConfigItem(
keyName = "lizardmanaoe",
name = "Lizardman Shamans",
description = "Configures whether or not AoE Projectile Warnings for Lizardman Shamans is displayed"
)
default boolean isShamansEnabled()
{
return true;
}
@ConfigItem(
keyName = "archaeologistaoe",
name = "Crazy Archaeologist",
description = "Configures whether or not AoE Projectile Warnings for Archaeologist is displayed"
)
default boolean isArchaeologistEnabled()
{
return true;
}
@ConfigItem(
keyName = "icedemon",
name = "Ice Demon",
description = "Configures whether or not AoE Projectile Warnings for Ice Demon is displayed"
)
default boolean isIceDemonEnabled()
{
return true;
}
@ConfigItem(
keyName = "vasa",
name = "Vasa",
description = "Configures whether or not AoE Projectile Warnings for Vasa is displayed"
)
default boolean isVasaEnabled()
{
return true;
}
@ConfigItem(
keyName = "tekton",
name = "Tekton",
description = "Configures whether or not AoE Projectile Warnings for Tekton is displayed"
)
default boolean isTektonEnabled()
{
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 = "gargboss",
name = "Gargoyle Boss",
description = "Configs whether or not AoE Projectile Warnings for Dawn/Dusk are displayed"
)
default boolean isGargBossEnabled()
{
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 = "bombDisplay",
name = "Display crystal phase bomb tracker",
description = "Display a timer and colour-coded AoE for Olm's crystal-phase bombs."
)
default boolean bombDisplay()
{
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 = "wintertodt",
name = "Wintertodt Snow Fall",
description = "Configures whether or not AOE Projectile Warnings for the Wintertodt snow fall are displayed"
)
default boolean isWintertodtEnabled()
{
return true;
}
@ConfigItem(
keyName = "outline",
name = "Display Outline",
description = "Configures whether or not AoE Projectile Warnings have an outline"
)
default boolean isOutlineEnabled()
{
return true;
}
@ConfigItem(
keyName = "lightning",
name = "Show Lightning Trails",
description = "Show Lightning Trails"
)
default boolean LightningTrail()
{
return true;
}
@ConfigItem(
keyName = "fade",
name = "Fade Warnings",
description = "Configures whether or not AoE Projectile Warnings fade over time"
)
default boolean isFadeEnabled()
{
return true;
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* 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.aoewarnings;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Projectile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.awt.*;
import java.time.Instant;
import java.util.Iterator;
import java.util.Map;
public class AoeWarningOverlay extends Overlay
{
private static final int FILL_START_ALPHA = 25;
private static final int OUTLINE_START_ALPHA = 255;
private final Client client;
private final AoeWarningPlugin plugin;
private final AoeWarningConfig config;
@Inject
public AoeWarningOverlay(@Nullable Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.UNDER_WIDGETS);
this.client = client;
this.plugin = plugin;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.enabled())
{
return null;
}
for (WorldPoint point : plugin.getLightningTrail())
{
drawTile(graphics, point, new Color(0,150,200), 2, 150, 50);
}
for (WorldPoint point : plugin.getAcidTrail())
{
drawTile(graphics, point, new Color(69, 241, 44), 2, 150, 50);
}
for (WorldPoint point : plugin.getCrystalSpike())
{
drawTile(graphics, point, new Color(255, 0, 84), 2, 150, 50);
}
Instant now = Instant.now();
Map<Projectile, AoeProjectile> projectiles = plugin.getProjectiles();
for (Iterator<AoeProjectile> it = projectiles.values().iterator(); it.hasNext();)
{
AoeProjectile aoeProjectile = it.next();
if (now.isAfter(aoeProjectile.getStartTime().plus(aoeProjectile.getAoeProjectileInfo().getLifeTime())))
{
it.remove();
continue;
}
Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, aoeProjectile.getTargetPoint(), aoeProjectile.getAoeProjectileInfo().getAoeSize());
if (tilePoly == null)
{
continue;
}
// how far through the projectiles lifetime between 0-1.
double progress = (System.currentTimeMillis() - aoeProjectile.getStartTime().toEpochMilli()) / (double) aoeProjectile.getAoeProjectileInfo().getLifeTime().toMillis();
int fillAlpha, outlineAlpha;
if (config.isFadeEnabled())
{
fillAlpha = (int) ((1 - progress) * FILL_START_ALPHA);//alpha drop off over lifetime
outlineAlpha = (int) ((1 - progress) * OUTLINE_START_ALPHA);
}
else
{
fillAlpha = FILL_START_ALPHA;
outlineAlpha = OUTLINE_START_ALPHA;
}
if (fillAlpha < 0)
{
fillAlpha = 0;
}
if (outlineAlpha < 0)
{
outlineAlpha = 0;
}
if (fillAlpha > 255)
{
fillAlpha = 255;
}
if (outlineAlpha > 255)
{
outlineAlpha = 255;//Make sure we don't pass in an invalid alpha
}
if (config.isOutlineEnabled())
{
graphics.setColor(new Color(0, 150, 200, outlineAlpha));
graphics.drawPolygon(tilePoly);
}
graphics.setColor(new Color(0, 150, 200, fillAlpha));
graphics.fillPolygon(tilePoly);
}
return null;
}
private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) {
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
if (point.distanceTo(playerLocation) >= 32) {
return;
}
LocalPoint lp = LocalPoint.fromWorld(client, point);
if (lp == null) {
return;
}
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
if (poly == null) {
return;
}
//OverlayUtil.renderPolygon(graphics, poly, color);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha));
graphics.setStroke(new BasicStroke(strokeWidth));
graphics.draw(poly);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
graphics.fill(poly);
}
}

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* 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.aoewarnings;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.GraphicID;
import net.runelite.api.GraphicsObject;
import net.runelite.api.ObjectID;
import net.runelite.api.Projectile;
import net.runelite.api.Client;
import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.GraphicsObjectCreated;
import net.runelite.api.events.ProjectileMoved;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
@PluginDescriptor(
name = "<font color=\"green\">!AoE Warnings</font>",
description = "Shows the final destination for AoE Attack projectiles",
tags = {"bosses", "combat", "pve", "overlay"}
)
@Slf4j
public class AoeWarningPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private AoeWarningOverlay coreOverlay;
@Inject
public AoeWarningConfig config;
@Inject
private BombOverlay bombOverlay;
@Inject
private Client client;
@Inject
private Notifier notifier;
@Getter
private final Map<WorldPoint, CrystalBomb> bombs = new HashMap<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> LightningTrail = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> AcidTrail = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> CrystalSpike = new ArrayList<>();
@Provides
AoeWarningConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(AoeWarningConfig.class);
}
private final Map<Projectile, AoeProjectile> projectiles = new HashMap<>();
public Map<Projectile, AoeProjectile> getProjectiles()
{
return projectiles;
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(coreOverlay);
overlayManager.add(bombOverlay);
LightningTrail.clear();
AcidTrail.clear();
CrystalSpike.clear();
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(coreOverlay);
overlayManager.remove(bombOverlay);
}
@Subscribe
public void onProjectileMoved(ProjectileMoved event)
{
Projectile projectile = event.getProjectile();
int projectileId = projectile.getId();
AoeProjectileInfo aoeProjectileInfo = AoeProjectileInfo.getById(projectileId);
if (aoeProjectileInfo != null && isConfigEnabledForProjectileId(projectileId))
{
LocalPoint targetPoint = event.getPosition();
AoeProjectile aoeProjectile = new AoeProjectile(Instant.now(), targetPoint, aoeProjectileInfo);
projectiles.put(projectile, aoeProjectile);
}
}
@Subscribe
public void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject gameObject = event.getGameObject();
final WorldPoint bombLocation = gameObject.getWorldLocation();
switch (gameObject.getId())
{
case ObjectID.CRYSTAL_BOMB:
bombs.put(bombLocation, new CrystalBomb(gameObject, client.getTickCount()));
break;
case ObjectID.ACID_POOL:
AcidTrail.add(bombLocation);
break;
case ObjectID.SMALL_CRYSTALS:
//todo
CrystalSpike.add(bombLocation);
break;
}
}
@Subscribe
public void onGameObjectDespawned(GameObjectDespawned event)
{
GameObject gameObject = event.getGameObject();
WorldPoint bombLocation = gameObject.getWorldLocation();
switch (gameObject.getId())
{
case ObjectID.CRYSTAL_BOMB:
//might as well check the ObjectID to save some time.
purgeBombs(bombs);
break;
case ObjectID.ACID_POOL:
AcidTrail.remove(bombLocation);
break;
case ObjectID.SMALL_CRYSTALS:
//todo
CrystalSpike.remove(bombLocation);
break;
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged delta)
{
if (client.getGameState() == GameState.LOGGED_IN)
{
purgeBombs(bombs);
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (config.LightningTrail())
{
LightningTrail.clear();
for (GraphicsObject o : client.getGraphicsObjects())
{
if (o.getId() == 1356)
{
LightningTrail.add(WorldPoint.fromLocal(client, o.getLocation()));
}
}
}
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = bombs.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
CrystalBomb bomb = entry.getValue();
bomb.bombClockUpdate();
//bombClockUpdate smooths the shown timer; not using this results in 1.2 --> .6 vs. 1.2 --> 1.1, etc.
}
}
private void purgeBombs(Map<WorldPoint, CrystalBomb> bombs)
{
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = bombs.entrySet().iterator();
Tile[][][] tiles = client.getScene().getTiles();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
WorldPoint world = entry.getKey();
LocalPoint local = LocalPoint.fromWorld(client, world);
Tile tile = tiles[world.getPlane()][local.getSceneX()][local.getSceneY()];
GameObject[] objects = tile.getGameObjects();
boolean containsObjects = false;
for (GameObject object : objects)
{
if (object != null)
{
containsObjects = true;
}
}
if (!containsObjects)
{
it.remove();
}
}
}
private boolean isConfigEnabledForProjectileId(int projectileId)
{
AoeProjectileInfo projectileInfo = AoeProjectileInfo.getById(projectileId);
if (projectileInfo == null)
{
return false;
}
switch (projectileInfo)
{
case LIZARDMAN_SHAMAN_AOE:
return config.isShamansEnabled();
case CRAZY_ARCHAEOLOGIST_AOE:
return config.isArchaeologistEnabled();
case ICE_DEMON_RANGED_AOE:
case ICE_DEMON_ICE_BARRAGE_AOE:
return config.isIceDemonEnabled();
case VASA_AWAKEN_AOE:
case VASA_RANGED_AOE:
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 DAWN_FREEZE:
case DUSK_CEILING:
return config.isGargBossEnabled();
case OLM_FALLING_CRYSTAL:
case OLM_BURNING:
case OLM_FALLING_CRYSTAL_TRAIL:
case OLM_ACID_TRAIL:
case OLM_FIRE_LINE:
return config.isOlmEnabled();
case CORPOREAL_BEAST:
case CORPOREAL_BEAST_DARK_CORE:
return config.isCorpEnabled();
case WINTERTODT_SNOW_FALL:
return config.isWintertodtEnabled();
}
return false;
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2018, PallasDieKatze (Pallas Cat)
* 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.aoewarnings;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.plugins.aoewarnings.CrystalBomb;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Polygon;
import java.awt.BasicStroke;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Instant;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@Slf4j
public class BombOverlay extends Overlay
{
private static final String SAFE = "#00cc00";
//safe
private static final String CAUTION = "#ffff00";
//1 tile in range (minor damage)
private static final String WARNING = "#ff9933";
//2 tiles in range (moderate damage)
private static final String DANGER = "#ff6600";
//3 tiles in range/adjacent to bomb (major damage)
private static final String LETHAL = "#cc0000";
//On the bomb, using it as a makeshift space launch vehicle. (massive damage)
private static final int BOMB_AOE = 7;
private static final int BOMB_DETONATE_TIME = 8;
//This is in ticks. It should be 10, but it varies from 8 to 11.
private static final double ESTIMATED_TICK_LENGTH = .6;
//Thank you Woox & co. for this assumption. .6 seconds/tick.
//Utilized from the npc highlight code for formatting text being displayed on the client canvas.
private static final NumberFormat TIME_LEFT_FORMATTER =
DecimalFormat.getInstance(Locale.US);
static
{
((DecimalFormat) TIME_LEFT_FORMATTER).applyPattern("#0.0");
}
private final Client client;
private final AoeWarningConfig config;
private final AoeWarningPlugin plugin;
@Inject
public BombOverlay(Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
{
this.client = client;
this.plugin = plugin;
this.config = config;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (config.bombDisplay())
{
drawBombs(graphics);
}
return null;
}
private void drawBombs(Graphics2D graphics)
//I can condense drawDangerZone into this. Ambivalent though.
{
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = plugin.getBombs().entrySet().iterator();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
CrystalBomb bomb = entry.getValue();
drawDangerZone(graphics, bomb);
}
}
private void drawDangerZone(Graphics2D graphics, CrystalBomb bomb)
{
final Player localPlayer = client.getLocalPlayer();
LocalPoint localLoc = LocalPoint.fromWorld(client, bomb.getWorldLocation());
double distance_x = Math.abs(bomb.getWorldLocation().getX() - localPlayer.getWorldLocation().getX());
double distance_y = Math.abs(bomb.getWorldLocation().getY() - localPlayer.getWorldLocation().getY());
Color color_code = Color.decode(SAFE);
//defaults to this unless conditionals met below.
if (distance_x < 1 && distance_y < 1)
{
color_code = Color.decode(LETHAL);
}
else if (distance_x < 2 && distance_y < 2)
{
color_code = Color.decode(DANGER);
}
else if (distance_x < 3 && distance_y < 3)
{
color_code = Color.decode(WARNING);
}
else if (distance_x < 4 && distance_y < 4)
{
color_code = Color.decode(CAUTION);
}
LocalPoint CenterPoint = new LocalPoint(localLoc.getX() + 0, localLoc.getY() + 0);
Polygon poly = Perspective.getCanvasTileAreaPoly(client, CenterPoint, BOMB_AOE);
if (poly != null)
{
//manually generating the polygon so as to assign a custom alpha value. Request adtl' arg for alpha maybe?
graphics.setColor(color_code);
graphics.setStroke(new BasicStroke(1));
graphics.drawPolygon(poly);
graphics.setColor(new Color(0, 0, 0, 10));
graphics.fillPolygon(poly);
}
Instant now = Instant.now();
double timeLeft = ((BOMB_DETONATE_TIME - (client.getTickCount() -
bomb.getTickStarted())) * ESTIMATED_TICK_LENGTH) -
(now.toEpochMilli() - bomb.getLastClockUpdate().toEpochMilli()) / 1000.0;
//divided by 1000.00 because of milliseconds :)
timeLeft = Math.max(0.0, timeLeft);
String bombTimerString = TIME_LEFT_FORMATTER.format(timeLeft);
int textWidth = graphics.getFontMetrics().stringWidth(bombTimerString);
int textHeight = graphics.getFontMetrics().getAscent();
Point canvasPoint = Perspective.localToCanvas(client, localLoc.getX(),
localLoc.getY(), bomb.getWorldLocation().getPlane());
if (canvasPoint != null)
{
Point canvasCenterPoint = new Point(
canvasPoint.getX() - textWidth / 2,
canvasPoint.getY() + textHeight / 2);
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, bombTimerString, color_code);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018, PallasDieKatze (Pallas Cat)
* 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.aoewarnings;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
import java.time.Instant;
@Slf4j
public class CrystalBomb
{
@Getter
private Instant plantedOn;
@Getter
private Instant lastClockUpdate;
@Getter
private int objectId;
@Getter
private int tickStarted;
//
@Getter
private WorldPoint worldLocation;
public CrystalBomb(GameObject gameObject, int startTick)
{
this.plantedOn = Instant.now();
this.objectId = gameObject.getId();
this.worldLocation = gameObject.getWorldLocation();
this.tickStarted = startTick;
}
public void bombClockUpdate()
{
lastClockUpdate = Instant.now();
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* 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.batools;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("BATools")
public interface BAToolsConfig extends Config
{
@ConfigItem(
keyName = "defTimer",
name = "Defender Tick Timer",
description = "Shows the current cycle tick of runners."
)
default boolean defTimer()
{
return false;
}
@ConfigItem(
keyName = "calls",
name = "Remove Incorrect Calls",
description = "Remove incorrect calls."
)
default boolean calls()
{
return false;
}
@ConfigItem(
keyName = "swapLadder",
name = "Swap ladder option",
description = "Swap Climb-down with Quick-start in the wave lobbies"
)
default boolean swapLadder()
{
return true;
}
@ConfigItem(
keyName = "healerCodes",
name = "Healer Codes",
description = "Overlay to show healer codes"
)
default boolean healerCodes()
{
return false;
}
@ConfigItem(
keyName = "healerMenuOption",
name = "Healer menu options",
description = "asd"
)
default boolean healerMenuOption()
{
return false;
}
@ConfigItem(
keyName = "antiDrag",
name = "Anti Drag",
description = "asd"
)
default boolean antiDrag()
{
return false;
}
@ConfigItem(
keyName = "antiDragDelay",
name = "Anti Drag Delay",
description = "asd"
)
default int antiDragDelay()
{
return 5;
}
@ConfigItem(
keyName = "eggBoi",
name = "Collector helper",
description = "asd"
)
default boolean eggBoi()
{
return false;
}
@ConfigItem(
keyName = "osHelp",
name = "Shift OS",
description = "asd"
)
default boolean osHelp()
{
return false;
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* 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.batools;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import net.runelite.api.NPCComposition;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.Overlay;
import java.time.Duration;
import java.time.Instant;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BAToolsOverlay extends Overlay
{
private static final Color RED = new Color(221, 44, 0);
private static final Color GREEN = new Color(0, 200, 83);
private static final Color ORANGE = new Color(255, 109, 0);
private static final Color YELLOW = new Color(255, 214, 0);
private static final Color CYAN = new Color(0, 184, 212);
private static final Color BLUE = new Color(41, 98, 255);
private static final Color DEEP_PURPLE = new Color(98, 0, 234);
private static final Color PURPLE = new Color(170, 0, 255);
private static final Color GRAY = new Color(158, 158, 158);
private final BAToolsConfig config;
private Client client;
private BAToolsPlugin plugin;
@Inject
public BAToolsOverlay(Client client, BAToolsPlugin plugin, BAToolsConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.config = config;
this.client = client;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if(!config.healerCodes())
{
return null;
}
for (Healer healer : plugin.getHealers().values())
{
NPCComposition composition = healer.getNpc().getComposition();
Color color = composition.getCombatLevel() > 1 ? YELLOW : ORANGE;
if (composition.getConfigs() != null)
{
NPCComposition transformedComposition = composition.transform();
if (transformedComposition == null)
{
color = GRAY;
}
else
{
composition = transformedComposition;
}
}
int timeLeft = healer.getLastFoodTime() - (int)Duration.between(plugin.getWave_start(), Instant.now()).getSeconds();
timeLeft = timeLeft < 1 ? 0 : timeLeft;
if(healer.getFoodRemaining() > 1)
{
color = GREEN;
}
else if(healer.getFoodRemaining() == 1)
{
if(timeLeft > 0)
{
color = RED;
}
else
{
color = GREEN;
}
}
else
{
continue;
}
String text = String.format("%d %d",
healer.getFoodRemaining(),
timeLeft);
OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
}
return null;
}
}

View File

@@ -0,0 +1,643 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* 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.batools;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import static net.runelite.api.Constants.CHUNK_SIZE;
import net.runelite.api.ItemID;
import net.runelite.api.MenuEntry;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.HitsplatApplied;
import net.runelite.api.events.InteractingChanged;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ItemManager;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
@Slf4j
@PluginDescriptor(
name = "BA Tools",
description = "Custom tools for Barbarian Assault",
tags = {"minigame", "overlay", "timer"}
)
public class BAToolsPlugin extends Plugin implements KeyListener
{
int inGameBit = 0;
int tickNum;
int pastCall = 0;
private int currentWave = 1;
private static final int BA_WAVE_NUM_INDEX = 2;
private final List<MenuEntry> entries = new ArrayList<>();
private HashMap<Integer, Instant> foodPressed = new HashMap<>();
private CycleCounter counter;
private Actor lastInteracted;
private boolean shiftDown;
@Inject
private Client client;
@Inject
private ConfigManager configManager;
@Inject
private ChatMessageManager chatMessageManager;
@Inject
private OverlayManager overlayManager;
@Inject
private BAToolsConfig config;
@Inject
private ItemManager itemManager;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private BAToolsOverlay overlay;
@Getter
private Map<NPC, Healer> healers;
@Getter
private Instant wave_start;
@Inject
private KeyManager keyManager;
@Provides
BAToolsConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(BAToolsConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
healers = new HashMap<>();
wave_start = Instant.now();
lastInteracted = null;
foodPressed.clear();
client.setInventoryDragDelay(config.antiDragDelay());
keyManager.registerKeyListener(this);
}
@Override
protected void shutDown() throws Exception
{
removeCounter();
healers.clear();
inGameBit = 0;
lastInteracted = null;
overlayManager.remove(overlay);
client.setInventoryDragDelay(5);
keyManager.unregisterKeyListener(this);
shiftDown = false;
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
switch (event.getGroupId())
{
case WidgetID.BA_REWARD_GROUP_ID:
{
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (rewardWidget != null && rewardWidget.getText().contains("<br>5"))
{
tickNum = 0;
}
}
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (config.antiDrag())
{
client.setInventoryDragDelay(config.antiDragDelay());
}
Widget callWidget = getWidget();
if (callWidget != null)
{
if (callWidget.getTextColor() != pastCall && callWidget.getTextColor() == 16316664)
{
tickNum = 0;
}
pastCall = callWidget.getTextColor();
}
if (inGameBit == 1)
{
if (tickNum > 9)
{
tickNum = 0;
}
if (counter == null)
{
addCounter();
}
//counter.setText(String.valueOf(tickNum));
counter.setCount(tickNum);
if (config.defTimer())
{
log.info("" + tickNum++);
}
}
}
private Widget getWidget()
{
if (client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT);
}
return null;
}
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
int inGame = client.getVar(Varbits.IN_GAME_BA);
if (inGameBit != inGame)
{
if (inGameBit == 1)
{
pastCall = 0;
removeCounter();
foodPressed.clear();
}
else
{
addCounter();
}
}
inGameBit = inGame;
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (event.getType() == ChatMessageType.CONSOLE
&& event.getMessage().startsWith("---- Wave:"))
{
String[] message = event.getMessage().split(" ");
currentWave = Integer.parseInt(message[BA_WAVE_NUM_INDEX]);
wave_start = Instant.now();
healers.clear();
}
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
NPC npc = event.getNpc();
if (isNpcHealer(npc.getId()))
{
if (checkNewSpawn(npc) || Duration.between(wave_start, Instant.now()).getSeconds() < 16)
{
int spawnNumber = healers.size();
healers.put(npc, new Healer(npc, spawnNumber, currentWave));
log.info("spawn number: " + spawnNumber + " on wave " + currentWave);
}
}
}
@Subscribe
public void onHitsplatApplied(HitsplatApplied hitsplatApplied)
{
Actor actor = hitsplatApplied.getActor();
if (healers.isEmpty() && !(actor instanceof NPC) && lastInteracted == null)
{
return;
}
for (Healer healer : healers.values())
{
if (healer.getNpc() == actor && actor == lastInteracted)
{
healer.setFoodRemaining(healer.getFoodRemaining() - 1);
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
if (healers.remove(event.getNpc()) != null && healers.isEmpty())
{
healers.clear();
}
}
@Subscribe
public void onInteractingChanged(InteractingChanged event)
{
Actor opponent = event.getTarget();
if (opponent != null && opponent instanceof NPC && isNpcHealer(((NPC) opponent).getId()) && event.getSource() != client.getLocalPlayer())
{
lastInteracted = opponent;
}
}
public static boolean isNpcHealer(int npcId)
{
return npcId == NpcID.PENANCE_HEALER ||
npcId == NpcID.PENANCE_HEALER_5766 ||
npcId == NpcID.PENANCE_HEALER_5767 ||
npcId == NpcID.PENANCE_HEALER_5768 ||
npcId == NpcID.PENANCE_HEALER_5769 ||
npcId == NpcID.PENANCE_HEALER_5770 ||
npcId == NpcID.PENANCE_HEALER_5771 ||
npcId == NpcID.PENANCE_HEALER_5772 ||
npcId == NpcID.PENANCE_HEALER_5773 ||
npcId == NpcID.PENANCE_HEALER_5774;
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event)
{
if (config.calls() && getWidget() != null && event.getTarget().endsWith("horn") && !event.getTarget().contains("Unicorn"))
{
MenuEntry[] menuEntries = client.getMenuEntries();
Widget callWidget = getWidget();
String call = Calls.getOption(callWidget.getText());
MenuEntry correctCall = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
String option = entry.getOption();
if (option.equals(call))
{
correctCall = entry;
}
else if (!option.startsWith("Tell-"))
{
entries.add(entry);
}
}
if (correctCall != null) //&& callWidget.getTextColor()==16316664)
{
entries.add(correctCall);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
else if (config.calls() && event.getTarget().endsWith("horn"))
{
entries.clear();
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
String option = Text.removeTags(event.getOption()).toLowerCase();
String target = Text.removeTags(event.getTarget()).toLowerCase();
if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder"))
{
swap("quick-start", option, target, true);
}
if (inGameBit == 1 && config.healerMenuOption() && event.getTarget().contains("Penance Healer"))
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
String targett = lastEntry.getTarget();
if (foodPressed.containsKey(lastEntry.getIdentifier()))
{
lastEntry.setTarget(lastEntry.getTarget().split("\\(")[0] + "(" + Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() + ")");
if (Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() > 20)
{
lastEntry.setTarget(lastEntry.getTarget().replace("<col=ffff00>", "<col=2bff63>"));
}
}
else
{
lastEntry.setTarget(targett.replace("<col=ffff00>", "<col=2bff63>"));
}
client.setMenuEntries(menuEntries);
}
if (client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown)
{
String[] currentCall = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT).getText().split(" ");
log.info("1 " + currentCall[0]);
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getTarget().contains(currentCall[0]) && entry.getOption().equals("Take"))
{
correctEgg = entry;
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
if (client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT) != null && inGameBit == 1 && config.osHelp() && event.getTarget().equals("<col=ffff>Healer item machine") && shiftDown)
{
String[] currentCall = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT).getText().split(" ");
if (!currentCall[0].contains("Pois."))
{
return;
}
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getOption().equals("Take-" + currentCall[1]))
{
correctEgg = entry;
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (!config.healerMenuOption() || !event.getMenuTarget().contains("Penance Healer") || client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) == null)
{
return;
}
String currentCall = client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT).getText();
String target = event.getMenuTarget();
if ((currentCall.equals("Pois. Worms") && (target.contains("Poisoned worms") && target.contains("->") && target.contains("Penance Healer")))
|| (currentCall.equals("Pois. Meat") && (target.contains("Poisoned meat") && target.contains("->") && target.contains("Penance Healer")))
|| (currentCall.equals("Pois. Tofu") && (target.contains("Poisoned tofu") && target.contains("->") && target.contains("Penance Healer"))))
{
foodPressed.put(event.getId(), Instant.now());
}
if (target.contains("->") && target.contains("Penance Healer"))
{
foodPressed.put(event.getId(), Instant.now());
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (config.antiDrag())
{
client.setInventoryDragDelay(config.antiDragDelay());
}
}
private void addCounter()
{
if (!config.defTimer() || counter != null)
{
return;
}
int itemSpriteId = ItemID.FIGHTER_TORSO;
BufferedImage taskImg = itemManager.getImage(itemSpriteId);
counter = new CycleCounter(taskImg, this, tickNum);
infoBoxManager.addInfoBox(counter);
}
private void removeCounter()
{
if (counter == null)
{
return;
}
infoBoxManager.removeInfoBox(counter);
counter = null;
}
private void swap(String optionA, String optionB, String target, boolean strict)
{
MenuEntry[] entries = client.getMenuEntries();
int idxA = searchIndex(entries, optionA, target, strict);
int idxB = searchIndex(entries, optionB, target, strict);
if (idxA >= 0 && idxB >= 0)
{
MenuEntry entry = entries[idxA];
entries[idxA] = entries[idxB];
entries[idxB] = entry;
client.setMenuEntries(entries);
}
}
private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict)
{
for (int i = entries.length - 1; i >= 0; i--)
{
MenuEntry entry = entries[i];
String entryOption = Text.removeTags(entry.getOption()).toLowerCase();
String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase();
if (strict)
{
if (entryOption.equals(option) && entryTarget.equals(target))
{
return i;
}
}
else
{
if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target))
{
return i;
}
}
}
return -1;
}
private static WorldPoint rotate(WorldPoint point, int rotation)
{
int chunkX = point.getX() & ~(CHUNK_SIZE - 1);
int chunkY = point.getY() & ~(CHUNK_SIZE - 1);
int x = point.getX() & (CHUNK_SIZE - 1);
int y = point.getY() & (CHUNK_SIZE - 1);
switch (rotation)
{
case 1:
return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane());
case 2:
return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane());
case 3:
return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane());
}
return point;
}
private boolean checkNewSpawn(NPC npc)
{
int regionId = 7509;
int regionX = 42;
int regionY = 46;
int z = 0;
// world point of the tile marker
WorldPoint worldPoint = new WorldPoint(
((regionId >>> 8) << 6) + regionX,
((regionId & 0xff) << 6) + regionY,
z
);
int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks();
for (int x = 0; x < instanceTemplateChunks[z].length; ++x)
{
for (int y = 0; y < instanceTemplateChunks[z][x].length; ++y)
{
int chunkData = instanceTemplateChunks[z][x][y];
int rotation = chunkData >> 1 & 0x3;
int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE;
int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE;
if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE
&& worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE)
{
WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)),
client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)),
worldPoint.getPlane());
p = rotate(p, rotation);
if (p.distanceTo(npc.getWorldLocation()) < 5)
{
return true;
}
}
}
}
return false;
}
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = true;
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = false;
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* 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.batools;
import java.util.HashMap;
import java.util.Map;
public enum Calls
{
//Attacker Calls
RED_EGG("Red egg", "Tell-red"),
GREEN_EGG("Green egg", "Tell-green"),
BLUE_EGG("Blue egg", "Tell-blue"),
//Collector Calls
CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"),
ACCURATE("Accurate/Field/Water", "Tell-accurate"),
AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"),
DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"),
//Healer Calls
TOFU("Tofu", "Tell-tofu"),
CRACKERS("Crackers", "Tell-crackers"),
WORMS("Worms", "Tell-worms"),
//Defender Calls
POIS_WORMS("Pois. Worms", "Tell-worms"),
POIS_TOFU("Pois. Tofu", "Tell-tofu"),
POIS_MEAT("Pois. Meat", "Tell-meat");
private final String call;
private final String option;
private static final Map<String, String> CALL_MENU = new HashMap<>();
static
{
for (Calls s : values())
{
CALL_MENU.put(s.getCall(), s.getOption());
}
}
Calls(String call, String option)
{
this.call = call;
this.option = option;
}
public String getCall()
{
return call;
}
public String getOption()
{
return option;
}
public static String getOption(String call)
{
return CALL_MENU.get(call);
}
}

View File

@@ -0,0 +1,14 @@
package net.runelite.client.plugins.batools;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.Counter;
import java.awt.image.BufferedImage;
public class CycleCounter extends Counter
{
public CycleCounter(BufferedImage img, Plugin plugin, int tick)
{
super(img, plugin, tick);
}
}

View File

@@ -0,0 +1,84 @@
package net.runelite.client.plugins.batools;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.NPC;
import net.runelite.api.Actor;
public class Healer
{
@Getter
private NPC npc;
@Getter
@Setter
private int wave;
@Getter
@Setter
private int spawnNumber;
@Getter
@Setter
private int foodRemaining;
@Getter
@Setter
private int lastFoodTime;
@Getter
@Setter
private int firstCallFood;
@Getter
@Setter
private int secondCallFood;
public Healer(NPC npc, int spawnNumber, int wave)
{
this.npc = npc;
this.wave = wave;
this.spawnNumber = spawnNumber;
this.firstCallFood = getCode(wave).getFirstCallFood()[spawnNumber];
this.secondCallFood = getCode(wave).getSecondCallFood()[spawnNumber];
this.foodRemaining = firstCallFood + secondCallFood;
this.lastFoodTime = getCode(wave).getSpacing()[spawnNumber];
}
private HealerCode getCode(int wave)
{
switch(wave)
{
case 1:
return HealerCode.WAVEONE;
case 2:
return HealerCode.WAVETWO;
case 3:
return HealerCode.WAVETHREE;
case 4:
return HealerCode.WAVEFOUR;
case 5:
return HealerCode.WAVEFIVE;
case 6:
return HealerCode.WAVESIX;
case 7:
return HealerCode.WAVESEVEN;
case 8:
return HealerCode.WAVEEIGHT;
case 9:
return HealerCode.WAVENINE;
case 10:
return HealerCode.WAVETEN;
default: return null;
}
}
}

View File

@@ -0,0 +1,34 @@
package net.runelite.client.plugins.batools;
import lombok.Getter;
enum HealerCode
{
WAVEONE(new int[] {1,1}, new int[] {0,0}, new int[] {0,0}),
WAVETWO(new int[] {1,1,2}, new int[] {0,0,0}, new int[] {0,0,21}),
WAVETHREE(new int[] {1,6,2}, new int[] {0,0,0}, new int[] {0,0,0}),
WAVEFOUR(new int[] {2,5,2,0}, new int[] {0,0,7,10}, new int[] {0,0,0,0}),
WAVEFIVE(new int[] {2,5,2,3,0}, new int[] {0,0,0,0,7}, new int[] {0,0,21,30,0}),
WAVESIX(new int[] {3,5,3,1,0,0}, new int[] {0,0,0,2,9,10}, new int[] {18,0,0,0,0,0}),
WAVESEVEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,0,0,0,6,8,10}, new int[] {27,33,0,0,51,0,0}),
WAVEEIGHT(new int[] {2,8,1,1,0,0,0}, new int[] {1,0,1,1,3,1,10}, new int[] {36,0,33,39,45,48,0}),
WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,1,1,1,1,1,1,10}, new int[] {0,21,0,0,0,0,0,0,0}),
WAVETEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,1,1,1,3,3,10}, new int[] {27,33,0,0,51,0,0});
@Getter
private final int[] firstCallFood;
@Getter
private final int[] secondCallFood;
@Getter
private final int[] spacing;
HealerCode(int[] firstCallFood, int[] secondCallFood, int[] spacing)
{
this.firstCallFood = firstCallFood;
this.secondCallFood = secondCallFood;
this.spacing = spacing;
}
}

View File

@@ -0,0 +1,168 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("clanmanmode")
public interface ClanManModeConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "highlightattackable",
name = "Highlight attackable targets",
description = "Highlights targets attackable by all clan members"
)
default boolean highlightAttackable()
{
return false;
}
@ConfigItem(
position = 1,
keyName = "attackablecolor",
name = "Attackable target c olor",
description = "Color of targets all clan members can target"
)
default Color getAttackableColor()
{
return new Color(0, 184, 212);
}
@ConfigItem(
position = 2,
keyName = "highlightattacked",
name = "Highlight clan targets",
description = "Highlights people being attacked by your clan"
)
default boolean highlightAttacked()
{
return false;
}
@ConfigItem(
position = 3,
keyName = "attackedcolor",
name = "Clan target color",
description = "Color of players being attacked by clan"
)
default Color getClanAttackableColor()
{
return new Color(0, 184, 212);
}
@ConfigItem(
position = 4,
keyName = "drawPlayerTiles",
name = "Draw tiles under players",
description = "Configures whether or not tiles under highlighted players should be drawn"
)
default boolean drawTiles()
{
return false;
}
@ConfigItem(
position = 5,
keyName = "drawOverheadPlayerNames",
name = "Draw names above players",
description = "Configures whether or not player names should be drawn above players"
)
default boolean drawOverheadPlayerNames()
{
return true;
}
@ConfigItem(
position = 6,
keyName = "drawMinimapNames",
name = "Draw names on minimap",
description = "Configures whether or not minimap names for players with rendered names should be drawn"
)
default boolean drawMinimapNames()
{
return false;
}
@ConfigItem(
position = 7,
keyName = "showtargets",
name = "Highlight My Attackers",
description = "Shows players interacting with you"
)
default boolean showAttackers()
{
return false;
}
@ConfigItem(
position = 8,
keyName = "attackcolor",
name = "Attacker Color",
description = "Color of attackers"
)
default Color getAttackerColor()
{
return new Color(255, 0, 0);
}
@ConfigItem(
position = 9,
keyName = "showbold",
name = "Bold names of clan targets",
description = "Turns names of clan targets bold"
)
default boolean ShowBold() { return false; }
@ConfigItem(
position = 10,
keyName = "hideafter",
name = "Hide attackable targets after login",
description = "Automatically disables attackable player highlighting after login"
)
default boolean hideAttackable() { return false; }
@ConfigItem(
position = 11,
keyName = "hidetime",
name = "Ticks to hide",
description = "How many ticks after you are logged in that attackbles are hidden (1 tick = 0.6 seconds)"
)
default int hideTime() { return 5; }
@ConfigItem(
position = 12,
keyName = "mycblvl",
name = "Calc targets on my own combat level",
description = "Calculates potential targets based off your own combat lvl instead of clans"
)
default boolean CalcSelfCB() { return false; }
@ConfigItem(
position = 13,
keyName = "hideatkopt",
name = "Hide attack option for clan members",
description = "Disables attack option for clan members"
)
default boolean hideAtkOpt() { return false; }
@ConfigItem(
position = 14,
keyName = "showclanmembers",
name = "Persistent Clan Members",
description = "Will highlight clan members even when not in clan chat"
)
default boolean PersistentClan() { return false; }
@ConfigItem(
position = 15,
keyName = "clancolor",
name = "Clan Member Color",
description = "Color of clan members"
)
default Color getClanMemberColor()
{
return new Color(255, 0, 0);
}
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Player;
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 ClanManModeMinimapOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
@Inject
private ClanManModeMinimapOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
ClanManModeService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
final String name = actor.getName().replace('\u00A0', ' ');
if (config.drawMinimapNames())
{
final net.runelite.api.Point minimapLocation = actor.getMinimapLocation();
if (minimapLocation != null)
{
OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color);
}
}
}
}

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.ClanMemberRank;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.game.ClanManager;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class ClanManModeOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
private final ClanManager clanManager;
@Inject
private ClanManModeOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService,
ClanManager clanManager)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
this.clanManager = clanManager;
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
ClanManModeService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
if (!config.drawOverheadPlayerNames())
{
return;
}
String name = actor.getName().replace('\u00A0', ' ');
int offset = actor.getLogicalHeight() + 40;
Point textLocation = actor.getCanvasTextLocation(graphics, name, offset);
if (textLocation != null)
{
if (config.getClanAttackableColor().equals(color) && config.ShowBold()) {
graphics.setFont(FontManager.getRunescapeBoldFont());
}
OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
}
}
}

View File

@@ -0,0 +1,137 @@
package net.runelite.client.plugins.clanmanmode;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ClanManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "<font color=\"aqua\">!Clan Man Mode</font>",
description = "Assists in clan PVP scenarios",
tags = {"highlight", "minimap", "overlay", "players"}
)
public class ClanManModePlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private ClanManModeConfig config;
@Inject
private ClanManModeOverlay ClanManModeOverlay;
@Inject
private ClanManModeTileOverlay ClanManModeTileOverlay;
@Inject
private ClanManModeMinimapOverlay ClanManModeMinimapOverlay;
@Inject
private Client client;
@Inject
private ClanManager clanManager;
@Provides
ClanManModeConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(ClanManModeConfig.class);
}
int wildernessLevel;
int clanmin;
int clanmax;
int inwildy;
int ticks;
Map<String, Integer> clan = new HashMap<>();
@Override
protected void startUp() throws Exception {
overlayManager.add(ClanManModeOverlay);
overlayManager.add(ClanManModeTileOverlay);
overlayManager.add(ClanManModeMinimapOverlay);
}
@Override
protected void shutDown() throws Exception {
overlayManager.remove(ClanManModeOverlay);
overlayManager.remove(ClanManModeTileOverlay);
overlayManager.remove(ClanManModeMinimapOverlay);
clan.clear();
ticks = 0;
wildernessLevel = 0;
clanmin = 0;
clanmax = 0;
inwildy = 0;
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) {
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN || gameStateChanged.getGameState() == GameState.HOPPING) {
ticks = 0;
}
}
@Subscribe
public void onGameTick(GameTick event) {
ticks++;
final Player localPlayer = client.getLocalPlayer();
if (!clan.containsKey(localPlayer.getName())) {
clan.put(localPlayer.getName(), localPlayer.getCombatLevel());
}
WorldPoint a = localPlayer.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
inwildy = client.getVar(Varbits.IN_WILDERNESS);
if (clan.size() > 0) {
clanmin = Collections.min(clan.values());
clanmax = Collections.max(clan.values());
}
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (!config.hideAtkOpt()) {
return;
}
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
if (option.equals("attack")) {
final Pattern ppattern = Pattern.compile("<col=ffffff>(.+?)<col=");
final Matcher pmatch = ppattern.matcher(event.getTarget());
pmatch.find();
if (pmatch.matches()) {
if (pmatch.group(1) != null) {
if (clan.containsKey(pmatch.group(1).replace(" ", " "))) {
MenuEntry[] entries = client.getMenuEntries();
entries = ArrayUtils.removeElement(entries, entries[entries.length - 1]);
client.setMenuEntries(entries);
}
}
}
}
}
}

View File

@@ -0,0 +1,157 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
@Singleton
public class ClanManModeService
{
private final Client client;
private final ClanManModeConfig config;
private final ClanManModePlugin plugin;
@Inject
private ClanManModeService(Client client, ClanManModeConfig config, ClanManModePlugin plugin)
{
this.config = config;
this.client = client;
this.plugin = plugin;
}
Map<String, String> interactors = new HashMap<>();
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
{
int minatk = plugin.clanmax - plugin.wildernessLevel;
int maxatk = plugin.clanmin + plugin.wildernessLevel;
final Player localPlayer = client.getLocalPlayer();
final String localName = localPlayer.getName();
int selfmin = localPlayer.getCombatLevel() - plugin.wildernessLevel;
int selfmax = localPlayer.getCombatLevel() + plugin.wildernessLevel;
for (Player player : client.getPlayers())
{
if (player == null || player.getName() == null) {
continue;
}
if (player == localPlayer) {
continue;
}
boolean isClanMember = player.isClanMember();
Actor interacting = player.getInteracting();
Player interactor = null;
if (interacting != null && !(interacting instanceof NPC)) {
interactor = ((Player) interacting);
}
if (config.showAttackers()) {
if (interactor != null) {
if (interactor.getName().equals(localName)) {
consumer.accept(player, config.getAttackerColor());
}
}
}
if (plugin.inwildy == 1) {
if (isClanMember) {
if (!plugin.clan.containsKey(player.getName())) {
plugin.clan.put(player.getName(), player.getCombatLevel());
}
if (config.highlightAttacked()) {
if (interactor != null) {
if (!interactors.containsKey(interactor.getName())) {
WorldPoint a = interactor.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
int wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
int wildydiff = plugin.wildernessLevel - wildernessLevel;
if (wildydiff < 0) {
wildydiff = 0;
}
if (config.CalcSelfCB()) {
if (interacting.getCombatLevel() <= selfmax && interacting.getCombatLevel() - wildydiff >= selfmin && !interactor.isClanMember()) {
interactors.put(interactor.getName(), player.getName());
consumer.accept(interactor, config.getClanAttackableColor());
}
} else {
if (interacting.getCombatLevel() <= maxatk && interacting.getCombatLevel() - wildydiff >= minatk && !interactor.isClanMember()) {
interactors.put(interactor.getName(), player.getName());
consumer.accept(interactor, config.getClanAttackableColor());
}
}
}
}
}
} else {
if (config.PersistentClan()) {
if (plugin.clan.containsKey(player.getName())) {
consumer.accept(player, config.getClanMemberColor());
}
}
if (config.highlightAttacked()) {
if (interactors.containsKey(player.getName())) {
String attackername = interactors.get(player.getName());
Boolean found = false;
for (Player attacker : client.getPlayers()) {
if (attacker == null || attacker.getName() == null) {
continue;
}
if (attacker.getName().equals(attackername)) {
found = true;
Actor ainteract = attacker.getInteracting();
if (ainteract != null) {
if (ainteract.getName().equals(player.getName())) {
consumer.accept(player, config.getClanAttackableColor());
} else {
interactors.remove(player.getName());
}
} else {
interactors.remove(player.getName());
}
break;
}
}
if (!found) {
interactors.remove(player.getName());
}
continue;
}
}
if (config.highlightAttackable()) {
if ((config.hideAttackable() && plugin.ticks >= config.hideTime()) || plugin.clan.containsKey(player.getName())) {
continue;
}
WorldPoint a = player.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
int wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
int wildydiff = plugin.wildernessLevel - wildernessLevel;
if (wildydiff < 0) {
wildydiff = 0;
}
if (config.CalcSelfCB()) {
if (player.getCombatLevel() <= selfmax && player.getCombatLevel() - wildydiff >= selfmin) {
consumer.accept(player, config.getAttackableColor());
}
} else {
if (player.getCombatLevel() <= maxatk && player.getCombatLevel() - wildydiff >= minatk) {
consumer.accept(player, config.getAttackableColor());
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.inject.Inject;
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 ClanManModeTileOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
@Inject
private ClanManModeTileOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.drawTiles())
{
return null;
}
ClanManModeService.forEachPlayer((player, color) ->
{
final Polygon poly = player.getCanvasTilePoly();
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
});
return null;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2017, Aria <aria@ar1as.space>
* 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.equipmentinspector;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.plugins.grounditems.config.ItemHighlightMode;
import net.runelite.client.plugins.grounditems.config.MenuHighlightMode;
import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
@ConfigGroup("grounditems")
public interface EquipmentInspectorConfig extends Config
{
@ConfigItem(
keyName = "ShowValue",
name = "Show the total value of the items",
description = "shows the total value of the items",
position = 1
)
default boolean ShowValue()
{
return true;
}
@ConfigItem(
keyName = "protecteditems",
name = "# of protected items",
description = "Limit 4",
position = 2
)
default int protecteditems()
{ return 1; }
@ConfigItem(
keyName = "ExactValue",
name = "Show exact value",
description = "shows the excact gp value",
position = 3
)
default boolean ExactValue()
{ return false; }
}

View File

@@ -0,0 +1,98 @@
package net.runelite.client.plugins.equipmentinspector;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ItemComposition;
import net.runelite.api.kit.KitType;
import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Singleton
public class EquipmentInspectorPanel extends PluginPanel
{
private final static String NO_PLAYER_SELECTED = "No player selected";
private GridBagConstraints c;
private JPanel equipmentPanels;
private JPanel header;
private JLabel nameLabel;
@Inject
private ItemManager itemManager;
public EquipmentInspectorPanel()
{
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
setBorder(new EmptyBorder(10, 10, 10, 10));
setBackground(ColorScheme.DARK_GRAY_COLOR);
equipmentPanels = new JPanel(new GridBagLayout());
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
header = new JPanel();
header.setLayout(new BorderLayout());
header.setBorder(new CompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(58, 58, 58)),
BorderFactory.createEmptyBorder(0, 0, 10, 0)));
nameLabel = new JLabel(NO_PLAYER_SELECTED);
nameLabel.setForeground(Color.WHITE);
header.add(nameLabel, BorderLayout.CENTER);
layout.setHorizontalGroup(layout.createParallelGroup()
.addComponent(equipmentPanels)
.addComponent(header)
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(header)
.addGap(10)
.addComponent(equipmentPanels)
);
update(new HashMap<>(), "");
}
public void update(Map<KitType, ItemComposition> playerEquipment, String playerName)
{
if (playerName.isEmpty() || playerName == null)
{
nameLabel.setText(NO_PLAYER_SELECTED);
}
else
{
nameLabel.setText("Player: " + playerName);
}
SwingUtilities.invokeLater(() ->
{
equipmentPanels.removeAll();
playerEquipment.forEach((kitType, itemComposition) ->
{
AsyncBufferedImage itemImage = itemManager.getImage(itemComposition.getId());
equipmentPanels.add(new ItemPanel(itemComposition, kitType, itemImage), c);
c.gridy++;
});
header.revalidate();
header.repaint();
}
);
}
}

View File

@@ -0,0 +1,240 @@
package net.runelite.client.plugins.equipmentinspector;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
import net.runelite.api.events.PlayerMenuOptionClicked;
import net.runelite.api.kit.KitType;
import net.runelite.client.chat.ChatColorType;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.menus.MenuManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.Text;
import net.runelite.http.api.item.ItemPrice;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
@PluginDescriptor(
name = "<font color=\"green\">!Equipment Inspector</font>",
enabledByDefault = false
)
@Slf4j
public class EquipmentInspectorPlugin extends Plugin {
private static final String INSPECT_EQUIPMENT = "Gear";
private static final String KICK_OPTION = "Kick";
@Inject
@Nullable
private Client client;
@Inject
private ItemManager itemManager;
@Inject
private EquipmentInspectorConfig config;
@Inject
private ChatMessageManager chatMessageManager;
@Inject
private MenuManager menuManager;
@Inject
private ScheduledExecutorService executor;
@Inject
private ClientToolbar pluginToolbar;
@Provides
EquipmentInspectorConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(EquipmentInspectorConfig.class);
}
private NavigationButton navButton;
private EquipmentInspectorPanel equipmentInspectorPanel;
private int TotalPrice = 0;
private int Prot1 = 0;
private int Prot2 = 0;
private int Prot3 = 0;
private int Prot4 = 0;
@Override
protected void startUp() throws Exception
{
equipmentInspectorPanel = injector.getInstance(EquipmentInspectorPanel.class);
if(client != null) {
menuManager.addPlayerMenuItem(INSPECT_EQUIPMENT);
}
BufferedImage icon;
synchronized (ImageIO.class)
{
icon = ImageIO.read(getClass().getResourceAsStream("normal.png"));
}
navButton = NavigationButton.builder()
.tooltip("Equipment Inspector")
.icon(icon)
.priority(5)
.panel(equipmentInspectorPanel)
.build();
pluginToolbar.addNavigation(navButton);
}
@Override
protected void shutDown() throws Exception
{
menuManager.removePlayerMenuItem(INSPECT_EQUIPMENT);
}
@Subscribe
public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event)
{
if (event.getMenuOption().equals(INSPECT_EQUIPMENT))
{
executor.execute(() ->
{
try
{
SwingUtilities.invokeAndWait(() ->
{
if (!navButton.isSelected())
{
navButton.getOnSelect().run();
}
});
}
catch (InterruptedException | InvocationTargetException e)
{
throw new RuntimeException(e);
}
String playerName = Text.removeTags(event.getMenuTarget());
// The player menu uses a non-breaking space in the player name, we need to replace this to compare
// against the playerName in the player cache.
String finalPlayerName = playerName.replace('\u00A0', ' ');
System.out.println(finalPlayerName);
List<Player> players = client.getPlayers();
Optional<Player> targetPlayer = players.stream()
.filter(Objects::nonNull)
.filter(p -> p.getName().equals(finalPlayerName)).findFirst();
if (targetPlayer.isPresent())
{
TotalPrice = 0;
Prot1 = 0;
Prot2 = 0;
Prot3 = 0;
Prot4 = 0;
Player p = targetPlayer.get();
Map<KitType, ItemComposition> playerEquipment = new HashMap<>();
for (KitType kitType : KitType.values())
{
int itemId = p.getPlayerComposition().getEquipmentId(kitType);
if (itemId != -1)
{
ItemComposition itemComposition = client.getItemDefinition(itemId);
playerEquipment.put(kitType, itemComposition);
int ItemPrice = itemManager.getItemPrice(itemId);
TotalPrice += ItemPrice;
if (ItemPrice > Prot1 ) {
Prot4 = Prot3;
Prot3 = Prot2;
Prot2 = Prot1;
Prot1 = ItemPrice;
} else if (ItemPrice > Prot2){
Prot4 = Prot3;
Prot3 = Prot2;
Prot2 = ItemPrice;
} else if (ItemPrice > Prot3){
Prot4 = Prot3;
Prot3 = ItemPrice;
} else if (ItemPrice > Prot4){
Prot4 = ItemPrice;
}
}
}
int IgnoredItems = config.protecteditems();
if (IgnoredItems != 0 && IgnoredItems != 1 && IgnoredItems != 2 && IgnoredItems != 3) {
IgnoredItems = 4;
}
if (config.ShowValue()) {
switch (IgnoredItems) {
case 1:
TotalPrice = TotalPrice - Prot1;
break;
case 2:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
break;
case 3:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
TotalPrice = TotalPrice - Prot3;
break;
case 4:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
TotalPrice = TotalPrice - Prot3;
TotalPrice = TotalPrice - Prot4;
break;
}
String StringPrice = "";
if (!config.ExactValue()) {
TotalPrice = TotalPrice / 1000;
StringPrice = NumberFormat.getIntegerInstance().format(TotalPrice);
StringPrice = StringPrice + 'K';
}
if (config.ExactValue()) {
StringPrice = NumberFormat.getIntegerInstance().format(TotalPrice);
}
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.FRIENDSCHATNOTIFICATION)
.runeLiteFormattedMessage(new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Risked Value: ")
.append(ChatColorType.NORMAL)
.append(StringPrice)
.build())
.build());
}
equipmentInspectorPanel.update(playerEquipment, playerName);
}
});
}
}
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.equipmentinspector;
import net.runelite.api.ItemComposition;
import net.runelite.api.kit.KitType;
import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class ItemPanel extends JPanel
{
ItemPanel(ItemComposition item, KitType kitType, AsyncBufferedImage icon)
{
setBorder(new EmptyBorder(3, 3, 3, 3));
setBackground(ColorScheme.DARK_GRAY_COLOR);
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
JLabel name = new JLabel(item.getName());
JLabel location = new JLabel(StringUtils.capitalize(kitType.toString().toLowerCase()));
location.setFont(FontManager.getRunescapeSmallFont());
JLabel imageLabel = new JLabel();
icon.addTo(imageLabel);
layout.setVerticalGroup(layout.createParallelGroup()
.addComponent(imageLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(name)
.addComponent(location)
)
);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addComponent(imageLabel)
.addGap(8)
.addGroup(layout.createParallelGroup()
.addComponent(name)
.addComponent(location)
)
);
// AWT's Z order is weird. This put image at the back of the stack
setComponentZOrder(imageLabel, getComponentCount() - 1);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.fightcavejadhelper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class FightCaveJadHelperOverlay extends Overlay
{
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final Client client;
private final FightCaveJadHelperPlugin plugin;
private final SpriteManager spriteManager;
private final PanelComponent imagePanelComponent = new PanelComponent();
@Inject
private FightCaveJadHelperOverlay(Client client, FightCaveJadHelperPlugin plugin, SpriteManager spriteManager)
{
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.HIGH);
this.client = client;
this.plugin = plugin;
this.spriteManager = spriteManager;
}
@Override
public Dimension render(Graphics2D graphics)
{
final JadAttack attack = plugin.getAttack();
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);
return imagePanelComponent.render(graphics);
}
private BufferedImage getPrayerImage(JadAttack attack)
{
final int prayerSpriteID = attack == JadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
return spriteManager.getSprite(prayerSpriteID, 0);
}
}

View File

@@ -0,0 +1,89 @@
package net.runelite.client.plugins.fightcavejadhelper;
import javax.annotation.Nullable;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Fight Cave - Jad</font>",
description = "Show what to pray against Jad",
tags = {"bosses", "combat", "minigame", "overlay", "prayer", "pve", "pvm"},
enabledByDefault = false
)
public class FightCaveJadHelperPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private FightCaveJadHelperOverlay overlay;
@Getter(AccessLevel.PACKAGE)
@Nullable
private JadAttack attack;
private NPC jad;
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
jad = null;
attack = null;
}
@Subscribe
public void onNpcSpawned(final NpcSpawned event)
{
final int id = event.getNpc().getId();
if (id == NpcID.TZTOKJAD || id == NpcID.TZTOKJAD_6506)
{
jad = event.getNpc();
}
}
@Subscribe
public void onNpcDespawned(final NpcDespawned event)
{
if (jad == event.getNpc())
{
jad = null;
attack = null;
}
}
@Subscribe
public void onAnimationChanged(final AnimationChanged event)
{
if (event.getActor() != jad)
{
return;
}
if (jad.getAnimation() == JadAttack.MAGIC.getAnimation())
{
attack = JadAttack.MAGIC;
}
else if (jad.getAnimation() == JadAttack.RANGE.getAnimation())
{
attack = JadAttack.RANGE;
}
}
}

View File

@@ -0,0 +1,29 @@
package net.runelite.client.plugins.fightcavejadhelper;
import net.runelite.api.AnimationID;
import net.runelite.api.Prayer;
public enum JadAttack
{
MAGIC(AnimationID.TZTOK_JAD_MAGIC_ATTACK, Prayer.PROTECT_FROM_MAGIC),
RANGE(AnimationID.TZTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
private final int animation;
private final Prayer prayer;
JadAttack(int animation, Prayer prayer)
{
this.animation = animation;
this.prayer = prayer;
}
public int getAnimation()
{
return animation;
}
public Prayer getPrayer()
{
return prayer;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("Fight Cave - Wave Helper")
public interface FightCaveWaveHelperConfig extends Config
{
@ConfigItem(
keyName = "waveDisplay",
name = "Wave display",
description = "Shows monsters that will spawn on the selected wave(s)."
)
default WaveDisplayMode waveDisplay()
{
return WaveDisplayMode.BOTH;
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Fight Cave - Waves</font>",
description = "Displays current and upcoming wave monsters in the Fight Caves",
tags = {"bosses", "combat", "minigame", "overlay", "pve", "pvm", "jad", "fire", "cape", "wave"},
enabledByDefault = false
)
public class FightCaveWaveHelperPlugin extends Plugin
{
private static final Pattern WAVE_PATTERN = Pattern.compile(".*Wave: (\\d+).*");
private static final int FIGHT_CAVE_REGION = 9551;
private static final int MAX_MONSTERS_OF_TYPE_PER_WAVE = 2;
static final int MAX_WAVE = 63;
@Getter
static final List<EnumMap<WaveMonster, Integer>> WAVES = new ArrayList<>();
@Getter
private int currentWave = -1;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private WaveOverlay waveOverlay;
static
{
final WaveMonster[] waveMonsters = WaveMonster.values();
// Add wave 1, future waves are derived from its contents
final EnumMap<WaveMonster, Integer> waveOne = new EnumMap<>(WaveMonster.class);
waveOne.put(waveMonsters[0], 1);
WAVES.add(waveOne);
for (int wave = 1; wave < MAX_WAVE; wave++)
{
final EnumMap<WaveMonster, Integer> prevWave = WAVES.get(wave - 1).clone();
int maxMonsterOrdinal = -1;
for (int i = 0; i < waveMonsters.length; i++)
{
final int ordinalMonsterQuantity = prevWave.getOrDefault(waveMonsters[i], 0);
if (ordinalMonsterQuantity == MAX_MONSTERS_OF_TYPE_PER_WAVE)
{
maxMonsterOrdinal = i;
break;
}
}
if (maxMonsterOrdinal >= 0)
{
prevWave.remove(waveMonsters[maxMonsterOrdinal]);
}
final int addedMonsterOrdinal = maxMonsterOrdinal >= 0 ? maxMonsterOrdinal + 1 : 0;
final WaveMonster addedMonster = waveMonsters[addedMonsterOrdinal];
final int addedMonsterQuantity = prevWave.getOrDefault(addedMonster, 0);
prevWave.put(addedMonster, addedMonsterQuantity + 1);
WAVES.add(prevWave);
}
}
@Provides
FightCaveWaveHelperConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(FightCaveWaveHelperConfig.class);
}
@Override
public void startUp()
{
overlayManager.add(waveOverlay);
}
@Override
public void shutDown()
{
overlayManager.remove(waveOverlay);
currentWave = -1;
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (!inFightCave())
{
currentWave = -1;
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
final Matcher waveMatcher = WAVE_PATTERN.matcher(event.getMessage());
if (event.getType() != ChatMessageType.GAMEMESSAGE
|| !inFightCave()
|| !waveMatcher.matches())
{
return;
}
currentWave = Integer.parseInt(waveMatcher.group(1));
}
boolean inFightCave()
{
return ArrayUtils.contains(client.getMapRegions(), FIGHT_CAVE_REGION);
}
static String formatMonsterQuantity(final WaveMonster monster, final int quantity)
{
return String.format("%dx %s", quantity, monster);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum WaveDisplayMode
{
CURRENT("Current wave"),
NEXT("Next wave"),
BOTH("Both");
private final String name;
@Override
public String toString()
{
return name;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import lombok.AllArgsConstructor;
@AllArgsConstructor
enum WaveMonster
{
TZ_KIH("Tz-Kih", 22),
TZ_KEK("Tz-Kek", 45),
TOK_XIL("Tok-Xil", 90),
YT_MEJKOT("Yt-MejKot", 180),
KET_ZEK("Ket-Zek", 360),
TZKOK_JAD("TzTok-Jad", 702);
private final String name;
private final int level;
@Override
public String toString()
{
return String.format("%s - Level %s", name, level);
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
class WaveOverlay extends Overlay
{
private static final Color HEADER_COLOR = ColorScheme.BRAND_ORANGE;
private final FightCaveWaveHelperConfig config;
private final FightCaveWaveHelperPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private WaveOverlay(FightCaveWaveHelperConfig config, FightCaveWaveHelperPlugin plugin)
{
setPosition(OverlayPosition.TOP_RIGHT);
this.config = config;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!plugin.inFightCave()
|| plugin.getCurrentWave() < 0)
{
return null;
}
panelComponent.getChildren().clear();
final int currentWave = plugin.getCurrentWave();
final int waveIndex = currentWave - 1;
if (config.waveDisplay() == WaveDisplayMode.CURRENT
|| config.waveDisplay() == WaveDisplayMode.BOTH)
{
final Map<WaveMonster, Integer> waveContents = FightCaveWaveHelperPlugin.getWAVES().get(waveIndex);
addWaveInfo("Wave " + plugin.getCurrentWave(), waveContents);
}
if ((config.waveDisplay() == WaveDisplayMode.NEXT
|| config.waveDisplay() == WaveDisplayMode.BOTH)
&& currentWave != FightCaveWaveHelperPlugin.MAX_WAVE)
{
final Map<WaveMonster, Integer> waveContents = FightCaveWaveHelperPlugin.getWAVES().get(waveIndex + 1);
addWaveInfo("Next wave", waveContents);
}
return panelComponent.render(graphics);
}
private void addWaveInfo(final String headerText, final Map<WaveMonster, Integer> waveContents)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text(headerText)
.color(HEADER_COLOR)
.build());
for (LineComponent line : buildWaveLines(waveContents))
{
panelComponent.getChildren().add(line);
}
}
private static Collection<LineComponent> buildWaveLines(final Map<WaveMonster, Integer> wave)
{
final List<Map.Entry<WaveMonster, Integer>> monsters = new ArrayList<>(wave.entrySet());
monsters.sort(Map.Entry.comparingByKey());
final List<LineComponent> outputLines = new ArrayList<>();
for (Map.Entry<WaveMonster, Integer> monsterEntry : monsters)
{
final WaveMonster monster = monsterEntry.getKey();
final int quantity = monsterEntry.getValue();
final LineComponent line = LineComponent.builder()
.left(FightCaveWaveHelperPlugin.formatMonsterQuantity(monster, quantity))
.build();
outputLines.add(line);
}
return outputLines;
}
}

View File

@@ -0,0 +1,43 @@
package net.runelite.client.plugins.freezetimers;
import net.runelite.api.Actor;
import net.runelite.client.plugins.freezetimers.Spell;
import net.runelite.client.util.Text;
public class Barrage
extends Spell {
public static final long DURATION = 20000L;
private long remainingTime;
private boolean isFinished;
public Barrage(Actor affectedTarget, Actor caster) {
super(affectedTarget, caster);
}
public long getRemainingTime() {
long elapsedTime = System.currentTimeMillis() - this.startTime;
if (Barrage.getDURATION() > elapsedTime) {
return Barrage.getDURATION() - elapsedTime;
}
this.isFinished = true;
return 0L;
}
public boolean equals(Object o) {
if (o instanceof Barrage) {
Barrage barrage = (Barrage)o;
return Text.standardize(this.getAffectedTarget().getName()).equals(Text.standardize(((Barrage)o).getAffectedTarget().getName())) && this.getStartTime() == ((Barrage)o).getStartTime();
}
return false;
}
public static long getDURATION() {
return 20000L;
}
@Override
public boolean isFinished() {
return this.isFinished;
}
}

View File

@@ -0,0 +1,51 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(value="freezetimers")
public interface FreezeTimersConfig
extends Config {
@ConfigItem(position=0, keyName="freezeenable", name="Enable PvP freeze timers", description="Configures whether or not to show freeze timers.")
default public boolean EnableFreezeTimers() {
return false;
}
@ConfigItem(position=1, keyName="tilehighlight", name="Frozen opponent tile highlighting", description="Configures whether or not to highlight tiles frozen opponents are standing on.")
default public boolean drawTiles() {
return false;
}
@ConfigItem(position=2, keyName="timercolor", name="Freeze Timer Color", description="Color of freeze timer")
default public Color FreezeTimerColor() {
return new Color(0, 184, 212);
}
@ConfigItem(position=3, keyName="spellIcon", name="Show spell icon", description="Shows the spell icon for the freeze spell affecting the target")
default public boolean spellIcon() {
return true;
}
@ConfigItem(position=4, keyName="refreezeTimer", name="Refreeze Timer", description="Show a timer that counts up until the target can be refrozen")
default public boolean refreezeTimer() {
return true;
}
@ConfigItem(position=5, keyName="refreezeTimerColor", name="Refreeze color", description="The color for the timer that counts until the target can be refrozen")
default public Color RefreezeTimerColor() {
return Color.red;
}
@ConfigItem(position = 6, keyName = "tbtimer", name = "Tele Block Timer", description = "Enables tele block timer")
default boolean TBTimer() {
return true;
}
@ConfigItem(position = 7, keyName = "timerpos", name = "Freeze Timer Position", description = "Position of freeze timer")
default int FreezeTimerPos() {
return 80;
}
}

View File

@@ -0,0 +1,157 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.HeadIcon;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersPlugin;
import net.runelite.client.plugins.freezetimers.FreezeTimersService;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class FreezeTimersOverlay
extends Overlay {
private final FreezeTimersService FreezeTimersService;
private final FreezeTimersConfig config;
private final FreezeTimersPlugin plugin;
private final SpriteManager spriteManager;
private final Client client;
@Inject
private FreezeTimersOverlay(FreezeTimersConfig config, FreezeTimersService FreezeTimersService2, FreezeTimersPlugin plugin, Client client, SpriteManager spriteManager) {
this.config = config;
this.FreezeTimersService = FreezeTimersService2;
this.plugin = plugin;
this.client = client;
this.spriteManager = spriteManager;
this.setPosition(OverlayPosition.DYNAMIC);
this.setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (!this.config.EnableFreezeTimers()) {
return null;
}
this.FreezeTimersService.forEachPlayer((player, color) -> this.renderPlayerOverlay(graphics, (Player)player, (Color)color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color) {
BufferedImage clanchatImage;
int timer = 0;
String name = actor.getName();
int freezetype = this.plugin.freezetype(name);
boolean frozenoverlay = false;
int offset = 5;
long dtime = this.plugin.opponentfreezetime(name);
long tbed = plugin.istbed(name);
Point textLocation = null;
HeadIcon headIcon = actor.getOverheadIcon();
int freezetime = 0;
if (freezetype == 1 || freezetype == 4) {
freezetime = 5000;
} else if (freezetype == 2 || freezetype == 5) {
freezetime = 10000;
} else if (freezetype == 3 || freezetype == 6) {
freezetime = 15000;
} else if (freezetype == 7) {
freezetime = 20000;
} else if (freezetype == 8) {
freezetime = 2500;
} else if (freezetype == 9) {
freezetime = 5000;
} else if (freezetype == 10) {
freezetime = 7500;
}
long currenttime = System.currentTimeMillis();
long timediff = currenttime - dtime;
timer = (freezetime - (int)timediff) / 1000;
if (timediff < (long)freezetime) {
textLocation = actor.getCanvasTextLocation(graphics, String.valueOf(timer), actor.getLogicalHeight() + config.FreezeTimerPos());
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
} else if (timediff < (long)(freezetime + 3000)) {
timer = Math.abs(timer);
++timer;
if (this.config.refreezeTimer()) {
textLocation = actor.getCanvasTextLocation(graphics, String.valueOf(timer), actor.getLogicalHeight() + config.FreezeTimerPos());
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
graphics.setFont(FontManager.getRunescapeBoldFont());
if (headIcon != null) {
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
}
frozenoverlay = true;
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), this.config.RefreezeTimerColor());
return;
}
} else {
this.plugin.deleteopponent(name);
}
if (textLocation != null && (clanchatImage = this.plugin.GetFreezeIcon(freezetype - 1)) != null) {
int width = clanchatImage.getWidth();
int textHeight = graphics.getFontMetrics().getHeight() - graphics.getFontMetrics().getMaxDescent();
Point imageLocation = new Point(textLocation.getX(), textLocation.getY() - (config.FreezeTimerPos() / 2));
graphics.setFont(FontManager.getRunescapeFont());
graphics.setStroke(new BasicStroke(3.0f));
if (this.config.spellIcon()) {
frozenoverlay = true;
graphics.drawOval(imageLocation.getX(), imageLocation.getY(), clanchatImage.getWidth(), clanchatImage.getHeight());
OverlayUtil.renderImageLocation(graphics, imageLocation, clanchatImage);
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), color);
} else {
graphics.setColor(Color.cyan);
graphics.drawOval(textLocation.getX() - 3, textLocation.getY() - 15, clanchatImage.getWidth(), graphics.getFontMetrics().getHeight());
graphics.setColor(Color.blue);
graphics.fillOval(textLocation.getX() - 3, textLocation.getY() - 15, clanchatImage.getWidth(), graphics.getFontMetrics().getHeight());
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), Color.WHITE);
}
}
if (config.TBTimer()) {
if (tbed > 0) {
int type = plugin.tbtype(name);
int tbexpiry;
if (type > 0) {
if (type == 1) {
tbexpiry = 300000;
} else if (type == 2) {
tbexpiry = 150000;
} else {
return;
}
long tbtime = currenttime - tbed;
int tbtimer = (tbexpiry - (int) tbtime) / 1000;
if (tbtime < tbexpiry) {
textLocation = actor.getCanvasTextLocation(graphics, Integer.toString(tbtimer), actor.getLogicalHeight() + config.FreezeTimerPos());
if (frozenoverlay) {
textLocation = new Point(textLocation.getX() + 40, textLocation.getY() - config.FreezeTimerPos());
} else {
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
}
} else {
plugin.deletetb(name);
}
}
}
}
}
}

View File

@@ -0,0 +1,402 @@
package net.runelite.client.plugins.freezetimers;
import com.google.inject.Provides;
import java.awt.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.ImageObserver;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.events.*;
import net.runelite.api.GameState;
import net.runelite.api.HeadIcon;
import net.runelite.api.IndexedSprite;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.freezetimers.Barrage;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersOverlay;
import net.runelite.client.plugins.freezetimers.FreezeTimersTileOverlay;
import net.runelite.client.plugins.freezetimers.Spell;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil;
import org.slf4j.Logger;
@PluginDescriptor(
name = "<font color=\"aqua\">!Freeze Timers</font>",
description = "PVP Freeze Timers",
tags = {"PvP", "Freeze", "Timers"}
)
public class FreezeTimersPlugin
extends Plugin {
@Inject
private OverlayManager overlayManager;
@Inject
private FreezeTimersConfig config;
@Inject
private FreezeTimersOverlay FreezeTimersOverlay;
@Inject
private FreezeTimersTileOverlay FreezeTimersTileOverlay;
@Inject
private Client client;
@Inject
private SpriteManager spriteManager;
private static final int[] FREEZE_ICONS = {
SpriteID.SPELL_BIND,
SpriteID.SPELL_SNARE,
SpriteID.SPELL_ENTANGLE,
SpriteID.SPELL_ICE_RUSH,
SpriteID.SPELL_ICE_BURST,
SpriteID.SPELL_ICE_BLITZ,
SpriteID.SPELL_ICE_BARRAGE,
SpriteID.SPELL_BIND,
SpriteID.SPELL_SNARE,
SpriteID.SPELL_ENTANGLE,
SpriteID.SPELL_TELE_BLOCK
};
private static final Dimension FREEZE_ICON_DIMENSION = new Dimension(25, 25);
private static final Color FREEZE_ICON_OUTLINE_COLOR = new Color(33, 33, 33);
private final BufferedImage[] FreezeIcons = new BufferedImage[FREEZE_ICONS.length];
private final int SPLASH_ID = 85;
Map<String, Long> tbedthings = new HashMap<>();
Map<String, Integer> tbtypes = new HashMap<>();
Map<String, Spell> testMap = new HashMap<String, Spell>();
Map<String, Long> frozenthings = new HashMap<String, Long>();
Map<String, WorldPoint> frozenthingpoints = new HashMap<String, WorldPoint>();
Map<String, Integer> freezetype = new HashMap<String, Integer>();
Map<Integer, Integer> magexp = new HashMap<Integer, Integer>();
int lastxp;
int ticks;
int currticks;
String currtarget;
String spell;
@Provides
FreezeTimersConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(FreezeTimersConfig.class);
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) {
if (gameStateChanged.getGameState() == GameState.LOGGED_IN) {
this.loadFreezeIcons();
}
}
@Override
protected void startUp() throws Exception {
this.overlayManager.add(this.FreezeTimersOverlay);
this.overlayManager.add(this.FreezeTimersTileOverlay);
}
@Override
protected void shutDown() throws Exception {
this.overlayManager.remove(this.FreezeTimersOverlay);
this.overlayManager.remove(this.FreezeTimersTileOverlay);
this.frozenthings.clear();
this.frozenthingpoints.clear();
this.tbedthings.clear();
this.tbtypes.clear();
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event) {
if (event.getMenuTarget().contains("->")) {
Pattern spattern = Pattern.compile(">(.+?)</col>");
Pattern ppattern = Pattern.compile("> <col=ffffff>(.+?)<col=");
Matcher smatch = spattern.matcher(event.getMenuTarget());
Matcher pmatch = ppattern.matcher(event.getMenuTarget());
smatch.find();
pmatch.find();
if (smatch.group(1) != null && pmatch.group(1) != null) {
this.currticks = this.ticks;
this.spell = smatch.group(1);
this.currtarget = pmatch.group(1).replace("\u00a0", " ");
}
}
}
@Subscribe
public void onExperienceChanged(ExperienceChanged event) {
if (event.getSkill() == Skill.MAGIC) {
int xp = this.client.getSkillExperience(Skill.MAGIC);
int gains = xp - this.lastxp;
this.lastxp = xp;
if (!this.magexp.containsKey(this.ticks)) {
this.magexp.clear();
this.magexp.put(this.ticks, gains);
}
}
}
@Subscribe
private void onAnimationChanged(AnimationChanged event) {
Logger l = this.client.getLogger();
Actor subject = event.getActor();
Actor target = subject.getInteracting();
if (subject.getAnimation() == 1979) {
try {
if (target.getGraphic() == 85 || target.getGraphic() != -1) {
return;
}
if (this.frozenthings.containsKey(target.getName())) {
return;
}
this.testMap.put(target.getName(), new Barrage(target, subject));
this.freezetype.put(target.getName(), 7);
this.frozenthings.put(target.getName(), System.currentTimeMillis());
this.frozenthingpoints.put(target.getName(), target.getWorldLocation());
}
catch (NullPointerException nullPointerException) {
// empty catch block
}
}
}
@Subscribe
public void onGameTick(GameTick event) {
int xp = 0;
boolean praymage = false;
if (this.magexp.containsKey(this.ticks)) {
xp = this.magexp.get(this.ticks);
}
if (xp > 0 && this.currtarget != null) {
if (this.frozenthings.containsKey(this.currtarget)) {
this.currtarget = null;
return;
}
WorldPoint targetPosition = null;
for (Player player : this.client.getPlayers()) {
String playerName;
if (player == null || !(playerName = player.getName()).equals(this.currtarget)) continue;
if (player.getOverheadIcon() != null && player.getOverheadIcon().equals((Object)HeadIcon.MAGIC)) {
praymage = true;
}
targetPosition = player.getWorldLocation();
break;
}
if (targetPosition != null) {
if (this.spell.equals("Bind") && xp > 30) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 8);
} else {
this.freezetype.put(this.currtarget, 1);
}
} else if (this.spell.equals("Snare") && xp > 60) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 9);
} else {
this.freezetype.put(this.currtarget, 2);
}
} else if (this.spell.equals("Entangle") && xp >= 89) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 10);
} else {
this.freezetype.put(this.currtarget, 3);
}
} else if (this.spell.equals("Ice Rush") && xp > 34) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 4);
} else if (this.spell.equals("Ice Burst") && xp > 40) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 5);
} else if (this.spell.equals("Ice Blitz") && xp > 46) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 6);
} else if (this.spell.equals("Ice Barrage") && xp > 52) {
Barrage barrage = new Barrage(this.client.getLocalPlayer().getInteracting(), this.client.getLocalPlayer());
this.testMap.put(this.currtarget, barrage);
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 7);
} else if (spell.equals("Tele Block") && xp == 95) {
if (config.TBTimer()) {
if (praymage) {
this.tbtypes.put(this.currtarget, 2);
} else {
this.tbtypes.put(this.currtarget, 1);
}
this.tbedthings.put(this.currtarget, System.currentTimeMillis());
}
}
}
}
if (this.currtarget != null && this.ticks > this.currticks + 1) {
Player local = this.client.getLocalPlayer();
Actor interacting = local.getInteracting();
if (interacting != null) {
if (!interacting.getName().equals(this.currtarget)) {
this.currtarget = null;
}
} else {
this.currtarget = null;
}
}
++this.ticks;
}
public long opponentfreezetime(String name) {
if (this.frozenthings.containsKey(name)) {
return this.frozenthings.get(name);
}
return 0L;
}
public WorldPoint playerpos(String name) {
if (this.frozenthingpoints.containsKey(name)) {
return this.frozenthingpoints.get(name);
}
return null;
}
public void updatePosition(String name, WorldPoint point) {
if (this.frozenthingpoints.containsKey(name)) {
this.frozenthingpoints.remove(name);
this.frozenthingpoints.put(name, point);
}
}
public int freezetype(String name) {
if (this.freezetype.containsKey(name)) {
return this.freezetype.get(name);
}
return 0;
}
public long istbed(String name) {
if (this.tbedthings.containsKey(name)) {
return this.tbedthings.get(name);
}
return 0;
}
public int tbtype(String name) {
if (this.tbtypes.containsKey(name)) {
return this.tbtypes.get(name);
}
return 0;
}
public void deleteopponent(String name) {
if (this.frozenthings.containsKey(name)) {
this.frozenthings.remove(name);
}
if (this.frozenthingpoints.containsKey(name)) {
this.frozenthingpoints.remove(name);
}
if (this.freezetype.containsKey(name)) {
this.freezetype.remove(name);
}
}
public void deletetb(String name) {
if (this.tbedthings.containsKey(name)) {
this.tbedthings.remove(name);
}
if (this.tbtypes.containsKey(name)) {
this.tbtypes.remove(name);
}
}
private void loadFreezeIcons() {
IndexedSprite[] freezeIcons = new IndexedSprite[]{};
IndexedSprite[] newfreezeIcons = Arrays.copyOf(freezeIcons, FREEZE_ICONS.length);
int curPosition = 0;
int i = 0;
while (i < FREEZE_ICONS.length) {
int resource = FREEZE_ICONS[i];
this.FreezeIcons[i] = FreezeTimersPlugin.rgbaToIndexedBufferedImage(FreezeTimersPlugin.FreezeIconFromSprite(this.spriteManager.getSprite(resource, 0)));
newfreezeIcons[curPosition] = FreezeTimersPlugin.createIndexedSprite(this.client, this.FreezeIcons[i]);
++i;
++curPosition;
}
}
private static IndexedSprite createIndexedSprite(Client client, BufferedImage bufferedImage) {
IndexColorModel indexedCM = (IndexColorModel)bufferedImage.getColorModel();
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
byte[] pixels = ((DataBufferByte)bufferedImage.getRaster().getDataBuffer()).getData();
int[] palette = new int[indexedCM.getMapSize()];
indexedCM.getRGBs(palette);
IndexedSprite newIndexedSprite = client.createIndexedSprite();
newIndexedSprite.setPixels(pixels);
newIndexedSprite.setPalette(palette);
newIndexedSprite.setWidth(width);
newIndexedSprite.setHeight(height);
newIndexedSprite.setOriginalWidth(width);
newIndexedSprite.setOriginalHeight(height);
newIndexedSprite.setOffsetX(0);
newIndexedSprite.setOffsetY(0);
return newIndexedSprite;
}
private static BufferedImage rgbaToIndexedBufferedImage(BufferedImage sourceBufferedImage) {
BufferedImage indexedImage = new BufferedImage(sourceBufferedImage.getWidth(), sourceBufferedImage.getHeight(), 13);
ColorModel cm = indexedImage.getColorModel();
IndexColorModel icm = (IndexColorModel)cm;
int size = icm.getMapSize();
byte[] reds = new byte[size];
byte[] greens = new byte[size];
byte[] blues = new byte[size];
icm.getReds(reds);
icm.getGreens(greens);
icm.getBlues(blues);
WritableRaster raster = indexedImage.getRaster();
int pixel = raster.getSample(0, 0, 0);
IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel);
BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null);
resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null);
return resultIndexedImage;
}
private static BufferedImage FreezeIconFromSprite(BufferedImage freezeSprite) {
BufferedImage freezeCanvas = ImageUtil.resizeCanvas(freezeSprite, FreezeTimersPlugin.FREEZE_ICON_DIMENSION.width, FreezeTimersPlugin.FREEZE_ICON_DIMENSION.height);
return ImageUtil.outlineImage(freezeCanvas, FREEZE_ICON_OUTLINE_COLOR);
}
BufferedImage GetFreezeIcon(int id) {
return this.FreezeIcons[id];
}
}

View File

@@ -0,0 +1,81 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import java.util.List;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersPlugin;
@Singleton
public class FreezeTimersService {
private final Client client;
private final FreezeTimersConfig config;
private final FreezeTimersPlugin plugin;
@Inject
private FreezeTimersService(Client client, FreezeTimersConfig config, FreezeTimersPlugin plugin) {
this.config = config;
this.plugin = plugin;
this.client = client;
}
public void forEachPlayer(BiConsumer<Player, Color> consumer) {
for (Player player : this.client.getPlayers()) {
if (player == null || player.getName() == null) continue;
String name = player.getName();
int freezetype = this.plugin.freezetype(name);
long tbed = plugin.istbed(name);
long dtime = this.plugin.opponentfreezetime(name);
int freezetime = 0;
if (freezetype == 1 || freezetype == 4) {
freezetime = 5000;
} else if (freezetype == 2 || freezetype == 5) {
freezetime = 10000;
} else if (freezetype == 3 || freezetype == 6) {
freezetime = 15000;
} else if (freezetype == 7) {
freezetime = 20000;
} else if (freezetype == 8) {
freezetime = 2500;
} else if (freezetype == 9) {
freezetime = 5000;
} else if (freezetype == 10) {
freezetime = 7500;
}
if (dtime <= 0L) continue;
long currenttime = System.currentTimeMillis();
long timediff = currenttime - dtime;
if (timediff < (long)freezetime) {
WorldPoint lastWorldPoint;
WorldPoint currentWorldPoint = player.getWorldLocation();
if (currentWorldPoint.equals(lastWorldPoint = this.plugin.playerpos(name))) {
consumer.accept(player, this.config.FreezeTimerColor());
continue;
}
if (timediff < 605L) {
this.plugin.updatePosition(name, currentWorldPoint);
consumer.accept(player, this.config.FreezeTimerColor());
continue;
}
this.plugin.deleteopponent(name);
continue;
}
if (timediff < (long)(freezetime + 3000)) {
consumer.accept(player, Color.YELLOW);
continue;
} else {
this.plugin.deleteopponent(name);
}
if (tbed > 0) {
consumer.accept(player, config.FreezeTimerColor());
return;
}
}
}
}

View File

@@ -0,0 +1,46 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import net.runelite.api.Player;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersService;
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 FreezeTimersTileOverlay
extends Overlay {
private final FreezeTimersService FreezeTimersService;
private final FreezeTimersConfig config;
@Inject
private FreezeTimersTileOverlay(FreezeTimersConfig config, FreezeTimersService FreezeTimersService2) {
this.config = config;
this.FreezeTimersService = FreezeTimersService2;
this.setLayer(OverlayLayer.ABOVE_SCENE);
this.setPosition(OverlayPosition.DYNAMIC);
this.setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (!this.config.drawTiles()) {
return null;
}
this.FreezeTimersService.forEachPlayer((player, color) -> {
Polygon poly = player.getCanvasTilePoly();
if (poly != null) {
OverlayUtil.renderPolygon(graphics, poly, color);
}
});
return null;
}
}

View File

@@ -0,0 +1,35 @@
package net.runelite.client.plugins.freezetimers;
public enum PlayerSpellEffect {
BARRAGE("Ice Barrage", 20000, false),
BLITZ("Ice Blitz", 15000, false);
private final String SPELL_NAME;
private long startTime;
private int duration;
private boolean halvable;
private PlayerSpellEffect(String name, int duration, boolean halvable) {
this.SPELL_NAME = name;
this.duration = duration;
this.halvable = halvable;
this.startTime = System.currentTimeMillis();
}
public String getSPELL_NAME() {
return this.SPELL_NAME;
}
public long getStartTime() {
return this.startTime;
}
public int getDuration() {
return this.duration;
}
public boolean isHalvable() {
return this.halvable;
}
}

View File

@@ -0,0 +1,34 @@
package net.runelite.client.plugins.freezetimers;
import net.runelite.api.Actor;
public abstract class Spell {
private final Actor affectedTarget;
private final Actor caster;
public final long startTime;
private long remainingTime;
private boolean isFinished;
protected Spell(Actor affectedTarget, Actor caster) {
this.affectedTarget = affectedTarget;
this.caster = caster;
this.startTime = System.currentTimeMillis();
}
public Actor getAffectedTarget() {
return this.affectedTarget;
}
public Actor getCaster() {
return this.caster;
}
public long getStartTime() {
return this.startTime;
}
public boolean isFinished() {
return this.isFinished;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2018, Damen <https://github.com/basicDamen>
* 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.grotesqueguardians;
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.GraphicsObject;
import net.runelite.api.Perspective;
import net.runelite.api.coords.LocalPoint;
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;
class GrotesqueGuardiansOverlay extends Overlay
{
private static final int GROTESQUE_GUARDIANS_REGION_ID = 6727;
private final Client client;
private static final int GROTESQUE_GUARDIANS_LIGHTNING_START = 1416;
private static final int GROTESQUE_GUARDIANS_LIGHTNING_END = 1431;
private static final int GROTESQUE_GUARDIANS_FALLING_ROCKS = 1436;
private static final int GROTESQUE_GUARDIANS_STONE_ORB = 160;
@Inject
private GrotesqueGuardiansOverlay(Client client)
{
this.client = client;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
setPriority(OverlayPriority.LOW);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!client.isInInstancedRegion() || client.getMapRegions()[0] != GROTESQUE_GUARDIANS_REGION_ID)
{
return null;
}
// TODO: Awaiting GraphicsObjectDespawn event to be tracked to make this more efficient.
for (GraphicsObject graphicsObject : client.getGraphicsObjects())
{
Color color = null;
if (graphicsObject.getId() >= GROTESQUE_GUARDIANS_LIGHTNING_START && graphicsObject.getId() <= GROTESQUE_GUARDIANS_LIGHTNING_END)
{
color = Color.ORANGE;
}
else if (graphicsObject.getId() == GROTESQUE_GUARDIANS_STONE_ORB)
{
color = Color.GRAY;
}
else if (graphicsObject.getId() == GROTESQUE_GUARDIANS_FALLING_ROCKS)
{
color = Color.YELLOW;
}
else
{
continue;
}
LocalPoint lp = graphicsObject.getLocation();
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
}
return null;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018, Damen <https://github.com/basicDamen>
* 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.grotesqueguardians;
import javax.inject.Inject;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Grotesque Guardians</font>",
description = "Display tile indicators for the Grotesque Guardian special attacks",
tags = {"grotesque", "guardians", "gargoyle", "garg"}
)
public class GrotesqueGuardiansPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private GrotesqueGuardiansOverlay overlay;
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
}
}

View File

@@ -0,0 +1,35 @@
package net.runelite.client.plugins.hideprayers;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("hideprayers")
public interface HidePrayersConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "pk prayers",
name = "Hides none pk prayers",
description = "Hides widget icons."
)
default boolean showPrayers() { return false; }
@ConfigItem(
position = 1,
keyName = "eagle/mystic",
name = "Shows eagle and mystic prayers",
description = "Hides widget icons."
)
default boolean showEagleMystic() { return false; }
@ConfigItem(
position = 1,
keyName = "ultstr",
name = "Shows ultimate strength",
description = "Hides widget icons."
)
default boolean showUltStrength() { return false; }
}

View File

@@ -0,0 +1,169 @@
package net.runelite.client.plugins.hideprayers;
import com.google.common.collect.ImmutableList;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import net.runelite.api.*;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import javax.inject.Inject;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@PluginDescriptor(
name = "<font color=\"green\">!Hide Prayers</font>",
description = "Hides specific Prayers in the Prayer tab."
)
public class HidePrayersPlugin extends Plugin {
private static final int PRAYER_COUNT = Prayer.values().length;
private static final List<WidgetInfo> PRAYER_WIDGET_INFO_LIST = ImmutableList.of(WidgetInfo.PRAYER_THICK_SKIN,
WidgetInfo.PRAYER_BURST_OF_STRENGTH, WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, WidgetInfo.PRAYER_SHARP_EYE,
WidgetInfo.PRAYER_MYSTIC_WILL, WidgetInfo.PRAYER_ROCK_SKIN, WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH,
WidgetInfo.PRAYER_IMPROVED_REFLEXES, WidgetInfo.PRAYER_RAPID_RESTORE, WidgetInfo.PRAYER_RAPID_HEAL,
WidgetInfo.PRAYER_PROTECT_ITEM, WidgetInfo.PRAYER_HAWK_EYE, WidgetInfo.PRAYER_MYSTIC_LORE,
WidgetInfo.PRAYER_STEEL_SKIN, WidgetInfo.PRAYER_ULTIMATE_STRENGTH, WidgetInfo.PRAYER_INCREDIBLE_REFLEXES,
WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, WidgetInfo.PRAYER_PROTECT_FROM_MISSILES,
WidgetInfo.PRAYER_PROTECT_FROM_MELEE, WidgetInfo.PRAYER_EAGLE_EYE, WidgetInfo.PRAYER_MYSTIC_MIGHT,
WidgetInfo.PRAYER_RETRIBUTION, WidgetInfo.PRAYER_REDEMPTION, WidgetInfo.PRAYER_SMITE,
WidgetInfo.PRAYER_PRESERVE, WidgetInfo.PRAYER_CHIVALRY, WidgetInfo.PRAYER_PIETY, WidgetInfo.PRAYER_RIGOUR,
WidgetInfo.PRAYER_AUGURY);
@Inject
private Client client;
@Inject
private HidePrayersConfig config;
@Provides
HidePrayersConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(HidePrayersConfig.class);
}
@Override
protected void startUp() throws Exception {
hidePrayers();
}
@Override
protected void shutDown() throws Exception {
restorePrayers();
}
@Subscribe
public void onGameStateChanged(GameStateChanged event) {
if (event.getGameState() == GameState.LOGGED_IN) {
hidePrayers();
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event) {
if (event.getGroup().equals("hideprayers")) {
hidePrayers();
}
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event) {
if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) {
hidePrayers();
}
}
private PrayerTabState getPrayerTabState() {
HashTable<WidgetNode> componentTable = client.getComponentTable();
for (WidgetNode widgetNode : componentTable.getNodes()) {
if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) {
return PrayerTabState.PRAYERS;
} else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) {
return PrayerTabState.QUICK_PRAYERS;
}
}
return PrayerTabState.NONE;
}
private void restorePrayers() {
if (client.getGameState() != GameState.LOGGED_IN)
return;
PrayerTabState prayerTabState = getPrayerTabState();
if (prayerTabState == PrayerTabState.PRAYERS) {
List<Widget> prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget)
.filter(Objects::nonNull).collect(Collectors.toList());
if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size())
return;
for (int index = 0; index < PRAYER_COUNT; index++)
prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false);
}
}
private void hidePrayers() {
if (client.getGameState() != GameState.LOGGED_IN)
return;
PrayerTabState prayerTabState = getPrayerTabState();
if (prayerTabState == PrayerTabState.PRAYERS) {
List<Widget> prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget)
.filter(Objects::nonNull).collect(Collectors.toList());
if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size())
return;
for (int index = 0; index < PRAYER_COUNT; index++) {
Prayer prayer = Prayer.values()[index];
Widget prayerWidget = prayerWidgets.get(prayer.ordinal());
if (!config.showPrayers() && !config.showEagleMystic())
prayerWidget.setHidden(false);
if (config.showPrayers()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false);// protect item
prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// mage
prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// range
prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// melee
prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false);// smite
if (config.showEagleMystic()) {
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true);// augury
} else {
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// augury
}
if (config.showUltStrength()) {
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true);// piety
} else {
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// piety
}
}
if (config.showEagleMystic()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle
prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true);// augury
}
if (config.showUltStrength()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ult Strength
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true);// piety
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
package net.runelite.client.plugins.hideprayers;
public enum PrayerTabState
{
NONE,
PRAYERS,
QUICK_PRAYERS
}

View File

@@ -0,0 +1,41 @@
package net.runelite.client.plugins.hydra;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("hydra")
public interface HydraConfig extends Config {
@ConfigItem(
position = 0,
keyName = "hydraenable",
name = "Enable Hydra (194 cb) Helper",
description = "Configures whether or not to enable Hydra Helper. (For use on regular hydra's only, will not work with Alchemical Hydra)."
)
default boolean EnableHydra() { return true; }
@ConfigItem(
position = 1,
keyName = "textindicators",
name = "Text Indicator",
description = "Configures if text indicator is shown above hydra's or not."
)
default boolean TextIndicator() { return true; }
@ConfigItem(
position = 2,
keyName = "countersize",
name = "Bold indicator",
description = "Configures if text indicator is bold or not."
)
default boolean BoldText() { return false; }
@ConfigItem(
position = 3,
keyName = "prayerhelper",
name = "Prayer Helper",
description = "Configures if prayer helper is shown or not."
)
default boolean PrayerHelper() { return true; }
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
public class HydraIndicatorOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private HydraIndicatorOverlay(HydraConfig config, HydraPlugin plugin) {
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.MED);
panelComponent.setPreferredSize(new Dimension(14, 0));
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.PrayerHelper()) {
return null;
}
if (plugin.Hydra != null) {
if (plugin.hydras.containsKey(plugin.Hydra.getIndex())) {
int val = plugin.hydras.get(plugin.Hydra.getIndex());
if (val != 0) {
panelComponent.getChildren().clear();
panelComponent.getChildren().add(LineComponent.builder().right(Integer.toString(val)).build());
return panelComponent.render(graphics);
}
}
}
return null;
}
}

View File

@@ -0,0 +1,76 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class HydraOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private Client client;
@Inject
private HydraOverlay(HydraConfig config, HydraPlugin plugin) {
this.config = config;
this.plugin = plugin;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
panelComponent.setPreferredSize(new Dimension(150, 0));
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.TextIndicator()) {
return null;
}
for (NPC hydra : client.getNpcs()) {
if (hydra == null || hydra.getName() == null) {
continue;
}
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (plugin.hydras.containsKey(hydra.getIndex())) {
int val = plugin.hydras.get(hydra.getIndex());
if (val != 0) {
if (config.BoldText()) {
graphics.setFont(FontManager.getRunescapeBoldFont());
}
if (plugin.hydraattacks.containsKey(hydra.getIndex())) {
int attack = plugin.hydraattacks.get(hydra.getIndex());
if (attack == 8261) {
if (val == 3) {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "MAGE", hydra.getLogicalHeight() + 100), "MAGE", Color.BLUE);
} else {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "RANGE", hydra.getLogicalHeight() + 100), "RANGE", Color.GREEN);
}
} else if (attack == 8262) {
if (val == 3) {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "RANGE", hydra.getLogicalHeight() + 100), "RANGE", Color.GREEN);
} else {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "MAGE", hydra.getLogicalHeight() + 100), "MAGE", Color.BLUE);
}
}
}
Point runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam = hydra.getCanvasTextLocation(graphics, Integer.toString(val), hydra.getLogicalHeight() + 40);
if (runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam != null) {
OverlayUtil.renderTextLocation(graphics, runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam, Integer.toString(val), Color.WHITE);
}
}
}
}
}
graphics.setFont(FontManager.getRunescapeFont());
return null;
}
}

View File

@@ -0,0 +1,145 @@
package net.runelite.client.plugins.hydra;
import net.runelite.api.events.*;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import java.util.HashMap;
import java.util.Map;
@PluginDescriptor(
name = "Hydra",
description = "Hydra Helper",
tags = {"Hydra", "Helper"}
)
public class HydraPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private HydraConfig config;
@Inject
private HydraOverlay HydraOverlay;
@Inject
private HydraPrayOverlay HydraPrayOverlay;
@Inject
private HydraIndicatorOverlay HydraIndicatorOverlay;
@Inject
private Client client;
@Inject
private SpriteManager spriteManager;
@Provides
HydraConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(HydraConfig.class);
}
Map<Integer, Integer> hydras = new HashMap<>();
Map<Integer, Integer> hydraattacks = new HashMap<>();
NPC Hydra;
@Override
protected void startUp() throws Exception {
overlayManager.add(HydraOverlay);
overlayManager.add(HydraPrayOverlay);
overlayManager.add(HydraIndicatorOverlay);
}
@Override
protected void shutDown() throws Exception {
overlayManager.remove(HydraOverlay);
overlayManager.remove(HydraPrayOverlay);
overlayManager.remove(HydraIndicatorOverlay);
hydras.clear();
hydraattacks.clear();
}
@Subscribe
public void onNpcSpawned(NpcSpawned event) {
if (!config.EnableHydra()) {
return;
}
NPC hydra = event.getNpc();
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (!hydras.containsKey(hydra.getIndex())) {
hydras.put(hydra.getIndex(), 3);
}
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event) {
if (!config.EnableHydra()) {
return;
}
NPC hydra = event.getNpc();
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (hydras.containsKey(hydra.getIndex())) {
hydras.remove(hydra.getIndex());
}
if (hydraattacks.containsKey(hydra.getIndex())) {
hydraattacks.remove(hydra.getIndex());
}
}
}
}
@Subscribe
public void onAnimationChanged(AnimationChanged event) {
Actor monster = event.getActor();
Actor local = client.getLocalPlayer();
if (monster instanceof NPC) {
NPC hydra = (NPC) monster;
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (hydras.containsKey(hydra.getIndex())) {
if (hydra.getAnimation() == 8261 || hydra.getAnimation() == 8262) {
if (hydra.getInteracting().equals(local)) {
Hydra = hydra;
}
if (hydraattacks.containsKey(hydra.getIndex())) {
int lastattack = hydraattacks.get(hydra.getIndex());
hydraattacks.replace(hydra.getIndex(), hydra.getAnimation());
if (lastattack != hydra.getAnimation()) {
hydras.replace(hydra.getIndex(), 2);
} else {
int currval = hydras.get(hydra.getIndex());
if (currval == 1) {
hydras.replace(hydra.getIndex(), 3);
} else {
hydras.replace(hydra.getIndex(), currval - 1);
}
}
} else {
hydraattacks.put(hydra.getIndex(), hydra.getAnimation());
int currval = hydras.get(hydra.getIndex());
if (currval == 1) {
hydras.replace(hydra.getIndex(), 3);
} else {
hydras.replace(hydra.getIndex(), currval - 1);
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,100 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class HydraPrayOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final SpriteManager spriteManager;
private final PanelComponent imagePanelComponent = new PanelComponent();
@Inject
private Client client;
@Inject
private HydraPrayOverlay(HydraConfig config, HydraPlugin plugin, SpriteManager spriteManager) {
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.HIGH);
this.spriteManager = spriteManager;
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.PrayerHelper()) {
return null;
}
if (plugin.Hydra != null) {
if (plugin.hydras.containsKey(plugin.Hydra.getIndex())) {
int val = plugin.hydras.get(plugin.Hydra.getIndex());
if (val != 0) {
if (plugin.hydraattacks.containsKey(plugin.Hydra.getIndex())) {
int attack = plugin.hydraattacks.get(plugin.Hydra.getIndex());
if (attack == 8261) {
if (val == 3) {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
} else {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
}
} else if (attack == 8262) {
if (val == 3) {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
} else {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
}
}
}
}
}
}
return null;
}
}

View File

@@ -43,6 +43,8 @@ public class InventoryTagsOverlay extends WidgetItemOverlay
{
this.itemManager = itemManager;
this.plugin = plugin;
showOnEquipment();
showOnInventory();
}
@Override

View File

@@ -51,6 +51,8 @@ class ItemChargeOverlay extends WidgetItemOverlay
{
this.itemChargePlugin = itemChargePlugin;
this.config = config;
showOnInventory();
showOnEquipment();
}
@Override

View File

@@ -0,0 +1,27 @@
package net.runelite.client.plugins.kittennotifier;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("kittennotifier")
public interface KittenNotifierConfig extends Config{
@ConfigItem(
keyName = "absolutelyNeeded",
name = "Notify only on Absolute Need",
description = "Only notify when kitten absolutely needs food or attention."
)
default boolean absolutelyNeeded() { return false; }
@ConfigItem(
keyName = "catOwned",
name = "",
description = "",
hidden = true
)
default boolean catOwned() { return false; }
@ConfigItem(
keyName = "catOwned",
name = "",
description = ""
)
void catOwned(Boolean bool);
}

View File

@@ -0,0 +1,84 @@
package net.runelite.client.plugins.kittennotifier;
import com.google.inject.Provides;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.NpcActionChanged;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.api.NPC;
import net.runelite.api.Client;
import javax.inject.Inject;
@PluginDescriptor(
name = "!Kitten Notifier",
description = "Sends a notification when your kitten needs food, attention, or is grown.",
tags = {"kitten, notifications"}
)
public class KittenNotifierPlugin extends Plugin{
@Inject
private Notifier notifier;
@Inject
private KittenNotifierConfig config;
@Inject
private Client client;
@Provides
KittenNotifierConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(KittenNotifierConfig.class);
}
@Subscribe
public void onChatMessage(ChatMessage event) {
if (event.getType() == ChatMessageType.ENGINE && !config.catOwned()) {
if (!config.absolutelyNeeded()) {
if (event.getMessage().contentEquals("<col=ef1020>Your kitten is hungry.</col>")) {
notifier.notify("Your kitten is hungry.");
}
if (event.getMessage().contentEquals("<col=ef1020>Your kitten wants attention.</col>")) {
notifier.notify("Your kitten wants attention.");
}
}
if (event.getMessage().contentEquals("<col=ef1020>Your kitten is very hungry.</col>")) {
notifier.notify("Your kitten is very hungry.");
}
if (event.getMessage().contentEquals("<col=ef1020>Your kitten really wants attention.</col>")) {
notifier.notify("Your kitten really wants attention.");
}
}
}
@Subscribe
public void onNpcActionChanged(NpcActionChanged event) {
if (!config.catOwned()) {
for (NPC npc : client.getNpcs()) {
if (npc.getInteracting() != null) {
if (npc.getName().contentEquals("Cat") && !config.catOwned()) {
// If this if statement is included in previous it could null.
if (npc.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) {
config.catOwned(true);
notifier.notify("Your kitten has grown into a cat.");
}
}
}
}
}
}
@Subscribe
public void onNpcSpawned(NpcSpawned event) {
NPC cat = event.getNpc();
if (cat.getName() != null) {
if (cat.getName().equalsIgnoreCase("Kitten")) {
if (cat.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) {
config.catOwned(false);
}
}
else if (cat.getName().contentEquals("Cat")) {
if (cat.getInteracting().getName().equalsIgnoreCase(client.getLocalPlayer().getName())) {
config.catOwned(true);
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
package net.runelite.client.plugins.lizardmenshaman;
import net.runelite.client.config.Config;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("shaman")
public interface LizardmenShamanConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "showTimer",
name = "Show timer",
description = "Display timer till for lizardman shaman spawns."
)
default boolean showTimer()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "notifyOnSpawn",
name = "Notify on spawn",
description = "Notify user when lizardman summons spawns."
)
default boolean notifyOnSpawn()
{
return true;
}
}

View File

@@ -0,0 +1,91 @@
package net.runelite.client.plugins.lizardmenshaman;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.AnimationChanged;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import java.util.HashMap;
import java.util.Map;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Lizard Shamans</font>",
description = "Configures timer for lizardmen shaman spawns.",
enabledByDefault = false,
tags = {"shaman", "lizard", "lizardmen"}
)
@Slf4j
public class LizardmenShamanPlugin extends Plugin
{
private static final String SHAMAN = "Lizardman shaman";
private static final String MESSAGE = "A Lizardman shaman has summoned his spawn!";
@Getter(AccessLevel.PACKAGE)
private final Map<LocalPoint, LizardmenShamanSpawn> spawns = new HashMap<>();
@Inject
private OverlayManager overlayManager;
@Inject
private ShamanSpawnOverlay overlay;
@Inject
private LizardmenShamanConfig config;
@Inject
private Notifier notifier;
@Inject
private Client client;
@Provides
LizardmenShamanConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(LizardmenShamanConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
spawns.clear();
}
@Subscribe
public void onAnimationChanged(AnimationChanged event)
{
Actor actor = event.getActor();
if (actor == null || actor.getName() == null)
{
return;
}
else if (actor.getName().equals(SHAMAN) && actor.getAnimation() == 7157)
{
if (config.showTimer())
{
spawns.put(event.getActor().getLocalLocation(), new LizardmenShamanSpawn(8.4, null));
}
if (config.notifyOnSpawn())
{
notifier.notify(MESSAGE);
}
}
}
}

View File

@@ -0,0 +1,18 @@
package net.runelite.client.plugins.lizardmenshaman;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@RequiredArgsConstructor
@AllArgsConstructor
class LizardmenShamanSpawn
{
private final Instant start = Instant.now();
private double countdownTimer;
private Instant end;
}

View File

@@ -0,0 +1,90 @@
package net.runelite.client.plugins.lizardmenshaman;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
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.components.ProgressPieComponent;
class ShamanSpawnOverlay extends Overlay
{
private final Client client;
private final LizardmenShamanPlugin plugin;
@Inject
private ShamanSpawnOverlay(Client client, LizardmenShamanPlugin plugin)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
plugin.getSpawns().forEach((localPoint, spawn) ->
{
final Instant now = Instant.now();
final long startCountdown = Duration.between(spawn.getStart(), now).getSeconds();
final double certainSec = spawn.getCountdownTimer() - startCountdown;
if (certainSec <= 0)
{
if (spawn.getEnd() == null)
{
spawn.setEnd(Instant.now());
}
}
final ProgressPieComponent pieComponent = new ProgressPieComponent();
final Point loc = Perspective.localToCanvas(client, localPoint, client.getPlane());
if (loc == null || certainSec < 0)
{
return;
}
pieComponent.setPosition(loc);
pieComponent.setProgress(certainSec / spawn.getCountdownTimer());
if (certainSec > 4.8)
{
pieComponent.setFill(Color.GREEN);
pieComponent.setBorderColor(Color.GREEN);
pieComponent.render(graphics);
}
else if (certainSec > 3.6)
{
pieComponent.setFill(Color.YELLOW);
pieComponent.setBorderColor(Color.YELLOW);
pieComponent.render(graphics);
}
else if (certainSec > 2.4)
{
pieComponent.setFill(Color.ORANGE);
pieComponent.setBorderColor(Color.ORANGE);
pieComponent.render(graphics);
}
else if (certainSec > 1.2)
{
pieComponent.setFill(new Color(255, 140, 0));
pieComponent.setBorderColor(new Color(255, 140, 0));
pieComponent.render(graphics);
}
else
{
pieComponent.setFill(Color.RED);
pieComponent.setBorderColor(Color.RED);
pieComponent.render(graphics);
}
});
return null;
}
}

View File

@@ -1,3 +1,4 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.

View File

@@ -0,0 +1,24 @@
package net.runelite.client.plugins.menumodifier;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("menumodifier")
public interface MenuModifierConfig extends Config
{
@ConfigItem(position = 0, keyName = "hideCancel", name = "Hide Cancel", description = "Hides the 'cancel' option from the right click menu")
default boolean hideCancel() { return true; }
@ConfigItem(position = 1, keyName = "hideExamine", name = "Hide Examine", description = "Hides the 'examine' option from the right click menu")
default boolean hideExamine() { return true; }
@ConfigItem(position = 2, keyName = "hideTradeWith", name = "Hide Trade With", description = "Hides the 'trade with' option from the right click menu")
default boolean hideTradeWith() { return true; }
@ConfigItem(position = 3, keyName = "hideReport", name = "Hide Report", description = "Hides the 'report' option from the right click menu")
default boolean hideReport() { return true; }
@ConfigItem(position = 4, keyName = "hideLookup", name = "Hide Lookup", description = "Hides the 'lookup' option from the right click menu")
default boolean hideLookup() { return true; }
}

View File

@@ -0,0 +1,39 @@
package net.runelite.client.plugins.menumodifier;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.MouseAdapter;
import javax.inject.Inject;
import java.awt.event.KeyEvent;
public class MenuModifierInputListener extends MouseAdapter implements KeyListener
{
private static final int HOTKEY = KeyEvent.VK_CONTROL;
@Override
public void keyTyped(KeyEvent e)
{
}
@Inject
private MenuModifierPlugin plugin;
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == HOTKEY)
{
plugin.setHotKeyPressed(true);
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == HOTKEY)
{
plugin.setHotKeyPressed(false);
}
}
}

View File

@@ -0,0 +1,168 @@
package net.runelite.client.plugins.menumodifier;
import net.runelite.api.events.MenuOpened;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Client;
import net.runelite.api.MenuEntry;
import net.runelite.api.Player;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.MiscUtils;
import net.runelite.client.util.Text;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@PluginDescriptor(
name = "<font color=\"green\">!Menu Modifier</font>",
description = "Changes right click menu for players",
tags = { "menu", "modifier", "right", "click", "pk", "bogla" },
enabledByDefault = false
)
public class MenuModifierPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private MenuModifierConfig config;
@Inject
private MenuModifierInputListener inputListener;
@Inject
private KeyManager keyManager;
@Provides
MenuModifierConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(MenuModifierConfig.class);
}
@Override
protected void startUp() throws Exception
{
keyManager.registerKeyListener(inputListener);
}
@Override
protected void shutDown() throws Exception
{
keyManager.unregisterKeyListener(inputListener);
}
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private boolean hotKeyPressed;
@Subscribe
public void onMenuOpened(MenuOpened event)
{
Player localPlayer = client.getLocalPlayer();
if (localPlayer == null)
return;
if (!(MiscUtils.getWildernessLevelFrom(client, localPlayer.getWorldLocation()) >= 0))
return;
if (hotKeyPressed)
return;
List<MenuEntry> menu_entries = new ArrayList<MenuEntry>();
for (MenuEntry entry : event.getMenuEntries())
{
String option = Text.removeTags(entry.getOption()).toLowerCase();
if (option.contains("trade with") && config.hideTradeWith())
continue;
if (option.contains("lookup") && config.hideLookup())
continue;
if (option.contains("report") && config.hideReport())
continue;
if (option.contains("examine") && config.hideExamine())
continue;
int identifier = entry.getIdentifier();
Player[] players = client.getCachedPlayers();
Player player = null;
if (identifier >= 0 && identifier < players.length)
player = players[identifier];
if (player == null)
{
menu_entries.add(entry);
continue;
}
if ((option.contains("attack") || option.contains("cast")) && (player.isFriend() || player.isClanMember()))
continue;
menu_entries.add(entry);
}
MenuEntry[] updated_menu_entries = new MenuEntry[menu_entries.size()];
updated_menu_entries = menu_entries.toArray(updated_menu_entries);
client.setMenuEntries(updated_menu_entries);
}
/*@Subscribe
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
{
if (true)
return;
if (!inWilderness)
return;
if (hotKeyPressed)
return;
String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase();
if ((option.contains("trade with") && config.hideTradeWith())
|| (option.contains("lookup") && config.hideLookup())
|| (option.contains("report") && config.hideReport())
|| (option.contains("examine") && config.hideExamine())
|| (option.contains("cancel") && config.hideCancel()))
{
int identifier = menuEntryAdded.getIdentifier();
Player[] players = client.getCachedPlayers();
Player player = null;
if (identifier >= 0 && identifier < players.length)
player = players[identifier];
if (player == null)
return;
//allow trading with friends/clanmates
if (option.contains("trade with") && (player.isFriend() || player.isClanMember()))
return;
MenuEntry[] menuEntries = client.getMenuEntries();
if (menuEntries.length > 0)
client.setMenuEntries(Arrays.copyOf(menuEntries, menuEntries.length - 1));
}
}*/
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
* 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.musicmodifier;
import javax.sound.midi.*;
import java.io.IOException;
public class MidiFileAdjuster {
private int bankLSBValue;
private int chPosition = -1;
private boolean customBank = false;
public Sequence reorderTracks(Sequence sequence) throws InvalidMidiDataException, IOException {
for (Track track : sequence.getTracks()) {
for (int i = 0; i < track.size(); i++) {
MidiEvent midiEvent = track.get(i);
MidiMessage midiMessage = midiEvent.getMessage();
if (midiMessage instanceof ShortMessage) {
ShortMessage sm = (ShortMessage) midiMessage;
if (sm.getChannel() < 16) {
getBankLSB(sm);
if (i == 0 & bankLSBValue != 1) {
chPosition++;
if (chPosition == 9) {
chPosition = 10;
}
}
if (!customBank) {
if (sm.getChannel() == 9) {
bankLSBValue = 1;
}
if (sm.getChannel() != 9) {
bankLSBValue = 0;
}
}
}
if (bankLSBValue == 1) {
int drumChannel = 9;
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.NOTE_OFF) {
sm.setMessage(ShortMessage.NOTE_OFF, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.NOTE_ON) {
sm.setMessage(ShortMessage.NOTE_ON, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.PITCH_BEND) {
sm.setMessage(ShortMessage.PITCH_BEND, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) {
sm.setMessage(ShortMessage.CHANNEL_PRESSURE, drumChannel, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.POLY_PRESSURE) {
sm.setMessage(ShortMessage.POLY_PRESSURE, drumChannel, sm.getData1(), sm.getData2());
}
} else {
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.NOTE_OFF) {
sm.setMessage(ShortMessage.NOTE_OFF, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.NOTE_ON) {
sm.setMessage(ShortMessage.NOTE_ON, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.PITCH_BEND) {
sm.setMessage(ShortMessage.PITCH_BEND, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) {
sm.setMessage(ShortMessage.CHANNEL_PRESSURE, chPosition, sm.getData1(), sm.getData2());
}
if (sm.getCommand() == ShortMessage.POLY_PRESSURE) {
sm.setMessage(ShortMessage.POLY_PRESSURE, chPosition, sm.getData1(), sm.getData2());
}
}
}
}
}
return sequence;
}
private void getBankLSB(ShortMessage sm) throws InvalidMidiDataException
{
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE)
{
if (sm.getData1() == 32)
{
bankLSBValue = sm.getData2();
customBank = true;
}
if (sm.getData1() == 0)
{
sm.setMessage(sm.getCommand(), sm.getChannel(), sm.getData1(), bankLSBValue);
}
}
}
}

View File

@@ -0,0 +1,355 @@
/*
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
* 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.musicmodifier;
import net.runelite.api.*;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.*;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.game.chatbox.ChatboxTextInput;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import javax.inject.Inject;
import java.io.File;
@PluginDescriptor(
name = "Music Track Customizer",
description = "Customize what track plays and how it sounds, with local files",
tags = {"music", "sound"},
enabledByDefault = false
)
public class MusicCustomizerPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private ChatboxPanelManager chatboxPanelManager;
@Inject
private ClientThread clientThread;
private RealTimeMIDIPlayer realTimeMIDIPlayer = new RealTimeMIDIPlayer();
private String songName = "Scape Main";
private ChatboxTextInput songInput;
private Widget playlistModeButton;
private Widget playlistBox;
private Widget hidePlaylistButton;
private Widget addPlaylistSongButton;
private Widget playlistText;
private Widget playlistSong;
private String defaultUnlockedSongs;
private boolean isLooping = true;
private boolean playlistMode = false;
private int newSongY = 34;
private int playlistCount = 0;
@Override
public void startUp()
{
playSong(songName);
}
@Override
public void shutDown()
{
if (realTimeMIDIPlayer != null)
{
realTimeMIDIPlayer.stopSong();
}
}
@Subscribe
public void onGameTick(GameTick event)
{
try
{
if (!playlistMode)
{
String newSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getText();
if (!newSong.equals(songName))
{
songName = newSong;
playSongFromList(songName);
}
}
} catch (NullPointerException ignored)
{
}
}
private void playSong(String song)
{
File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
"Music/" + song + ".mid/");
if (realTimeMIDIPlayer.midi == null)
{
realTimeMIDIPlayer.midi = midiMusicFile;
realTimeMIDIPlayer.run();
}
else
{
if (realTimeMIDIPlayer.isPlaying())
{
realTimeMIDIPlayer.stopSong();
}
realTimeMIDIPlayer.midi = midiMusicFile;
realTimeMIDIPlayer.run();
}
}
@Subscribe
private void onWidgetLoaded(WidgetLoaded widgetLoaded)
{
if (widgetLoaded.getGroupId() == WidgetID.MUSICTAB_GROUP_ID)
{
Widget musicPlayerSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
if (musicPlayerSongs != null)
{
playlistModeButton = musicPlayerSongs.createChild(-1, WidgetType.GRAPHIC);
playlistModeButton.setSpriteId(SpriteID.RS2_TAB_MUSIC);
playlistModeButton.setOriginalWidth(32);
playlistModeButton.setOriginalHeight(32);
playlistModeButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
playlistModeButton.setOriginalX(0);
playlistModeButton.setOriginalY(0);
playlistModeButton.setHasListener(true);
playlistModeButton.setAction(1, "Open");
playlistModeButton.setOnOpListener((JavaScriptCallback) e -> openPlaylist());
playlistModeButton.setName("Playlist");
playlistModeButton.setHidden(true); //Playlist is not enabled for this release (Unfinished).
playlistModeButton.revalidate();
}
}
}
private void openPlaylist()
{
playlistMode = true;
Widget currentPlayingSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME);
Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR);
allInGameSongs.setHidden(true);
musicScrollbar.setHidden(true);
defaultUnlockedSongs = client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).getText();
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10");
playlistBox = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE);
playlistText = playlistBox.createChild(-1, WidgetType.TEXT);
playlistText.setText("Music Playlist");
playlistText.setFontId(497);
playlistText.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
playlistText.setOriginalX(40);
playlistText.setOriginalY(14);
playlistText.setOriginalHeight(1);
playlistText.setOriginalWidth(1);
playlistText.setTextColor(currentPlayingSong.getTextColor());
playlistText.revalidate();
hidePlaylistButton = playlistBox.createChild(-1, WidgetType.GRAPHIC);
hidePlaylistButton.setSpriteId(SpriteID.RS2_TAB_MUSIC);
hidePlaylistButton.setOriginalWidth(32);
hidePlaylistButton.setOriginalHeight(32);
hidePlaylistButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
hidePlaylistButton.setOriginalX(0);
hidePlaylistButton.setOriginalY(6);
hidePlaylistButton.setHasListener(true);
hidePlaylistButton.setAction(1, "Close");
hidePlaylistButton.setOnOpListener((JavaScriptCallback) e -> closePlaylist());
hidePlaylistButton.setName("Playlist");
hidePlaylistButton.revalidate();
addPlaylistSongButton = playlistBox.createChild(-1, WidgetType.GRAPHIC);
addPlaylistSongButton.setSpriteId(SpriteID.BANK_ADD_TAB_ICON);
addPlaylistSongButton.setOriginalWidth(36);
addPlaylistSongButton.setOriginalHeight(32);
addPlaylistSongButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_LEFT);
addPlaylistSongButton.setOriginalX(0);
addPlaylistSongButton.setOriginalY(6);
addPlaylistSongButton.setHasListener(true);
addPlaylistSongButton.setAction(1, "Add to");
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput());
addPlaylistSongButton.setName("Playlist");
addPlaylistSongButton.revalidate();
if (playlistSong != null)
{
playlistSong.setHidden(false);
}
}
private void closePlaylist()
{
playlistMode = false;
Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR);
allInGameSongs.setHidden(false);
musicScrollbar.setHidden(false);
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(defaultUnlockedSongs);
playlistText.setHidden(true);
addPlaylistSongButton.setHidden(true);
hidePlaylistButton.setHidden(true);
if (playlistSong != null)
{
playlistSong.setHidden(true);
}
}
private void addSongFromInput()
{
addPlaylistSongButton.setAction(1, "Close search");
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> closeInput());
songInput = chatboxPanelManager.openTextInput("Please type a valid song name")
.onChanged(s -> clientThread.invokeLater(() -> updateSongs(s)))
.onClose(() ->
{
clientThread.invokeLater(() -> updateSongs(songInput.getValue()));
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput());
addPlaylistSongButton.setAction(1, "Add to");
})
.build();
}
private void updateSongs()
{
String song = "";
if (chatboxIsOpen())
{
song = songInput.getValue();
}
updateSongs(song);
}
private void updateSongs(String song)
{
if (playlistBox == null)
{
return;
}
if (new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
"Music/" + song + ".mid/").exists())
{
playListSongPlayer(song);
}
}
private void playListSongPlayer(String song)
{
if (!song.equals(songName) && !chatboxIsOpen() && playlistCount < 10)
{
Widget playlistWidget = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE);
playlistSong = playlistWidget.createChild(-1, WidgetType.TEXT);
playlistSong.setText(song);
playlistSong.setFontId(495);
playlistSong.setOriginalX(12);
playlistSong.setOriginalY(newSongY);
playlistSong.setOriginalWidth(120);
playlistSong.setOriginalHeight(16);
playlistSong.setTextColor(client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getTextColor());
playlistSong.setHasListener(true);
playlistSong.setAction(1, "Play");
playlistSong.setOnOpListener((JavaScriptCallback) e -> playSongFromList(song));
playlistSong.setName(song);
playlistSong.revalidate();
newSongY = newSongY + 15;
songName = song;
playlistCount++;
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10");
if (playlistCount == 10)
{
addPlaylistSongButton.setHidden(true);
}
}
}
private boolean chatboxIsOpen()
{
return songInput != null && chatboxPanelManager.getCurrentInput() == songInput;
}
private void closeInput()
{
updateSongs();
chatboxPanelManager.close();
}
private void playSongFromList(String song)
{
client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).setName(song);
File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
"Music/" + song + ".mid/");
if (realTimeMIDIPlayer.midi == null)
{
realTimeMIDIPlayer.midi = midiMusicFile;
realTimeMIDIPlayer.run();
}
else
{
if (realTimeMIDIPlayer.isPlaying())
{
realTimeMIDIPlayer.stopSong();
}
realTimeMIDIPlayer.midi = midiMusicFile;
realTimeMIDIPlayer.run();
}
}
}

View File

@@ -0,0 +1,229 @@
/*
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
* 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.musicmodifier;
import com.sun.media.sound.AudioSynthesizer;
import javax.sound.midi.*;
import javax.sound.sampled.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class RealTimeMIDIPlayer implements Runnable
{
private AudioFormat format;
private Sequence midiSequence;
private Soundbank soundbank;
private SourceDataLine sdl;
private MusicCustomizerPlugin customMusicPlugin;
private MidiFileAdjuster adjuster;
private Clip clip;
public boolean looping = true;
public File soundFont = new File(System.getProperty("user.home") + "/RuneLiteAudio/SoundFonts/" +
"RuneScape 2.sf2/");
public File midi;
@Override
public void run() {
try {
adjuster = new MidiFileAdjuster(); //Unfinished class
midiSequence = MidiSystem.getSequence(midi);
soundbank = MidiSystem.getSoundbank(soundFont);
init();
}
catch (IOException | InvalidMidiDataException e)
{
e.printStackTrace();
}
}
public void stopSong()
{
if (sdl.isRunning())
{
sdl.stop();
}
}
public static AudioSynthesizer findAudioSynthesizer() throws MidiUnavailableException
{
Synthesizer synth = MidiSystem.getSynthesizer();
if (synth instanceof AudioSynthesizer)
return (AudioSynthesizer) synth;
double gain = 0.8D;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
MidiChannel[] channels = synth.getChannels();
for (int i = 0; i < channels.length; i++)
{
channels[i].controlChange(7, ((int) (channels[i].getController(7) * gain)));
}
for (int i = 0; i < infos.length; i++)
{
MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
if (device instanceof AudioSynthesizer)
return (AudioSynthesizer) device;
}
return null;
}
public boolean isPlaying()
{
return sdl.isActive();
}
public static double send(Sequence sequence, Receiver receiver) {
float divtype = sequence.getDivisionType();
assert (sequence.getDivisionType() == Sequence.PPQ);
Track[] tracks = sequence.getTracks();
int[] trackspos = new int[tracks.length];
int mpq = 500000;
int seqres = sequence.getResolution();
long lasttick = 0;
long curtime = 0;
while (true) {
MidiEvent selevent = null;
int seltrack = -1;
for (int i = 0; i < tracks.length; i++) {
int trackpos = trackspos[i];
Track track = tracks[i];
if (trackpos < track.size()) {
MidiEvent event = track.get(trackpos);
if (selevent == null
|| event.getTick() < selevent.getTick()) {
selevent = event;
seltrack = i;
}
}
}
if (seltrack == -1)
break;
trackspos[seltrack]++;
long tick = selevent.getTick();
if (divtype == Sequence.PPQ)
curtime += ((tick - lasttick) * mpq) / seqres;
else
curtime = (long) ((tick * 1000000.0 * divtype) / seqres);
lasttick = tick;
MidiMessage msg = selevent.getMessage();
if (msg instanceof MetaMessage) {
if (divtype == Sequence.PPQ)
if (((MetaMessage) msg).getType() == 0x51) {
byte[] data = ((MetaMessage) msg).getData();
mpq = ((data[0] & 0xff) << 16)
| ((data[1] & 0xff) << 8) | (data[2] & 0xff);
}
} else {
if (receiver != null)
receiver.send(msg, curtime);
}
}
return curtime / 1000000.0;
}
public void init() {
new Thread(new Runnable() {
@Override
public void run() {
AudioSynthesizer synth = null;
try {
synth = findAudioSynthesizer();
format = new AudioFormat(44100, 16, 2, true, false);
Map<String, Object> info = new HashMap<String, Object>();
info.put("resamplerType", "sinc");
info.put("maxPolyphony", "8192");
AudioInputStream ais = synth.openStream(format, info);
synth.unloadAllInstruments(synth.getDefaultSoundbank());
synth.loadAllInstruments(soundbank);
double total = send(midiSequence, synth.getReceiver());
long length = (long) (ais.getFormat().getFrameRate() * (total + 4));
AudioInputStream stream = new AudioInputStream(ais, format, length);
sdl = AudioSystem.getSourceDataLine(format);
sdl.open(format);
sdl.start();
writeAudio(sdl, stream);
} catch (LineUnavailableException | MidiUnavailableException e) {
e.printStackTrace();
}
}
}).start();
}
public void writeAudio(SourceDataLine sdl, AudioInputStream stream)
{
new Thread(new Runnable() {
@Override
public void run() {
byte[] sampledAudio = new byte[1024];
int numBytesRead = 0;
while (numBytesRead != -1) {
try
{
numBytesRead = stream.read(sampledAudio, 0, sampledAudio.length);
if (numBytesRead >= 0) {
sdl.write(sampledAudio, 0, numBytesRead);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
if (!isPlaying() && looping)
{
this.run();
}
}
}
}
}).start();
}
}

View File

@@ -0,0 +1,11 @@
package net.runelite.client.plugins.nexthitnotifier;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
@ConfigGroup("nexthitnotifier")
public interface NextHitNotifierConfig extends Config
{
}

View File

@@ -0,0 +1,59 @@
package net.runelite.client.plugins.nexthitnotifier;
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.TitleComponent;
import net.runelite.client.util.MiscUtils;
import javax.inject.Inject;
import java.awt.*;
public class NextHitNotifierOverlay extends Overlay
{
private final Client client;
private final NextHitNotifierPlugin plugin;
private final NextHitNotifierConfig config;
private final PanelComponent panelComponent = new PanelComponent();
private final Dimension panelSize = new Dimension(48, 0);
@Inject
private NextHitNotifierOverlay(Client client, NextHitNotifierPlugin plugin, NextHitNotifierConfig config)
{
setPosition(OverlayPosition.BOTTOM_LEFT);
//setPosition(OverlayPosition.DYNAMIC);
//setPosition(OverlayPosition.DETACHED);
this.client = client;
this.plugin = plugin;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
panelComponent.getChildren().clear();
panelComponent.setPreferredSize(panelSize);
String lastHitText = Integer.toString(plugin.lastHit);
int lastHit = plugin.lastHit;
if (plugin.showTime < 0)
{
lastHitText = "0";
lastHit = 0;
}
int g = (int)MiscUtils.clamp((float)Math.floor(lastHit / 30.f) * 255.f, 0.f, 255.f);
int r = 255 - g;
Color textColor = Color.getHSBColor(Color.RGBtoHSB(r, g, 0, null)[0], 1.f, 1.f);
panelComponent.getChildren().add(TitleComponent.builder().text("Next hit:").color(Color.YELLOW).build());
panelComponent.getChildren().add(TitleComponent.builder().text(lastHitText).color(textColor).build());
return panelComponent.render(graphics);
}
}

View File

@@ -0,0 +1,116 @@
package net.runelite.client.plugins.nexthitnotifier;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.Skill;
import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
@PluginDescriptor(
name = "<font color=\"green\">!Next Hit Notifier</font>",
description = "Shows estimated next hit based on xp drop.",
tags = { "experience", "damage", "overlay", "pking", "bogla" },
enabledByDefault = false
)
public class NextHitNotifierPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private NextHitNotifierOverlay overlay;
private int lastHpXp = 0;
int lastHit = 0;
int showTime = 0;
@Provides
NextHitNotifierConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(NextHitNotifierConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() == GameState.LOGGED_IN)
{
lastHpXp = client.getSkillExperience(Skill.HITPOINTS);
lastHit = 0;
showTime = 0;
}
else
{
lastHpXp = 0;
lastHit = 0;
showTime = 0;
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (showTime > 0)
showTime--;
else
lastHit = 0;
}
@Subscribe
public void onExperienceChanged(ExperienceChanged event)
{
if (client.getGameState() != GameState.LOGGED_IN)
{
lastHpXp = 0;
lastHit = 0;
showTime = 0;
return;
}
final Skill skill = event.getSkill();
if (skill != Skill.HITPOINTS)
return;
final int currentXp = client.getSkillExperience(skill);
int gainedXp = currentXp - lastHpXp;
//filter out big xp drops (such as login)
if (gainedXp > 1000)
{
lastHpXp = client.getSkillExperience(skill);
return;
}
lastHit = (int)Math.rint(gainedXp / 1.33f);
lastHpXp = currentXp;
showTime = 3;
}
}

View File

@@ -0,0 +1,55 @@
package net.runelite.client.plugins.pkvision;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("pkvision")
public interface PKVisionConfig extends Config
{
@ConfigItem(position = 0, keyName = "drawOwnName", name = "Highlight own player", description = "Configures whether or not your own player should be highlighted")
default boolean highlightOwnPlayer()
{
return false;
}
@ConfigItem(position = 1, keyName = "ownNameColor", name = "Own player color", description = "Color of your own player")
default Color getOwnPlayerColor()
{
return new Color(0, 184, 212);
}
@ConfigItem(position = 2, keyName = "drawFriendNames", name = "Highlight friends", description = "Configures whether or not friends should be highlighted")
default boolean highlightFriends()
{
return true;
}
@ConfigItem(position = 3, keyName = "friendNameColor", name = "Friend color", description = "Color of friend names" )
default Color getFriendColor()
{
return new Color(0, 200, 80);
}
@ConfigItem(position = 4, keyName = "drawPlayerTiles", name = "Draw tiles under players", description = "Configures whether or not tiles under highlighted players should be drawn")
default boolean drawTiles()
{
return false;
}
@ConfigItem(position = 5, keyName = "drawPlayerNames", name = "Draw names above players", description = "Configures whether or not player names should be drawn above players")
default boolean drawPlayerNames() { return true; }
@ConfigItem(position = 6, keyName = "drawPlayerLevels", name = "Draw levels above players", description = "Configures whether or not player levels should be drawn above players")
default boolean drawPlayerLevels()
{
return true;
}
//@ConfigItem(position = 7, keyName = "drawPlayerHealth", name = "Draw health above players", description = "Configures whether or not player levels should be drawn above players")
//default boolean drawPlayerHealth()
//{
// return true;
//}
}

View File

@@ -0,0 +1,43 @@
package net.runelite.client.plugins.pkvision;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Player;
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 PKVisionMinimapOverlay extends Overlay
{
private final PKVisionService pkVisionService;
@Inject
private PKVisionMinimapOverlay(PKVisionService pkVisionService)
{
this.pkVisionService = pkVisionService;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
pkVisionService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
final net.runelite.api.Point minimapLocation = actor.getMinimapLocation();
if (minimapLocation != null)
OverlayUtil.renderTextLocation(graphics, minimapLocation, Integer.toString(actor.getCombatLevel()), color);
}
}

View File

@@ -0,0 +1,55 @@
package net.runelite.client.plugins.pkvision;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class PKVisionOverlay extends Overlay
{
private final PKVisionService pkVisionService;
private final PKVisionConfig config;
@Inject
private PKVisionOverlay(PKVisionConfig config, PKVisionService pkVisionService, PKVisionPlugin pkVisionPlugin)
{
this.config = config;
this.pkVisionService = pkVisionService;
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
pkVisionService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
if (!config.drawPlayerNames() && !config.drawPlayerLevels())
return;
String text = "";
if (config.drawPlayerLevels())
text += "(" + actor.getCombatLevel() + ") ";
if (config.drawPlayerNames())
text += actor.getName().replace('\u00A0', ' ');
Point textLocation = actor.getCanvasTextLocation(graphics, text, actor.getLogicalHeight() + 40);
if (textLocation != null)
OverlayUtil.renderTextLocation(graphics, textLocation, text, color);
}
}

View File

@@ -0,0 +1,135 @@
package net.runelite.client.plugins.pkvision;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import java.awt.Color;
import javax.inject.Inject;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.*;
import net.runelite.api.MenuEntry;
import net.runelite.api.Player;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ColorUtil;
import net.runelite.client.util.MiscUtils;
import net.runelite.client.util.Text;
@PluginDescriptor(
name = "<font color=\"aqua\">!PK Vision</font>",
description = "Highlight players on-screen and/or on the minimap",
tags = {"highlight", "minimap", "overlay", "players", "pk", "helper", "vision", "bogla"},
enabledByDefault = false
)
public class PKVisionPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private PKVisionConfig config;
@Inject
private PKVisionOverlay pkVisionOverlay;
@Inject
private PKVisionTileOverlay pkVisionTileOverlay;
@Inject
private PKVisionMinimapOverlay pkVisionMinimapOverlay;
@Inject
private Client client;
@Provides
PKVisionConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(PKVisionConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(pkVisionOverlay);
overlayManager.add(pkVisionTileOverlay);
overlayManager.add(pkVisionMinimapOverlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(pkVisionOverlay);
overlayManager.remove(pkVisionTileOverlay);
overlayManager.remove(pkVisionMinimapOverlay);
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
{
int type = menuEntryAdded.getType();
String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase();
if (type >= 2000)
type -= 2000;
int identifier = menuEntryAdded.getIdentifier();
if (type == FOLLOW.getId() || type == TRADE.getId()
|| type == ITEM_USE_ON_PLAYER.getId() || type == PLAYER_FIRST_OPTION.getId()
|| type == PLAYER_SECOND_OPTION.getId() || type == PLAYER_THIRD_OPTION.getId()
|| type == PLAYER_FOURTH_OPTION.getId() || type == PLAYER_FIFTH_OPTION.getId()
|| type == PLAYER_SIXTH_OPTION.getId() || type == PLAYER_SEVENTH_OPTION.getId()
|| type == PLAYER_EIGTH_OPTION.getId() || type == SPELL_CAST_ON_PLAYER.getId()
|| type == RUNELITE.getId())
{
final Player localPlayer = client.getLocalPlayer();
Player[] players = client.getCachedPlayers();
Player player = null;
if (identifier >= 0 && identifier < players.length)
player = players[identifier];
if (player == null)
return;
Color color = null;
if (config.highlightFriends() && (player.isFriend() || player.isClanMember()))
{
color = config.getFriendColor();
}
else if (!player.isFriend() && !player.isClanMember())
{
int lvlDelta = player.getCombatLevel() - localPlayer.getCombatLevel();
int wildyLvl = MiscUtils.getWildernessLevelFrom(client, player.getWorldLocation());
if (wildyLvl <= 0)
return;
int R = MiscUtils.clamp((int)(((float)(lvlDelta + wildyLvl) / (float)(wildyLvl * 2)) * 255.f), 0, 255);
int G = MiscUtils.clamp(255 - R, 0, 255);
if (Math.abs(lvlDelta) <= wildyLvl)
color = Color.getHSBColor(Color.RGBtoHSB(R, G, 0, null)[0], 1.f, 1.f);
}
if (color != null)
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
// strip out existing <col...
String target = lastEntry.getTarget();
int idx = target.indexOf('>');
if (idx != -1)
target = target.substring(idx + 1);
lastEntry.setTarget(ColorUtil.prependColorTag(target, color));
client.setMenuEntries(menuEntries);
}
}
}
}

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.pkvision;
import java.awt.Color;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.client.util.MiscUtils;
@Singleton
public class PKVisionService
{
private final Client client;
private final PKVisionConfig config;
@Inject
private PKVisionService(Client client, PKVisionConfig config)
{
this.config = config;
this.client = client;
}
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
{
final Player localPlayer = client.getLocalPlayer();
for (Player player : client.getPlayers())
{
if (player == null || player.getName() == null)
continue;
if (player == localPlayer)
{
if (config.highlightOwnPlayer())
consumer.accept(player, config.getOwnPlayerColor());
continue;
}
if (config.highlightFriends() && (player.isFriend() || player.isClanMember()))
{
consumer.accept(player, config.getFriendColor());
}
else if (player != localPlayer && !player.isFriend() && !player.isClanMember())
{
int lvlDelta = player.getCombatLevel() - localPlayer.getCombatLevel();
int wildyLvl = MiscUtils.getWildernessLevelFrom(client, player.getWorldLocation());
if (wildyLvl <= 0)
continue;
if (Math.abs(lvlDelta) > wildyLvl)
continue;
int R = MiscUtils.clamp((int)(((float)(lvlDelta + wildyLvl) / (float)(wildyLvl * 2)) * 255.f), 0, 255);
int G = MiscUtils.clamp(255 - R, 0, 255);
consumer.accept(player, Color.getHSBColor(Color.RGBtoHSB(R, G, 0, null)[0], 1.f, 1.f));
}
}
}
}

View File

@@ -0,0 +1,44 @@
package net.runelite.client.plugins.pkvision;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.inject.Inject;
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 PKVisionTileOverlay extends Overlay
{
private final PKVisionService pkVisionService;
private final PKVisionConfig config;
@Inject
private PKVisionTileOverlay(PKVisionConfig config, PKVisionService pkVisionService)
{
this.config = config;
this.pkVisionService = pkVisionService;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.drawTiles())
return null;
pkVisionService.forEachPlayer((player, color) ->
{
final Polygon poly = player.getCanvasTilePoly();
if (poly != null)
OverlayUtil.renderPolygon(graphics, poly, color);
});
return null;
}
}

View File

@@ -0,0 +1,88 @@
package net.runelite.client.plugins.plankmakehelper;
import net.runelite.api.*;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.*;
public class PlankMakeOverlay extends Overlay {
private final PlankMakePlugin plugin;
private final Client client;
@Inject
public PlankMakeOverlay(final PlankMakePlugin plugin, final Client client) {
super(plugin);
this.plugin = plugin;
this.client = client;
setPosition(OverlayPosition.DETACHED);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (hasPlankableItems()) {
renderInventory(graphics);
renderPlankMakeSpell(graphics);
}
return null;
}
private void renderInventory(Graphics2D graphics) {
Widget inventory = client.getWidget(WidgetInfo.INVENTORY);
int firstItemSeenIndex = -1;
if (inventory != null) {
for (WidgetItem item : inventory.getWidgetItems()) {
if (PlankMakePlugin.isLogAndPlankable(item.getId())) {
if (firstItemSeenIndex == -1) {
firstItemSeenIndex = item.getIndex();
}
if (!inventory.isHidden()) {
if (item.getIndex() != firstItemSeenIndex) {
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(item.getCanvasBounds()), Color.BLUE);
}
}
}
}
if (firstItemSeenIndex != -1) {
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(inventory.getWidgetItem(firstItemSeenIndex).getCanvasBounds()), Color.CYAN);
}
}
}
private void renderPlankMakeSpell(Graphics2D graphics) {
Widget plankMakeSpell = client.getWidget(218,128);
if (plankMakeSpell != null && (plankMakeSpell.getCanvasLocation().getX() != 29 & plankMakeSpell.getCanvasLocation().getY() != 32)) {
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(plankMakeSpell.getBounds()), Color.CYAN);
}
}
private boolean hasPlankableItems() {
ItemContainer invo = client.getItemContainer(InventoryID.INVENTORY);
if (invo != null) {
if (invo.getItems().length > 0) {
for (Item item : invo.getItems()) {
if (PlankMakePlugin.isLogAndPlankable(item.getId())) {
return true;
}
}
}
}
return false;
}
static Polygon RectangleToPolygon(Rectangle rect) {
int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x};
int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height};
return new Polygon(xpoints, ypoints, 4);
}
}

View File

@@ -0,0 +1,49 @@
package net.runelite.client.plugins.plankmakehelper;
import net.runelite.api.Client;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
@PluginDescriptor(
name = "Plank Make Helper",
description = "Highlights planks and plank make spell",
tags = {"overlay", "plankmaking", "lunar", "money", "moneymaking", "gp"}
)
public class PlankMakePlugin extends Plugin {
@Inject
private OverlayManager overlayManager;
@Inject
private Client client;
@Inject
private PlankMakeOverlay overlay;
@Override
protected void startUp() {
overlayManager.add(overlay);
}
@Override
protected void shutDown() {
overlayManager.remove(overlay);
}
static boolean isLogAndPlankable(int itemID) {
switch (itemID) {
case 6332: //mahogany
case 1521: //oak
case 6333: //teak
case 1511: //plain
return true;
default:
return false;
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import net.runelite.api.Player;
/**
* Contains a player object
* When they attacked me
* And (in milliseconds) when to expire the overlay around them
*/
public class PlayerContainer {
private Player player;
private long whenTheyAttackedMe;
private int millisToExpireHighlight;
public PlayerContainer(Player player, long whenTheyAttackedMe, int millisToExpireHighlight) {
this.player = player;
this.whenTheyAttackedMe = whenTheyAttackedMe;
this.millisToExpireHighlight = millisToExpireHighlight;
}
//getters
public Player getPlayer() {
return player;
}
public long getWhenTheyAttackedMe() {
return whenTheyAttackedMe;
}
public int getMillisToExpireHighlight() { return millisToExpireHighlight; };
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import java.awt.*;
@ConfigGroup("prayagainstplayer")
public interface PrayAgainstPlayerConfig extends Config {
@ConfigItem(
position = 0,
keyName = "attackerPlayerColor",
name = "Attacker color",
description = "This is the color that will be used to highlight attackers."
)
default Color attackerPlayerColor() { return new Color(0xFF0006); }
@ConfigItem(
position = 1,
keyName = "potentialPlayerColor",
name = "Potential Attacker color",
description = "This is the color that will be used to highlight potential attackers."
)
default Color potentialPlayerColor() { return new Color(0xFFFF00); }
////
@ConfigItem(
position = 2,
keyName = "attackerTargetTimeout",
name = "Attacker Timeout",
description = "Seconds until attacker is no longer highlighted."
)
default int attackerTargetTimeout() { return 10; }
@ConfigItem(
position = 3,
keyName = "potentialTargetTimeout",
name = "Potential Attacker Timeout",
description = "Seconds until potential attacker is no longer highlighted."
)
default int potentialTargetTimeout() { return 10; }
@ConfigItem(
position = 4,
keyName = "newSpawnTimeout",
name = "New Player Timeout",
description = "Seconds until logged in/spawned player is no longer highlighted."
)
default int newSpawnTimeout() { return 5; }
////
////
@ConfigItem(
position = 5,
keyName = "ignoreFriends",
name = "Ignore Friends",
description = "This lets you decide whether you want friends to be highlighted by this plugin."
)
default boolean ignoreFriends() { return true; }
@ConfigItem(
position = 6,
keyName = "ignoreClanMates",
name = "Ignore Clan Mates",
description = "This lets you decide whether you want clan mates to be highlighted by this plugin."
)
default boolean ignoreClanMates() { return true; }
////
@ConfigItem(
position = 7,
keyName = "markNewPlayer",
name = "Mark new player as potential attacker",
description = "Marks someone that logged in or teleported as a potential attacker for your safety\nDO NOT RUN THIS IN WORLD 1-2 GRAND EXCHANGE!"
)
default boolean markNewPlayer() { return false; }
@ConfigItem(
position = 8,
keyName = "drawTargetPrayAgainst",
name = "Draw what to pray on attacker",
description = "Tells you what to pray from what weapon the attacker is holding"
)
default boolean drawTargetPrayAgainst() { return true; }
@ConfigItem(
position = 9,
keyName = "drawPotentialTargetPrayAgainst",
name = "Draw what to pray on potential attacker",
description = "Tells you what to pray from what weapon the potential attacker is holding"
)
default boolean drawPotentialTargetPrayAgainst() { return true; }
@ConfigItem(
position = 10,
keyName = "drawTargetPrayAgainstPrayerTab",
name = "Draw what to pray from prayer tab",
description = "Tells you what to pray from what weapon the attacker is holding from the prayer tab"
)
default boolean drawTargetPrayAgainstPrayerTab() { return false; }
@ConfigItem(
position = 11,
keyName = "drawTargetsName",
name = "Draw name on attacker",
description = "Configures whether or not the attacker\'s name should be shown"
)
default boolean drawTargetsName() { return true; }
@ConfigItem(
position = 12,
keyName = "drawPotentialTargetsName",
name = "Draw name on potential attacker",
description = "Configures whether or not the potential attacker\'s name should be shown"
)
default boolean drawPotentialTargetsName() { return true; }
@ConfigItem(
position = 13,
keyName = "drawTargetHighlight",
name = "Draw highlight around attacker",
description = "Configures whether or not the attacker should be highlighted"
)
default boolean drawTargetHighlight() { return true; }
@ConfigItem(
position = 14,
keyName = "drawPotentialTargetHighlight",
name = "Draw highlight around potential attacker",
description = "Configures whether or not the potential attacker should be highlighted"
)
default boolean drawPotentialTargetHighlight() { return true; }
@ConfigItem(
position = 15,
keyName = "drawTargetTile",
name = "Draw tile under attacker",
description = "Configures whether or not the attacker\'s tile be highlighted"
)
default boolean drawTargetTile() { return false; }
@ConfigItem(
position = 16,
keyName = "drawPotentialTargetTile",
name = "Draw tile under potential attacker",
description = "Configures whether or not the potential attacker\'s tile be highlighted"
)
default boolean drawPotentialTargetTile() { return false; }
@ConfigItem(
position = 17,
keyName = "drawUnknownWeapons",
name = "Draw unknown weapons",
description = "Configures whether or not the unknown weapons should be shown when a player equips one"
)
default boolean drawUnknownWeapons() { return false; }
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import net.runelite.api.Client;
import net.runelite.api.ItemComposition;
import net.runelite.api.Player;
import net.runelite.api.kit.KitType;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.util.Text;
import net.runelite.api.Point;
import javax.inject.Inject;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ConcurrentModificationException;
class PrayAgainstPlayerOverlay extends Overlay {
private final PrayAgainstPlayerPlugin plugin;
private final PrayAgainstPlayerConfig config;
private final Client client;
@Inject
private PrayAgainstPlayerOverlay(PrayAgainstPlayerPlugin plugin, PrayAgainstPlayerConfig config, Client client) {
super(plugin);
this.plugin = plugin;
this.config = config;
this.client = client;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics) {
renderPotentialPlayers(graphics);
renderAttackingPlayers(graphics);
return null;
}
private void renderPotentialPlayers(Graphics2D graphics) {
if (plugin.getPotentialPlayersAttackingMe() == null || !plugin.getPotentialPlayersAttackingMe().isEmpty()) {
try {
for (PlayerContainer container : plugin.getPotentialPlayersAttackingMe()) {
if ((System.currentTimeMillis() > (container.getWhenTheyAttackedMe() + container.getMillisToExpireHighlight())) && (container.getPlayer().getInteracting() != client.getLocalPlayer())) {
plugin.removePlayerFromPotentialContainer(container);
}
if (config.drawPotentialTargetsName()) renderNameAboveHead(graphics, container.getPlayer(), config.potentialPlayerColor());
if (config.drawPotentialTargetHighlight()) renderHighlightedPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
if (config.drawPotentialTargetTile()) renderTileUnderPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
if (config.drawPotentialTargetPrayAgainst()) renderPrayAgainstOnPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
}
} catch (ConcurrentModificationException e) {
}
}
}
private void renderAttackingPlayers(Graphics2D graphics) {
if (plugin.getPlayersAttackingMe() == null || !plugin.getPlayersAttackingMe().isEmpty()) {
try {
for (PlayerContainer container : plugin.getPlayersAttackingMe()) {
if ((System.currentTimeMillis() > (container.getWhenTheyAttackedMe() + container.getMillisToExpireHighlight())) && (container.getPlayer().getInteracting() != client.getLocalPlayer())) {
plugin.removePlayerFromAttackerContainer(container);
}
if (config.drawTargetsName()) renderNameAboveHead(graphics, container.getPlayer(), config.attackerPlayerColor());
if (config.drawTargetHighlight()) renderHighlightedPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
if (config.drawTargetTile()) renderTileUnderPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
if (config.drawTargetPrayAgainst()) renderPrayAgainstOnPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
}
} catch (ConcurrentModificationException e) {
}
}
}
private void renderNameAboveHead(Graphics2D graphics, Player player, Color color) {
final String name = Text.sanitize(player.getName());
final int offset = player.getLogicalHeight() + 40;
Point textLocation = player.getCanvasTextLocation(graphics, name, offset);
if (textLocation != null) {
OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
}
}
private void renderHighlightedPlayer(Graphics2D graphics, Player player, Color color) {
try {
OverlayUtil.renderPolygon(graphics, player.getConvexHull(), color);
} catch (NullPointerException e) {
}
}
private void renderTileUnderPlayer(Graphics2D graphics, Player player, Color color) {
Polygon poly = player.getCanvasTilePoly();
OverlayUtil.renderPolygon(graphics, poly, color);
}
private void renderPrayAgainstOnPlayer(Graphics2D graphics, Player player, Color color) {
final int offset = (player.getLogicalHeight() / 2) + 75;
BufferedImage icon;
switch (WeaponType.checkWeaponOnPlayer(client, player)) {
case WEAPON_MELEE:
icon = plugin.getProtectionIcon(WeaponType.WEAPON_MELEE);
break;
case WEAPON_MAGIC:
icon = plugin.getProtectionIcon(WeaponType.WEAPON_MAGIC);
break;
case WEAPON_RANGED:
icon = plugin.getProtectionIcon(WeaponType.WEAPON_RANGED);
break;
default:
icon = null;
break;
}
try {
if (icon != null) {
Point point = player.getCanvasImageLocation(icon, offset);
OverlayUtil.renderImageLocation(graphics, point, icon);
} else {
if (config.drawUnknownWeapons()) {
int itemId = player.getPlayerComposition().getEquipmentId(KitType.WEAPON);
ItemComposition itemComposition = client.getItemDefinition(itemId);
final String str = itemComposition.getName().toUpperCase();
Point point = player.getCanvasTextLocation(graphics, str, offset);
OverlayUtil.renderTextLocation(graphics, point, str, color);
}
}
} catch (Exception e) {
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.*;
import java.util.ConcurrentModificationException;
class PrayAgainstPlayerOverlayPrayerTab extends Overlay {
private final PrayAgainstPlayerPlugin plugin;
private final PrayAgainstPlayerConfig config;
private final Client client;
@Inject
private PrayAgainstPlayerOverlayPrayerTab (PrayAgainstPlayerPlugin plugin, PrayAgainstPlayerConfig config, Client client) {
super(plugin);
this.plugin = plugin;
this.config = config;
this.client = client;
setPosition(OverlayPosition.DETACHED);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (plugin.getPlayersAttackingMe() == null || !plugin.getPlayersAttackingMe().isEmpty()) {
try {
for (PlayerContainer container : plugin.getPlayersAttackingMe()) {
if (plugin.getPlayersAttackingMe() != null && plugin.getPlayersAttackingMe().size() > 0) {
//no reason to show you what prayers to pray in your prayer tab if multiple people are attacking you
if ((plugin.getPlayersAttackingMe().size() == 1) && (config.drawTargetPrayAgainstPrayerTab())) {
renderPrayerToClick(graphics, container.getPlayer());
}
}
}
} catch (ConcurrentModificationException e) {
}
}
return null;
}
private void renderPrayerToClick(Graphics2D graphics, Player player) {
Widget PROTECT_FROM_MAGIC = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC);
Widget PROTECT_FROM_RANGED = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
Widget PROTECT_FROM_MELEE = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MELEE);
Color color = Color.RED;
if (PROTECT_FROM_MELEE.isHidden()) return;
switch (WeaponType.checkWeaponOnPlayer(client, player)) {
case WEAPON_MAGIC:
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_MAGIC.getBounds()), color);
break;
case WEAPON_MELEE:
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_MELEE.getBounds()), color);
break;
case WEAPON_RANGED:
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_RANGED.getBounds()), color);
break;
default:
break;
}
}
private static Polygon rectangleToPolygon(Rectangle rect) {
int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x};
int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height};
return new Polygon(xpoints, ypoints, 4);
}
}

View File

@@ -0,0 +1,327 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import com.google.inject.Provides;
import net.runelite.api.*;
import net.runelite.api.events.*;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil;
import javax.inject.Inject;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
import java.util.Arrays;
@PluginDescriptor(
name = "<font color=\"aqua\">!Pray Against Player</font>",
description = "Use plugin in PvP situations for best results!!",
tags = {"highlight", "pvp", "overlay", "players"}
)
/**
* I am fully aware that there is plenty of overhead and is a MESS!
* If you'd like to contribute please do!
*/
public class PrayAgainstPlayerPlugin extends Plugin {
private static final int[] PROTECTION_ICONS = {
SpriteID.PRAYER_PROTECT_FROM_MISSILES,
SpriteID.PRAYER_PROTECT_FROM_MELEE,
SpriteID.PRAYER_PROTECT_FROM_MAGIC
};
private static final Dimension PROTECTION_ICON_DIMENSION = new Dimension(33, 33);
private static final Color PROTECTION_ICON_OUTLINE_COLOR = new Color(33, 33, 33);
public final BufferedImage[] ProtectionIcons = new BufferedImage[PROTECTION_ICONS.length];
private ArrayList<PlayerContainer> potentialPlayersAttackingMe;
private ArrayList<PlayerContainer> playersAttackingMe;
@Inject
private Client client;
@Inject
private SpriteManager spriteManager;
@Inject
private OverlayManager overlayManager;
@Inject
private PrayAgainstPlayerOverlay overlay;
@Inject
private PrayAgainstPlayerOverlayPrayerTab overlayPrayerTab;
@Inject
private PrayAgainstPlayerConfig config;
@Provides
PrayAgainstPlayerConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(PrayAgainstPlayerConfig.class);
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) {
if (gameStateChanged.getGameState() == GameState.LOGGED_IN) {
loadProtectionIcons();
}
}
@Override
protected void startUp() {
potentialPlayersAttackingMe = new ArrayList<>();
playersAttackingMe = new ArrayList<>();
overlayManager.add(overlay);
overlayManager.add(overlayPrayerTab);
}
@Override
protected void shutDown() throws Exception {
overlayManager.remove(overlay);
overlayManager.remove(overlayPrayerTab);
}
@Subscribe
protected void onAnimationChanged(AnimationChanged animationChanged) {
if ((animationChanged.getActor() instanceof Player) && (animationChanged.getActor().getInteracting() instanceof Player) && (animationChanged.getActor().getInteracting() == client.getLocalPlayer())) {
Player sourcePlayer = (Player) animationChanged.getActor();
//is the client is a friend/clan and the config is set to ignore friends/clan dont add them to list
if (client.isFriended(sourcePlayer.getName(), true) && config.ignoreFriends()) return;
if (client.isClanMember(sourcePlayer.getName()) && config.ignoreClanMates()) return;
if ((sourcePlayer.getAnimation() != -1) && (!isBlockAnimation(sourcePlayer.getAnimation()))) {
//if attacker attacks again, reset his timer so overlay doesn't go away
if (findPlayerInAttackerList(sourcePlayer) != null) {
resetPlayerFromAttackerContainerTimer(findPlayerInAttackerList(sourcePlayer));
}
//if he attacks and he was in the potential attackers list, remove him
if (!potentialPlayersAttackingMe.isEmpty() && potentialPlayersAttackingMe.contains(findPlayerInPotentialList(sourcePlayer))) {
removePlayerFromPotentialContainer(findPlayerInPotentialList(sourcePlayer));
}
//if he's not in the attackers list, add him
if (findPlayerInAttackerList(sourcePlayer) == null) {
PlayerContainer container = new PlayerContainer(sourcePlayer, System.currentTimeMillis(), (config.attackerTargetTimeout() * 1000));
playersAttackingMe.add(container);
}
}
}
}
@Subscribe
protected void onInteractingChanged(InteractingChanged interactingChanged) {
//if someone interacts with you, add them to the potential attackers list
if ((interactingChanged.getSource() instanceof Player) && (interactingChanged.getTarget() instanceof Player)) {
Player sourcePlayer = (Player) interactingChanged.getSource();
Player targetPlayer = (Player) interactingChanged.getTarget();
if ((targetPlayer == client.getLocalPlayer()) && (findPlayerInPotentialList(sourcePlayer) == null)) { //we're being interacted with
//is the client is a friend/clan and the config is set to ignore friends/clan dont add them to list
if (client.isFriended(sourcePlayer.getName(), true) && config.ignoreFriends()) return;
if (client.isClanMember(sourcePlayer.getName()) && config.ignoreClanMates()) return;
PlayerContainer container = new PlayerContainer(sourcePlayer, System.currentTimeMillis(), (config.potentialTargetTimeout() * 1000));
potentialPlayersAttackingMe.add(container);
}
}
}
@Subscribe
protected void onPlayerDespawned(PlayerDespawned playerDespawned) {
PlayerContainer container = findPlayerInAttackerList(playerDespawned.getPlayer());
PlayerContainer container2 = findPlayerInPotentialList(playerDespawned.getPlayer());
if (container != null) {
playersAttackingMe.remove(container);
}
if (container2 != null) {
potentialPlayersAttackingMe.remove(container2);
}
}
@Subscribe
protected void onPlayerSpawned(PlayerSpawned playerSpawned) {
if (config.markNewPlayer()) {
Player p = playerSpawned.getPlayer();
if (client.isFriended(p.getName(), true) && config.ignoreFriends()) return;
if (client.isClanMember(p.getName()) && config.ignoreClanMates()) return;
PlayerContainer container = findPlayerInPotentialList(p);
if (container == null) {
container = new PlayerContainer(p, System.currentTimeMillis(), (config.newSpawnTimeout() * 1000));
potentialPlayersAttackingMe.add(container);
}
}
}
PlayerContainer findPlayerInAttackerList(Player player) {
if (playersAttackingMe.isEmpty()) {
return null;
}
for (int i = 0 ; i < playersAttackingMe.size() ; i++) {
PlayerContainer container = playersAttackingMe.get(i);
if (container.getPlayer() == player) {
return container;
}
}
return null;
}
PlayerContainer findPlayerInPotentialList(Player player) {
if (potentialPlayersAttackingMe.isEmpty()) {
return null;
}
for (int i = 0 ; i < potentialPlayersAttackingMe.size() ; i++) {
PlayerContainer container = potentialPlayersAttackingMe.get(i);
if (container.getPlayer() == player) {
return container;
}
}
return null;
}
/**
* Resets player timer in case he attacks again, so his highlight doesn't go away so easily
* @param container
*/
public void resetPlayerFromAttackerContainerTimer(PlayerContainer container) {
removePlayerFromAttackerContainer(container);
PlayerContainer newContainer = new PlayerContainer(container.getPlayer(), System.currentTimeMillis(), (config.attackerTargetTimeout() * 1000));
playersAttackingMe.add(newContainer);
}
public void removePlayerFromPotentialContainer(PlayerContainer container) {
if ((potentialPlayersAttackingMe != null) && (!potentialPlayersAttackingMe.isEmpty()) && (potentialPlayersAttackingMe.contains(container))) {
potentialPlayersAttackingMe.remove(container);
}
}
public void removePlayerFromAttackerContainer(PlayerContainer container) {
if ((playersAttackingMe != null) && (!playersAttackingMe.isEmpty()) && (playersAttackingMe.contains(container))) {
playersAttackingMe.remove(container);
}
}
private boolean isBlockAnimation(int anim) {
switch (anim) {
case AnimationID.BLOCK_DEFENDER:
case AnimationID.BLOCK_NO_SHIELD:
case AnimationID.BLOCK_SHIELD:
case AnimationID.BLOCK_SWORD:
case AnimationID.BLOCK_UNARMED:
return true;
default:
return false;
}
}
public ArrayList<PlayerContainer> getPotentialPlayersAttackingMe() { return potentialPlayersAttackingMe; }
public ArrayList<PlayerContainer> getPlayersAttackingMe() { return playersAttackingMe; }
//All of the methods below are from the Zulrah plugin!!! Credits to it's respective owner
private void loadProtectionIcons() {
final IndexedSprite[] protectionIcons = {};
final IndexedSprite[] newProtectionIcons = Arrays.copyOf(protectionIcons, PROTECTION_ICONS.length);
int curPosition = 0;
for (int i = 0; i < PROTECTION_ICONS.length; i++, curPosition++)
{
final int resource = PROTECTION_ICONS[i];
ProtectionIcons[i] = rgbaToIndexedBufferedImage(ProtectionIconFromSprite(spriteManager.getSprite(resource, 0)));
newProtectionIcons[curPosition] = createIndexedSprite(client, ProtectionIcons[i]);
}
}
private static IndexedSprite createIndexedSprite(final Client client, final BufferedImage bufferedImage) {
final IndexColorModel indexedCM = (IndexColorModel) bufferedImage.getColorModel();
final int width = bufferedImage.getWidth();
final int height = bufferedImage.getHeight();
final byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
final int[] palette = new int[indexedCM.getMapSize()];
indexedCM.getRGBs(palette);
final IndexedSprite newIndexedSprite = client.createIndexedSprite();
newIndexedSprite.setPixels(pixels);
newIndexedSprite.setPalette(palette);
newIndexedSprite.setWidth(width);
newIndexedSprite.setHeight(height);
newIndexedSprite.setOriginalWidth(width);
newIndexedSprite.setOriginalHeight(height);
newIndexedSprite.setOffsetX(0);
newIndexedSprite.setOffsetY(0);
return newIndexedSprite;
}
private static BufferedImage rgbaToIndexedBufferedImage(final BufferedImage sourceBufferedImage) {
final BufferedImage indexedImage = new BufferedImage(
sourceBufferedImage.getWidth(),
sourceBufferedImage.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED);
final ColorModel cm = indexedImage.getColorModel();
final IndexColorModel icm = (IndexColorModel) cm;
final int size = icm.getMapSize();
final byte[] reds = new byte[size];
final byte[] greens = new byte[size];
final byte[] blues = new byte[size];
icm.getReds(reds);
icm.getGreens(greens);
icm.getBlues(blues);
final WritableRaster raster = indexedImage.getRaster();
final int pixel = raster.getSample(0, 0, 0);
final IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel);
final BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null);
resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null);
return resultIndexedImage;
}
private static BufferedImage ProtectionIconFromSprite(final BufferedImage freezeSprite) {
final BufferedImage freezeCanvas = ImageUtil.resizeCanvas(freezeSprite, PROTECTION_ICON_DIMENSION.width, PROTECTION_ICON_DIMENSION.height);
return ImageUtil.outlineImage(freezeCanvas, PROTECTION_ICON_OUTLINE_COLOR);
}
BufferedImage getProtectionIcon(WeaponType weaponType) {
switch (weaponType) {
case WEAPON_RANGED:
return ProtectionIcons[0];
case WEAPON_MELEE:
return ProtectionIcons[1];
case WEAPON_MAGIC:
return ProtectionIcons[2];
}
return null;
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.prayagainstplayer;
import net.runelite.api.Client;
import net.runelite.api.ItemComposition;
import net.runelite.api.Player;
import net.runelite.api.kit.KitType;
enum WeaponType {
WEAPON_MELEE,
WEAPON_RANGED,
WEAPON_MAGIC,
WEAPON_UNKNOWN;
/**
* im fully aware this could of been done better!!!
* @param client
* @param attacker
* @return
*/
public static WeaponType checkWeaponOnPlayer (Client client, Player attacker) {
int itemId = attacker.getPlayerComposition().getEquipmentId(KitType.WEAPON);
ItemComposition itemComposition = client.getItemDefinition(itemId);
String weaponNameGivenLowerCase = itemComposition.getName().toLowerCase();
if (itemId == -1) return WEAPON_MELEE;
if (weaponNameGivenLowerCase == null || weaponNameGivenLowerCase.toLowerCase().contains("null")) return WEAPON_MELEE;
for (String meleeWeaponName : meleeWeaponNames) {
if (weaponNameGivenLowerCase.contains(meleeWeaponName) && !weaponNameGivenLowerCase.contains("thrownaxe")) {
return WEAPON_MELEE;
}
}
for (String rangedWeaponName : rangedWeaponNames) {
if (weaponNameGivenLowerCase.contains(rangedWeaponName)) {
return WEAPON_RANGED;
}
}
for (String magicWeaponName : magicWeaponNames) {
if (weaponNameGivenLowerCase.contains(magicWeaponName)) {
return WEAPON_MAGIC;
}
}
return WEAPON_UNKNOWN;
}
private static String[] meleeWeaponNames = {
"sword",
"scimitar",
"dagger",
"spear",
"mace",
"axe",
"whip",
"tentacle",
"-ket-",
"-xil-",
"warhammer",
"halberd",
"claws",
"hasta",
"scythe",
"maul",
"anchor",
"sabre",
"excalibur",
"machete",
"dragon hunter lance",
"event rpg",
"silverlight",
"darklight",
"arclight",
"flail",
"granite hammer",
"rapier",
"bulwark"
};
private static String[] rangedWeaponNames = {
"bow",
"blowpipe",
"xil-ul",
"knife",
"dart",
"thrownaxe",
"chinchompa",
"ballista"
};
private static String[] magicWeaponNames = {
"staff",
"trident",
"wand",
"dawnbringer"
};
}

View File

@@ -0,0 +1,123 @@
/*
* Decompiled with CFR 0.139.
*/
package net.runelite.client.plugins.profiles;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.util.ImageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ProfilePanel
extends JPanel {
private static final Logger log = LoggerFactory.getLogger(ProfilePanel.class);
private static final ImageIcon DELETE_ICON;
private static final ImageIcon DELETE_HOVER_ICON;
private final String loginText;
private String password = null;
ProfilePanel(final Client client, final String data, final ProfilesConfig config) {
String[] parts = data.split(":");
this.loginText = parts[1];
if (parts.length == 3) {
this.password = parts[2];
}
final ProfilePanel panel = this;
this.setLayout(new BorderLayout());
this.setBackground(ColorScheme.DARKER_GRAY_COLOR);
JPanel labelWrapper = new JPanel(new BorderLayout());
labelWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
labelWrapper.setBorder(new CompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR), BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR)));
JPanel panelActions = new JPanel(new BorderLayout(3, 0));
panelActions.setBorder(new EmptyBorder(0, 0, 0, 8));
panelActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
final JLabel delete = new JLabel();
delete.setIcon(DELETE_ICON);
delete.setToolTipText("Delete account profile");
delete.addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e) {
panel.getParent().remove(panel);
ProfilesPanel.removeProfile(data);
}
@Override
public void mouseEntered(MouseEvent e) {
delete.setIcon(DELETE_HOVER_ICON);
}
@Override
public void mouseExited(MouseEvent e) {
delete.setIcon(DELETE_ICON);
}
});
panelActions.add((Component)delete, "East");
JLabel label = new JLabel();
label.setText(parts[0]);
label.setBorder(null);
label.setBackground(ColorScheme.DARKER_GRAY_COLOR);
label.setPreferredSize(new Dimension(0, 24));
label.setForeground(Color.WHITE);
label.setBorder(new EmptyBorder(0, 8, 0, 0));
labelWrapper.add((Component)label, "Center");
labelWrapper.add((Component)panelActions, "East");
label.addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
client.setUsername(ProfilePanel.this.loginText);
if (config.rememberPassword() && ProfilePanel.this.password != null) {
client.setPassword(ProfilePanel.this.password);
}
}
}
});
JPanel bottomContainer = new JPanel(new BorderLayout());
bottomContainer.setBorder(new EmptyBorder(8, 0, 8, 0));
bottomContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
bottomContainer.addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
client.setUsername(ProfilePanel.this.loginText);
}
}
});
JLabel login = new JLabel();
login.setText(config.isStreamerMode() ? "Hidden email" : this.loginText);
login.setBorder(null);
login.setPreferredSize(new Dimension(0, 24));
login.setForeground(Color.WHITE);
login.setBorder(new EmptyBorder(0, 8, 0, 0));
bottomContainer.add((Component)login, "Center");
this.add((Component)labelWrapper, "North");
this.add((Component)bottomContainer, "Center");
}
static {
BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ProfilesPlugin.class, "net/runelite/client/plugins/profiles/delete_icon.png");
DELETE_ICON = new ImageIcon(deleteImg);
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
}
}

View File

@@ -0,0 +1,36 @@
/*
* Decompiled with CFR 0.139.
*/
package net.runelite.client.plugins.profiles;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(value="profiles")
public interface ProfilesConfig
extends Config {
@ConfigItem(keyName="profilesData", name="", description="", hidden=true)
default public String profilesData() {
return "";
}
@ConfigItem(keyName="profilesData", name="", description="")
public void profilesData(String var1);
@ConfigItem(keyName="rememberPassword", name="Remember Password", description="Remembers passwords for accounts")
default public boolean rememberPassword() {
return true;
}
@ConfigItem(keyName="streamerMode", name="Hide email addresses", description="Hides your account emails")
default public boolean isStreamerMode() {
return false;
}
@ConfigItem(keyName="switchPanel", name="Auto-open Panel", description="Automatically switch to the account switcher panel on the login screen")
default public boolean switchPanel() {
return true;
}
}

View File

@@ -0,0 +1,248 @@
/*
* Decompiled with CFR 0.139.
*/
package net.runelite.client.plugins.profiles;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import net.runelite.api.Client;
import net.runelite.client.plugins.profiles.ProfilePanel;
import net.runelite.client.plugins.profiles.ProfilesConfig;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ProfilesPanel
extends PluginPanel {
private static final Logger log = LoggerFactory.getLogger(ProfilesPanel.class);
private static final String ACCOUNT_USERNAME = "Account Username";
private static final String ACCOUNT_LABEL = "Account Label";
private static final String PASSWORD_LABEL = "Account Password";
private static final Dimension PREFERRED_SIZE = new Dimension(205, 30);
private static final Dimension MINIMUM_SIZE = new Dimension(0, 30);
private final Client client;
private static ProfilesConfig profilesConfig;
private final JTextField txtAccountLabel = new JTextField("Account Label");
private final JPasswordField txtAccountLogin = new JPasswordField("Account Username");
private final JPasswordField txtPasswordLogin = new JPasswordField("Account Password");
private final JPanel profilesPanel = new JPanel();
private GridBagConstraints c;
@Inject
public ProfilesPanel(Client client, final ProfilesConfig config) {
this.client = client;
profilesConfig = config;
this.setBorder(new EmptyBorder(18, 10, 0, 10));
this.setBackground(ColorScheme.DARK_GRAY_COLOR);
this.setLayout(new GridBagLayout());
this.c = new GridBagConstraints();
this.c.fill = 2;
this.c.gridx = 0;
this.c.gridy = 0;
this.c.weightx = 1.0;
this.c.weighty = 0.0;
this.c.insets = new Insets(0, 0, 4, 0);
this.txtAccountLabel.setPreferredSize(PREFERRED_SIZE);
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
this.txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
this.txtAccountLabel.setMinimumSize(MINIMUM_SIZE);
this.txtAccountLabel.addFocusListener(new FocusListener(){
@Override
public void focusGained(FocusEvent e) {
if (ProfilesPanel.this.txtAccountLabel.getText().equals(ProfilesPanel.ACCOUNT_LABEL)) {
ProfilesPanel.this.txtAccountLabel.setText("");
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
}
}
@Override
public void focusLost(FocusEvent e) {
if (ProfilesPanel.this.txtAccountLabel.getText().isEmpty()) {
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
ProfilesPanel.this.txtAccountLabel.setText(ProfilesPanel.ACCOUNT_LABEL);
}
}
});
this.add((Component)this.txtAccountLabel, this.c);
++this.c.gridy;
this.txtAccountLogin.setEchoChar('\u0000');
this.txtAccountLogin.setPreferredSize(PREFERRED_SIZE);
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
this.txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
this.txtAccountLogin.setMinimumSize(MINIMUM_SIZE);
this.txtAccountLogin.addFocusListener(new FocusListener(){
@Override
public void focusGained(FocusEvent e) {
if (ProfilesPanel.ACCOUNT_USERNAME.equals(String.valueOf(ProfilesPanel.this.txtAccountLogin.getPassword()))) {
ProfilesPanel.this.txtAccountLogin.setText("");
if (config.isStreamerMode()) {
ProfilesPanel.this.txtAccountLogin.setEchoChar('*');
}
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
}
}
@Override
public void focusLost(FocusEvent e) {
if (ProfilesPanel.this.txtAccountLogin.getPassword().length == 0) {
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
ProfilesPanel.this.txtAccountLogin.setText(ProfilesPanel.ACCOUNT_USERNAME);
ProfilesPanel.this.txtAccountLogin.setEchoChar('\u0000');
}
}
});
this.add((Component)this.txtAccountLogin, this.c);
++this.c.gridy;
this.txtPasswordLogin.setEchoChar('\u0000');
this.txtPasswordLogin.setPreferredSize(PREFERRED_SIZE);
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
this.txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
this.txtPasswordLogin.setToolTipText("Account password");
this.txtPasswordLogin.setMinimumSize(MINIMUM_SIZE);
this.txtPasswordLogin.addFocusListener(new FocusListener(){
@Override
public void focusGained(FocusEvent e) {
if (ProfilesPanel.PASSWORD_LABEL.equals(String.valueOf(ProfilesPanel.this.txtPasswordLogin.getPassword()))) {
ProfilesPanel.this.txtPasswordLogin.setText("");
ProfilesPanel.this.txtPasswordLogin.setEchoChar('*');
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
}
}
@Override
public void focusLost(FocusEvent e) {
if (ProfilesPanel.this.txtPasswordLogin.getPassword().length == 0) {
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
ProfilesPanel.this.txtPasswordLogin.setText(ProfilesPanel.PASSWORD_LABEL);
ProfilesPanel.this.txtPasswordLogin.setEchoChar('\u0000');
}
}
});
if (config.rememberPassword()) {
this.add((Component)this.txtPasswordLogin, this.c);
++this.c.gridy;
}
this.c.insets = new Insets(0, 0, 15, 0);
final JButton btnAddAccount = new JButton("Add Account");
btnAddAccount.setPreferredSize(PREFERRED_SIZE);
btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR);
btnAddAccount.setMinimumSize(MINIMUM_SIZE);
btnAddAccount.addActionListener(e -> {
String labelText = String.valueOf(this.txtAccountLabel.getText());
String loginText = String.valueOf(this.txtAccountLogin.getPassword());
String passwordText = String.valueOf(this.txtPasswordLogin.getPassword());
if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME)) {
return;
}
String data = config.rememberPassword() && this.txtPasswordLogin.getPassword() != null ? labelText + ":" + loginText + ":" + passwordText : labelText + ":" + loginText;
log.info(data);
this.addAccount(data);
ProfilesPanel.addProfile(data);
this.txtAccountLabel.setText(ACCOUNT_LABEL);
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
this.txtAccountLogin.setText(ACCOUNT_USERNAME);
this.txtAccountLogin.setEchoChar('\u0000');
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
this.txtPasswordLogin.setText(PASSWORD_LABEL);
this.txtPasswordLogin.setEchoChar('\u0000');
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
});
this.txtAccountLogin.addKeyListener(new KeyAdapter(){
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 10) {
btnAddAccount.doClick();
btnAddAccount.requestFocus();
}
}
});
this.txtAccountLogin.addMouseListener(new MouseListener(){
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
this.add((Component)btnAddAccount, this.c);
++this.c.gridy;
this.profilesPanel.setLayout(new GridBagLayout());
this.add((Component)this.profilesPanel, this.c);
this.c.gridy = 0;
this.c.insets = new Insets(0, 0, 5, 0);
this.addAccounts(config.profilesData());
}
void redrawProfiles() {
this.profilesPanel.removeAll();
this.c.gridy = 0;
this.addAccounts(profilesConfig.profilesData());
}
private void addAccount(String data) {
ProfilePanel profile = new ProfilePanel(this.client, data, profilesConfig);
++this.c.gridy;
this.profilesPanel.add((Component)profile, this.c);
this.revalidate();
this.repaint();
}
void addAccounts(String data) {
if (!(data = data.trim()).contains(":")) {
return;
}
Arrays.stream(data.split("\\n")).forEach(this::addAccount);
}
static void addProfile(String data) {
profilesConfig.profilesData(profilesConfig.profilesData() + data + "\n");
}
static void removeProfile(String data) {
profilesConfig.profilesData(profilesConfig.profilesData().replaceAll(data + "\\n", ""));
}
}

View File

@@ -0,0 +1,128 @@
/*
* Decompiled with CFR 0.139.
*/
package net.runelite.client.plugins.profiles;
import com.google.inject.Provides;
import java.awt.image.BufferedImage;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;
@PluginDescriptor(name="Account Switcher", description="Allow for a allows you to easily switch between multiple OSRS Accounts", tags={"profile", "account", "login", "log in"})
public class ProfilesPlugin
extends Plugin {
@Inject
private ClientToolbar clientToolbar;
@Inject
private Client client;
@Inject
private ProfilesConfig config;
private ProfilesPanel panel;
private NavigationButton navButton;
String text = "Hello World";
private static String key = "Bar12345Bar12345";
private static Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
@Provides
ProfilesConfig getConfig(ConfigManager configManager) {
return configManager.getConfig(ProfilesConfig.class);
}
@Override
protected void startUp() throws Exception {
this.panel = this.injector.getInstance(ProfilesPanel.class);
BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "/net/runelite/client/plugins/profiles/profiles_icon.png");
this.navButton = NavigationButton.builder().tooltip("Profiles").icon(icon).priority(8).panel(this.panel).build();
this.clientToolbar.addNavigation(this.navButton);
}
@Override
protected void shutDown() {
this.clientToolbar.removeNavigation(this.navButton);
}
@Subscribe
private void onConfigChanged(ConfigChanged event) throws Exception {
if (event.getGroup().equals("profiles") && event.getKey().equals("rememberPassword")) {
this.panel = this.injector.getInstance(ProfilesPanel.class);
this.shutDown();
this.startUp();
}
}
public static String decryptText(String text) {
byte[] bb = new byte[text.length()];
for (int i = 0; i < text.length(); ++i) {
bb[i] = (byte)text.charAt(i);
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES");
}
catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
try {
cipher.init(2, aesKey);
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
try {
Logger.getLogger("EncryptionLogger").info("Decrypted " + text + " to " + new String(cipher.doFinal(bb)));
return new String(cipher.doFinal(bb));
}
catch (BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
return "";
}
}
public static String encryptText(String text) {
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(1, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : encrypted) {
sb.append((char)b);
}
Logger.getLogger("EncryptionLogger").info("Encrypted " + text + " to " + sb.toString());
return sb.toString();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (NoSuchPaddingException e) {
e.printStackTrace();
}
catch (BadPaddingException e) {
e.printStackTrace();
}
catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
return "";
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
import com.google.common.collect.ImmutableSet;
import java.util.Set;
import static net.runelite.api.ObjectID.SPEARTRAP_21280;
public class Obstacles
{
static final Set<Integer> WALL_OBSTACLE_IDS = ImmutableSet.of(
26618, 26619, 26620, 26621
);
static final Set<Integer> TRAP_OBSTACLE_IDS = ImmutableSet.of(
SPEARTRAP_21280
);
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("pyramidplunder")
public interface PyramidPlunderConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "highlightDoors",
name = "Highlights doors",
description = "Highlights the four doors in each room"
)
default boolean highlightDoors()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "highlightSpearTrap",
name = "Highlights spear traps",
description = "Highlights the spear traps in each room"
)
default boolean highlightSpearTrap()
{
return false;
}
@ConfigItem(
position = 3,
keyName = "showTimer",
name = "Display numerical timer",
description = "Displays a numerical timer instead of the default timer"
)
default boolean showTimer()
{
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More