461 lines
11 KiB
Java
461 lines
11 KiB
Java
package ee.futur.easygiantsfoundry;
|
|
|
|
import ee.futur.easygiantsfoundry.enums.Heat;
|
|
import ee.futur.easygiantsfoundry.enums.MetalBarType;
|
|
import ee.futur.easygiantsfoundry.enums.Stage;
|
|
import java.awt.Color;
|
|
import java.awt.Dimension;
|
|
import java.awt.Graphics2D;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import javax.inject.Inject;
|
|
import javax.inject.Singleton;
|
|
import net.runelite.api.Client;
|
|
import net.runelite.client.ui.ColorScheme;
|
|
import net.runelite.client.ui.overlay.OverlayPanel;
|
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
|
import net.runelite.client.ui.overlay.components.LineComponent;
|
|
import net.runelite.client.ui.overlay.components.TitleComponent;
|
|
|
|
@Singleton
|
|
public class FoundryOverlay2D extends OverlayPanel
|
|
{
|
|
private static final int REGION_ID = 13491;
|
|
private static final int PANEL_WIDTH = 240;
|
|
|
|
private final Client client;
|
|
private final EasyGiantsFoundryPlugin plugin;
|
|
private final EasyGiantsFoundryState state;
|
|
private final MetalBarCounter metalBarCounter;
|
|
private final EasyGiantsFoundryConfig config;
|
|
|
|
@Inject
|
|
private FoundryOverlay2D(
|
|
Client client,
|
|
EasyGiantsFoundryPlugin plugin,
|
|
EasyGiantsFoundryState state,
|
|
MetalBarCounter metalBarCounter,
|
|
EasyGiantsFoundryConfig config)
|
|
{
|
|
this.client = client;
|
|
this.plugin = plugin;
|
|
this.state = state;
|
|
this.metalBarCounter = metalBarCounter;
|
|
this.config = config;
|
|
setPosition(OverlayPosition.BOTTOM_LEFT);
|
|
}
|
|
|
|
@Override
|
|
public Dimension render(Graphics2D graphics)
|
|
{
|
|
if (!config.alwaysDrawInfoPanel() && client.getLocalPlayer().getWorldLocation().getRegionID() != REGION_ID)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
panelComponent.getChildren().clear();
|
|
panelComponent.setPreferredSize(new Dimension(PANEL_WIDTH, 0));
|
|
|
|
boolean hasContent = false;
|
|
if (config.drawTitle())
|
|
{
|
|
panelComponent.getChildren().add(TitleComponent.builder().text("Easy Giants' Foundry").build());
|
|
hasContent = true;
|
|
}
|
|
|
|
boolean swordPickedUp = state.isEnabled() && state.getCurrentStage() != null;
|
|
if (swordPickedUp)
|
|
{
|
|
hasContent = appendSection(buildStatusLines(), hasContent);
|
|
hasContent = appendSection(buildProgressLines(), hasContent);
|
|
hasContent = appendSection(buildHeatPlannerLines(), hasContent);
|
|
}
|
|
|
|
hasContent = appendSection(buildReputationLines(), hasContent);
|
|
hasContent = appendSection(buildMetalLines(), hasContent);
|
|
|
|
if (!hasContent)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return super.render(graphics);
|
|
}
|
|
|
|
private boolean appendSection(List<LineComponent> lines, boolean hasPreviousContent)
|
|
{
|
|
if (lines.isEmpty())
|
|
{
|
|
return hasPreviousContent;
|
|
}
|
|
|
|
if (hasPreviousContent)
|
|
{
|
|
panelComponent.getChildren().add(LineComponent.builder().left(" ").right("").build());
|
|
}
|
|
|
|
panelComponent.getChildren().addAll(lines);
|
|
return true;
|
|
}
|
|
|
|
private List<LineComponent> buildStatusLines()
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
Heat heat = state.getCurrentHeat();
|
|
Stage stage = state.getCurrentStage();
|
|
|
|
if (config.drawHeatInfo())
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Heat")
|
|
.right(heat.getName() + " (" + state.getHeatAmount() / 10 + "%)")
|
|
.rightColor(heat.getColor())
|
|
.build()
|
|
);
|
|
}
|
|
|
|
if (config.drawStageInfo())
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Stage")
|
|
.right(stage.getName() + " (" + state.getProgressAmount() / 10 + "%)")
|
|
.rightColor(stage.getHeat().getColor())
|
|
.build()
|
|
);
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
private List<LineComponent> buildProgressLines()
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
int actionsLeft = state.getActionsLeftInStage();
|
|
int heatLeft = state.getActionsForHeatLevel();
|
|
|
|
if (config.drawActionsLeft())
|
|
{
|
|
lines.add(LineComponent.builder().left("Actions left").right(Integer.toString(actionsLeft)).build());
|
|
}
|
|
|
|
if (config.drawHeatLeft())
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Heat left")
|
|
.right(Integer.toString(heatLeft))
|
|
.rightColor(getHeatColor(actionsLeft, heatLeft))
|
|
.build()
|
|
);
|
|
}
|
|
|
|
if (config.drawBonusActions())
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Bonus actions")
|
|
.right(state.getBonusActionsReceived() + "/" + state.getBonusActionsExpected())
|
|
.rightColor(getBonusActionsColor(state.getBonusActionsReceived(), state.getBonusActionsExpected()))
|
|
.build()
|
|
);
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
private List<LineComponent> buildHeatPlannerLines()
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
if (!config.drawHeatDelta() && !config.drawHeatPlan() && !config.drawHeatActionTimer())
|
|
{
|
|
return lines;
|
|
}
|
|
|
|
if (state.getCurrentStage() == null)
|
|
{
|
|
return lines;
|
|
}
|
|
|
|
int heatChangeNeeded = state.getHeatChangeNeeded();
|
|
|
|
if (config.drawHeatDelta())
|
|
{
|
|
lines.add(buildHeatDeltaLine(heatChangeNeeded));
|
|
}
|
|
|
|
if (config.drawHeatPlan())
|
|
{
|
|
lines.addAll(buildHeatPlanLines(heatChangeNeeded));
|
|
}
|
|
|
|
if (config.drawHeatActionTimer())
|
|
{
|
|
LineComponent timerLine = buildHeatActionTimerLine();
|
|
if (timerLine != null)
|
|
{
|
|
lines.add(timerLine);
|
|
}
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
private LineComponent buildHeatDeltaLine(int heatChangeNeeded)
|
|
{
|
|
String location;
|
|
if (heatChangeNeeded > 0)
|
|
{
|
|
location = "Lava";
|
|
}
|
|
else if (heatChangeNeeded < 0)
|
|
{
|
|
location = "Waterfall";
|
|
}
|
|
else
|
|
{
|
|
location = "In range";
|
|
}
|
|
|
|
String deltaText = heatChangeNeeded == 0
|
|
? "0 (in range)"
|
|
: String.format("%+d (%s)", heatChangeNeeded, location);
|
|
|
|
Color color = heatChangeNeeded == 0 ? ColorScheme.PROGRESS_COMPLETE_COLOR : config.lavaWaterfallColour();
|
|
|
|
return LineComponent.builder()
|
|
.left("Heat Δ")
|
|
.right(deltaText)
|
|
.rightColor(color)
|
|
.build();
|
|
}
|
|
|
|
private List<LineComponent> buildHeatPlanLines(int heatChangeNeeded)
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
|
|
if (heatChangeNeeded == 0)
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Heat plan")
|
|
.right("Hold")
|
|
.rightColor(ColorScheme.PROGRESS_COMPLETE_COLOR)
|
|
.build()
|
|
);
|
|
return lines;
|
|
}
|
|
|
|
boolean isHeating = heatChangeNeeded > 0;
|
|
HeatActionSolver.DurationResult fast = solveHeatAction(true, isHeating);
|
|
HeatActionSolver.DurationResult slow = solveHeatAction(false, isHeating);
|
|
boolean added = false;
|
|
|
|
if (fast != null && fast.getDuration() > 0)
|
|
{
|
|
lines.add(buildHeatPlanLine("Fast", isHeating, true, fast));
|
|
added = true;
|
|
}
|
|
|
|
if (slow != null && slow.getDuration() > 0)
|
|
{
|
|
lines.add(buildHeatPlanLine("Slow", isHeating, false, slow));
|
|
added = true;
|
|
}
|
|
|
|
if (!added)
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Heat plan")
|
|
.right("Hold")
|
|
.rightColor(ColorScheme.PROGRESS_COMPLETE_COLOR)
|
|
.build()
|
|
);
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
private LineComponent buildHeatPlanLine(String label, boolean isHeating, boolean fast, HeatActionSolver.DurationResult result)
|
|
{
|
|
String actionName = getActionName(isHeating, fast);
|
|
String value = String.format("%s %dt → %s%s",
|
|
actionName,
|
|
result.getDuration(),
|
|
formatPredictedHeat(result.getPredictedHeat()),
|
|
formatPlanStatus(result));
|
|
|
|
return LineComponent.builder()
|
|
.left(label)
|
|
.right(value)
|
|
.rightColor(config.lavaWaterfallColour())
|
|
.build();
|
|
}
|
|
|
|
private HeatActionSolver.DurationResult solveHeatAction(boolean fast, boolean isHeating)
|
|
{
|
|
Stage stage = state.getCurrentStage();
|
|
if (stage == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return HeatActionSolver.solve(
|
|
stage,
|
|
state.getCurrentHeatRange(),
|
|
state.getActionsLeftInStage(),
|
|
state.getHeatAmount(),
|
|
fast,
|
|
isHeating,
|
|
config.heatActionPadTicks(),
|
|
state.isPlayerRunning()
|
|
);
|
|
}
|
|
|
|
private LineComponent buildHeatActionTimerLine()
|
|
{
|
|
HeatActionStateMachine machine = state.heatActionStateMachine;
|
|
if (machine.isIdle() || machine.getActionname() == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return LineComponent.builder()
|
|
.left("Action")
|
|
.right(String.format(
|
|
"%s %dt → %s%s",
|
|
prettifyActionName(machine.getActionname()),
|
|
machine.getRemainingDuration(),
|
|
formatPredictedHeat(machine.getPredictedHeat()),
|
|
machine.isGoalInRange() ? "" : machine.isOverShooting() ? " (overshoot)" : " (limit)"))
|
|
.rightColor(config.lavaWaterfallColour())
|
|
.build();
|
|
}
|
|
|
|
private String formatPredictedHeat(int predictedHeat)
|
|
{
|
|
return heatPercent(predictedHeat) + "%";
|
|
}
|
|
|
|
private String formatPlanStatus(HeatActionSolver.DurationResult result)
|
|
{
|
|
if (result == null || result.isGoalInRange())
|
|
{
|
|
return "";
|
|
}
|
|
|
|
return result.isOvershooting() ? " (overshoot)" : " (limit)";
|
|
}
|
|
|
|
private String getActionName(boolean isHeating, boolean fast)
|
|
{
|
|
if (isHeating)
|
|
{
|
|
return fast ? "Dunk" : "Heat";
|
|
}
|
|
return fast ? "Quench" : "Cool";
|
|
}
|
|
|
|
private String prettifyActionName(String action)
|
|
{
|
|
if (action == null || action.isEmpty())
|
|
{
|
|
return "";
|
|
}
|
|
|
|
switch (action)
|
|
{
|
|
case "dunks":
|
|
return "Dunk";
|
|
case "heats":
|
|
return "Heat";
|
|
case "cools":
|
|
return "Cool";
|
|
case "quenches":
|
|
return "Quench";
|
|
default:
|
|
return Character.toUpperCase(action.charAt(0)) + action.substring(1);
|
|
}
|
|
}
|
|
|
|
private int heatPercent(int heat)
|
|
{
|
|
return Math.max(0, Math.min(1000, heat)) / 10;
|
|
}
|
|
|
|
private List<LineComponent> buildReputationLines()
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
if (!config.drawShopPoints())
|
|
{
|
|
return lines;
|
|
}
|
|
|
|
lines.add(LineComponent.builder().left("Reputation").right(Integer.toString(plugin.getReputation())).build());
|
|
return lines;
|
|
}
|
|
|
|
private List<LineComponent> buildMetalLines()
|
|
{
|
|
List<LineComponent> lines = new ArrayList<>();
|
|
if (!config.drawMetals())
|
|
{
|
|
return lines;
|
|
}
|
|
|
|
if (!metalBarCounter.isSeenBank())
|
|
{
|
|
lines.add(
|
|
LineComponent.builder()
|
|
.left("Metals: open bank")
|
|
.leftColor(Color.RED)
|
|
.build()
|
|
);
|
|
}
|
|
|
|
addMetalCount(lines, "Bronze bars:", metalBarCounter.get(MetalBarType.BRONZE));
|
|
addMetalCount(lines, "Iron bars:", metalBarCounter.get(MetalBarType.IRON));
|
|
addMetalCount(lines, "Steel bars:", metalBarCounter.get(MetalBarType.STEEL));
|
|
addMetalCount(lines, "Mithril bars:", metalBarCounter.get(MetalBarType.MITHRIL));
|
|
addMetalCount(lines, "Adamant bars:", metalBarCounter.get(MetalBarType.ADAMANT));
|
|
addMetalCount(lines, "Runite bars:", metalBarCounter.get(MetalBarType.RUNITE));
|
|
|
|
return lines;
|
|
}
|
|
|
|
private void addMetalCount(List<LineComponent> lines, String displayName, int count)
|
|
{
|
|
if (count > 0 || config.drawAllMetals())
|
|
{
|
|
lines.add(LineComponent.builder().left(displayName).right(Integer.toString(count)).build());
|
|
}
|
|
}
|
|
|
|
private Color getHeatColor(int actions, int heat)
|
|
{
|
|
if (heat >= actions)
|
|
{
|
|
return ColorScheme.PROGRESS_COMPLETE_COLOR;
|
|
}
|
|
|
|
if (heat > 0)
|
|
{
|
|
return ColorScheme.PROGRESS_INPROGRESS_COLOR;
|
|
}
|
|
|
|
return ColorScheme.PROGRESS_ERROR_COLOR;
|
|
}
|
|
|
|
private Color getBonusActionsColor(int received, int expected)
|
|
{
|
|
if (received >= expected)
|
|
{
|
|
return ColorScheme.PROGRESS_COMPLETE_COLOR;
|
|
}
|
|
|
|
return ColorScheme.PROGRESS_INPROGRESS_COLOR;
|
|
}
|
|
}
|