Implement Skill Calculator plug-in

This commit is contained in:
Kruithne
2018-04-23 17:40:32 +01:00
committed by Adam
parent 0acde2bd06
commit b923335ed1
29 changed files with 7537 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import com.google.gson.Gson;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import net.runelite.client.plugins.skillcalculator.beans.SkillData;
class CacheSkillData
{
private final Map<String, SkillData> cache = new HashMap<>();
SkillData getSkillData(String dataFile)
{
if (cache.containsKey(dataFile))
{
return cache.get(dataFile);
}
InputStream skillDataFile = SkillCalculatorPlugin.class.getResourceAsStream(dataFile);
SkillData skillData = new Gson().fromJson(new InputStreamReader(skillDataFile), SkillData.class);
cache.put(dataFile, skillData);
return skillData;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.Skill;
@AllArgsConstructor
@Getter
enum CalculatorType
{
MINING(Skill.MINING, "skill_mining.json"),
AGILITY(Skill.AGILITY, "skill_agility.json"),
SMITHING(Skill.SMITHING, "skill_smithing.json"),
HERBLORE(Skill.HERBLORE, "skill_herblore.json"),
FISHING(Skill.FISHING, "skill_fishing.json"),
THIEVING(Skill.THIEVING, "skill_thieving.json"),
COOKING(Skill.COOKING, "skill_cooking.json"),
PRAYER(Skill.PRAYER, "skill_prayer.json"),
CRAFTING(Skill.CRAFTING, "skill_crafting.json"),
FIREMAKING(Skill.FIREMAKING, "skill_firemaking.json"),
MAGIC(Skill.MAGIC, "skill_magic.json"),
FLETCHING(Skill.FLETCHING, "skill_fletching.json"),
WOODCUTTING(Skill.WOODCUTTING, "skill_woodcutting.json"),
RUNECRAFT(Skill.RUNECRAFT, "skill_runecraft.json"),
FARMING(Skill.FARMING, "skill_farming.json"),
CONSTRUCTION(Skill.CONSTRUCTION, "skill_construction.json"),
HUNTER(Skill.HUNTER, "skill_hunter.json");
private final Skill skill;
private final String dataFile;
}

View File

@@ -0,0 +1,295 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.runelite.api.Client;
import net.runelite.api.Experience;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.skillcalculator.beans.SkillData;
import net.runelite.client.plugins.skillcalculator.beans.SkillDataBonus;
import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry;
class SkillCalculator extends JPanel
{
private Client client;
private SkillData skillData;
private List<UIActionSlot> uiActionSlots = new ArrayList<>();
private UICalculatorInputArea uiInput;
private CacheSkillData cacheSkillData = new CacheSkillData();
static SpriteManager spriteManager;
static ItemManager itemManager;
private UICombinedActionSlot combinedActionSlot = new UICombinedActionSlot();
private ArrayList<UIActionSlot> combinedActionSlots = new ArrayList<>();
private int currentLevel = 1;
private int currentXP = Experience.getXpForLevel(currentLevel);
private int targetLevel = currentLevel + 1;
private int targetXP = Experience.getXpForLevel(targetLevel);
private float xpFactor = 1.0f;
private static int MAX_XP = Experience.getXpForLevel(Experience.MAX_VIRT_LEVEL);
private static DecimalFormat XP_FORMAT = new DecimalFormat("#.#");
SkillCalculator(Client client, UICalculatorInputArea uiInput)
{
this.client = client;
this.uiInput = uiInput;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createLineBorder(getBackground().brighter()));
// Register listeners on the input fields..
uiInput.uiFieldCurrentLevel.addActionListener(e -> onFieldCurrentLevelUpdated());
uiInput.uiFieldCurrentXP.addActionListener(e -> onFieldCurrentXPUpdated());
uiInput.uiFieldTargetLevel.addActionListener(e -> onFieldTargetLevelUpdated());
uiInput.uiFieldTargetXP.addActionListener(e -> onFieldTargetXPUpdated());
}
void openCalculator(CalculatorType calculatorType)
{
// Load the skill data.
skillData = cacheSkillData.getSkillData(calculatorType.getDataFile());
// Reset the XP factor, removing bonuses.
xpFactor = 1.0f;
// Update internal skill/XP values.
currentXP = client.getSkillExperience(calculatorType.getSkill());
currentLevel = Experience.getLevelForXp(currentXP);
targetLevel = enforceSkillBounds(currentLevel + 1);
targetXP = Experience.getXpForLevel(targetLevel);
// Remove all components (action slots) from this panel.
removeAll();
// Add in checkboxes for available skill bonuses.
renderBonusOptions();
// Add the combined action slot.
add(combinedActionSlot);
// Create action slots for the skill actions.
renderActionSlots();
// Update the input fields.
updateInputFields();
}
private void updateCombinedAction()
{
int size = combinedActionSlots.size();
if (size > 1)
{
combinedActionSlot.setTitle(size + " actions selected");
}
else if (size == 1)
{
combinedActionSlot.setTitle("1 action selected");
}
else
{
combinedActionSlot.setTitle("No action selected");
combinedActionSlot.setText("Shift-click to select multiple");
return;
}
int actionCount = 0;
int neededXP = targetXP - currentXP;
double xp = 0;
for (UIActionSlot slot : combinedActionSlots)
xp += slot.value;
if (neededXP > 0)
actionCount = (int) Math.ceil(neededXP / xp);
combinedActionSlot.setText(formatXPActionString(xp, actionCount));
}
private void clearCombinedSlots()
{
for (UIActionSlot slot : combinedActionSlots)
slot.setSelected(false);
combinedActionSlots.clear();
}
private void renderBonusOptions()
{
if (skillData.bonuses != null)
{
for (SkillDataBonus bonus : skillData.bonuses)
{
JPanel uiOption = new JPanel(new BorderLayout());
JLabel uiLabel = new JLabel(bonus.name);
JCheckBox uiCheckbox = new JCheckBox();
// Adding an empty 8-pixel border on the left gives us nice padding.
uiOption.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
// Adjust XP bonus depending on check-state of the boxes.
uiCheckbox.addActionListener(e -> adjustXPBonus(uiCheckbox.isSelected(), bonus.value));
uiOption.add(uiLabel, BorderLayout.WEST);
uiOption.add(uiCheckbox, BorderLayout.EAST);
add(uiOption);
}
}
}
private void renderActionSlots()
{
// Wipe the list of references to the slot components.
uiActionSlots.clear();
// Create new components for the action slots.
for (SkillDataEntry action : skillData.actions)
{
UIActionSlot slot = new UIActionSlot(action);
uiActionSlots.add(slot); // Keep our own reference.
add(slot); // Add component to the panel.
slot.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
if (!e.isShiftDown())
clearCombinedSlots();
if (slot.isSelected)
combinedActionSlots.remove(slot);
else
combinedActionSlots.add(slot);
slot.setSelected(!slot.isSelected);
updateCombinedAction();
}
});
}
// Refresh the rendering of this panel.
revalidate();
repaint();
}
private void calculate()
{
for (UIActionSlot slot : uiActionSlots)
{
int actionCount = 0;
int neededXP = targetXP - currentXP;
double xp = slot.action.xp * xpFactor;
if (neededXP > 0)
actionCount = (int) Math.ceil(neededXP / xp);
slot.setText(formatXPActionString(xp, actionCount));
slot.setAvailable(currentLevel >= slot.action.level);
slot.value = xp;
}
}
private String formatXPActionString(double xp, int actionCount)
{
return XP_FORMAT.format(xp) + "xp - " + NumberFormat.getIntegerInstance().format(actionCount) + (actionCount > 1 ? " actions" : " action");
}
private void updateInputFields()
{
if (targetXP < currentXP)
{
targetLevel = enforceSkillBounds(currentLevel + 1);
targetXP = Experience.getXpForLevel(targetLevel);
}
uiInput.setCurrentLevelInput(currentLevel);
uiInput.setCurrentXPInput(currentXP);
uiInput.setTargetLevelInput(targetLevel);
uiInput.setTargetXPInput(targetXP);
calculate();
}
private void adjustXPBonus(boolean addBonus, float value)
{
xpFactor += addBonus ? value : -value;
calculate();
}
private void onFieldCurrentLevelUpdated()
{
currentLevel = enforceSkillBounds(uiInput.getCurrentLevelInput());
currentXP = Experience.getXpForLevel(currentLevel);
updateInputFields();
}
private void onFieldCurrentXPUpdated()
{
currentXP = enforceXPBounds(uiInput.getCurrentXPInput());
currentLevel = Experience.getLevelForXp(currentXP);
updateInputFields();
}
private void onFieldTargetLevelUpdated()
{
targetLevel = enforceSkillBounds(uiInput.getTargetLevelInput());
targetXP = Experience.getXpForLevel(targetLevel);
updateInputFields();
}
private void onFieldTargetXPUpdated()
{
targetXP = enforceXPBounds(uiInput.getTargetXPInput());
targetLevel = Experience.getLevelForXp(targetXP);
updateInputFields();
}
private static int enforceSkillBounds(int input)
{
return Math.min(Experience.MAX_VIRT_LEVEL, Math.max(1, input));
}
private static int enforceXPBounds(int input)
{
return Math.min(MAX_XP, Math.max(0, input));
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import net.runelite.api.Client;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.PluginPanel;
class SkillCalculatorPanel extends PluginPanel
{
private JButton activeButton;
private int uiButtonIndex = 0;
private final SkillCalculator uiCalculator;
private final SkillIconManager iconManager;
private final JPanel uiButtonGrid = new JPanel();
private final GridBagLayout uiButtonGridLayout = new GridBagLayout();
private final GridBagConstraints uiButtonGridConstraints = new GridBagConstraints();
SkillCalculatorPanel(SkillIconManager iconManager, Client client)
{
super();
this.iconManager = iconManager;
BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS);
setLayout(layout);
uiButtonGridConstraints.fill = GridBagConstraints.BOTH;
uiButtonGridConstraints.weightx = 1;
uiButtonGridConstraints.ipady = 12;
uiButtonGridConstraints.insets = new Insets(2, 2, 2, 2);
uiButtonGrid.setLayout(uiButtonGridLayout);
uiButtonGrid.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
addCalculatorButtons();
final UICalculatorInputArea uiInput = new UICalculatorInputArea();
uiCalculator = new SkillCalculator(client, uiInput);
add(uiButtonGrid);
add(Box.createRigidArea(new Dimension(0, 8)));
add(uiInput);
add(Box.createRigidArea(new Dimension(0, 14)));
add(uiCalculator);
}
private void addCalculatorButtons()
{
for (CalculatorType calculatorType : CalculatorType.values())
{
final JButton uiButton = new JButton();
final BufferedImage icon = iconManager.getSkillImage(calculatorType.getSkill());
uiButton.addActionListener(e -> openCalculator(calculatorType, uiButton));
uiButton.setIcon(new ImageIcon(icon));
uiButton.setToolTipText(calculatorType.getSkill().getName());
uiButton.setFocusPainted(false);
uiButtonGridConstraints.gridx = uiButtonIndex % 4;
uiButtonGridLayout.setConstraints(uiButton, uiButtonGridConstraints);
uiButtonGrid.add(uiButton);
uiButtonIndex++;
}
}
private void openCalculator(CalculatorType calculatorType, JButton button)
{
// Remove highlight from existing button..
if (activeButton != null)
activeButton.setSelected(false);
// Set the new button as selected..
button.setSelected(true);
activeButton = button;
// Invoke the calculator component..
uiCalculator.openCalculator(calculatorType);
// Refresh rendering..
revalidate();
repaint();
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.PluginToolbar;
@PluginDescriptor(name = "Skill Calculator")
public class SkillCalculatorPlugin extends Plugin
{
@Inject
private ClientUI ui;
@Inject
private Client client;
@Inject
private SkillIconManager skillIconManager;
@Inject
private ItemManager itemManager;
@Inject
private SpriteManager spriteManager;
@Inject
private PluginToolbar pluginToolbar;
private NavigationButton uiNavigationButton;
private SkillCalculatorPanel uiPanel;
@Override
protected void startUp() throws Exception
{
BufferedImage icon;
synchronized (ImageIO.class)
{
icon = ImageIO.read(getClass().getResourceAsStream("calc.png"));
}
SkillCalculator.spriteManager = spriteManager;
SkillCalculator.itemManager = itemManager;
uiPanel = new SkillCalculatorPanel(skillIconManager, client);
uiNavigationButton = NavigationButton.builder().name("Skill Calculator").icon(icon).panel(uiPanel).build();
pluginToolbar.addNavigation(uiNavigationButton);
}
@Override
protected void shutDown() throws Exception
{
pluginToolbar.removeNavigation(uiNavigationButton);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.JShadowedLabel;
class UIActionSlot extends JPanel
{
SkillDataEntry action;
private JShadowedLabel uiLabelActions;
private static final Dimension ICON_SIZE = new Dimension(32, 32);
boolean isAvailable = false;
boolean isSelected = false;
double value = 0;
UIActionSlot(SkillDataEntry action)
{
this.action = action;
BorderLayout layout = new BorderLayout();
layout.setHgap(8);
setLayout(layout);
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JLabel uiIcon = new JLabel();
if (action.icon != null)
SkillCalculator.itemManager.getImage(action.icon).addTo(uiIcon);
else if (action.sprite != null)
SkillCalculator.spriteManager.addSpriteTo(uiIcon, action.sprite, 0);
uiIcon.setMinimumSize(ICON_SIZE);
uiIcon.setMaximumSize(ICON_SIZE);
uiIcon.setPreferredSize(ICON_SIZE);
uiIcon.setHorizontalAlignment(JLabel.CENTER);
add(uiIcon, BorderLayout.LINE_START);
JPanel uiInfo = new JPanel(new GridLayout(2, 1));
uiInfo.setOpaque(false);
JShadowedLabel uiLabelName = new JShadowedLabel(action.name);
uiInfo.add(uiLabelName);
uiLabelActions = new JShadowedLabel("Unknown");
uiLabelActions.setFont(FontManager.getRunescapeSmallFont());
uiInfo.add(uiLabelActions);
add(uiInfo, BorderLayout.CENTER);
}
void setSelected(boolean selected)
{
isSelected = selected;
updateBackground();
}
void setAvailable(boolean available)
{
isAvailable = available;
updateBackground();
}
void setText(String text)
{
uiLabelActions.setText(text);
}
private void updateBackground()
{
if (isSelected)
this.setBackground(isAvailable ? Color.GREEN : Color.RED);
else
this.setBackground(isAvailable ? Color.GREEN.darker() : Color.RED.darker());
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
class UICalculatorInputArea extends JPanel
{
private final GridBagLayout uiLayout;
private final GridBagConstraints uiConstraints;
private int gridX = 0;
private int gridY = 0;
JTextField uiFieldCurrentLevel;
JTextField uiFieldCurrentXP;
JTextField uiFieldTargetLevel;
JTextField uiFieldTargetXP;
UICalculatorInputArea()
{
uiLayout = new GridBagLayout();
uiConstraints = new GridBagConstraints();
uiConstraints.insets = new Insets(3, 9, 3, 9);
setLayout(uiLayout);
uiFieldCurrentLevel = addComponent("Current Level");
uiFieldCurrentXP = addComponent("Current XP");
uiFieldTargetLevel = addComponent("Target Level");
uiFieldTargetXP = addComponent("Target XP");
}
int getCurrentLevelInput()
{
return getInput(uiFieldCurrentLevel);
}
void setCurrentLevelInput(int value)
{
setInput(uiFieldCurrentLevel, value);
}
int getCurrentXPInput()
{
return getInput(uiFieldCurrentXP);
}
void setCurrentXPInput(Object value)
{
setInput(uiFieldCurrentXP, value);
}
int getTargetLevelInput()
{
return getInput(uiFieldTargetLevel);
}
void setTargetLevelInput(Object value)
{
setInput(uiFieldTargetLevel, value);
}
int getTargetXPInput()
{
return getInput(uiFieldTargetXP);
}
void setTargetXPInput(Object value)
{
setInput(uiFieldTargetXP, value);
}
private int getInput(JTextField field)
{
try
{
return Integer.parseInt(field.getText());
}
catch (NumberFormatException e)
{
return 0;
}
}
private void setInput(JTextField field, Object value)
{
field.setText(String.valueOf(value));
}
private JTextField addComponent(String label)
{
final JLabel uiLabel = new JLabel(label);
final JTextField uiField = new JTextField(6);
uiConstraints.gridx = gridX;
uiConstraints.gridy = gridY;
uiLayout.setConstraints(uiLabel, uiConstraints);
add(uiLabel);
uiConstraints.gridy++;
uiLayout.setConstraints(uiField, uiConstraints);
add(uiField);
gridX++;
if (gridX % 2 == 0)
{
gridY += 2;
gridX = 0;
}
return uiField;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.JShadowedLabel;
class UICombinedActionSlot extends JPanel
{
private JShadowedLabel uiLabelActions;
private JShadowedLabel uiLabelTitle;
private static final Dimension ICON_SIZE = new Dimension(32, 32);
UICombinedActionSlot()
{
BorderLayout layout = new BorderLayout();
layout.setHgap(8);
setLayout(layout);
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JLabel uiIcon = new JLabel();
SkillCalculator.spriteManager.addSpriteTo(uiIcon, 582, 0);
uiIcon.setMinimumSize(ICON_SIZE);
uiIcon.setMaximumSize(ICON_SIZE);
uiIcon.setPreferredSize(ICON_SIZE);
uiIcon.setHorizontalAlignment(JLabel.CENTER);
add(uiIcon, BorderLayout.LINE_START);
JPanel uiInfo = new JPanel(new GridLayout(2, 1));
uiInfo.setOpaque(false);
uiLabelTitle = new JShadowedLabel("No Action Selected");
uiInfo.add(uiLabelTitle);
uiLabelActions = new JShadowedLabel("Shift-click to select multiple");
uiLabelActions.setFont(FontManager.getRunescapeSmallFont());
uiInfo.add(uiLabelActions);
setBackground(Color.orange);
add(uiInfo, BorderLayout.CENTER);
}
void setText(String text)
{
uiLabelActions.setText(text);
}
void setTitle(String text)
{
uiLabelTitle.setText(text);
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator.beans;
public class SkillData
{
public SkillDataEntry[] actions;
public SkillDataBonus[] bonuses;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator.beans;
public class SkillDataBonus
{
public String name;
public float value;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@gmail.com>
* 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.skillcalculator.beans;
public class SkillDataEntry
{
public String name;
public int level;
public double xp;
public Integer icon;
public Integer sprite;
}