kingdom: add notification message for favor and coffer value
This allows setting a configurable threshold where you will receive a message informing you your favor and/or coffer is low on login Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
@@ -387,9 +387,10 @@ public enum Varbits
|
|||||||
MULTICOMBAT_AREA(4605),
|
MULTICOMBAT_AREA(4605),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kingdom Management
|
* Kingdom of Miscellania Management
|
||||||
|
* Kingdom Approval is represented as a 7-bit unsigned integer; 127 corresponds to 100% approval
|
||||||
*/
|
*/
|
||||||
KINGDOM_FAVOR(72),
|
KINGDOM_APPROVAL(72),
|
||||||
KINGDOM_COFFER(74),
|
KINGDOM_COFFER(74),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Brandt Hill <https://github.com/BrandtHill>
|
||||||
|
* 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.kingdomofmiscellania;
|
||||||
|
|
||||||
|
import net.runelite.client.config.Config;
|
||||||
|
import net.runelite.client.config.ConfigGroup;
|
||||||
|
import net.runelite.client.config.ConfigItem;
|
||||||
|
import net.runelite.client.config.Range;
|
||||||
|
|
||||||
|
@ConfigGroup(KingdomConfig.CONFIG_GROUP_NAME)
|
||||||
|
public interface KingdomConfig extends Config
|
||||||
|
{
|
||||||
|
String CONFIG_GROUP_NAME = "kingdomofmiscellania";
|
||||||
|
int MAX_COFFER = 7_500_000;
|
||||||
|
int MAX_APPROVAL_PERCENT = 100;
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
position = 1,
|
||||||
|
keyName = "sendNotifications",
|
||||||
|
name = "Send Notifications",
|
||||||
|
description = "Send chat notifications upon login showing current estimated coffer and approval"
|
||||||
|
)
|
||||||
|
default boolean shouldSendNotifications()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Range(
|
||||||
|
max = MAX_COFFER
|
||||||
|
)
|
||||||
|
@ConfigItem(
|
||||||
|
position = 2,
|
||||||
|
keyName = "cofferThreshold",
|
||||||
|
name = "Coffer Threshold",
|
||||||
|
description = "Send notifications if coffer is below this value"
|
||||||
|
)
|
||||||
|
default int getCofferThreshold()
|
||||||
|
{
|
||||||
|
return MAX_COFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Range(
|
||||||
|
max = MAX_APPROVAL_PERCENT
|
||||||
|
)
|
||||||
|
@ConfigItem(
|
||||||
|
position = 3,
|
||||||
|
keyName = "approvalThreshold",
|
||||||
|
name = "Approval Threshold",
|
||||||
|
description = "Send notifications if approval percentage is below this value"
|
||||||
|
)
|
||||||
|
default int getApprovalThreshold()
|
||||||
|
{
|
||||||
|
return MAX_APPROVAL_PERCENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,20 +34,20 @@ public class KingdomCounter extends Counter
|
|||||||
|
|
||||||
KingdomCounter(BufferedImage image, KingdomPlugin plugin)
|
KingdomCounter(BufferedImage image, KingdomPlugin plugin)
|
||||||
{
|
{
|
||||||
super(image, plugin, plugin.getFavor());
|
super(image, plugin, plugin.getApproval());
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText()
|
public String getText()
|
||||||
{
|
{
|
||||||
return KingdomPlugin.getFavorPercent(plugin.getFavor()) + "%";
|
return KingdomPlugin.getApprovalPercent(plugin.getApproval()) + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTooltip()
|
public String getTooltip()
|
||||||
{
|
{
|
||||||
return "Favor: " + plugin.getFavor() + "/127" + "</br>"
|
return "Approval: " + plugin.getApproval() + "/" + KingdomPlugin.MAX_APPROVAL + "</br>"
|
||||||
+ "Coffer: " + QuantityFormatter.quantityToStackSize(plugin.getCoffer());
|
+ "Coffer: " + QuantityFormatter.quantityToStackSize(plugin.getCoffer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,32 +25,55 @@
|
|||||||
package net.runelite.client.plugins.kingdomofmiscellania;
|
package net.runelite.client.plugins.kingdomofmiscellania;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.api.ChatMessageType;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import static net.runelite.api.ItemID.TEAK_CHEST;
|
import static net.runelite.api.ItemID.TEAK_CHEST;
|
||||||
|
import net.runelite.api.Quest;
|
||||||
|
import net.runelite.api.QuestState;
|
||||||
import net.runelite.api.VarPlayer;
|
import net.runelite.api.VarPlayer;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
import net.runelite.api.events.GameStateChanged;
|
import net.runelite.api.events.GameStateChanged;
|
||||||
|
import net.runelite.api.events.GameTick;
|
||||||
import net.runelite.api.events.VarbitChanged;
|
import net.runelite.api.events.VarbitChanged;
|
||||||
|
import net.runelite.client.chat.ChatColorType;
|
||||||
|
import net.runelite.client.chat.ChatMessageBuilder;
|
||||||
|
import net.runelite.client.chat.ChatMessageManager;
|
||||||
|
import net.runelite.client.chat.QueuedMessage;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
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.infobox.InfoBoxManager;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||||
|
import net.runelite.client.util.QuantityFormatter;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Kingdom of Miscellania",
|
name = "Kingdom of Miscellania",
|
||||||
description = "Show amount of favor when inside Miscellania",
|
description = "Show amount of approval when inside Miscellania",
|
||||||
tags = {"favor", "favour", "managing", "overlay"},
|
tags = {"favor", "favour", "managing", "overlay", "approval", "coffer"},
|
||||||
enabledByDefault = false
|
enabledByDefault = false
|
||||||
)
|
)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class KingdomPlugin extends Plugin
|
public class KingdomPlugin extends Plugin
|
||||||
{
|
{
|
||||||
private static final ImmutableSet<Integer> KINGDOM_REGION = ImmutableSet.of(10044, 10300);
|
private static final ImmutableSet<Integer> KINGDOM_REGION = ImmutableSet.of(10044, 10300);
|
||||||
|
private static final String CONFIG_LAST_CHANGED_KEY = "lastChanged";
|
||||||
|
private static final String CONFIG_COFFER_KEY = "coffer";
|
||||||
|
private static final String CONFIG_APPROVAL_KEY = "approval";
|
||||||
|
private static final String CHAT_MESSAGE_FORMAT = "Your Kingdom of Miscellania approval is %d%%, and your coffer has %s coins.";
|
||||||
|
private static final int MAX_WITHDRAWAL_BASE = 50_000;
|
||||||
|
private static final int MAX_WITHDRAWAL_ROYAL_TROUBLE = 75_000;
|
||||||
|
private static final float APPROVAL_DECREMENT_BASE = 0.025f;
|
||||||
|
private static final float APPROVAL_DECREMENT_ROYAL_TROUBLE = 0.010f;
|
||||||
|
static final int MAX_APPROVAL = 127;
|
||||||
|
|
||||||
|
private boolean loggingIn;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Client client;
|
private Client client;
|
||||||
@@ -61,8 +84,14 @@ public class KingdomPlugin extends Plugin
|
|||||||
@Inject
|
@Inject
|
||||||
private ItemManager itemManager;
|
private ItemManager itemManager;
|
||||||
|
|
||||||
@Getter
|
@Inject
|
||||||
private int favor = 0, coffer = 0;
|
private KingdomConfig config;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ConfigManager configManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ChatMessageManager chatMessageManager;
|
||||||
|
|
||||||
private KingdomCounter counter;
|
private KingdomCounter counter;
|
||||||
|
|
||||||
@@ -72,11 +101,28 @@ public class KingdomPlugin extends Plugin
|
|||||||
removeKingdomInfobox();
|
removeKingdomInfobox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
KingdomConfig getConfig(ConfigManager configManager)
|
||||||
|
{
|
||||||
|
return configManager.getConfig(KingdomConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onVarbitChanged(VarbitChanged event)
|
public void onVarbitChanged(VarbitChanged event)
|
||||||
{
|
{
|
||||||
favor = client.getVar(Varbits.KINGDOM_FAVOR);
|
final int coffer = client.getVar(Varbits.KINGDOM_COFFER);
|
||||||
coffer = client.getVar(Varbits.KINGDOM_COFFER);
|
final int approval = client.getVar(Varbits.KINGDOM_APPROVAL);
|
||||||
|
|
||||||
|
if (client.getGameState() == GameState.LOGGED_IN
|
||||||
|
&& isThroneOfMiscellaniaCompleted()
|
||||||
|
&& (isInKingdom() || coffer > 0 && approval > 0)
|
||||||
|
&& (getCoffer() != coffer || getApproval() != approval))
|
||||||
|
{
|
||||||
|
setLastChanged(Instant.now());
|
||||||
|
setCoffer(coffer);
|
||||||
|
setApproval(approval);
|
||||||
|
}
|
||||||
|
|
||||||
processInfobox();
|
processInfobox();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,11 +133,25 @@ public class KingdomPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
processInfobox();
|
processInfobox();
|
||||||
}
|
}
|
||||||
|
else if (event.getGameState() == GameState.LOGGING_IN)
|
||||||
|
{
|
||||||
|
loggingIn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameTick(GameTick gameTick)
|
||||||
|
{
|
||||||
|
if (loggingIn)
|
||||||
|
{
|
||||||
|
loggingIn = false;
|
||||||
|
createNotification();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processInfobox()
|
private void processInfobox()
|
||||||
{
|
{
|
||||||
if (client.getGameState() == GameState.LOGGED_IN && hasCompletedQuest() && isInKingdom())
|
if (client.getGameState() == GameState.LOGGED_IN && isThroneOfMiscellaniaCompleted() && isInKingdom())
|
||||||
{
|
{
|
||||||
addKingdomInfobox();
|
addKingdomInfobox();
|
||||||
}
|
}
|
||||||
@@ -99,7 +159,33 @@ public class KingdomPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
removeKingdomInfobox();
|
removeKingdomInfobox();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotification()
|
||||||
|
{
|
||||||
|
if (!config.shouldSendNotifications() || !isThroneOfMiscellaniaCompleted())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLastChanged() == null)
|
||||||
|
{
|
||||||
|
log.debug("Kingdom Of Miscellania values not yet set. Visit Miscellania to automatically set values.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instant lastChanged = getLastChanged();
|
||||||
|
int lastCoffer = getCoffer();
|
||||||
|
int lastApproval = getApproval();
|
||||||
|
int estimatedCoffer = estimateCoffer(lastChanged, lastCoffer);
|
||||||
|
int estimatedApproval = estimateApproval(lastChanged, lastApproval);
|
||||||
|
if (estimatedCoffer < config.getCofferThreshold() || getApprovalPercent(estimatedApproval) < config.getApprovalThreshold())
|
||||||
|
{
|
||||||
|
sendChatMessage(String.format(
|
||||||
|
CHAT_MESSAGE_FORMAT,
|
||||||
|
getApprovalPercent(estimatedApproval),
|
||||||
|
QuantityFormatter.quantityToStackSize(estimatedCoffer)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addKingdomInfobox()
|
private void addKingdomInfobox()
|
||||||
@@ -122,20 +208,92 @@ public class KingdomPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int estimateCoffer(Instant lastChanged, int lastCoffer)
|
||||||
|
{
|
||||||
|
int daysSince = (int) Duration.between(lastChanged, Instant.now()).toDays();
|
||||||
|
int maxDailyWithdrawal = isRoyalTroubleCompleted() ? MAX_WITHDRAWAL_ROYAL_TROUBLE : MAX_WITHDRAWAL_BASE;
|
||||||
|
int maxDailyThreshold = maxDailyWithdrawal * 10;
|
||||||
|
|
||||||
|
for (int i = 0; i < daysSince; i++)
|
||||||
|
{
|
||||||
|
lastCoffer -= (lastCoffer > maxDailyThreshold) ? maxDailyWithdrawal : lastCoffer / 10;
|
||||||
|
}
|
||||||
|
return lastCoffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int estimateApproval(Instant lastChanged, int lastApproval)
|
||||||
|
{
|
||||||
|
int daysSince = (int) Duration.between(lastChanged, Instant.now()).toDays();
|
||||||
|
float dailyPercentage = isRoyalTroubleCompleted() ? APPROVAL_DECREMENT_ROYAL_TROUBLE : APPROVAL_DECREMENT_BASE;
|
||||||
|
|
||||||
|
lastApproval -= (int) (daysSince * dailyPercentage * MAX_APPROVAL);
|
||||||
|
return Math.max(lastApproval, 0);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isInKingdom()
|
private boolean isInKingdom()
|
||||||
{
|
{
|
||||||
return client.getLocalPlayer() != null
|
return client.getLocalPlayer() != null
|
||||||
&& KINGDOM_REGION.contains(client.getLocalPlayer().getWorldLocation().getRegionID());
|
&& KINGDOM_REGION.contains(client.getLocalPlayer().getWorldLocation().getRegionID());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasCompletedQuest()
|
private boolean isThroneOfMiscellaniaCompleted()
|
||||||
{
|
{
|
||||||
return client.getVar(VarPlayer.THRONE_OF_MISCELLANIA) > 0;
|
return client.getVar(VarPlayer.THRONE_OF_MISCELLANIA) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getFavorPercent(int favor)
|
private boolean isRoyalTroubleCompleted()
|
||||||
{
|
{
|
||||||
return (favor * 100) / 127;
|
return Quest.ROYAL_TROUBLE.getState(client) == QuestState.FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getApprovalPercent(int approval)
|
||||||
|
{
|
||||||
|
return (approval * 100) / MAX_APPROVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendChatMessage(String chatMessage)
|
||||||
|
{
|
||||||
|
final String message = new ChatMessageBuilder()
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(chatMessage)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
chatMessageManager.queue(
|
||||||
|
QueuedMessage.builder()
|
||||||
|
.type(ChatMessageType.CONSOLE)
|
||||||
|
.runeLiteFormattedMessage(message)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Instant getLastChanged()
|
||||||
|
{
|
||||||
|
return configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_LAST_CHANGED_KEY, Instant.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLastChanged(Instant lastChanged)
|
||||||
|
{
|
||||||
|
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_LAST_CHANGED_KEY, lastChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCoffer()
|
||||||
|
{
|
||||||
|
Integer coffer = configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_COFFER_KEY, int.class);
|
||||||
|
return coffer == null ? 0 : coffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCoffer(int coffer)
|
||||||
|
{
|
||||||
|
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_COFFER_KEY, coffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getApproval()
|
||||||
|
{
|
||||||
|
Integer approval = configManager.getRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_APPROVAL_KEY, int.class);
|
||||||
|
return approval == null ? 0 : approval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setApproval(int approval)
|
||||||
|
{
|
||||||
|
configManager.setRSProfileConfiguration(KingdomConfig.CONFIG_GROUP_NAME, CONFIG_APPROVAL_KEY, approval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user