xptracker: add option to reset per hour rates

This commit is contained in:
James Shelton
2021-05-08 00:10:06 +01:00
committed by Adam
parent 4c0abc4511
commit 8a5a0f88f9
6 changed files with 103 additions and 26 deletions

View File

@@ -30,6 +30,7 @@ import lombok.Data;
class XpAction class XpAction
{ {
private int actions = 0; private int actions = 0;
private int actionsSinceReset = 0;
private boolean actionsHistoryInitialized = false; private boolean actionsHistoryInitialized = false;
private int[] actionExps = new int[10]; private int[] actionExps = new int[10];
private int actionExpIndex = 0; private int actionExpIndex = 0;

View File

@@ -135,6 +135,10 @@ class XpInfoBox extends JPanel
final JMenuItem resetOthers = new JMenuItem("Reset others"); final JMenuItem resetOthers = new JMenuItem("Reset others");
resetOthers.addActionListener(e -> xpTrackerPlugin.resetOtherSkillState(skill)); resetOthers.addActionListener(e -> xpTrackerPlugin.resetOtherSkillState(skill));
// Create reset per hour menu
final JMenuItem resetPerHour = new JMenuItem("Reset/hr");
resetPerHour.addActionListener(e -> xpTrackerPlugin.resetSkillPerHourState(skill));
// Create reset others menu // Create reset others menu
pauseSkill.addActionListener(e -> xpTrackerPlugin.pauseSkill(skill, !paused)); pauseSkill.addActionListener(e -> xpTrackerPlugin.pauseSkill(skill, !paused));
@@ -144,6 +148,7 @@ class XpInfoBox extends JPanel
popupMenu.add(openXpTracker); popupMenu.add(openXpTracker);
popupMenu.add(reset); popupMenu.add(reset);
popupMenu.add(resetOthers); popupMenu.add(resetOthers);
popupMenu.add(resetPerHour);
popupMenu.add(pauseSkill); popupMenu.add(pauseSkill);
popupMenu.add(canvasItem); popupMenu.add(canvasItem);
popupMenu.addPopupMenuListener(new PopupMenuListener() popupMenu.addPopupMenuListener(new PopupMenuListener()

View File

@@ -90,6 +90,10 @@ class XpPanel extends PluginPanel
final JMenuItem reset = new JMenuItem("Reset All"); final JMenuItem reset = new JMenuItem("Reset All");
reset.addActionListener(e -> xpTrackerPlugin.resetAndInitState()); reset.addActionListener(e -> xpTrackerPlugin.resetAndInitState());
// Create reset all per hour menu
final JMenuItem resetPerHour = new JMenuItem("Reset All/hr");
resetPerHour.addActionListener(e -> xpTrackerPlugin.resetAllSkillsPerHourState());
// Create pause all menu // Create pause all menu
final JMenuItem pauseAll = new JMenuItem("Pause All"); final JMenuItem pauseAll = new JMenuItem("Pause All");
pauseAll.addActionListener(e -> xpTrackerPlugin.pauseAllSkills(true)); pauseAll.addActionListener(e -> xpTrackerPlugin.pauseAllSkills(true));
@@ -104,6 +108,7 @@ class XpPanel extends PluginPanel
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5)); popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
popupMenu.add(openXpTracker); popupMenu.add(openXpTracker);
popupMenu.add(reset); popupMenu.add(reset);
popupMenu.add(resetPerHour);
popupMenu.add(pauseAll); popupMenu.add(pauseAll);
popupMenu.add(unpauseAll); popupMenu.add(unpauseAll);
overallPanel.setComponentPopupMenu(popupMenu); overallPanel.setComponentPopupMenu(popupMenu);

View File

@@ -32,7 +32,7 @@ import net.runelite.api.Skill;
/** /**
* Internal state for the XpTrackerPlugin * Internal state for the XpTrackerPlugin
* * <p>
* Note: This class's operations are not currently synchronized. * Note: This class's operations are not currently synchronized.
* It is intended to be called by the XpTrackerPlugin on the client thread. * It is intended to be called by the XpTrackerPlugin on the client thread.
*/ */
@@ -53,7 +53,8 @@ class XpState
/** /**
* Resets a single skill * Resets a single skill
* @param skill Skill to reset *
* @param skill Skill to reset
* @param currentXp Current XP to set to, if unknown set to -1 * @param currentXp Current XP to set to, if unknown set to -1
*/ */
void resetSkill(Skill skill, long currentXp) void resetSkill(Skill skill, long currentXp)
@@ -62,15 +63,26 @@ class XpState
xpSkills.put(skill, new XpStateSingle(skill, currentXp)); xpSkills.put(skill, new XpStateSingle(skill, currentXp));
} }
/**
* Resets the per hour rates of a single skill
*
* @param skill Skill to reset per hour rates
*/
void resetSkillPerHour(Skill skill)
{
xpSkills.get(skill).resetPerHour();
}
/** /**
* Updates a skill with the current known XP. * Updates a skill with the current known XP.
* When the result of this operation is XpUpdateResult.UPDATED, the UI should be updated accordingly. * When the result of this operation is XpUpdateResult.UPDATED, the UI should be updated accordingly.
* This is to distinguish events that reload all the skill's current values (such as world hopping) * This is to distinguish events that reload all the skill's current values (such as world hopping)
* and also first-login when the skills are not initialized (the start XP will be -1 in this case). * and also first-login when the skills are not initialized (the start XP will be -1 in this case).
* @param skill Skill to update *
* @param currentXp Current known XP for this skill * @param skill Skill to update
* @param currentXp Current known XP for this skill
* @param goalStartXp Possible XP start goal * @param goalStartXp Possible XP start goal
* @param goalEndXp Possible XP end goal * @param goalEndXp Possible XP end goal
* @return Whether or not the skill has been initialized, there was no change, or it has been updated * @return Whether or not the skill has been initialized, there was no change, or it has been updated
*/ */
XpUpdateResult updateSkill(Skill skill, long currentXp, int goalStartXp, int goalEndXp) XpUpdateResult updateSkill(Skill skill, long currentXp, int goalStartXp, int goalEndXp)
@@ -92,7 +104,7 @@ class XpState
else else
{ {
long startXp = state.getStartXp(); long startXp = state.getStartXp();
int gainedXp = state.getXpGained(); int gainedXp = state.getTotalXpGained();
if (startXp + gainedXp > currentXp) if (startXp + gainedXp > currentXp)
{ {
@@ -119,8 +131,9 @@ class XpState
/** /**
* Updates skill with average actions based on currently interacted NPC. * Updates skill with average actions based on currently interacted NPC.
* @param skill experience gained skill *
* @param npc currently interacted NPC * @param skill experience gained skill
* @param npc currently interacted NPC
* @param npcHealth health of currently interacted NPC * @param npcHealth health of currently interacted NPC
*/ */
void updateNpcExperience(Skill skill, NPC npc, Integer npcHealth, int xpModifier) void updateNpcExperience(Skill skill, NPC npc, Integer npcHealth, int xpModifier)
@@ -161,8 +174,9 @@ class XpState
/** /**
* Update number of actions performed for skill if last interacted NPC died. * Update number of actions performed for skill if last interacted NPC died.
* (eg. amount of kills in this case) * (eg. amount of kills in this case)
* @param skill skill to update actions for *
* @param npc npc that just died * @param skill skill to update actions for
* @param npc npc that just died
* @param npcHealth max health of npc that just died * @param npcHealth max health of npc that just died
* @return UPDATED in case new kill was successfully added * @return UPDATED in case new kill was successfully added
*/ */
@@ -170,13 +184,13 @@ class XpState
{ {
XpStateSingle state = getSkill(skill); XpStateSingle state = getSkill(skill);
if (state.getXpGained() <= 0 || npcHealth == null || npc != interactedNPC) if (state.getXpGainedSinceReset() <= 0 || npcHealth == null || npc != interactedNPC)
{ {
return XpUpdateResult.NO_CHANGE; return XpUpdateResult.NO_CHANGE;
} }
final XpAction xpAction = state.getXpAction(XpActionType.ACTOR_HEALTH); final XpAction xpAction = state.getXpAction(XpActionType.ACTOR_HEALTH);
xpAction.setActions(xpAction.getActions() + 1); xpAction.setActionsSinceReset(xpAction.getActionsSinceReset() + 1);
return xpAction.isActionsHistoryInitialized() ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE; return xpAction.isActionsHistoryInitialized() ? XpUpdateResult.UPDATED : XpUpdateResult.NO_CHANGE;
} }
@@ -188,7 +202,8 @@ class XpState
/** /**
* Forcefully initialize a skill with a known start XP from the current XP. * Forcefully initialize a skill with a known start XP from the current XP.
* This is used in resetAndInitState by the plugin. It should not result in showing the XP in the UI. * This is used in resetAndInitState by the plugin. It should not result in showing the XP in the UI.
* @param skill Skill to initialize *
* @param skill Skill to initialize
* @param currentXp Current known XP for the skill * @param currentXp Current known XP for the skill
*/ */
void initializeSkill(Skill skill, long currentXp) void initializeSkill(Skill skill, long currentXp)
@@ -211,6 +226,7 @@ class XpState
/** /**
* Obtain an immutable snapshot of the provided skill * Obtain an immutable snapshot of the provided skill
* intended for use with the UI which operates on another thread * intended for use with the UI which operates on another thread
*
* @param skill Skill to obtain the snapshot for * @param skill Skill to obtain the snapshot for
* @return An immutable snapshot of the specified skill for this session since first login or last reset * @return An immutable snapshot of the specified skill for this session since first login or last reset
*/ */
@@ -223,6 +239,7 @@ class XpState
/** /**
* Obtain an immutable snapshot of the provided skill * Obtain an immutable snapshot of the provided skill
* intended for use with the UI which operates on another thread * intended for use with the UI which operates on another thread
*
* @return An immutable snapshot of total information for this session since first login or last reset * @return An immutable snapshot of total information for this session since first login or last reset
*/ */
@NonNull @NonNull

View File

@@ -45,12 +45,16 @@ class XpStateSingle
private long startXp; private long startXp;
@Getter @Getter
private int xpGained = 0; private int xpGainedSinceReset = 0;
private int xpGainedBeforeReset = 0;
@Setter @Setter
private XpActionType actionType = XpActionType.EXPERIENCE; private XpActionType actionType = XpActionType.EXPERIENCE;
@Setter
private long skillTime = 0; private long skillTime = 0;
private int startLevelExp = 0; private int startLevelExp = 0;
private int endLevelExp = 0; private int endLevelExp = 0;
@@ -68,12 +72,17 @@ class XpStateSingle
long getCurrentXp() long getCurrentXp()
{ {
return startXp + xpGained; return startXp + getTotalXpGained();
}
int getTotalXpGained()
{
return xpGainedBeforeReset + xpGainedSinceReset;
} }
private int getActionsHr() private int getActionsHr()
{ {
return toHourly(getXpAction(actionType).getActions()); return toHourly(getXpAction(actionType).getActionsSinceReset());
} }
private int toHourly(int value) private int toHourly(int value)
@@ -136,7 +145,7 @@ class XpStateSingle
// below will be a custom formatter that handles spans larger than 1 day // below will be a custom formatter that handles spans larger than 1 day
long seconds = getTimeElapsedInSeconds(); long seconds = getTimeElapsedInSeconds();
if (seconds <= 0 || xpGained <= 0) if (seconds <= 0 || xpGainedSinceReset <= 0)
{ {
return -1; return -1;
} }
@@ -144,7 +153,7 @@ class XpStateSingle
// formula is xpRemaining / xpPerSecond // formula is xpRemaining / xpPerSecond
// xpPerSecond being xpGained / seconds // xpPerSecond being xpGained / seconds
// This can be simplified so division is only done once and we can work in whole numbers! // This can be simplified so division is only done once and we can work in whole numbers!
return (getXpRemaining() * seconds) / xpGained; return (getXpRemaining() * seconds) / xpGainedSinceReset;
} }
private String getTimeTillLevel(XpGoalTimeType goalTimeType) private String getTimeTillLevel(XpGoalTimeType goalTimeType)
@@ -197,7 +206,22 @@ class XpStateSingle
int getXpHr() int getXpHr()
{ {
return toHourly(xpGained); return toHourly(xpGainedSinceReset);
}
void resetPerHour()
{
//reset actions per hour
for (XpAction action : actions.values())
{
action.setActions(action.getActions() + action.getActionsSinceReset());
action.setActionsSinceReset(0);
}
//reset xp per hour
xpGainedBeforeReset += xpGainedSinceReset;
xpGainedSinceReset = 0;
setSkillTime(0);
} }
boolean update(long currentXp, int goalStartXp, int goalEndXp) boolean update(long currentXp, int goalStartXp, int goalEndXp)
@@ -208,7 +232,7 @@ class XpStateSingle
return false; return false;
} }
long originalXp = xpGained + startXp; long originalXp = getTotalXpGained() + startXp;
int actionExp = (int) (currentXp - originalXp); int actionExp = (int) (currentXp - originalXp);
// No experience gained // No experience gained
@@ -237,10 +261,10 @@ class XpStateSingle
} }
action.setActionExpIndex((action.getActionExpIndex() + 1) % action.getActionExps().length); action.setActionExpIndex((action.getActionExpIndex() + 1) % action.getActionExps().length);
action.setActions(action.getActions() + 1); action.setActionsSinceReset(action.getActionsSinceReset() + 1);
// Calculate experience gained // Calculate experience gained
xpGained = (int) (currentXp - startXp); xpGainedSinceReset = (int) (currentXp - (startXp + xpGainedBeforeReset));
// Determine XP goals, overall has no goals // Determine XP goals, overall has no goals
if (skill != Skill.OVERALL) if (skill != Skill.OVERALL)
@@ -273,7 +297,7 @@ class XpStateSingle
public void tick(long delta) public void tick(long delta)
{ {
// Don't tick skills that have not gained XP or have been reset. // Don't tick skills that have not gained XP or have been reset.
if (xpGained <= 0) if (xpGainedSinceReset <= 0)
{ {
return; return;
} }
@@ -285,12 +309,12 @@ class XpStateSingle
return XpSnapshotSingle.builder() return XpSnapshotSingle.builder()
.startLevel(Experience.getLevelForXp(startLevelExp)) .startLevel(Experience.getLevelForXp(startLevelExp))
.endLevel(Experience.getLevelForXp(endLevelExp)) .endLevel(Experience.getLevelForXp(endLevelExp))
.xpGainedInSession(xpGained) .xpGainedInSession(getTotalXpGained())
.xpRemainingToGoal(getXpRemaining()) .xpRemainingToGoal(getXpRemaining())
.xpPerHour(getXpHr()) .xpPerHour(getXpHr())
.skillProgressToGoal(getSkillProgress()) .skillProgressToGoal(getSkillProgress())
.actionType(actionType) .actionType(actionType)
.actionsInSession(getXpAction(actionType).getActions()) .actionsInSession(getXpAction(actionType).getActions() + getXpAction(actionType).getActionsSinceReset())
.actionsRemainingToGoal(getActionsRemaining()) .actionsRemainingToGoal(getActionsRemaining())
.actionsPerHour(getActionsHr()) .actionsPerHour(getActionsHr())
.timeTillGoal(getTimeTillLevel(XpGoalTimeType.DAYS)) .timeTillGoal(getTimeTillLevel(XpGoalTimeType.DAYS))

View File

@@ -323,6 +323,7 @@ public class XpTrackerPlugin extends Plugin
/** /**
* Reset an individual skill with the client's current known state of the skill * Reset an individual skill with the client's current known state of the skill
* Will also clear the skill from the UI. * Will also clear the skill from the UI.
*
* @param skill Skill to reset * @param skill Skill to reset
*/ */
void resetSkillState(Skill skill) void resetSkillState(Skill skill)
@@ -335,6 +336,7 @@ public class XpTrackerPlugin extends Plugin
/** /**
* Reset all skills except for the one provided * Reset all skills except for the one provided
*
* @param skill Skill to ignore during reset * @param skill Skill to ignore during reset
*/ */
void resetOtherSkillState(Skill skill) void resetOtherSkillState(Skill skill)
@@ -349,6 +351,29 @@ public class XpTrackerPlugin extends Plugin
} }
} }
/**
* Reset the xp gained since last reset of the skill
* Does not clear the skill from the UI.
*
* @param skill Skill to reset per hour rate
*/
void resetSkillPerHourState(Skill skill)
{
xpState.resetSkillPerHour(skill);
}
/**
* Reset the xp gained since last reset of all skills including OVERALL
* Does not clear the UI.
*/
void resetAllSkillsPerHourState()
{
for (Skill skill : Skill.values())
{
resetSkillPerHourState(skill);
}
}
@Subscribe @Subscribe
public void onStatChanged(StatChanged statChanged) public void onStatChanged(StatChanged statChanged)
{ {
@@ -377,7 +402,7 @@ public class XpTrackerPlugin extends Plugin
final Actor interacting = client.getLocalPlayer().getInteracting(); final Actor interacting = client.getLocalPlayer().getInteracting();
if (interacting instanceof NPC && COMBAT.contains(skill)) if (interacting instanceof NPC && COMBAT.contains(skill))
{ {
final int xpModifier = worldSetToType(client.getWorldType()).modifier(client);; final int xpModifier = worldSetToType(client.getWorldType()).modifier(client);
final NPC npc = (NPC) interacting; final NPC npc = (NPC) interacting;
xpState.updateNpcExperience(skill, npc, npcManager.getHealth(npc.getId()), xpModifier); xpState.updateNpcExperience(skill, npc, npcManager.getHealth(npc.getId()), xpModifier);
} }