Add barbarian assault game duration timer (#4590)

Shows the wave duration and game duration: https://imgur.com/a/HGVeZ2z

Closes #1152
This commit is contained in:
Jacob McElroy
2018-09-21 14:50:46 +08:00
committed by Tomas Slusny
parent 76c9e47c91
commit ddd4188a02
6 changed files with 155 additions and 109 deletions

View File

@@ -79,6 +79,7 @@ public class WidgetID
public static final int BA_COLLECTOR_GROUP_ID = 486; public static final int BA_COLLECTOR_GROUP_ID = 486;
public static final int BA_DEFENDER_GROUP_ID = 487; public static final int BA_DEFENDER_GROUP_ID = 487;
public static final int BA_HEALER_GROUP_ID = 488; public static final int BA_HEALER_GROUP_ID = 488;
public static final int BA_REWARD_GROUP_ID = 497;
public static final int LEVEL_UP_GROUP_ID = 233; public static final int LEVEL_UP_GROUP_ID = 233;
public static final int DIALOG_SPRITE_GROUP_ID = 193; public static final int DIALOG_SPRITE_GROUP_ID = 193;
public static final int QUEST_COMPLETED_GROUP_ID = 277; public static final int QUEST_COMPLETED_GROUP_ID = 277;
@@ -521,6 +522,7 @@ public class WidgetID
static final int TO_CALL = 9; static final int TO_CALL = 9;
static final int ROLE_SPRITE = 10; static final int ROLE_SPRITE = 10;
static final int ROLE = 11; static final int ROLE = 11;
static final int REWARD_TEXT = 57;
} }
static class LevelUp static class LevelUp

View File

@@ -335,6 +335,8 @@ public enum WidgetInfo
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),
BA_REWARD_TEXT(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_TEXT),
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),
LEVEL_UP_LEVEL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.LEVEL), LEVEL_UP_LEVEL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.LEVEL),

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, Cameron <https://github.com/noremac201>
* 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
@@ -40,4 +41,14 @@ public interface BarbarianAssaultConfig extends Config
{ {
return true; return true;
} }
@ConfigItem(
keyName = "waveTimes",
name = "Show wave and game duration",
description = "Displays wave and game duration"
)
default boolean waveTimes()
{
return true;
}
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * Copyright (c) 2018, Cameron <https://github.com/noremac201>
* 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
@@ -28,18 +29,23 @@ import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.awt.Font; import java.awt.Font;
import java.awt.Image; import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.ChatMessageType; import net.runelite.api.ChatMessageType;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.ItemID; import net.runelite.api.ItemID;
import net.runelite.api.MenuEntry;
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.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.kit.KitType; import net.runelite.api.kit.KitType;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.chat.ChatColorType;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
@@ -49,22 +55,27 @@ import net.runelite.client.util.ImageUtil;
@PluginDescriptor( @PluginDescriptor(
name = "Barbarian Assault", name = "Barbarian Assault",
description = "Show a timer to the next call change", description = "Show a timer to the next call change and game/wave duration in chat.",
tags = {"minigame", "overlay"} tags = {"minigame", "overlay", "timer"}
) )
public class BarbarianAssaultPlugin extends Plugin public class BarbarianAssaultPlugin extends Plugin
{ {
private final List<MenuEntry> entries = new ArrayList<>(); private static final int BA_WAVE_NUM_INDEX = 2;
private static final String START_WAVE = "1";
private static final int BA_ALL_KILLED_INDEX = 4; private static final String ENDGAME_REWARD_NEEDLE_TEXT = "<br>5";
private Font font; private Font font;
private Image clockImage; private Image clockImage;
private int inGameBit = 0; private int inGameBit = 0;
private String currentWave = START_WAVE;
private GameTimer gameTime;
@Inject @Inject
private Client client; private Client client;
@Inject
private ChatMessageManager chatMessageManager;
@Inject @Inject
private OverlayManager overlayManager; private OverlayManager overlayManager;
@@ -94,15 +105,53 @@ public class BarbarianAssaultPlugin extends Plugin
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
overlayManager.remove(overlay); overlayManager.remove(overlay);
gameTime = null;
currentWave = START_WAVE;
inGameBit = 0;
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID)
{
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (config.waveTimes() && rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null)
{
announceTime("Game finished, duration: ", gameTime.getTime(false));
}
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (event.getType() == ChatMessageType.SERVER
&& event.getMessage().startsWith("---- Wave:"))
{
String[] message = event.getMessage().split(" ");
currentWave = message[BA_WAVE_NUM_INDEX];
if (currentWave.equals(START_WAVE))
{
gameTime = new GameTimer();
}
else if (gameTime != null)
{
gameTime.setWaveStartTime();
}
}
} }
@Subscribe @Subscribe
public void onGameTick(GameTick event) public void onGameTick(GameTick event)
{ {
if (client.getVar(Varbits.IN_GAME_BA) == 1 && if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null)
overlay.getCurrentRound() == null &&
client.getLocalPlayer() != null)
{ {
return;
}
switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE)) switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE))
{ {
case ItemID.ATTACKER_ICON: case ItemID.ATTACKER_ICON:
@@ -119,49 +168,41 @@ public class BarbarianAssaultPlugin extends Plugin
break; break;
} }
} }
}
@Subscribe @Subscribe
public void onVarbitChange(VarbitChanged event) public void onVarbitChange(VarbitChanged event)
{ {
int inGame = client.getVar(Varbits.IN_GAME_BA); int inGame = client.getVar(Varbits.IN_GAME_BA);
if (inGameBit != inGame && inGameBit == 1) if (inGameBit != inGame)
{
if (inGameBit == 1)
{ {
// end of game
overlay.setCurrentRound(null); overlay.setCurrentRound(null);
if (config.waveTimes() && gameTime != null)
{
announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true));
}
}
} }
inGameBit = inGame; inGameBit = inGame;
} }
@Subscribe private void announceTime(String preText, String time)
public void onMessageEvent(ChatMessage event)
{ {
if (event.getType() == ChatMessageType.SERVER final String chatMessage = new ChatMessageBuilder()
&& event.getMessage().startsWith("All of the Penance")) .append(ChatColorType.NORMAL)
{ .append(preText)
String[] message = event.getMessage().split(" "); .append(ChatColorType.HIGHLIGHT)
Round round = overlay.getCurrentRound(); .append(time)
if (round != null) .build();
{
switch (message[BA_ALL_KILLED_INDEX]) chatMessageManager.queue(QueuedMessage.builder()
{ .type(ChatMessageType.GAME)
case "Healers": .runeLiteFormattedMessage(chatMessage)
round.setHealersKilled(true); .build());
break;
case "Runners":
round.setRunnersKilled(true);
break;
case "Fighters":
round.setFightersKilled(true);
break;
case "Rangers":
round.setRangersKilled(true);
break;
}
}
}
} }
public Font getFont() public Font getFont()

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Cameron <https://github.com/noremac201> * 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
@@ -24,61 +24,51 @@
*/ */
package net.runelite.client.plugins.barbarianassault; package net.runelite.client.plugins.barbarianassault;
import java.util.HashMap; import java.time.Duration;
import java.util.Map; import java.time.Instant;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public enum Calls class GameTimer
{ {
//Attacker Calls final private Instant startTime = Instant.now();
RED_EGG("Red egg", "Tell-red"), private Instant prevWave = startTime;
GREEN_EGG("Green egg", "Tell-green"),
BLUE_EGG("Blue egg", "Tell-blue"),
//Collector Calls
CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"),
ACCURATE("Accurate/Field/Water", "Tell-accurate"),
AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"),
DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"),
//Healer Calls
TOFU("Tofu", "Tell-tofu"),
CRACKERS("Crackers", "Tell-crackers"),
WORMS("Worms", "Tell-worms"),
//Defender Calls
POIS_WORMS("Pois. Worms", "Tell-worms"),
POIS_TOFU("Pois. Tofu", "Tell-tofu"),
POIS_MEAT("Pois. Meat", "Tell-meat");
private final String call; String getTime(boolean waveTime)
private final String option;
private static final Map<String, String> CALL_MENU = new HashMap<>();
static
{ {
for (Calls s : values()) final Instant now = Instant.now();
final Duration elapsed;
if (waveTime)
{ {
CALL_MENU.put(s.getCall(), s.getOption()); elapsed = Duration.between(prevWave, now);
} }
else
{
elapsed = Duration.between(startTime, now).minusMillis(600);
} }
Calls(String call, String option) return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds()));
{
this.call = call;
this.option = option;
} }
public String getCall() void setWaveStartTime()
{ {
return call; prevWave = Instant.now();
} }
public String getOption() private static String formatTime(LocalTime time)
{ {
return option; if (time.getHour() > 0)
}
public static String getOption(String call)
{ {
return CALL_MENU.get(call); return time.format(DateTimeFormatter.ofPattern("HH:mm"));
}
else if (time.getMinute() > 9)
{
return time.format(DateTimeFormatter.ofPattern("mm:ss"));
}
else
{
return time.format(DateTimeFormatter.ofPattern("m:ss"));
}
} }
} }