Update BA Plugins, Update from RL master (#226)

* xp tracker: display >1m exp with thousandths precision

* fishing plugin: fix trawler timer with one tick left

* Remove gray pixel from Dragon Scimitar cursor (#8725)

* client: add smelting plugin

Co-authored-by: Adam <Adam@sigterm.info>

* constants: add GAME_TICK_LENGTH and use where needed

Also update many usages of 20ms to CLIENT_TICK_LENGTH

* regenmeter: add option to notify before next hp regen

* barrows plugin: add prayer drain timer

* chat: ensure queued messages are always cleared after adding

Mark queued message type as non null because addChatMessage will throw
if it is. This was causing the client to get stuck trying to add the
same broken message each loop.

* party plugin: add partyinfo debug command

* party service: check joins are for the current party

The server can resume party membership on handshake to parties other
than the current client party (eg. if the client is restarted or for any
other reason the current party changes). This desyncs otherwise if the
joins aren't checked to be in the current party.

* Updated barbassault/ba tools

* Update
This commit is contained in:
James
2019-05-12 02:16:04 -07:00
committed by Kyleeld
parent b0ddb194e4
commit 33885b86f1
45 changed files with 1391 additions and 434 deletions

View File

@@ -34,5 +34,6 @@ import net.runelite.http.api.ws.WebsocketMessage;
public class UserJoin extends WebsocketMessage public class UserJoin extends WebsocketMessage
{ {
private final UUID memberId; private final UUID memberId;
private final UUID partyId;
private final String name; private final String name;
} }

View File

@@ -89,4 +89,12 @@ public class Constants
* the maximum framerate of 50 fps. * the maximum framerate of 50 fps.
*/ */
public static final int CLIENT_TICK_LENGTH = 20; public static final int CLIENT_TICK_LENGTH = 20;
/**
* The number of milliseconds in a server game tick.
* <p>
* This is the length of a single game cycle under ideal conditions.
* All game-play actions operate within multiples of this duration.
*/
public static final int GAME_TICK_LENGTH = 600;
} }

View File

@@ -217,6 +217,7 @@ public enum Varbits
* Barbarian Assault * Barbarian Assault
*/ */
IN_GAME_BA(3923), IN_GAME_BA(3923),
BA_GC(4768),
/** /**
* 0 = Outside wilderness * 0 = Outside wilderness

View File

@@ -573,36 +573,47 @@ public class WidgetID
static final int VENT_C_STATUS = 25; static final int VENT_C_STATUS = 25;
} }
public static class BarbarianAssault static class BarbarianAssault
{ {
static class ATK static class ATK
{ {
static final int CALL_TEXT = 8; static final int LISTEN = 8;
static final int TO_CALL_WIDGET = 9; static final int TO_CALL_WIDGET = 9;
static final int TO_CALL = 10; static final int TO_CALL = 10;
static final int ROLE_SPRITE = 11; static final int ROLE_SPRITE = 11;
static final int ROLE = 12; static final int ROLE = 12;
} }
static class HLR { static class HLR
{
static final int TEAMMATE1 = 18; static final int TEAMMATE1 = 18;
static final int TEAMMATE2 = 22; static final int TEAMMATE2 = 22;
static final int TEAMMATE3 = 26; static final int TEAMMATE3 = 26;
static final int TEAMMATE4 = 30; static final int TEAMMATE4 = 30;
} }
public static class REWARD_VALUES static class REWARD_VALUES
{ {
public static final int RUNNERS_PASSED = 14; static final int RUNNERS_PASSED = 14;
static final int HITPOINTS_REPLENISHED = 19; static final int HITPOINTS_REPLENISHED = 19;
static final int WRONG_POISON_PACKS_USED = 20; static final int WRONG_POISON_PACKS_USED = 20;
static final int EGGS_COLLECTED = 21; static final int EGGS_COLLECTED = 21;
static final int FAILED_ATTACKER_ATTACKS = 22; static final int FAILED_ATTACKER_ATTACKS = 22;
static final int RUNNERS_PASSED_POINTS = 24;
static final int RANGERS_KILLED = 25;
static final int FIGHTERS_KILLED = 26;
static final int HEALERS_KILLED = 27;
static final int RUNNERS_KILLED = 28;
static final int HITPOINTS_REPLENISHED_POINTS = 29;
static final int WRONG_POISON_PACKS_USED_POINTS = 30;
static final int EGGS_COLLECTED_POINTS = 31;
static final int FAILED_ATTACKER_ATTACKS_POINTS = 32;
static final int BASE_POINTS = 33;
static final int HONOUR_POINTS_REWARD = 49; static final int HONOUR_POINTS_REWARD = 49;
} }
static final int CORRECT_STYLE = 3; static final int GAME_WIDGET = 3;
static final int CURRENT_WAVE_WIDGET = 4; static final int CURRENT_WAVE_WIDGET = 4;
static final int CURRENT_WAVE = 5; static final int CURRENT_WAVE = 5;
static final int CALL_WIDGET = 6; static final int LISTEN_WIDGET = 6;
static final int HEARD_CALL = 7; static final int LISTEN = 7;
static final int TO_CALL_WIDGET = 8; static final int TO_CALL_WIDGET = 8;
static final int TO_CALL = 9; static final int TO_CALL = 9;
static final int ROLE_SPRITE = 10; static final int ROLE_SPRITE = 10;

View File

@@ -362,7 +362,7 @@ public enum WidgetInfo
BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_HEAL_ROLE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_HEAL_ROLE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_HEAL_ROLE_SPRITE(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), BA_HEAL_ROLE_SPRITE(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),
@@ -373,20 +373,19 @@ public enum WidgetInfo
BA_COLL_WAVE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_COLL_WAVE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_COLL_CALL_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), BA_COLL_CALL_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_COLL_HEARD_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.HEARD_CALL),
BA_COLL_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_COLL_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),
BA_ATK_WAVE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_ATK_WAVE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_ATK_CALL_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.TO_CALL), BA_ATK_CALL_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.TO_CALL),
BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN),
BA_ATK_ROLE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE), BA_ATK_ROLE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE),
BA_ATK_ROLE_SPRITE(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE_SPRITE), BA_ATK_ROLE_SPRITE(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE_SPRITE),
BA_DEF_WAVE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_DEF_WAVE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE),
BA_DEF_CALL_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), BA_DEF_CALL_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL),
BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN),
BA_DEF_ROLE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_DEF_ROLE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE),
BA_DEF_ROLE_SPRITE(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), BA_DEF_ROLE_SPRITE(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE),
@@ -396,7 +395,17 @@ public enum WidgetInfo
BA_WRONG_POISON_PACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED), BA_WRONG_POISON_PACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED),
BA_EGGS_COLLECTED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED), BA_EGGS_COLLECTED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED),
BA_FAILED_ATTACKER_ATTACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS), BA_FAILED_ATTACKER_ATTACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS),
BA_RUNNERS_PASSED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED_POINTS),
BA_RANGERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RANGERS_KILLED),
BA_FIGHTERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FIGHTERS_KILLED),
BA_HEALERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HEALERS_KILLED),
BA_RUNNERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_KILLED),
BA_HITPOINTS_REPLENISHED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED_POINTS),
BA_WRONG_POISON_PACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED_POINTS),
BA_EGGS_COLLECTED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED_POINTS),
BA_FAILED_ATTACKER_ATTACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS_POINTS),
BA_HONOUR_POINTS_REWARD(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HONOUR_POINTS_REWARD), BA_HONOUR_POINTS_REWARD(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HONOUR_POINTS_REWARD),
BA_BASE_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.BASE_POINTS),
LEVEL_UP(WidgetID.LEVEL_UP_GROUP_ID, 0), LEVEL_UP(WidgetID.LEVEL_UP_GROUP_ID, 0),
LEVEL_UP_SKILL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL), LEVEL_UP_SKILL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL),

View File

@@ -42,6 +42,7 @@ import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider; import net.runelite.api.BufferProvider;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.MainBufferProvider; import net.runelite.api.MainBufferProvider;
import net.runelite.api.NullItemID; import net.runelite.api.NullItemID;
import net.runelite.api.RenderOverview; import net.runelite.api.RenderOverview;
@@ -79,7 +80,7 @@ import net.runelite.client.util.DeferredEventBus;
@Slf4j @Slf4j
public class Hooks implements Callbacks public class Hooks implements Callbacks
{ {
private static final long CHECK = 600; // ms - how often to run checks private static final long CHECK = Constants.GAME_TICK_LENGTH; // ms - how often to run checks
private static final Injector injector = RuneLite.getInjector(); private static final Injector injector = RuneLite.getInjector();
private static final Client client = injector.getInstance(Client.class); private static final Client client = injector.getInstance(Client.class);

View File

@@ -547,11 +547,17 @@ public class ChatMessageManager
public void process() public void process()
{ {
if (!queuedMessages.isEmpty()) if (!queuedMessages.isEmpty())
{
try
{ {
queuedMessages.forEach(this::add); queuedMessages.forEach(this::add);
}
finally
{
queuedMessages.clear(); queuedMessages.clear();
} }
} }
}
private void add(QueuedMessage message) private void add(QueuedMessage message)
{ {

View File

@@ -26,12 +26,14 @@ package net.runelite.client.chat;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NonNull;
import net.runelite.api.ChatMessageType; import net.runelite.api.ChatMessageType;
@Data @Data
@Builder @Builder
public class QueuedMessage public class QueuedMessage
{ {
@NonNull
private final ChatMessageType type; private final ChatMessageType type;
private final String value; private final String value;
private String name; private String name;

View File

@@ -27,6 +27,7 @@ package net.runelite.client.plugins.antidrag;
import java.awt.Color; import java.awt.Color;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import net.runelite.client.config.Alpha; import net.runelite.client.config.Alpha;
import net.runelite.api.Constants;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
@@ -44,7 +45,7 @@ public interface AntiDragConfig extends Config
) )
default int dragDelay() default int dragDelay()
{ {
return 600 / 20; // one game tick return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick
} }
@ConfigItem( @ConfigItem(

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -25,33 +24,35 @@
*/ */
package net.runelite.client.plugins.barbarianassault; package net.runelite.client.plugins.barbarianassault;
import java.awt.Color;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
import java.awt.*;
@ConfigGroup("barbarianAssault") @ConfigGroup("barbarianAssault")
public interface BarbarianAssaultConfig extends Config public interface BarbarianAssaultConfig extends Config
{ {
@ConfigItem( @ConfigItem(
keyName = "showTimer", keyName = "showTimer",
name = "Show call change timer", name = "Show call change timer",
description = "Show time to next call change" description = "Show time to next call change",
position = 0
) )
default boolean showTimer() { return true; } default boolean showTimer() { return true; }
@ConfigItem( @ConfigItem(
keyName = "waveTimes", keyName = "waveTimes",
name = "Show wave and game duration", name = "Show wave and game duration",
description = "Displays wave and game duration" description = "Displays wave and game duration",
position = 1
) )
default boolean waveTimes() { return true; } default boolean waveTimes() { return true; }
@ConfigItem( @ConfigItem(
keyName = "showEggCountMessage", keyName = "showEggCountMessage",
name = "Show count of eggs collected as collector.", name = "Show count of eggs collected as collector.",
description = "Display egg count as collector after each wave", description = "Display egg count as collector after each wave",
position = 0 position = 2
) )
default boolean showEggCount() { return false; } default boolean showEggCount() { return false; }
@@ -59,7 +60,7 @@ public interface BarbarianAssaultConfig extends Config
keyName = "showEggCountOverlay", keyName = "showEggCountOverlay",
name = "Overlay of eggs counted", name = "Overlay of eggs counted",
description = "Display current egg count as collector", description = "Display current egg count as collector",
position = 1 position = 3
) )
default boolean showEggCountOverlay() { return false; } default boolean showEggCountOverlay() { return false; }
@@ -67,7 +68,7 @@ public interface BarbarianAssaultConfig extends Config
keyName = "showHpCountMessage", keyName = "showHpCountMessage",
name = "Show count of Hp healed as healer.", name = "Show count of Hp healed as healer.",
description = "Display healed count as healer after each wave", description = "Display healed count as healer after each wave",
position = 2 position = 4
) )
default boolean showHpCount() { return false; } default boolean showHpCount() { return false; }
@@ -75,7 +76,7 @@ public interface BarbarianAssaultConfig extends Config
keyName = "showHpCountOverlay", keyName = "showHpCountOverlay",
name = "Overlay of Hp counted", name = "Overlay of Hp counted",
description = "Display current healed count as healer", description = "Display current healed count as healer",
position = 3 position = 5
) )
default boolean showHpCountOverlay() { return false; } default boolean showHpCountOverlay() { return false; }
@@ -83,18 +84,15 @@ public interface BarbarianAssaultConfig extends Config
keyName = "highlightCollectorEggs", keyName = "highlightCollectorEggs",
name = "Highlight collector eggs", name = "Highlight collector eggs",
description = "Highlight called egg colors", description = "Highlight called egg colors",
position = 4 position = 6
) )
default boolean highlightCollectorEggs() default boolean highlightCollectorEggs() { return false; }
{
return false;
}
@ConfigItem( @ConfigItem(
keyName = "showTotalRewards", keyName = "showTotalRewards",
name = "Summarize total reward points", name = "Summarize total reward points",
description = "Displays total eggs/healed hp and missed attacks/lost runners", description = "Displays total eggs/healed hp and missed attacks/lost runners",
position = 5 position = 7
) )
default boolean showTotalRewards(){ return false; }; default boolean showTotalRewards(){ return false; };
@@ -102,14 +100,37 @@ public interface BarbarianAssaultConfig extends Config
keyName = "showSummaryOfPoints", keyName = "showSummaryOfPoints",
name = "Display summary of advanced points", name = "Display summary of advanced points",
description = "Gives summary of advanced points breakdown in chat log", description = "Gives summary of advanced points breakdown in chat log",
position = 7 position = 8
) )
default boolean showSummaryOfPoints() { return false; }; default boolean showSummaryOfPoints() { return false; };
@ConfigItem( @ConfigItem(
keyName = "wrongPoisonFoodTextColor", keyName = "wrongPoisonFoodTextColor",
name = "Change healer wrong poison pack color", name = "Change healer wrong poison pack color",
description = "Change healer wrong poison pack color", description = "Change healer wrong poison pack color",
position = 8 position = 9
) )
default Color wrongPoisonFoodTextColor() { return Color.BLACK;} default Color wrongPoisonFoodTextColor() { return Color.BLACK;}
@ConfigItem(
keyName = "highlightItems",
name = "Highlight called poison/bait",
description = "Highlights the poison or bait that was called by your teammate",
position = 10
)
default boolean highlightItems()
{
return false;
}
@ConfigItem(
keyName = "highlightColor",
name = "Highlight color",
description = "Configures the color to highlight the called poison/bait",
position = 11
)
default Color highlightColor()
{
return Color.GREEN;
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@ import java.awt.Polygon;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Stroke; import java.awt.Stroke;
import java.util.Map; import java.util.Map;
import java.awt.image.BufferedImage;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -44,12 +45,17 @@ import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayLayer;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.util.ImageUtil;
class BarbarianAssaultOverlay extends Overlay class BarbarianAssaultOverlay extends Overlay
{ {
@@ -60,6 +66,7 @@ class BarbarianAssaultOverlay extends Overlay
private static final int OFFSET_Z = 20; private static final int OFFSET_Z = 20;
private final Client client; private final Client client;
private final ItemManager itemManager;
private final BarbarianAssaultPlugin plugin; private final BarbarianAssaultPlugin plugin;
private final BarbarianAssaultConfig config; private final BarbarianAssaultConfig config;
@@ -67,13 +74,15 @@ class BarbarianAssaultOverlay extends Overlay
@Setter @Setter
private Round currentRound; private Round currentRound;
@Inject @Inject
private BarbarianAssaultOverlay(Client client, BarbarianAssaultPlugin plugin, BarbarianAssaultConfig config) private BarbarianAssaultOverlay(Client client, ItemManager itemManager, BarbarianAssaultPlugin plugin, BarbarianAssaultConfig config)
{ {
super(plugin); super(plugin);
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_WIDGETS); setLayer(OverlayLayer.ABOVE_WIDGETS);
this.client = client; this.client = client;
this.itemManager = itemManager;
this.plugin = plugin; this.plugin = plugin;
this.config = config; this.config = config;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "B.A. overlay")); getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "B.A. overlay"));
@@ -115,21 +124,38 @@ class BarbarianAssaultOverlay extends Overlay
graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null); graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null);
} }
if (role == Role.COLLECTOR && config.highlightCollectorEggs()) if (role == Role.COLLECTOR && config.highlightCollectorEggs()) {
{
String heardCall = plugin.getCollectorHeardCall(); String heardCall = plugin.getCollectorHeardCall();
Color highlightColor = BarbarianAssaultPlugin.getEggColor(heardCall); Color highlightColor = BarbarianAssaultPlugin.getEggColor(heardCall);
Map<WorldPoint, Integer> calledEggMap = plugin.getCalledEggMap(); Map<WorldPoint, Integer> calledEggMap = plugin.getCalledEggMap();
Map<WorldPoint, Integer> yellowEggMap = plugin.getYellowEggs(); Map<WorldPoint, Integer> yellowEggMap = plugin.getYellowEggs();
if (calledEggMap != null) if (calledEggMap != null) {
{
renderEggLocations(graphics, calledEggMap, highlightColor); renderEggLocations(graphics, calledEggMap, highlightColor);
} }
// Always show yellow eggs // Always show yellow eggs
renderEggLocations(graphics, yellowEggMap, Color.YELLOW); renderEggLocations(graphics, yellowEggMap, Color.YELLOW);
} }
Widget inventory = client.getWidget(WidgetInfo.INVENTORY);
if (config.highlightItems() && inventory != null && !inventory.isHidden() && ((role == Role.DEFENDER || role == Role.HEALER))) {
int listenItemId = plugin.getListenItemId(role.getListen());
if (listenItemId != -1) {
Color color = config.highlightColor();
BufferedImage highlight = ImageUtil.fillImage(itemManager.getImage(listenItemId), new Color(color.getRed(), color.getGreen(), color.getBlue(), 150));
for (WidgetItem item : inventory.getWidgetItems())
{
if (item.getId() == listenItemId)
{
OverlayUtil.renderImageLocation(graphics, item.getCanvasLocation(), highlight);
}
}
}
}
if (role == Role.HEALER) if (role == Role.HEALER)
{ {
for (HealerTeam teammate : HealerTeam.values()) for (HealerTeam teammate : HealerTeam.values())
@@ -156,9 +182,22 @@ class BarbarianAssaultOverlay extends Overlay
graphics.fillRect(x, y, filledWidth, HEALTH_BAR_HEIGHT); graphics.fillRect(x, y, filledWidth, HEALTH_BAR_HEIGHT);
} }
} }
return null; return null;
} }
private static int getBarWidth(int base, int current, int size)
{
final double ratio = (double) current / base;
if (ratio >= 1)
{
return size;
}
return (int) Math.round(ratio * size);
}
private void renderEggLocations(Graphics2D graphics, Map<WorldPoint, Integer> eggMap, Color color) private void renderEggLocations(Graphics2D graphics, Map<WorldPoint, Integer> eggMap, Color color)
{ {
Player player = client.getLocalPlayer(); Player player = client.getLocalPlayer();
@@ -201,16 +240,4 @@ class BarbarianAssaultOverlay extends Overlay
graphics.setStroke(originalStroke); graphics.setStroke(originalStroke);
} }
private static int getBarWidth(int base, int current, int size)
{
final double ratio = (double) current / base;
if (ratio >= 1)
{
return size;
}
return (int) Math.round(ratio * size);
}
} }

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -43,12 +42,14 @@ import net.runelite.api.Client;
import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.EquipmentInventorySlot;
import net.runelite.api.InventoryID; import net.runelite.api.InventoryID;
import net.runelite.api.Item; import net.runelite.api.Item;
import net.runelite.api.GameState;
import net.runelite.api.ItemID; import net.runelite.api.ItemID;
import net.runelite.api.Varbits; import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded; import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetInfo;
@@ -60,6 +61,7 @@ import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.FontManager; import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
@@ -71,9 +73,10 @@ import lombok.extern.slf4j.Slf4j;
@PluginDescriptor( @PluginDescriptor(
name = "Barbarian Assault", name = "Barbarian Assault+",
description = "Show a timer to the next call change and game/wave duration in chat.", description = "Custom barbarian assault plugin, use along with BA Tools",
tags = {"minigame", "overlay", "timer"} tags = {"minigame", "overlay", "timer"},
type = PluginType.PVM // don't remove this, added this because our barbarian assault plugin is big time modified
) )
public class BarbarianAssaultPlugin extends Plugin public class BarbarianAssaultPlugin extends Plugin
{ {
@@ -95,35 +98,27 @@ public class BarbarianAssaultPlugin extends Plugin
private int totalHpHealed = 0; private int totalHpHealed = 0;
private boolean hasAnnounced; private boolean hasAnnounced;
private int[] pointsList;
String[] descriptions = {"Runners: ",
"Hitpoints: ",
"Wrong heal packs: ",
"Eggs: ",
"Failed attacks: ",
"Honour Points: "};
private Font font; private Font font;
private Image clockImage; private final Image clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png");
private int inGameBit = 0; private int inGameBit = 0;
private String currentWave = START_WAVE; private String currentWave = START_WAVE;
private GameTimer gameTime; private GameTimer gameTime;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> redEggs; private final HashMap<WorldPoint, Integer> redEggs = new HashMap<>();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> greenEggs; private final HashMap<WorldPoint, Integer> greenEggs = new HashMap<>();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> blueEggs; private final HashMap<WorldPoint, Integer> blueEggs = new HashMap<>();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> yellowEggs; private final HashMap<WorldPoint, Integer> yellowEggs = new HashMap<>();
@Inject @Inject
@Getter
private Client client; private Client client;
@Inject @Inject
@@ -138,33 +133,45 @@ public class BarbarianAssaultPlugin extends Plugin
@Inject @Inject
private BarbarianAssaultOverlay overlay; private BarbarianAssaultOverlay overlay;
private final ImmutableList<WidgetInfo> WIDGETS = ImmutableList.of(
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS,
WidgetInfo.BA_RUNNERS_PASSED,
WidgetInfo.BA_EGGS_COLLECTED,
WidgetInfo.BA_HITPOINTS_REPLENISHED,
WidgetInfo.BA_WRONG_POISON_PACKS,
WidgetInfo.BA_HONOUR_POINTS_REWARD
);
private final ImmutableList<WidgetInfo> POINTSWIDGETS = ImmutableList.of(
//base
WidgetInfo.BA_BASE_POINTS,
//att
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS,
WidgetInfo.BA_RANGERS_KILLED,
WidgetInfo.BA_FIGHTERS_KILLED,
//def
WidgetInfo.BA_RUNNERS_PASSED_POINTS,
WidgetInfo.BA_RUNNERS_KILLED,
//coll
WidgetInfo.BA_EGGS_COLLECTED_POINTS,
//heal
WidgetInfo.BA_HEALERS_KILLED,
WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS,
WidgetInfo.BA_WRONG_POISON_PACKS_POINTS
);
@Provides @Provides
BarbarianAssaultConfig provideConfig(ConfigManager configManager) BarbarianAssaultConfig provideConfig(ConfigManager configManager)
{ {
return configManager.getConfig(BarbarianAssaultConfig.class); return configManager.getConfig(BarbarianAssaultConfig.class);
} }
private static final ImmutableList<WidgetInfo> WIDGETS = ImmutableList.of( private Game game;
WidgetInfo.BA_RUNNERS_PASSED, private Wave wave;
WidgetInfo.BA_HITPOINTS_REPLENISHED,
WidgetInfo.BA_WRONG_POISON_PACKS,
WidgetInfo.BA_EGGS_COLLECTED,
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS,
WidgetInfo.BA_HONOUR_POINTS_REWARD
);
@Override @Override
protected void startUp() throws Exception protected void startUp() throws Exception
{ {
overlayManager.add(overlay); overlayManager.add(overlay);
font = FontManager.getRunescapeFont() font = FontManager.getRunescapeFont()
.deriveFont(Font.BOLD, 24); .deriveFont(Font.BOLD, 24);
clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png");
redEggs = new HashMap<>();
greenEggs = new HashMap<>();
blueEggs = new HashMap<>();
yellowEggs = new HashMap<>();
pointsList = new int[6];
} }
@Override @Override
@@ -178,6 +185,16 @@ public class BarbarianAssaultPlugin extends Plugin
positiveEggCount = 0; positiveEggCount = 0;
wrongEggs = 0; wrongEggs = 0;
HpHealed = 0; HpHealed = 0;
clearAllEggMaps();
}
@Subscribe
public void onGameStateChanged(final GameStateChanged event)
{
if (event.getGameState() == GameState.LOADING)
{
clearAllEggMaps();
}
} }
@Subscribe @Subscribe
@@ -185,25 +202,25 @@ public class BarbarianAssaultPlugin extends Plugin
{ {
if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID)
{ {
wave = new Wave(client);
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null) if (rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null)
{ {
if (config.waveTimes()) if (config.waveTimes())
announceTime("Game finished, duration: ", gameTime.getTime(false)); announceTime("Game finished, duration: ", gameTime.getTime(false));
if (config.showTotalRewards()) if (config.showTotalRewards())
announceSomething("Game Summary: " + "Total Runners: " + pointsList[0] {
+ "; Total Hp Replenished: " + pointsList[1] announceSomething(game.getGameSummary());
+ "; Total Wrong Heal Packs: " + pointsList[2] }
+ "; Total Eggs: " + pointsList[3]
+ "; Total Failed attacks: " + pointsList[4]
+ "; Total Honour Points: " + (80 + pointsList[5]));
} }
Widget pointsWidget = client.getWidget(WidgetInfo.BA_RUNNERS_PASSED); Widget pointsWidget = client.getWidget(WidgetInfo.BA_RUNNERS_PASSED);
if (!rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && pointsWidget != null if (!rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && pointsWidget != null
&& config.showSummaryOfPoints() && !hasAnnounced && client.getVar(Varbits.IN_GAME_BA) == 0) && config.showSummaryOfPoints() && !hasAnnounced && client.getVar(Varbits.IN_GAME_BA) == 0)
{ {
announceSomething("Wave Points Summary: " + giveSummaryOfPoints()); wave.setWaveAmounts();
hasAnnounced = true; wave.setWavePoints();
game.getWaves().add(wave);
announceSomething(wave.getWaveSummary());
} }
} }
} }
@@ -211,6 +228,27 @@ public class BarbarianAssaultPlugin extends Plugin
@Subscribe @Subscribe
public void onChatMessage(ChatMessage chatMessage) public void onChatMessage(ChatMessage chatMessage)
{ {
if (chatMessage.getMessage().toLowerCase().contains("testing"))
{
ArrayList<Wave> waves = new ArrayList<>();
for (int i = 0; i < 1; i++)
{
Wave wave1 = new Wave(client);
int[] amounts = {4, 0, 30, 10, 1, 38};
int[] points = {-3, -2, 6, -4, -8, -11};
int[] otherPoints = {38, 35, 33, 30};
wave1.setWaveAmounts(amounts);
wave1.setWavePoints(points, otherPoints);
waves.add(wave1);
announceSomething(wave1.getWaveSummary());
}
Game game1 = new Game(client, waves);
announceSomething(game1.getGameSummary());
}
if (chatMessage.getMessage().toLowerCase().startsWith("wave points"))
{
hasAnnounced = true;
}
if (!chatMessage.getType().equals(ChatMessageType.GAMEMESSAGE)) if (!chatMessage.getType().equals(ChatMessageType.GAMEMESSAGE))
{ {
return; return;
@@ -235,7 +273,7 @@ public class BarbarianAssaultPlugin extends Plugin
gameTime = new GameTimer(); gameTime = new GameTimer();
totalHpHealed = 0; totalHpHealed = 0;
totalCollectedEggCount = 0; totalCollectedEggCount = 0;
pointsList = new int[]{0,0,0,0,0,0}; game = new Game(client);
} }
else if (gameTime != null) else if (gameTime != null)
{ {
@@ -429,41 +467,17 @@ public class BarbarianAssaultPlugin extends Plugin
} }
} }
private void announceSomething(String something) private void announceSomething(final ChatMessageBuilder chatMessage)
{ {
final String chatMessage = new ChatMessageBuilder()
.append(something)
.build();
chatMessageManager.queue(QueuedMessage.builder() chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.CONSOLE) .type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(chatMessage) .runeLiteFormattedMessage(chatMessage.build())
.build()); .build());
} }
private String giveSummaryOfPoints()
{
StringBuilder message = new StringBuilder();
for (int i = 0; i < WIDGETS.size(); i++)
{
Widget w = client.getWidget(WIDGETS.get(i));
if (w != null && !w.getText().equals(""))
{
pointsList[i] += Integer.parseInt(w.getText());
}
else
{
log.info("widget null");
}
message.append(descriptions[i])
.append(Integer.parseInt(w.getText()))
.append("; ");
}
return message.toString();
}
String getCollectorHeardCall() String getCollectorHeardCall()
{ {
Widget widget = client.getWidget(WidgetInfo.BA_COLL_HEARD_TEXT); Widget widget = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT);
String call = null; String call = null;
if (widget != null) if (widget != null)
@@ -589,6 +603,14 @@ public class BarbarianAssaultPlugin extends Plugin
return (tile.getWorldLocation().equals(local.getWorldLocation())); return (tile.getWorldLocation().equals(local.getWorldLocation()));
} }
private void clearAllEggMaps()
{
redEggs.clear();
greenEggs.clear();
blueEggs.clear();
yellowEggs.clear();
}
public Font getFont() public Font getFont()
{ {
return font; return font;
@@ -598,4 +620,30 @@ public class BarbarianAssaultPlugin extends Plugin
{ {
return clockImage; return clockImage;
} }
public int getListenItemId(WidgetInfo listenInfo)
{
Widget listenWidget = client.getWidget(listenInfo);
if (listenWidget != null)
{
switch (listenWidget.getText())
{
case "Tofu":
return ItemID.TOFU;
case "Crackers":
return ItemID.CRACKERS;
case "Worms":
return ItemID.WORMS;
case "Pois. Worms":
return ItemID.POISONED_WORMS;
case "Pois. Tofu":
return ItemID.POISONED_TOFU;
case "Pois. Meat":
return ItemID.POISONED_MEAT;
}
}
return -1;
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.barbarianassault;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.chat.ChatColorType;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.eventbus.Subscribe;
import java.util.ArrayList;
public class Game
{
@Getter
private Client client;
@Getter
private String currentWave;
@Getter
private ArrayList<Wave> waves = new ArrayList<>();
private String[] totalDescriptions = {
"A: ",
"; D: ",
"; C: ",
"; Vial: ",
"; H packs: ",
"; Total: "};
private String[] otherPointsDescriptions = {
" A: ",
"; D: ",
"; C: ",
"; H: "
};
private int[] totalPoints = new int[6];
private int[] totalAmounts = new int[6];
private int[] otherRolesPoints = new int[4];
Game(Client client)
{
this.client = client;
}
Game(Client client, ArrayList<Wave> waves)
{
this.client = client;
this.waves = waves;
}
@Subscribe
public void onChatMessage(ChatMessage chatMessage)
{
if (chatMessage.getMessage().startsWith("---- Wave:"))
{
String[] tempMessage = chatMessage.getMessage().split(" ");
currentWave = tempMessage[2];
String[] temp = currentWave.split(" ");
}
if (currentWave.equals("1"))
{
waves = null;
totalPoints = new int[6];
totalAmounts = new int[6];
}
}
ChatMessageBuilder getGameSummary()
{
int[] amountsList;
int[] pointsList;
int[] otherRolesPointsList;
ChatMessageBuilder message = new ChatMessageBuilder();
message.append("Round points: ");
for (Wave w : waves)
{
amountsList = w.getWaveAmounts();
pointsList = w.getWavePoints();
otherRolesPointsList = w.getOtherRolesPointsList();
for (int j = 0; j < totalAmounts.length; j++) {
totalAmounts[j] += amountsList[j];
}
for (int k = 0; k < totalPoints.length; k++) {
totalPoints[k] += pointsList[k];
}
for (int z = 0; z < otherRolesPoints.length; z++) {
otherRolesPoints[z] += otherRolesPointsList[z];
}
}
for (int i = 0; i < otherRolesPoints.length; i++)
{
otherRolesPoints[i] += 80;
}
totalAmounts[5] += 80;
for (int i = 0; i < totalDescriptions.length; i++)
{
if (i != 4)
{
message.append(totalDescriptions[i]);
message.append(String.valueOf(totalAmounts[i]));
message.append("(");
if (totalPoints[i] < 0)
{
message.append(ChatColorType.HIGHLIGHT);
message.append(String.valueOf(totalPoints[i]));
message.append(ChatColorType.NORMAL);
}
else
{
message.append(String.valueOf(totalPoints[i]));
}
message.append(")");
}
}
message.append(System.getProperty("line.separator"));
message.append("All roles points this game: ");
for(int i = 0; i < otherPointsDescriptions.length; i++)
{
message.append(otherPointsDescriptions[i]);
message.append(String.valueOf(otherRolesPoints[i]));
}
return message;
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,7 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import net.runelite.api.Constants;
class GameTimer class GameTimer
{ {
@@ -45,7 +46,7 @@ class GameTimer
} }
else else
{ {
elapsed = Duration.between(startTime, now).minusMillis(600); elapsed = Duration.between(startTime, now).minusMillis(Constants.GAME_TICK_LENGTH);
} }
return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds())); return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds()));

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@@ -29,6 +29,7 @@ import java.time.Instant;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.runelite.api.Constants;
class Round class Round
{ {
@@ -52,7 +53,7 @@ class Round
public Round(Role role) public Round(Role role)
{ {
this.roundRole = role; this.roundRole = role;
this.roundStartTime = Instant.now().plusMillis(1200); this.roundStartTime = Instant.now().plusMillis(2 * Constants.GAME_TICK_LENGTH);
} }
public long getRoundTime() public long getRoundTime()

View File

@@ -0,0 +1,226 @@
/*
* Copyright (c) 2018, https://runelitepl.us
* 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.barbarianassault;
import com.google.common.collect.ImmutableList;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.chat.ChatMessageManager;
import javax.inject.Inject;
import java.awt.*;
class Wave
{
@Getter
private Client client;
private final ImmutableList<WidgetInfo> WIDGETS = ImmutableList.of(
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS,
WidgetInfo.BA_RUNNERS_PASSED,
WidgetInfo.BA_EGGS_COLLECTED,
WidgetInfo.BA_HITPOINTS_REPLENISHED,
WidgetInfo.BA_WRONG_POISON_PACKS,
WidgetInfo.BA_HONOUR_POINTS_REWARD
);
private final ImmutableList<WidgetInfo> POINTSWIDGETS = ImmutableList.of(
//base
WidgetInfo.BA_BASE_POINTS,
//att
WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS,
WidgetInfo.BA_RANGERS_KILLED,
WidgetInfo.BA_FIGHTERS_KILLED,
//def
WidgetInfo.BA_RUNNERS_PASSED_POINTS,
WidgetInfo.BA_RUNNERS_KILLED,
//coll
WidgetInfo.BA_EGGS_COLLECTED_POINTS,
//heal
WidgetInfo.BA_HEALERS_KILLED,
WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS,
WidgetInfo.BA_WRONG_POISON_PACKS_POINTS
);
private int[] amountsList = new int[6];
private int[] allPointsList = new int[10];
private int[] importantPointsList = new int[6];
private int[] otherRolesPointsList = new int[4];
private String[] descriptions = {
" A: ",
" D: ",
" C: ",
" Vial: ",
" H packs: ",
" Total: "};
private String[] otherPointsDescriptions = {
" A: ",
" D: ",
" C: ",
" H: "
};
Wave(Client client)
{
this.client = client;
}
int[] getOtherRolesPointsList()
{
return otherRolesPointsList;
}
int[] getWaveAmounts()
{
return amountsList;
}
int[] getWavePoints()
{
return importantPointsList;
}
void setWaveAmounts(int[] amounts)
{
for (int i = 0; i < amounts.length; i++)
{
amountsList[i] = amounts[i];
}
}
void setWavePoints(int[] points, int[] otherRolesPoints)
{
for (int i = 0; i < points.length; i++)
{
importantPointsList[i] = points[i];
}
for (int i = 0; i < otherRolesPoints.length; i++)
{
otherRolesPointsList[i] = otherRolesPoints[i];
}
}
void setWaveAmounts()
{
for (int i = 0; i < WIDGETS.size(); i++)
{
Widget w = client.getWidget(WIDGETS.get(i));
if (w != null)
{
amountsList[i] = Integer.parseInt(w.getText());
}
}
}
void setWavePoints()
{
for (int i = 0; i < POINTSWIDGETS.size(); i++)
{
Widget w = client.getWidget(POINTSWIDGETS.get(i));
allPointsList[i] = Integer.parseInt(w.getText());
switch (i)
{
case 1:
importantPointsList[0] += allPointsList[i];
break;
case 4:
importantPointsList[1] += allPointsList[i];
break;
case 6:
importantPointsList[2] += allPointsList[i];
break;
case 8:
case 9:
importantPointsList[3] += allPointsList[i];
break;
default:
break;
}
}
importantPointsList[5] = 0;
for (int i = 0; i < importantPointsList.length-1; i++)
{
importantPointsList[5] += importantPointsList[i];
}
for (int i = 0; i < POINTSWIDGETS.size(); i++)
{
Widget w = client.getWidget(POINTSWIDGETS.get(i));
switch (i)
{
case 0:
otherRolesPointsList[0] += Integer.parseInt(w.getText());
otherRolesPointsList[1] += Integer.parseInt(w.getText());
otherRolesPointsList[2] += Integer.parseInt(w.getText());
otherRolesPointsList[3] += Integer.parseInt(w.getText());
break;
case 1:
case 2:
case 3:
otherRolesPointsList[0] += Integer.parseInt(w.getText());
break;
case 4:
case 5:
otherRolesPointsList[1] += Integer.parseInt(w.getText());
break;
case 6:
otherRolesPointsList[2] += Integer.parseInt(w.getText());
break;
case 7:
case 8:
case 9:
otherRolesPointsList[3] += Integer.parseInt(w.getText());
break;
default:
break;
}
}
}
ChatMessageBuilder getWaveSummary()
{
ChatMessageBuilder message = new ChatMessageBuilder();
message.append("Wave points:");
for(int i = 0; i < descriptions.length; i++)
{
if (i != 4)
{
message.append(descriptions[i]);
message.append(String.valueOf(amountsList[i]));
message.append("(");
if (importantPointsList[i] < 0)
{
message.append(Color.RED, String.valueOf(importantPointsList[i]));
}
else
{
message.append(String.valueOf(importantPointsList[i]));
}
message.append(")");
}
}
message.append(System.getProperty("line.separator"));
message.append("All roles points this wave: ");
for(int i = 0; i < otherPointsDescriptions.length; i++)
{
message.append(otherPointsDescriptions[i]);
message.append(String.valueOf(otherRolesPointsList[i]));
}
return message;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

View File

@@ -97,4 +97,15 @@ public interface BarrowsConfig extends Config
{ {
return true; return true;
} }
@ConfigItem(
keyName = "showPrayerDrainTimer",
name = "Show Prayer Drain Timer",
description = "Configure whether or not a countdown until the next prayer drain is displayed",
position = 6
)
default boolean showPrayerDrainTimer()
{
return true;
}
} }

View File

@@ -42,6 +42,7 @@ import net.runelite.api.ItemContainer;
import net.runelite.api.NullObjectID; import net.runelite.api.NullObjectID;
import net.runelite.api.ObjectID; import net.runelite.api.ObjectID;
import net.runelite.api.WallObject; import net.runelite.api.WallObject;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameObjectChanged; import net.runelite.api.events.GameObjectChanged;
import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameObjectSpawned;
@@ -60,9 +61,11 @@ import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.StackFormatter; import net.runelite.client.util.StackFormatter;
@PluginDescriptor( @PluginDescriptor(
@@ -89,12 +92,16 @@ public class BarrowsPlugin extends Plugin
WidgetInfo.BARROWS_PUZZLE_ANSWER3 WidgetInfo.BARROWS_PUZZLE_ANSWER3
); );
private static final int CRYPT_REGION_ID = 14231;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final Set<WallObject> walls = new HashSet<>(); private final Set<WallObject> walls = new HashSet<>();
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final Set<GameObject> ladders = new HashSet<>(); private final Set<GameObject> ladders = new HashSet<>();
private boolean wasInCrypt = false;
@Getter @Getter
private Widget puzzleAnswer; private Widget puzzleAnswer;
@@ -113,6 +120,12 @@ public class BarrowsPlugin extends Plugin
@Inject @Inject
private ItemManager itemManager; private ItemManager itemManager;
@Inject
private SpriteManager spriteManager;
@Inject
private InfoBoxManager infoBoxManager;
@Inject @Inject
private ChatMessageManager chatMessageManager; private ChatMessageManager chatMessageManager;
@@ -140,6 +153,8 @@ public class BarrowsPlugin extends Plugin
walls.clear(); walls.clear();
ladders.clear(); ladders.clear();
puzzleAnswer = null; puzzleAnswer = null;
wasInCrypt = false;
stopPrayerDrainTimer();
// Restore widgets // Restore widgets
final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL); final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL);
@@ -155,6 +170,15 @@ public class BarrowsPlugin extends Plugin
} }
} }
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals("barrows") && !config.showPrayerDrainTimer())
{
stopPrayerDrainTimer();
}
}
@Subscribe @Subscribe
public void onWallObjectSpawned(WallObjectSpawned event) public void onWallObjectSpawned(WallObjectSpawned event)
{ {
@@ -220,11 +244,24 @@ public class BarrowsPlugin extends Plugin
{ {
if (event.getGameState() == GameState.LOADING) if (event.getGameState() == GameState.LOADING)
{ {
wasInCrypt = isInCrypt();
// on region changes the tiles get set to null // on region changes the tiles get set to null
walls.clear(); walls.clear();
ladders.clear(); ladders.clear();
puzzleAnswer = null; puzzleAnswer = null;
} }
else if (event.getGameState() == GameState.LOGGED_IN)
{
boolean isInCrypt = isInCrypt();
if (wasInCrypt && !isInCrypt)
{
stopPrayerDrainTimer();
}
else if (!wasInCrypt && isInCrypt)
{
startPrayerDrainTimer();
}
}
} }
@Subscribe @Subscribe
@@ -271,4 +308,22 @@ public class BarrowsPlugin extends Plugin
} }
} }
} }
private void startPrayerDrainTimer()
{
if (config.showPrayerDrainTimer())
{
infoBoxManager.addInfoBox(new BarrowsPrayerDrainTimer(this, spriteManager));
}
}
private void stopPrayerDrainTimer()
{
infoBoxManager.removeIf(BarrowsPrayerDrainTimer.class::isInstance);
}
private boolean isInCrypt()
{
return client.getLocalPlayer().getWorldLocation().getRegionID() == CRYPT_REGION_ID;
}
} }

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2019, Ryan <progrs.site@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.barrows;
import java.awt.Color;
import java.time.Duration;
import java.time.Instant;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.infobox.InfoBox;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
class BarrowsPrayerDrainTimer extends InfoBox
{
private static final long PRAYER_DRAIN_INTERVAL_MS = 18200;
private final Instant startTime;
BarrowsPrayerDrainTimer(BarrowsPlugin plugin, SpriteManager spriteManager)
{
super(spriteManager.getSprite(SpriteID.TAB_PRAYER, 0), plugin);
setPriority(InfoBoxPriority.MED);
setTooltip("Prayer Drain");
startTime = Instant.now();
}
@Override
public String getText()
{
Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime());
int seconds = (int) (timeLeft.toMillis() / 1000L);
return String.format("0:%02d", seconds);
}
@Override
public Color getTextColor()
{
Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime());
//check if timer has 10% of time left
if (timeLeft.getSeconds() < (PRAYER_DRAIN_INTERVAL_MS / 1000 * .10))
{
return Color.RED.brighter();
}
return Color.WHITE;
}
private Instant getNextPrayerDrainTime()
{
Duration timePassed = Duration.between(startTime, Instant.now());
// Get how many intervals have passed so far and add one more to find the next prayer drain time
return startTime.plusMillis((timePassed.toMillis() / PRAYER_DRAIN_INTERVAL_MS + 1) * PRAYER_DRAIN_INTERVAL_MS);
}
}

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -145,7 +144,7 @@ public interface BAToolsConfig extends Config
@ConfigItem( @ConfigItem(
keyName = "attackStyles", keyName = "attackStyles",
name = "Attack Styles", name = "Attack Styles",
description = "asd" description = "Hide attack styles depending on weapon."
) )
default boolean attackStyles() default boolean attackStyles()
{ {
@@ -153,13 +152,24 @@ public interface BAToolsConfig extends Config
} }
@ConfigItem( @ConfigItem(
keyName = "tagging", keyName = "removeBA",
name = "Attack Tags", name = "*Barbarian Assault Helper*",
description = "asd" description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
) )
default boolean tagging() default boolean removeBA() { return true; }
{
return false; @ConfigItem(
} keyName = "removeWrongEggs",
name = "Remove wrong eggs - *Barbarian Assault Helper*",
description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
)
default boolean removeWrongEggs() { return false; }
@ConfigItem(
keyName = "removeWrongHealFood",
name = "Remove wrong Heal Food - *Barbarian Assault Helper*",
description = "Remove unnecessary menu options in Barbarian Assault depending on role<br>Examples: Remove attack options when not attacker<br>Remove take options when not collector"
)
default boolean removeHealWrongFood() { return false; }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -69,8 +69,11 @@ public class BAToolsOverlay extends Overlay
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
if(config.healerCodes()) if(!config.healerCodes())
{ {
return null;
}
for (Healer healer : plugin.getHealers().values()) for (Healer healer : plugin.getHealers().values())
{ {
NPCComposition composition = healer.getNpc().getComposition(); NPCComposition composition = healer.getNpc().getComposition();
@@ -87,16 +90,16 @@ public class BAToolsOverlay extends Overlay
composition = transformedComposition; composition = transformedComposition;
} }
} }
int timeLeft = healer.getLastFoodTime() - (int) Duration.between(plugin.getWave_start(), Instant.now()).getSeconds(); int timeLeft = healer.getLastFoodTime() - (int)Duration.between(plugin.getWave_start(), Instant.now()).getSeconds();
timeLeft = timeLeft < 1 ? 0 : timeLeft; timeLeft = timeLeft < 1 ? 0 : timeLeft;
if (healer.getFoodRemaining() > 1) if(healer.getFoodRemaining() > 1)
{ {
color = GREEN; color = GREEN;
} }
else if (healer.getFoodRemaining() == 1) else if(healer.getFoodRemaining() == 1)
{ {
if (timeLeft > 0) if(timeLeft > 0)
{ {
color = RED; color = RED;
} }
@@ -115,13 +118,8 @@ public class BAToolsOverlay extends Overlay
timeLeft); timeLeft);
OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
}
}
if(!config.eggBoi()) OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
{
return null;
} }
return null; return null;
} }

View File

@@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -36,10 +35,7 @@ import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -64,7 +60,6 @@ import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded; import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.events.WidgetHiddenChanged;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetInfo;
@@ -79,6 +74,7 @@ import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text; import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
@Slf4j @Slf4j
@PluginDescriptor( @PluginDescriptor(
@@ -167,14 +163,64 @@ public class BAToolsPlugin extends Plugin implements KeyListener
} }
@Subscribe @Subscribe
public void onWidgetHiddenChanged(WidgetHiddenChanged event) 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.setCount(tickNum);
if (config.defTimer())
{
//log.info("" + tickNum++);
tickNum++;
}
}
Widget weapon = client.getWidget(593, 1); Widget weapon = client.getWidget(593, 1);
if(config.attackStyles() if(config.attackStyles()
&& weapon!=null && weapon!=null
&& inGameBit == 1 && inGameBit == 1
&& (weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws")) && weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws")
&& client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT)!=null) && client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT)!=null)
{ {
String style = client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT).getText(); String style = client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT).getText();
@@ -225,77 +271,12 @@ public class BAToolsPlugin extends Plugin implements KeyListener
} }
else else
{
if(client.getWidget(WidgetInfo.COMBAT_STYLE_ONE)!=null)
{ {
client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false);
}
if(client.getWidget(WidgetInfo.COMBAT_STYLE_TWO)!=null)
{
client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false);
}
if(client.getWidget(WidgetInfo.COMBAT_STYLE_THREE)!=null)
{
client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false);
}
if(client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR)!=null)
{
client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(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.setCount(tickNum);
if (config.defTimer())
{
log.info("" + tickNum++);
}
}
if(config.prayerMetronome() && isAnyPrayerActive()) if(config.prayerMetronome() && isAnyPrayerActive())
{ {
@@ -373,7 +354,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener
{ {
int spawnNumber = healers.size(); int spawnNumber = healers.size();
healers.put(npc, new Healer(npc, spawnNumber, currentWave)); healers.put(npc, new Healer(npc, spawnNumber, currentWave));
log.info("spawn number: " + spawnNumber + " on wave " + currentWave); //log.info("spawn number: " + spawnNumber + " on wave " + currentWave);
} }
} }
} }
@@ -461,21 +442,124 @@ public class BAToolsPlugin extends Plugin implements KeyListener
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); 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()]));
}
final int itemId = event.getIdentifier();
String option = Text.removeTags(event.getOption()).toLowerCase(); String option = Text.removeTags(event.getOption()).toLowerCase();
String target = Text.removeTags(event.getTarget()).toLowerCase(); String target = Text.removeTags(event.getTarget()).toLowerCase();
if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder")) if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder"))
{ {
swap("quick-start", option, target, true); swap("quick-start", option, target, true);
} }
else if(config.removeBA() && client.getVar(Varbits.IN_GAME_BA) == 1 && !option.contains("tell-"))//if in barbarian assault and menu isnt from a horn
{
if(itemId == ItemID.LOGS && !target.contains("healing vial"))
{
if(client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)
remove(new String[]{"take", "light"}, target, true);
else//remove "Light" option (and "Take" option if not defender).
remove("light", target, true);
}
else if(option.equals("use"))
{
if (config.removeHealWrongFood()) {
Widget healer = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT);
if (healer != null) {
String item = target.split("-")[0].trim();
List<String> poison = Arrays.asList("poisoned tofu", "poisoned meat", "poisoned worms");
List<String> vials = Arrays.asList("healing vial", "healing vial(1)", "healing vial(2)", "healing vial(3)", "healing vial(4)");//"healing vial(4)"
if (poison.contains(item)) {//if item is a poison item
int calledPoison = 0;
switch (healer.getText())//choose which poison to hide the use/destroy option for
{
case "Pois. Tofu":
calledPoison = ItemID.POISONED_TOFU;
break;
case "Pois. Meat":
calledPoison = ItemID.POISONED_MEAT;
break;
case "Pois. Worms":
calledPoison = ItemID.POISONED_WORMS;
break;
}
System.out.println(target.equals(item));
if (target.equals(item))//if targeting the item itself
{
if (calledPoison != 0 && itemId != calledPoison)//if no call or chosen item is not the called one
{
remove(new String[]{"use", "destroy", "examine"}, target, true);//remove options
}
} else if (!target.contains("penance healer")) {
remove(option, target, true);
}
} else if (vials.contains(item))//if item is the healer's healing vial
{
if ((event.getTarget().contains("Penance Healer") || event.getTarget().contains("Penance Fighter") || event.getTarget().contains("Penance Ranger"))) if (!target.equals(item))//if target is not the vial itself
{
if (!target.contains("level") || target.contains("penance") || target.contains("queen spawn"))//if someone has "penance" or "queen spawn" in their name, gg...
{
remove(option, target, true);
}
}
}
}
}
}
else if(option.equals("attack") && client.getWidget(WidgetInfo.BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker
{//remove attack option from everything but queen spawns
remove(option, target, true);
}
else if((option.equals("fix") || (option.equals("block") && target.equals("penance cave"))) && client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)//if not defender
{//the check for option requires checking target as well because defensive attack style option is also called "block".
remove(option, target, true);
}
else if((option.equals("load")) && client.getWidget(WidgetInfo.BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options
{
remove(new String[]{option, "look-in"}, target, true);
}
else if(config.removeWrongEggs() && option.equals("take"))
{
Widget eggToColl = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT);
if(eggToColl != null)//if we're a collector
{
List<Integer> eggsToHide = new ArrayList<>();
eggsToHide.add(ItemID.HAMMER);
switch(eggToColl.getText())//choose which eggs to hide take option for
{
case "Red eggs":
eggsToHide.add(ItemID.BLUE_EGG);
eggsToHide.add(ItemID.GREEN_EGG);
break;
case "Blue eggs":
eggsToHide.add(ItemID.RED_EGG);
eggsToHide.add(ItemID.GREEN_EGG);
break;
case "Green eggs":
eggsToHide.add(ItemID.RED_EGG);
eggsToHide.add(ItemID.BLUE_EGG);
break;
}
if(eggsToHide.contains(itemId))
{
remove(option, target, true);//hide wrong eggs
}
}
else
{
List<Integer> defenderItems = Arrays.asList(ItemID.HAMMER, ItemID.TOFU, ItemID.CRACKERS, ItemID.WORMS);//logs are handled separately due to hiding "light" option too.
if(client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null || !defenderItems.contains(itemId))//if not defender, or item is not a defenderItem
{
remove(option, target, true);//hide everything except hammer/logs and bait if Defender
}
}
}
}
if (inGameBit == 1 && config.healerMenuOption() && event.getTarget().contains("Penance Healer"))
{ {
MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry[] menuEntries = client.getMenuEntries();
@@ -502,7 +586,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener
if (client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown) 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(" "); String[] currentCall = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT).getText().split(" ");
log.info("1 " + currentCall[0]); //log.info("1 " + currentCall[0]);
MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null; MenuEntry correctEgg = null;
entries.clear(); entries.clear();
@@ -525,22 +609,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
} }
if (client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT) != null && inGameBit == 1 && config.attackStyles() && shiftDown)
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getOption().contains("Walk here"))
{
entries.add(entry);
}
}
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) 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(" "); String[] currentCall = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT).getText().split(" ");
@@ -573,28 +641,27 @@ public class BAToolsPlugin extends Plugin implements KeyListener
@Subscribe @Subscribe
public void onMenuOptionClicked(MenuOptionClicked event) public void onMenuOptionClicked(MenuOptionClicked event)
{ {
if(config.tagging() && (event.getMenuTarget().contains("Penance Ranger") || event.getMenuTarget().contains("Penance Fighter"))) 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(); String target = event.getMenuTarget();
if (event.getMenuOption().contains("Attack"))
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()); foodPressed.put(event.getId(), Instant.now());
} }
log.info(target);
}
if (config.healerMenuOption() && event.getMenuTarget().contains("Penance Healer")) if (target.contains("->") && target.contains("Penance Healer"))
{
String target = event.getMenuTarget();
if (target.contains("->"))
{ {
foodPressed.put(event.getId(), Instant.now()); foodPressed.put(event.getId(), Instant.now());
} }
} }
}
@Subscribe @Subscribe
public void onConfigChanged(ConfigChanged event) public void onConfigChanged(ConfigChanged event)
{ {
@@ -630,6 +697,30 @@ public class BAToolsPlugin extends Plugin implements KeyListener
counter = null; counter = null;
} }
private void remove(String option, String target, boolean strict)
{
MenuEntry[] entries = client.getMenuEntries();
int idx = searchIndex(entries, option, target, strict);
if(idx >= 0 && entries[idx] != null)
{
entries = ArrayUtils.removeElement(entries, entries[idx]);
client.setMenuEntries(entries);
}
}
private void remove(String[] options, String target, boolean strict)
{
MenuEntry[] entries = client.getMenuEntries();
for(int i = 0; i < options.length; i++)
{
int idx = searchIndex(entries, options[i], target, strict);
if(idx >= 0 && entries[idx] != null)
entries = ArrayUtils.removeElement(entries, entries[idx]);
}
client.setMenuEntries(entries);
}
private void swap(String optionA, String optionB, String target, boolean strict) private void swap(String optionA, String optionB, String target, boolean strict)
{ {
MenuEntry[] entries = client.getMenuEntries(); MenuEntry[] entries = client.getMenuEntries();

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, https://runelitepl.us
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -24,9 +24,11 @@
*/ */
package net.runelite.client.plugins.batools; package net.runelite.client.plugins.batools;
import lombok.Getter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Getter
public enum Calls public enum Calls
{ {
//Attacker Calls //Attacker Calls
@@ -66,16 +68,6 @@ public enum Calls
this.option = option; this.option = option;
} }
public String getCall()
{
return call;
}
public String getOption()
{
return option;
}
public static String getOption(String call) public static String getOption(String call)
{ {
return CALL_MENU.get(call); return CALL_MENU.get(call);

View File

@@ -35,11 +35,11 @@ enum HealerCode
WAVETHREE(new int[] {1,6,2}, new int[] {0,0,0}, new int[] {0,0,0}), 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}), 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}), 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}), WAVESIX(new int[] {3,5,2,2,0,0}, new int[] {0,0,0,2,9,10}, new int[] {12,18,21,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}), WAVESEVEN(new int[] {3,7,1,1,0,0,0}, new int[] {2,0,1,1,2,4,10}, new int[] {0,21,0,0,30,45,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}), WAVEEIGHT(new int[] {1,9,1,1,0,0,0}, new int[] {1,0,1,1,2,2,10}, new int[] {0,0,0,0,33,42,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}), WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,0,1,1,2,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}); WAVETEN(new int[] {2,5,1,1,0,0,0}, new int[] {1,0,1,1,4,4,8}, new int[] {21,33,0,33,30,45,0});
@Getter @Getter

View File

@@ -35,6 +35,7 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.Skill; import net.runelite.api.Skill;
import net.runelite.api.events.BoostedLevelChanged; import net.runelite.api.events.BoostedLevelChanged;
@@ -411,6 +412,6 @@ public class BoostsPlugin extends Plugin
int getChangeTime(final int time) int getChangeTime(final int time)
{ {
final long diff = System.currentTimeMillis() - lastTickMillis; final long diff = System.currentTimeMillis() - lastTickMillis;
return time != -1 ? (int)(time * 0.6 - (diff / 1000d)) : time; return time != -1 ? (int)((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time;
} }
} }

View File

@@ -396,6 +396,11 @@ public class FishingPlugin extends Plugin
} }
long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds(); long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds();
if (timeLeft < 0)
{
timeLeft = 0;
}
int minutes = (int) timeLeft / 60; int minutes = (int) timeLeft / 60;
int seconds = (int) timeLeft % 60; int seconds = (int) timeLeft % 60;

View File

@@ -38,6 +38,7 @@ import net.runelite.api.Actor;
import net.runelite.api.AnimationID; import net.runelite.api.AnimationID;
import static net.runelite.api.AnimationID.*; import static net.runelite.api.AnimationID.*;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.GraphicID; import net.runelite.api.GraphicID;
import net.runelite.api.Hitsplat; import net.runelite.api.Hitsplat;
@@ -71,9 +72,10 @@ import net.runelite.client.util.PvPUtil;
public class IdleNotifierPlugin extends Plugin public class IdleNotifierPlugin extends Plugin
{ {
// This must be more than 500 client ticks (10 seconds) before you get AFK kicked // This must be more than 500 client ticks (10 seconds) before you get AFK kicked
private static final int LOGOUT_WARNING_CLIENT_TICKS = ((4 * 60) + 40) * 50;// 4 minutes and 40 seconds private static final int LOGOUT_WARNING_MILLIS = (4 * 60 + 40) * 1000; // 4 minutes and 40 seconds
private static final int COMBAT_WARNING_MILLIS = 19 * 60 * 1000; // 19 minutes private static final int COMBAT_WARNING_MILLIS = 19 * 60 * 1000; // 19 minutes
private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / 20; private static final int LOGOUT_WARNING_CLIENT_TICKS = LOGOUT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH;
private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH;
private static final int HIGHEST_MONSTER_ATTACK_SPEED = 8; // Except Scarab Mage, but they are with other monsters private static final int HIGHEST_MONSTER_ATTACK_SPEED = 8; // Except Scarab Mage, but they are with other monsters
private static final Duration SIX_HOUR_LOGOUT_WARNING_AFTER_DURATION = Duration.ofMinutes(340); private static final Duration SIX_HOUR_LOGOUT_WARNING_AFTER_DURATION = Duration.ofMinutes(340);

View File

@@ -36,6 +36,7 @@ import java.time.Instant;
import java.util.Locale; import java.util.Locale;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NPCComposition; import net.runelite.api.NPCComposition;
import net.runelite.api.Perspective; import net.runelite.api.Perspective;
@@ -57,9 +58,6 @@ public class NpcSceneOverlay extends Overlay
// a dark background // a dark background
private static final Color TEXT_COLOR = Color.WHITE; private static final Color TEXT_COLOR = Color.WHITE;
// Estimated time of a game tick in seconds
private static final double ESTIMATED_TICK_LENGTH = 0.6;
private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US);
static static
@@ -128,7 +126,7 @@ public class NpcSceneOverlay extends Overlay
} }
final Instant now = Instant.now(); final Instant now = Instant.now();
final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * ESTIMATED_TICK_LENGTH; final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * (Constants.GAME_TICK_LENGTH / 1000.0);
final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0; final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0;
final double timeLeft = Math.max(0.0, baseTick - sinceLast); final double timeLeft = Math.max(0.0, baseTick - sinceLast);
final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft); final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft);

View File

@@ -37,6 +37,7 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatMessageType; import net.runelite.api.ChatMessageType;
@@ -48,6 +49,7 @@ import net.runelite.api.Skill;
import net.runelite.api.SoundEffectID; import net.runelite.api.SoundEffectID;
import net.runelite.api.Tile; import net.runelite.api.Tile;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CommandExecuted;
import net.runelite.api.events.FocusChanged; import net.runelite.api.events.FocusChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.MenuOptionClicked;
@@ -120,6 +122,10 @@ public class PartyPlugin extends Plugin implements KeyListener
@Inject @Inject
private ChatMessageManager chatMessageManager; private ChatMessageManager chatMessageManager;
@Inject
@Named("developerMode")
boolean developerMode;
@Getter @Getter
private final Map<UUID, PartyData> partyDataMap = Collections.synchronizedMap(new HashMap<>()); private final Map<UUID, PartyData> partyDataMap = Collections.synchronizedMap(new HashMap<>());
@@ -448,6 +454,23 @@ public class PartyPlugin extends Plugin implements KeyListener
worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance); worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance);
} }
@Subscribe
public void onCommandExecuted(CommandExecuted commandExecuted)
{
if (!developerMode || !commandExecuted.getCommand().equals("partyinfo"))
{
return;
}
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyId()).build());
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local Party " + party.getLocalPartyId()).build());
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local ID " + party.getLocalMember().getMemberId()).build());
for (PartyMember partyMember : party.getMembers())
{
chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value(" " + partyMember.getName() + " " + partyMember.getMemberId()).build());
}
}
@Nullable @Nullable
PartyData getPartyData(final UUID uuid) PartyData getPartyData(final UUID uuid)
{ {

View File

@@ -39,6 +39,7 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor; import net.runelite.api.Actor;
import net.runelite.api.AnimationID; import net.runelite.api.AnimationID;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.DecorativeObject; import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject; import net.runelite.api.GameObject;
import net.runelite.api.GameState; import net.runelite.api.GameState;
@@ -74,7 +75,6 @@ public class PohPlugin extends Plugin
{ {
static final Set<Integer> BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212); static final Set<Integer> BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212);
static final Set<Integer> BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213); static final Set<Integer> BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213);
private static final double ESTIMATED_TICK_LENGTH = 0.6;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final Map<TileObject, Tile> pohObjects = new HashMap<>(); private final Map<TileObject, Tile> pohObjects = new HashMap<>();
@@ -243,7 +243,8 @@ public class PohPlugin extends Plugin
private static void updateBurner(IncenseBurner incenseBurner, int fmLevel) private static void updateBurner(IncenseBurner incenseBurner, int fmLevel)
{ {
incenseBurner.setCountdownTimer((200 + fmLevel) * ESTIMATED_TICK_LENGTH); final double tickLengthSeconds = Constants.GAME_TICK_LENGTH / 1000.0;
incenseBurner.setRandomTimer(fmLevel * ESTIMATED_TICK_LENGTH); incenseBurner.setCountdownTimer((200 + fmLevel) * tickLengthSeconds);
incenseBurner.setRandomTimer(fmLevel * tickLengthSeconds);
} }
} }

View File

@@ -35,6 +35,7 @@ import javax.inject.Inject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Setter; import lombok.Setter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.Point; import net.runelite.api.Point;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.Skill; import net.runelite.api.Skill;
@@ -50,7 +51,7 @@ import org.apache.commons.lang3.StringUtils;
class PrayerDoseOverlay extends Overlay class PrayerDoseOverlay extends Overlay
{ {
private static final float PULSE_TIME = 1200f; private static final float PULSE_TIME = 2f * Constants.GAME_TICK_LENGTH;
private static final Color START_COLOR = new Color(0, 255, 255); private static final Color START_COLOR = new Color(0, 255, 255);
private static final Color END_COLOR = new Color(0, 92, 92); private static final Color END_COLOR = new Color(0, 92, 92);

View File

@@ -32,6 +32,7 @@ import javax.inject.Inject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.InventoryID; import net.runelite.api.InventoryID;
import net.runelite.api.Item; import net.runelite.api.Item;
import net.runelite.api.ItemContainer; import net.runelite.api.ItemContainer;
@@ -268,7 +269,7 @@ public class PrayerPlugin extends Plugin
{ {
long timeSinceLastTick = Duration.between(startOfLastTick, Instant.now()).toMillis(); long timeSinceLastTick = Duration.between(startOfLastTick, Instant.now()).toMillis();
float tickProgress = (timeSinceLastTick % 600) / 600f; float tickProgress = (timeSinceLastTick % Constants.GAME_TICK_LENGTH) / (float) Constants.GAME_TICK_LENGTH;
return tickProgress * Math.PI; return tickProgress * Math.PI;
} }

View File

@@ -57,4 +57,14 @@ public interface RegenMeterConfig extends Config
{ {
return false; return false;
} }
@ConfigItem(
keyName = "notifyBeforeHpRegenDuration",
name = "Hitpoint Regen Notification (seconds)",
description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification."
)
default int getNotifyBeforeHpRegenSeconds()
{
return 0;
}
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 Abex * Copyright (c) 2019, Sean Dewar <https://github.com/seandewar>
* Copyright (c) 2018, Abex
* Copyright (c) 2018, Zimaya <https://github.com/Zimaya> * Copyright (c) 2018, Zimaya <https://github.com/Zimaya>
* Copyright (c) 2017, Adam <Adam@sigterm.info> * Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved. * All rights reserved.
@@ -30,6 +31,7 @@ import com.google.inject.Provides;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.Skill; import net.runelite.api.Skill;
@@ -37,6 +39,7 @@ import net.runelite.api.VarPlayer;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
@@ -46,7 +49,7 @@ import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor( @PluginDescriptor(
name = "Regeneration Meter", name = "Regeneration Meter",
description = "Track and show the hitpoints and special attack regeneration timers", description = "Track and show the hitpoints and special attack regeneration timers",
tags = {"combat", "health", "hitpoints", "special", "attack", "overlay"} tags = {"combat", "health", "hitpoints", "special", "attack", "overlay", "notifications"}
) )
public class RegenMeterPlugin extends Plugin public class RegenMeterPlugin extends Plugin
{ {
@@ -59,6 +62,9 @@ public class RegenMeterPlugin extends Plugin
@Inject @Inject
private OverlayManager overlayManager; private OverlayManager overlayManager;
@Inject
private Notifier notifier;
@Inject @Inject
private RegenMeterOverlay overlay; private RegenMeterOverlay overlay;
@@ -149,5 +155,18 @@ public class RegenMeterPlugin extends Plugin
// Show it going down // Show it going down
hitpointsPercentage = 1 - hitpointsPercentage; hitpointsPercentage = 1 - hitpointsPercentage;
} }
if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen))
{
notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!");
}
}
private boolean shouldNotifyHpRegenThisTick(int ticksPerHPRegen)
{
// if the configured duration lies between two ticks, choose the earlier tick
final int ticksBeforeHPRegen = ticksPerHPRegen - ticksSinceHPRegen;
final int notifyTick = (int) Math.ceil(config.getNotifyBeforeHpRegenSeconds() * 1000d / Constants.GAME_TICK_LENGTH);
return ticksBeforeHPRegen == notifyTick;
} }
} }

View File

@@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides; import com.google.inject.Provides;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.EquipmentInventorySlot;
import net.runelite.api.InventoryID; import net.runelite.api.InventoryID;
import net.runelite.api.Item; import net.runelite.api.Item;
@@ -171,7 +172,7 @@ public class RunEnergyPlugin extends Plugin
String getEstimatedRunTimeRemaining(boolean inSeconds) String getEstimatedRunTimeRemaining(boolean inSeconds)
{ {
// Calculate the amount of energy lost every 2 ticks (0.6 seconds). // Calculate the amount of energy lost every tick.
// Negative weight has the same depletion effect as 0 kg. // Negative weight has the same depletion effect as 0 kg.
final int effectiveWeight = Math.max(client.getWeight(), 0); final int effectiveWeight = Math.max(client.getWeight(), 0);
double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64; double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64;
@@ -182,7 +183,7 @@ public class RunEnergyPlugin extends Plugin
} }
// Calculate the number of seconds left // Calculate the number of seconds left
final double secondsLeft = (client.getEnergy() * 0.6) / lossRate; final double secondsLeft = (client.getEnergy() * Constants.GAME_TICK_LENGTH) / (lossRate * 1000.0);
// Return the text // Return the text
if (inSeconds) if (inSeconds)

View File

@@ -286,7 +286,7 @@ class XpInfoBox extends JPanel
static String htmlLabel(String key, int value) static String htmlLabel(String key, int value)
{ {
String valueStr = StackFormatter.quantityToRSDecimalStack(value); String valueStr = StackFormatter.quantityToRSDecimalStack(value, true);
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
} }
} }

View File

@@ -61,6 +61,14 @@ public class StackFormatter
DecimalFormatSymbols.getInstance(Locale.ENGLISH) DecimalFormatSymbols.getInstance(Locale.ENGLISH)
); );
/**
* A more precise decimal number formatter, outputting thousandths
*/
private static final NumberFormat PRECISE_DECIMAL_FORMATTER = new DecimalFormat(
"#,###.###",
DecimalFormatSymbols.getInstance(Locale.ENGLISH)
);
/** /**
* Convert a quantity to a nicely formatted stack size. * Convert a quantity to a nicely formatted stack size.
* See the StackFormatterTest to see expected output. * See the StackFormatterTest to see expected output.
@@ -152,6 +160,24 @@ public class StackFormatter
* with K after 100,000 and M after 10,000,000 * with K after 100,000 and M after 10,000,000
*/ */
public static String quantityToRSDecimalStack(int quantity) public static String quantityToRSDecimalStack(int quantity)
{
return quantityToRSDecimalStack(quantity, false);
}
/**
* Convert a quantity to stack size as it would
* appear in RuneScape. (with decimals)
* <p>
* This differs from quantityToRSStack in that it displays
* decimals. Ex: 27100 is 27.1k (not 27k)
* <p>
*
* @param quantity The quantity to convert.
* @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million.
* @return The stack size as it would appear in RS, with decimals,
* with K after 100,000 and M after 10,000,000
*/
public static String quantityToRSDecimalStack(int quantity, boolean precise)
{ {
String quantityStr = String.valueOf(quantity); String quantityStr = String.valueOf(quantity);
if (quantityStr.length() <= 4) if (quantityStr.length() <= 4)
@@ -160,7 +186,13 @@ public class StackFormatter
} }
int power = (int) Math.log10(quantity); int power = (int) Math.log10(quantity);
return DECIMAL_FORMATTER.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3];
// Output thousandths for values above a million
NumberFormat format = precise && power >= 6
? PRECISE_DECIMAL_FORMATTER
: DECIMAL_FORMATTER;
return format.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3];
} }
/** /**

View File

@@ -114,6 +114,13 @@ public class PartyService
@Subscribe @Subscribe
public void onUserJoin(final UserJoin message) public void onUserJoin(final UserJoin message)
{ {
if (!partyId.equals(message.getPartyId()))
{
// This can happen when a session is resumed server side after the client party
// changes when disconnected.
return;
}
final PartyMember partyMember = new PartyMember(message.getMemberId(), message.getName()); final PartyMember partyMember = new PartyMember(message.getMemberId(), message.getName());
members.add(partyMember); members.add(partyMember);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 343 B

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2019, Stephen <stepzhu@umich.edu>
* 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.smelting;
import com.google.inject.Guice;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.ChatMessage;
import net.runelite.client.ui.overlay.OverlayManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SmeltingPluginTest
{
private static final String SMELT_CANNONBALL = "You remove the cannonballs from the mould";
private static final String SMELT_BAR = "You retrieve a bar of steel.";
@Inject
SmeltingPlugin smeltingPlugin;
@Mock
@Bind
SmeltingConfig config;
@Mock
@Bind
SmeltingOverlay smeltingOverlay;
@Mock
@Bind
OverlayManager overlayManager;
@Before
public void before()
{
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
@Test
public void testCannonballs()
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_CANNONBALL, "", 0);
smeltingPlugin.onChatMessage(chatMessage);
SmeltingSession smeltingSession = smeltingPlugin.getSession();
assertNotNull(smeltingSession);
assertEquals(4, smeltingSession.getCannonBallsSmelted());
}
@Test
public void testBars()
{
ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_BAR, "", 0);
smeltingPlugin.onChatMessage(chatMessage);
SmeltingSession smeltingSession = smeltingPlugin.getSession();
assertNotNull(smeltingSession);
assertEquals(1, smeltingSession.getBarsSmelted());
}
}

View File

@@ -97,6 +97,31 @@ public class StackFormatterTest
assertEquals("-400B", StackFormatter.quantityToStackSize(-400_000_000_000L)); assertEquals("-400B", StackFormatter.quantityToStackSize(-400_000_000_000L));
} }
@Test
public void quantityToPreciseStackSize()
{
assertEquals("0", StackFormatter.quantityToRSDecimalStack(0));
assertEquals("8500", StackFormatter.quantityToRSDecimalStack(8_500, true));
assertEquals("10K", StackFormatter.quantityToRSDecimalStack(10_000, true));
assertEquals("21.7K", StackFormatter.quantityToRSDecimalStack(21_710, true));
assertEquals("100K", StackFormatter.quantityToRSDecimalStack(100_000, true));
assertEquals("100.3K", StackFormatter.quantityToRSDecimalStack(100_310, true));
assertEquals("1M", StackFormatter.quantityToRSDecimalStack(1_000_000, true));
assertEquals("8.45M", StackFormatter.quantityToRSDecimalStack(8_450_000, true));
assertEquals("8.451M", StackFormatter.quantityToRSDecimalStack(8_451_000, true));
assertEquals("10M", StackFormatter.quantityToRSDecimalStack(10_000_000, true));
assertEquals("12.8M", StackFormatter.quantityToRSDecimalStack(12_800_000, true));
assertEquals("12.85M", StackFormatter.quantityToRSDecimalStack(12_850_000, true));
assertEquals("12.851M", StackFormatter.quantityToRSDecimalStack(12_851_000, true));
assertEquals("100M", StackFormatter.quantityToRSDecimalStack(100_000_000, true));
assertEquals("250.1M", StackFormatter.quantityToRSDecimalStack(250_100_000, true));
assertEquals("250.151M", StackFormatter.quantityToRSDecimalStack(250_151_000, true));
assertEquals("1B", StackFormatter.quantityToRSDecimalStack(1_000_000_000, true));
assertEquals("1.5B", StackFormatter.quantityToRSDecimalStack(1500_000_000, true));
assertEquals("1.55B", StackFormatter.quantityToRSDecimalStack(1550_000_000, true));
assertEquals("2.147B", StackFormatter.quantityToRSDecimalStack(Integer.MAX_VALUE, true));
}
@Test @Test
public void stackSizeToQuantity() throws ParseException public void stackSizeToQuantity() throws ParseException
{ {