Add performance stats plugin
This commit is contained in:
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* 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.performancestats;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
class Performance
|
||||||
|
{
|
||||||
|
private static final double TICK_LENGTH = 0.6;
|
||||||
|
|
||||||
|
String username;
|
||||||
|
|
||||||
|
double damageDealt = 0;
|
||||||
|
double highestHitDealt = 0;
|
||||||
|
|
||||||
|
double damageTaken = 0;
|
||||||
|
double highestHitTaken = 0;
|
||||||
|
|
||||||
|
int lastActivityTick = -1;
|
||||||
|
@Setter
|
||||||
|
double ticksSpent = 0;
|
||||||
|
|
||||||
|
void addDamageDealt(double a, int currentTick)
|
||||||
|
{
|
||||||
|
damageDealt += a;
|
||||||
|
if (a > highestHitDealt)
|
||||||
|
{
|
||||||
|
highestHitDealt = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastActivityTick = currentTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDamageTaken(double a, int currentTick)
|
||||||
|
{
|
||||||
|
damageTaken += a;
|
||||||
|
if (a > highestHitTaken)
|
||||||
|
{
|
||||||
|
highestHitTaken = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastActivityTick = currentTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
void incrementTicksSpent()
|
||||||
|
{
|
||||||
|
ticksSpent++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
damageDealt = 0;
|
||||||
|
highestHitDealt = 0;
|
||||||
|
damageTaken = 0;
|
||||||
|
highestHitTaken = 0;
|
||||||
|
lastActivityTick = -1;
|
||||||
|
ticksSpent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getSecondsSpent()
|
||||||
|
{
|
||||||
|
return Math.round(this.ticksSpent * TICK_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getDPS()
|
||||||
|
{
|
||||||
|
return Math.round( (this.damageDealt / this.getSecondsSpent()) * 100) / 100.00;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getHumanReadableSecondsSpent()
|
||||||
|
{
|
||||||
|
final double secondsSpent = getSecondsSpent();
|
||||||
|
if (secondsSpent <= 60)
|
||||||
|
{
|
||||||
|
return String.format("%2.0f", secondsSpent) + "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
final double s = secondsSpent % 3600 % 60;
|
||||||
|
final double m = Math.floor(secondsSpent % 3600 / 60);
|
||||||
|
final double h = Math.floor(secondsSpent / 3600);
|
||||||
|
|
||||||
|
return h < 1 ? String.format("%2.0f:%02.0f", m, s) : String.format("%2.0f:%02.0f:%02.0f", h, m, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* 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.performancestats;
|
||||||
|
|
||||||
|
import net.runelite.client.config.Config;
|
||||||
|
import net.runelite.client.config.ConfigGroup;
|
||||||
|
import net.runelite.client.config.ConfigItem;
|
||||||
|
|
||||||
|
@ConfigGroup("performancestats")
|
||||||
|
public interface PerformanceStatsConfig extends Config
|
||||||
|
{
|
||||||
|
@ConfigItem(
|
||||||
|
position = 0,
|
||||||
|
keyName = "submitTimeout",
|
||||||
|
name = "Submit Timeout (seconds)",
|
||||||
|
description = "Submits after this many seconds of inactivity"
|
||||||
|
)
|
||||||
|
default int submitTimeout()
|
||||||
|
{
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* 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.performancestats;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import net.runelite.api.MenuAction;
|
||||||
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||||
|
import net.runelite.client.ui.overlay.components.ComponentConstants;
|
||||||
|
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||||
|
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||||
|
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||||
|
|
||||||
|
public class PerformanceStatsOverlay extends Overlay
|
||||||
|
{
|
||||||
|
private static final String TARGET = "Performance Stats";
|
||||||
|
private static final String[] COLUMNS = {
|
||||||
|
"Player", "Dealt", "Taken", "DPS", "Elapsed"
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PerformanceStatsPlugin tracker;
|
||||||
|
private final PanelComponent panelComponent = new PanelComponent();
|
||||||
|
private final TableComponent tableComponent = new TableComponent();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PerformanceStatsOverlay(PerformanceStatsPlugin tracker)
|
||||||
|
{
|
||||||
|
super(tracker);
|
||||||
|
setPosition(OverlayPosition.TOP_RIGHT);
|
||||||
|
setPriority(OverlayPriority.LOW);
|
||||||
|
this.tracker = tracker;
|
||||||
|
|
||||||
|
getMenuEntries().add(new OverlayMenuEntry(MenuAction.RUNELITE_OVERLAY, "Pause", TARGET));
|
||||||
|
getMenuEntries().add(new OverlayMenuEntry(MenuAction.RUNELITE_OVERLAY, "Reset", TARGET));
|
||||||
|
getMenuEntries().add(new OverlayMenuEntry(MenuAction.RUNELITE_OVERLAY, "Submit", TARGET));
|
||||||
|
|
||||||
|
panelComponent.setPreferredSize(new Dimension(350, 0));
|
||||||
|
panelComponent.setBackgroundColor(ComponentConstants.STANDARD_BACKGROUND_COLOR);
|
||||||
|
|
||||||
|
tableComponent.setDefaultAlignment(TableAlignment.CENTER);
|
||||||
|
tableComponent.setColumns(COLUMNS);
|
||||||
|
|
||||||
|
panelComponent.getChildren().add(tableComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return TARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension render(Graphics2D graphics)
|
||||||
|
{
|
||||||
|
if (!tracker.isEnabled())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Performance performance = tracker.getPerformance();
|
||||||
|
graphics.setColor(Color.WHITE);
|
||||||
|
|
||||||
|
tableComponent.getRows().clear();
|
||||||
|
|
||||||
|
final String[] rowElements = createRowElements(performance);
|
||||||
|
tableComponent.addRow(rowElements);
|
||||||
|
|
||||||
|
return panelComponent.render(graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] createRowElements(Performance performance)
|
||||||
|
{
|
||||||
|
return new String[]
|
||||||
|
{
|
||||||
|
performance.getUsername(),
|
||||||
|
String.valueOf((int) Math.round(performance.getDamageDealt())) + " | " + String.valueOf((int) Math.round(performance.getHighestHitDealt())),
|
||||||
|
String.valueOf((int) Math.round(performance.getDamageTaken())) + " | " + String.valueOf((int) Math.round(performance.getHighestHitTaken())),
|
||||||
|
String.valueOf(performance.getDPS()),
|
||||||
|
performance.getHumanReadableSecondsSpent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* 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.performancestats;
|
||||||
|
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.api.Actor;
|
||||||
|
import net.runelite.api.ChatMessageType;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.NPC;
|
||||||
|
import net.runelite.api.Skill;
|
||||||
|
import net.runelite.api.WorldType;
|
||||||
|
import net.runelite.api.events.ExperienceChanged;
|
||||||
|
import net.runelite.api.events.GameStateChanged;
|
||||||
|
import net.runelite.api.events.GameTick;
|
||||||
|
import net.runelite.api.events.HitsplatApplied;
|
||||||
|
import net.runelite.api.events.ScriptCallbackEvent;
|
||||||
|
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.events.OverlayMenuClicked;
|
||||||
|
import net.runelite.client.game.NPCManager;
|
||||||
|
import net.runelite.client.plugins.Plugin;
|
||||||
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
import net.runelite.client.ui.overlay.OverlayManager;
|
||||||
|
|
||||||
|
@PluginDescriptor(
|
||||||
|
name = "Performance Stats",
|
||||||
|
description = "Displays your current performance stats",
|
||||||
|
tags = {"performance", "stats", "dps", "damage", "combat"},
|
||||||
|
enabledByDefault = false
|
||||||
|
)
|
||||||
|
@Slf4j
|
||||||
|
public class PerformanceStatsPlugin extends Plugin
|
||||||
|
{
|
||||||
|
// For every damage point dealt 1.33 experience is given to the player's hitpoints (base rate)
|
||||||
|
private static final double HITPOINT_RATIO = 1.33;
|
||||||
|
private static final double DMM_MULTIPLIER_RATIO = 10;
|
||||||
|
|
||||||
|
private static final double GAME_TICK_SECONDS = 0.6;
|
||||||
|
private static final DecimalFormat numberFormat = new DecimalFormat("#,###");
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ChatMessageManager chatMessageManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PerformanceStatsConfig config;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PerformanceStatsOverlay performanceTrackerOverlay;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private OverlayManager overlayManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private NPCManager npcManager;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private boolean enabled = false;
|
||||||
|
@Getter
|
||||||
|
private boolean paused = false;
|
||||||
|
@Getter
|
||||||
|
private final Performance performance = new Performance();
|
||||||
|
|
||||||
|
// Keep track of actor last tick as sometimes getInteracting can return null when hp xp event is triggered
|
||||||
|
// as the player clicked away at the perfect time
|
||||||
|
private Actor oldTarget;
|
||||||
|
private double hpExp;
|
||||||
|
private boolean hopping;
|
||||||
|
private int pausedTicks = 0;
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
PerformanceStatsConfig getConfig(ConfigManager configManager)
|
||||||
|
{
|
||||||
|
return configManager.getConfig(PerformanceStatsConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startUp()
|
||||||
|
{
|
||||||
|
overlayManager.add(performanceTrackerOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void shutDown()
|
||||||
|
{
|
||||||
|
overlayManager.remove(performanceTrackerOverlay);
|
||||||
|
disable();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameStateChanged(GameStateChanged event)
|
||||||
|
{
|
||||||
|
switch (event.getGameState())
|
||||||
|
{
|
||||||
|
case LOGIN_SCREEN:
|
||||||
|
disable();
|
||||||
|
break;
|
||||||
|
case HOPPING:
|
||||||
|
hopping = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onHitsplatApplied(HitsplatApplied e)
|
||||||
|
{
|
||||||
|
if (isPaused())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.getActor().equals(client.getLocalPlayer()))
|
||||||
|
{
|
||||||
|
// Auto enables when hitsplat is applied to player
|
||||||
|
if (!isEnabled())
|
||||||
|
{
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
performance.addDamageTaken(e.getHitsplat().getAmount(), client.getTickCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onExperienceChanged(ExperienceChanged c)
|
||||||
|
{
|
||||||
|
if (isPaused() || hopping)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.getSkill().equals(Skill.HITPOINTS))
|
||||||
|
{
|
||||||
|
final double oldExp = hpExp;
|
||||||
|
hpExp = client.getSkillExperience(Skill.HITPOINTS);
|
||||||
|
|
||||||
|
// Ignore initial login
|
||||||
|
if (client.getTickCount() < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double diff = hpExp - oldExp;
|
||||||
|
if (diff < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto enables when player receives hp exp
|
||||||
|
if (!isEnabled())
|
||||||
|
{
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
final double damageDealt = calculateDamageDealt(diff);
|
||||||
|
performance.addDamageDealt(damageDealt, client.getTickCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onScriptCallbackEvent(ScriptCallbackEvent e)
|
||||||
|
{
|
||||||
|
// Handles Fake XP drops (Ironman in PvP, DMM Cap, 200m xp, etc)
|
||||||
|
if (isPaused())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"fakeXpDrop".equals(e.getEventName()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] intStack = client.getIntStack();
|
||||||
|
final int intStackSize = client.getIntStackSize();
|
||||||
|
|
||||||
|
final int skillId = intStack[intStackSize - 2];
|
||||||
|
final Skill skill = Skill.values()[skillId];
|
||||||
|
if (skill.equals(Skill.HITPOINTS))
|
||||||
|
{
|
||||||
|
// Auto enables when player would have received hp exp
|
||||||
|
if (!isEnabled())
|
||||||
|
{
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int exp = intStack[intStackSize - 1];
|
||||||
|
performance.addDamageDealt(calculateDamageDealt(exp), client.getTickCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameTick(GameTick t)
|
||||||
|
{
|
||||||
|
oldTarget = client.getLocalPlayer().getInteracting();
|
||||||
|
|
||||||
|
if (!isEnabled())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPaused())
|
||||||
|
{
|
||||||
|
pausedTicks++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
performance.incrementTicksSpent();
|
||||||
|
hopping = false;
|
||||||
|
|
||||||
|
final int timeout = config.submitTimeout();
|
||||||
|
if (timeout > 0)
|
||||||
|
{
|
||||||
|
final double tickTimeout = timeout / GAME_TICK_SECONDS;
|
||||||
|
final int activityDiff = (client.getTickCount() - pausedTicks) - performance.getLastActivityTick();
|
||||||
|
if (activityDiff > tickTimeout)
|
||||||
|
{
|
||||||
|
// offset the tracker time to account for idle timeout
|
||||||
|
// Leave an additional tick to pad elapsed time
|
||||||
|
final double offset = tickTimeout - GAME_TICK_SECONDS;
|
||||||
|
performance.setTicksSpent(performance.getTicksSpent() - offset);
|
||||||
|
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onOverlayMenuClicked(OverlayMenuClicked c)
|
||||||
|
{
|
||||||
|
if (!c.getOverlay().equals(performanceTrackerOverlay))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c.getEntry().getOption())
|
||||||
|
{
|
||||||
|
case "Pause":
|
||||||
|
togglePaused();
|
||||||
|
break;
|
||||||
|
case "Reset":
|
||||||
|
reset();
|
||||||
|
break;
|
||||||
|
case "Submit":
|
||||||
|
submit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enable()
|
||||||
|
{
|
||||||
|
this.enabled = true;
|
||||||
|
hpExp = client.getSkillExperience(Skill.HITPOINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disable()
|
||||||
|
{
|
||||||
|
this.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void togglePaused()
|
||||||
|
{
|
||||||
|
this.paused = !this.paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset()
|
||||||
|
{
|
||||||
|
this.enabled = false;
|
||||||
|
this.paused = false;
|
||||||
|
|
||||||
|
this.performance.reset();
|
||||||
|
pausedTicks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submit()
|
||||||
|
{
|
||||||
|
final String message = createPerformanceMessage(performance);
|
||||||
|
|
||||||
|
chatMessageManager.queue(QueuedMessage.builder()
|
||||||
|
.type(ChatMessageType.GAMEMESSAGE)
|
||||||
|
.runeLiteFormattedMessage(message)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates damage dealt based on HP xp gained accounting for multipliers such as DMM mode
|
||||||
|
* @param diff HP xp gained
|
||||||
|
* @return damage dealt
|
||||||
|
*/
|
||||||
|
private double calculateDamageDealt(double diff)
|
||||||
|
{
|
||||||
|
double damageDealt = diff / HITPOINT_RATIO;
|
||||||
|
// DeadMan mode has an XP modifier
|
||||||
|
if (client.getWorldType().contains(WorldType.DEADMAN))
|
||||||
|
{
|
||||||
|
damageDealt = damageDealt / DMM_MULTIPLIER_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some NPCs have an XP modifier, account for it here.
|
||||||
|
Actor a = client.getLocalPlayer().getInteracting();
|
||||||
|
if (!(a instanceof NPC))
|
||||||
|
{
|
||||||
|
// If we are interacting with nothing we may have clicked away at the perfect time fall back to last tick
|
||||||
|
if (!(oldTarget instanceof NPC))
|
||||||
|
{
|
||||||
|
log.warn("Couldn't find current or past target for experienced gain...");
|
||||||
|
return damageDealt;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = oldTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int npcId = ((NPC) a).getId();
|
||||||
|
return damageDealt / npcManager.getXpModifier(npcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createPerformanceMessage(final Performance p)
|
||||||
|
{
|
||||||
|
// Expected result: Damage Dealt: ## (Max: ##), Damage Taken: ## (Max: ##), Time Spent: ##:## (DPS: ##.##)
|
||||||
|
return new ChatMessageBuilder()
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append("Damage dealt: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(numberFormat.format(p.getDamageDealt()))
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append(" (Max: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(numberFormat.format(p.getHighestHitDealt()))
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append("), Damage Taken: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(numberFormat.format(p.getDamageTaken()))
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append(" (Max: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(numberFormat.format(p.getHighestHitTaken()))
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append("), Time Spent: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(p.getHumanReadableSecondsSpent())
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append(" (DPS: ")
|
||||||
|
.append(ChatColorType.HIGHLIGHT)
|
||||||
|
.append(String.valueOf(p.getDPS()))
|
||||||
|
.append(ChatColorType.NORMAL)
|
||||||
|
.append(")")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
runelite-client/src/main/scripts/FakeXPDrops.hash
Normal file
1
runelite-client/src/main/scripts/FakeXPDrops.hash
Normal file
@@ -0,0 +1 @@
|
|||||||
|
32FBC48F8C6D8E62E02BCF09F444BA036F76133B6596396F0AB9E474687D9F3F
|
||||||
256
runelite-client/src/main/scripts/FakeXPDrops.rs2asm
Normal file
256
runelite-client/src/main/scripts/FakeXPDrops.rs2asm
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
.id 2091
|
||||||
|
.int_stack_count 2
|
||||||
|
.string_stack_count 0
|
||||||
|
.int_var_count 2
|
||||||
|
.string_var_count 0
|
||||||
|
iload 0
|
||||||
|
iload 1
|
||||||
|
sconst "fakeXpDrop"
|
||||||
|
runelite_callback ;
|
||||||
|
pop_int
|
||||||
|
pop_int
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 207
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL9
|
||||||
|
jump LABEL16
|
||||||
|
LABEL9:
|
||||||
|
get_varc_int 207
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 207
|
||||||
|
jump LABEL216
|
||||||
|
LABEL16:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 208
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL25
|
||||||
|
jump LABEL32
|
||||||
|
LABEL25:
|
||||||
|
get_varc_int 208
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 208
|
||||||
|
jump LABEL216
|
||||||
|
LABEL32:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 209
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL41
|
||||||
|
jump LABEL48
|
||||||
|
LABEL41:
|
||||||
|
get_varc_int 209
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 209
|
||||||
|
jump LABEL216
|
||||||
|
LABEL48:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 210
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL57
|
||||||
|
jump LABEL64
|
||||||
|
LABEL57:
|
||||||
|
get_varc_int 210
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 210
|
||||||
|
jump LABEL216
|
||||||
|
LABEL64:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 211
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL73
|
||||||
|
jump LABEL80
|
||||||
|
LABEL73:
|
||||||
|
get_varc_int 211
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 211
|
||||||
|
jump LABEL216
|
||||||
|
LABEL80:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 212
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL89
|
||||||
|
jump LABEL96
|
||||||
|
LABEL89:
|
||||||
|
get_varc_int 212
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 212
|
||||||
|
jump LABEL216
|
||||||
|
LABEL96:
|
||||||
|
iconst 105
|
||||||
|
iconst 83
|
||||||
|
iconst 681
|
||||||
|
get_varc_int 213
|
||||||
|
coordx
|
||||||
|
enum
|
||||||
|
iload 0
|
||||||
|
if_icmpeq LABEL105
|
||||||
|
jump LABEL112
|
||||||
|
LABEL105:
|
||||||
|
get_varc_int 213
|
||||||
|
iconst 0
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 213
|
||||||
|
jump LABEL216
|
||||||
|
LABEL112:
|
||||||
|
get_varc_int 207
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL116
|
||||||
|
jump LABEL127
|
||||||
|
LABEL116:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 207
|
||||||
|
jump LABEL216
|
||||||
|
LABEL127:
|
||||||
|
get_varc_int 208
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL131
|
||||||
|
jump LABEL142
|
||||||
|
LABEL131:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 208
|
||||||
|
jump LABEL216
|
||||||
|
LABEL142:
|
||||||
|
get_varc_int 209
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL146
|
||||||
|
jump LABEL157
|
||||||
|
LABEL146:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 209
|
||||||
|
jump LABEL216
|
||||||
|
LABEL157:
|
||||||
|
get_varc_int 210
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL161
|
||||||
|
jump LABEL172
|
||||||
|
LABEL161:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 210
|
||||||
|
jump LABEL216
|
||||||
|
LABEL172:
|
||||||
|
get_varc_int 211
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL176
|
||||||
|
jump LABEL187
|
||||||
|
LABEL176:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 211
|
||||||
|
jump LABEL216
|
||||||
|
LABEL187:
|
||||||
|
get_varc_int 212
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL191
|
||||||
|
jump LABEL202
|
||||||
|
LABEL191:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 212
|
||||||
|
jump LABEL216
|
||||||
|
LABEL202:
|
||||||
|
get_varc_int 213
|
||||||
|
iconst -1
|
||||||
|
if_icmpeq LABEL206
|
||||||
|
jump LABEL216
|
||||||
|
LABEL206:
|
||||||
|
iconst 0
|
||||||
|
iconst 83
|
||||||
|
iconst 105
|
||||||
|
iconst 81
|
||||||
|
iload 0
|
||||||
|
enum
|
||||||
|
iconst 0
|
||||||
|
iload 1
|
||||||
|
movecoord
|
||||||
|
set_varc_int 213
|
||||||
|
LABEL216:
|
||||||
|
return
|
||||||
Reference in New Issue
Block a user