From 85b43fa92bf87d299a6c732c931335deb92bbad7 Mon Sep 17 00:00:00 2001 From: HanhSantos Date: Sat, 16 Aug 2025 09:42:34 -0700 Subject: [PATCH] feat(overall): Add Overall Mode This commit introduces a new "Overall" mode to the Combat Logger. When enabled, all combat data is logged into a single, continuous fight session, which persists until the mode is disabled or the client is closed. This provides users with a way to track their total damage over an entire play session without creating separate entries for each encounter. Key Changes: Overall Mode: Added an "Enable Overall Mode" toggle in the plugin configuration. Implemented logic in FightManager to start, stop, and manage a single overallFight object. Modified addDamage and addTicks to route all data to the overallFight when the mode is active, preventing the creation of new fight sessions. Added startUp and shutDown methods to CombatLoggerPlugin to correctly initialize and terminate the "Overall" mode when RuneLite starts or closes with the setting enabled. --- .../com/combatlogger/CombatLoggerConfig.java | 13 ++++ .../com/combatlogger/CombatLoggerPlugin.java | 65 ++++++++++++++++-- .../java/com/combatlogger/FightManager.java | 68 ++++++++++++++++++- .../combatlogger/panel/CombatLoggerPanel.java | 22 ++++-- 4 files changed, 157 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/combatlogger/CombatLoggerConfig.java b/src/main/java/com/combatlogger/CombatLoggerConfig.java index 389208f..436b9a5 100644 --- a/src/main/java/com/combatlogger/CombatLoggerConfig.java +++ b/src/main/java/com/combatlogger/CombatLoggerConfig.java @@ -62,6 +62,19 @@ default Color selfDamageMeterColor() return new Color(139, 15, 16); } + /** + * Configuration item for enabling the "Overall" fight mode. + * When enabled, all combat data is logged into a single, continuous fight session + * instead of creating a new session for each encounter. + */ + @ConfigItem( + keyName = "overallMode", + name = "Enable Overall Mode", + description = "Logs all damage into a single 'Overall' fight until disabled.", + position = 3 + ) + default boolean overallMode() { return false; } + /* Overlay Settings * POSITIONS: 26-49 * */ diff --git a/src/main/java/com/combatlogger/CombatLoggerPlugin.java b/src/main/java/com/combatlogger/CombatLoggerPlugin.java index 0d2a7c8..640e924 100644 --- a/src/main/java/com/combatlogger/CombatLoggerPlugin.java +++ b/src/main/java/com/combatlogger/CombatLoggerPlugin.java @@ -181,6 +181,11 @@ CombatLoggerConfig provideConfig(ConfigManager configManager) return configManager.getConfig(CombatLoggerConfig.class); } + /** + * This method is called when the plugin is started. + * We need to check the state of the config here to initialize the plugin correctly, + * as onConfigChanged won't fire for settings that are already enabled on startup. + */ @Override protected void startUp() { @@ -209,8 +214,19 @@ protected void startUp() setOverlayVisible(true); resetOverlayTimeout(); } + + // Check if "Overall Mode" is enabled in the configuration when the plugin starts. + if (config.overallMode()) + { + // If it is, we must manually start the session. + fightManager.startOverallMode(); + } } + /** + * This method is called when the plugin is stopped. + * It's good practice to clean up and finalize any ongoing sessions. + */ @Override protected void shutDown() { @@ -233,6 +249,9 @@ protected void shutDown() logQueueManager.shutDown(eventBus); fightManager.shutDown(); setOverlayVisible(false); + // If the "Overall" fight is active, this will properly end it and add it + // to the fight history dropdown. + fightManager.stopOverallMode(); } @@ -294,9 +313,29 @@ public void onNpcChanged(NpcChanged event) ); } + + /** + * Called on every in-game tick (0.6 seconds). + * This method is used for time-based updates, like incrementing fight timers. + */ @Subscribe public void onGameTick(GameTick event) { + // --- Overall Mode Timer Logic --- + // This block handles the timer for the "Overall" fight mode. + // It's placed in onGameTick to ensure the timer increments accurately once per tick, + // preventing the bug where it increased with every damage event. + if (config.overallMode()) + { + Fight overallFight = fightManager.getOverallFight(); + // Only increment the timer if the overall fight exists and is not considered over + if (overallFight != null && !overallFight.isOver()) + { + overallFight.setFightLengthTicks(overallFight.getFightLengthTicks() + 1); + } + } + // --- End of Overall Mode Logic --- + Fight currentFight = fightManager.getLastFight(); boolean fightOngoing = currentFight != null && !currentFight.isOver(); @@ -326,7 +365,7 @@ else if (!fightOngoing && inFight) } } - panel.updatePanel(); + panel.updatePanel(config); if (checkPlayerName && client.getLocalPlayer() != null && client.getLocalPlayer().getName() != null) { @@ -1234,7 +1273,10 @@ public void onMenuOpened(MenuOpened event) } } - + /** + * Handles configuration changes for the plugin. + * Specifically, this starts or stops the "Overall" fight mode when the setting is toggled. + */ @Subscribe public void onConfigChanged(ConfigChanged event) { @@ -1246,12 +1288,12 @@ public void onConfigChanged(ConfigChanged event) switch (event.getKey()) { case "secondaryMetric": - panel.updatePanel(); + panel.updatePanel(config); break; case "selfDamageMeterColor": fightManager.clearPlayerColors(); - panel.updatePanel(); + panel.updatePanel(config); break; case "enableOverlay": @@ -1277,6 +1319,21 @@ public void onConfigChanged(ConfigChanged event) damageOverlay.setOpacity(config.overlayOpacity()); break; } + + // If the "overallMode" setting was changed, handle it + if (event.getKey().equals("overallMode")) + { + if (config.overallMode()) + { + // If the user enabled overall mode, start a new session + fightManager.startOverallMode(); + } + else + { + // If the user disabled overall mode, stop the current session + fightManager.stopOverallMode(); + } + } } protected static String getCurrentTimestamp() diff --git a/src/main/java/com/combatlogger/FightManager.java b/src/main/java/com/combatlogger/FightManager.java index 7c381a8..d790db4 100644 --- a/src/main/java/com/combatlogger/FightManager.java +++ b/src/main/java/com/combatlogger/FightManager.java @@ -43,6 +43,9 @@ public class FightManager private final Client client; private final Map playerColors = new ConcurrentHashMap<>(); private final EventBus eventBus; + @Getter + private Fight overallFight = null; + @Getter private final BoundedQueue fights = new BoundedQueue<>(20); @@ -101,8 +104,26 @@ public void shutDown() eventBus.unregister(this); } + public void startOverallMode() + { + overallFight = new Fight(); + overallFight.setFightName("Overall"); + overallFight.setMainTarget("Overall"); + overallFight.setOver(false); + } + + public void stopOverallMode() + { + if (overallFight != null) + { + overallFight.setOver(true); + // You might want to add the overallFight to the regular fights list here to view it after stopping + fights.add(overallFight); + overallFight = null; + } + } - public List getPlayerDamageForFight(Fight fight) + public List getPlayerDamageForFight(Fight fight) { if (fight == null) { @@ -204,6 +225,13 @@ public void clearFights() fights.clear(); selectedFight = null; clearPlayerColors(); // Optionally clear player colors when clearing fights + + // Add this check to reset the overall fight + if (config.overallMode()) + { + // Re-initialize the overall session + startOverallMode(); + } } /** @@ -254,6 +282,25 @@ public void clearPlayerColors() public void addDamage(DamageLog damageLog) { + // --- Overall Mode Logic --- + // If overall mode is enabled, we only log damage to the overallFight session. + if (config.overallMode()) + { + if (overallFight != null) + { + // Update the last activity tick to keep the session alive + overallFight.setLastActivityTick(client.getTickCount()); + // Get or create player data for the damage source + Fight.PlayerData playerData = overallFight.getPlayerDataMap().computeIfAbsent(damageLog.getSource(), Fight.PlayerData::new); + // Add the damage amount to the player's stats + playerData.addDamage(damageLog.getTargetName(), damageLog.getDamageAmount()); + } + // IMPORTANT: We return here to prevent the code below from running, + // which would create a new, separate fight for this damage event. + return; + } + // --- End of Overall Mode Logic --- + if (NON_DAMAGE_HITSPLATS.contains(damageLog.getHitsplatName())) { return; @@ -316,6 +363,25 @@ public void addDamage(DamageLog damageLog) public void addTicks(AttackAnimationLog attackAnimationLog) { + // --- Overall Mode Logic --- + // If overall mode is enabled, we only log activity ticks to the overallFight session. + if (config.overallMode()) + { + if (overallFight != null) + { + // Update the last activity tick + overallFight.setLastActivityTick(client.getTickCount()); + // Get or create player data for the attacker + Fight.PlayerData playerData = overallFight.getPlayerDataMap().computeIfAbsent(attackAnimationLog.getSource(), Fight.PlayerData::new); + // Add the activity ticks based on the animation/weapon used + playerData.addActivityTicks(attackAnimationLog.getTargetName(), + AnimationIds.getTicks(attackAnimationLog.getAnimationId(), attackAnimationLog.getWeaponId())); + } + // IMPORTANT: Return here to prevent creating a new, separate fight. + return; + } + // --- End of Overall Mode Logic --- + Fight currentFight; if (fights.isEmpty() || fights.peekLast().isOver()) diff --git a/src/main/java/com/combatlogger/panel/CombatLoggerPanel.java b/src/main/java/com/combatlogger/panel/CombatLoggerPanel.java index e48c84d..b77d985 100644 --- a/src/main/java/com/combatlogger/panel/CombatLoggerPanel.java +++ b/src/main/java/com/combatlogger/panel/CombatLoggerPanel.java @@ -92,14 +92,14 @@ public CombatLoggerPanel(CombatLoggerConfig config, FightManager fightManager) cardLayout = new CardLayout(); damageMeterPanel = new JPanel(cardLayout); - updateFightsComboBox(fightManager.getFights()); + updateFightsComboBox(config,fightManager.getFights()); JButton clearFightsButton = createButton(CLOSE_ICON, "Clear all fights", () -> { if (isConfirmed("Are you sure you want to clear all fights?", "Clear all fights")) { fightManager.clearFights(); - updateFightsComboBox(fightManager.getFights()); + updateFightsComboBox(config,fightManager.getFights()); updateOverviewPanel(new ArrayList<>()); showOverviewPanel(); } @@ -165,12 +165,16 @@ public void updateCurrentFightLength(String fightLength) currentFightLengthLabel.setText(fightLength); } - public void updateFightsComboBox(BoundedQueue fights) + public void updateFightsComboBox(CombatLoggerConfig config, BoundedQueue fights) { List updatedFights = new ArrayList<>(); // Reverse order so the newest fights are first fights.descendingIterator().forEachRemaining(updatedFights::add); + if (config.overallMode() && fightManager.getOverallFight() != null) { + updatedFights.add(0, fightManager.getOverallFight()); // Add overall fight to the top + } + List existingFights = new ArrayList<>(); for (int i = 0; i < fightsComboBox.getItemCount(); i++) { @@ -213,9 +217,15 @@ private boolean isConfirmed(final String message, final String title) /** * Update the panel with the latest data */ - public void updatePanel() + public void updatePanel(CombatLoggerConfig config) { - selectedFight = fightManager.getSelectedFight(); + // If in overall mode, force the selected fight to be the overall fight + if (config.overallMode() && fightManager.getOverallFight() != null) { + selectedFight = fightManager.getOverallFight(); + } else { + selectedFight = fightManager.getSelectedFight(); + } + if (selectedFight != null) { List playerStats = fightManager.getPlayerDamageForFight(selectedFight); @@ -227,7 +237,7 @@ public void updatePanel() updateCurrentFightLength("00:00"); } - updateFightsComboBox(fightManager.getFights()); + updateFightsComboBox(config,fightManager.getFights()); } }