smokerunecrafter: Performs Smoke Runecrafting at Fire Altar. Requires Fire Tiara equipped, uses Rings of Dueling, Air Talismans, Air Runes, Pure Essence. Will stop and log-out (if enabled) when out of materials.

This commit is contained in:
illumineawake 2020-07-18 17:23:47 +10:00
parent 4d245e9a0a
commit 9cdf4f1faa
8 changed files with 958 additions and 2 deletions

View File

@ -1 +1 @@
[{"projectUrl":"","provider":"illumine","name":"BotUtils","description":"Illumine - Utils required for plugins to function with added automation","id":"botutils-plugin","releases":[{"date":"2020-07-17","sha512sum":"CC6ED545C37F39D54ED1BC4F20E86688AEF1D0242EF8B4A5F64C194EB847598813D7CBDAA1A0579A6774270CAD85F039047678D6ED2F3F6857C45196D316AC88","version":"2.7.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/botutils-2.7.0.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Magic Splasher","description":"Illumine automated magic splasher","id":"magicsplasher-plugin","releases":[{"date":"2020-07-17","sha512sum":"9AE9B6C54B95CAC57416EC725F688028F7327907B1828C2F18BD0AA8301919EEED15A5F7302D9C29DFB45F5302DBC6F3D81D487F81F745C83629321ED2DA40C2","version":"1.9.1","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/magicsplasher-1.9.1.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Power Skiller","description":"Illumine auto power skiller plugin","id":"powerskiller-plugin","releases":[{"date":"2020-07-17","sha512sum":"A7ECB905D1C35A5631EB21EEE78651EACD628655F18003D7BAF76164A4012CA665679B7002CBBB0075A9686CAFBB9CD72E5EB54541CD4B6D50EDC23FFA04079C","version":"2.9.1","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/powerskiller-2.9.1.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Quick Eater","description":"Illumine - auto eat food below configured HP","id":"quickeater-plugin","releases":[{"date":"2020-07-17","sha512sum":"1B0F9937CAE7D2E1F0F2D1020F0D1DFA6751B402EBA5E7E7E6B073DFC05041E803344D002C5D4B12447A4EB2B97833E2FB10A2397A0C6670096ED96F096AA24D","version":"1.7.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/quickeater-1.7.0.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Rooftop Agility","description":"Illumine automated rooftop agility plugin","id":"rooftopagility-plugin","releases":[{"date":"2020-07-17","sha512sum":"96B1EFC590911614909DC8EEB502F42AC76AE2979C708A944866AED80BCE0991E7D2245FE0F058394D5812147574E191A5B414613CF8C258F6945115267FE649","version":"2.5.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/rooftopagility-2.5.0.jar?raw=true","requires":"0.0.1"}]}]
[{"projectUrl":"","provider":"illumine","name":"BotUtils","description":"Illumine - Utils required for plugins to function with added automation","id":"botutils-plugin","releases":[{"date":"2020-07-18","sha512sum":"CC6ED545C37F39D54ED1BC4F20E86688AEF1D0242EF8B4A5F64C194EB847598813D7CBDAA1A0579A6774270CAD85F039047678D6ED2F3F6857C45196D316AC88","version":"2.7.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/botutils-2.7.0.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Magic Splasher","description":"Illumine automated magic splasher","id":"magicsplasher-plugin","releases":[{"date":"2020-07-18","sha512sum":"9AE9B6C54B95CAC57416EC725F688028F7327907B1828C2F18BD0AA8301919EEED15A5F7302D9C29DFB45F5302DBC6F3D81D487F81F745C83629321ED2DA40C2","version":"1.9.1","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/magicsplasher-1.9.1.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Power Skiller","description":"Illumine auto power skiller plugin","id":"powerskiller-plugin","releases":[{"date":"2020-07-18","sha512sum":"A7ECB905D1C35A5631EB21EEE78651EACD628655F18003D7BAF76164A4012CA665679B7002CBBB0075A9686CAFBB9CD72E5EB54541CD4B6D50EDC23FFA04079C","version":"2.9.1","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/powerskiller-2.9.1.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Quick Eater","description":"Illumine - auto eat food below configured HP","id":"quickeater-plugin","releases":[{"date":"2020-07-18","sha512sum":"1B0F9937CAE7D2E1F0F2D1020F0D1DFA6751B402EBA5E7E7E6B073DFC05041E803344D002C5D4B12447A4EB2B97833E2FB10A2397A0C6670096ED96F096AA24D","version":"1.7.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/quickeater-1.7.0.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Rooftop Agility","description":"Illumine automated rooftop agility plugin","id":"rooftopagility-plugin","releases":[{"date":"2020-07-18","sha512sum":"96B1EFC590911614909DC8EEB502F42AC76AE2979C708A944866AED80BCE0991E7D2245FE0F058394D5812147574E191A5B414613CF8C258F6945115267FE649","version":"2.5.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/rooftopagility-2.5.0.jar?raw=true","requires":"0.0.1"}]}, {"projectUrl":"","provider":"illumine","name":"Smoke Runecrafter Plugin","description":"Illumine - Smoke Runecrafting plugin","id":"smokerunecrafterplugin-plugin","releases":[{"date":"2020-07-18","sha512sum":"AD6055A9141F84865426B8C41A6D74DF7CCAA9D0725620A7EF6E6EF303AFC4318BD15215099B752DDE78C4AAEED290C276633210FD97AA494085ABC8223C20F1","version":"1.0.0","url":"https://github.com/illumineawake/illu-plugins/blob/master/release/smokerunecrafter-1.0.0.jar?raw=true","requires":"0.0.1"}]}]

Binary file not shown.

View File

@ -28,8 +28,9 @@ rootProject.name = "Illumine Plugins"
include(":botutils")
include(":magicsplasher")
include("powerskiller")
include(":rooftopagility")
include(":quickeater")
include(":rooftopagility")
include(":smokerunecrafter")
for (project in rootProject.children) {
project.apply {

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2019 Owain van Brakel <https://github.com/Owain94>
* 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.
*/
version = "1.0.0"
project.extra["PluginName"] = "Smoke Runecrafter Plugin"
project.extra["PluginDescription"] = "Illumine - Smoke Runecrafting plugin"
dependencies {
compileOnly(project(":botutils"))
}
tasks {
jar {
manifest {
attributes(mapOf(
"Plugin-Version" to project.version,
"Plugin-Id" to nameToId(project.extra["PluginName"] as String),
"Plugin-Provider" to project.extra["PluginProvider"],
"Plugin-Dependencies" to nameToId("BotUtils"),
"Plugin-Description" to project.extra["PluginDescription"],
"Plugin-License" to project.extra["PluginLicense"]
))
}
}
}

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2018, SomeoneWithAnInternetConnection
* Copyright (c) 2018, oplosthee <https://github.com/oplosthee>
* 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.smokerunecrafter;
import net.runelite.client.config.Button;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
import net.runelite.client.config.ConfigTitleSection;
import net.runelite.client.config.Range;
import net.runelite.client.config.Title;
@ConfigGroup("SmokeRuneCrafter")
public interface SmokeRuneCrafterConfig extends Config
{
@ConfigSection(
keyName = "delayConfig",
name = "Sleep Delay Configuration",
description = "Configure how the bot handles sleep delays",
position = 0
)
default boolean delayConfig()
{
return false;
}
@Range(
min = 0,
max = 550
)
@ConfigItem(
keyName = "sleepMin",
name = "Sleep Min",
description = "",
position = 1,
section = "delayConfig"
)
default int sleepMin()
{
return 60;
}
@Range(
min = 0,
max = 550
)
@ConfigItem(
keyName = "sleepMax",
name = "Sleep Max",
description = "",
position = 2,
section = "delayConfig"
)
default int sleepMax()
{
return 350;
}
@Range(
min = 0,
max = 550
)
@ConfigItem(
keyName = "sleepTarget",
name = "Sleep Target",
description = "",
position = 3,
section = "delayConfig"
)
default int sleepTarget()
{
return 120;
}
@Range(
min = 0,
max = 550
)
@ConfigItem(
keyName = "sleepDeviation",
name = "Sleep Deviation",
description = "",
position = 4,
section = "delayConfig"
)
default int sleepDeviation()
{
return 150;
}
@ConfigItem(
keyName = "sleepWeightedDistribution",
name = "Sleep Weighted Distribution",
description = "Shifts the random distribution towards the lower end at the target, otherwise it will be an even distribution",
position = 5,
section = "delayConfig"
)
default boolean sleepWeightedDistribution()
{
return false;
}
@ConfigSection(
keyName = "delayTickConfig",
name = "Game Tick Configuration",
description = "Configure how the bot handles game tick delays, 1 game tick equates to roughly 600ms",
position = 10
)
default boolean delayTickConfig()
{
return false;
}
@Range(
min = 0,
max = 10
)
@ConfigItem(
keyName = "tickDelayMin",
name = "Game Tick Min",
description = "",
position = 11,
section = "delayTickConfig"
)
default int tickDelayMin()
{
return 0;
}
@Range(
min = 0,
max = 10
)
@ConfigItem(
keyName = "tickDelayMax",
name = "Game Tick Max",
description = "",
position = 12,
section = "delayTickConfig"
)
default int tickDelayMax()
{
return 2;
}
@Range(
min = 0,
max = 10
)
@ConfigItem(
keyName = "tickDelayTarget",
name = "Game Tick Target",
description = "",
position = 13,
section = "delayTickConfig"
)
default int tickDelayTarget()
{
return 0;
}
@Range(
min = 0,
max = 10
)
@ConfigItem(
keyName = "tickDelayDeviation",
name = "Game Tick Deviation",
description = "",
position = 14,
section = "delayTickConfig"
)
default int tickDelayDeviation()
{
return 2;
}
@ConfigItem(
keyName = "tickDelayWeightedDistribution",
name = "Game Tick Weighted Distribution",
description = "Shifts the random distribution towards the lower end at the target, otherwise it will be an even distribution",
position = 15,
section = "delayTickConfig"
)
default boolean tickDelayWeightedDistribution()
{
return false;
}
@ConfigTitleSection(
keyName = "instructionsTitle",
name = "Instructions",
description = "",
position = 16
)
default Title instructionsTitle()
{
return new Title();
}
@ConfigItem(
keyName = "instructions",
name = "",
description = "Instructions. Don't enter anything into this field",
position = 20,
titleSection = "instructionsTitle"
)
default String instructions()
{
return "Must have a Fire Tiara equipped. Requires Ring of Dueling, Air Talisman, Air Runes, Pure Essence. " +
"Stops and logs out (if enabled) when out of these materials. Does NOT support pouches or Magic Imbue currently.";
}
@ConfigItem(
keyName = "logout",
name = "Log out when out of items",
description = "",
position = 40
)
default boolean logout()
{
return false;
}
@ConfigItem(
keyName = "startButton",
name = "Start/Stop",
description = "Test button that changes variable value",
position = 50
)
default Button startButton()
{
return null;
}
}

View File

@ -0,0 +1,100 @@
package net.runelite.client.plugins.smokerunecrafter;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY_CONFIG;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPanel;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.util.ColorUtil;
import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration;
@Slf4j
@Singleton
class SmokeRuneCrafterOverlay extends OverlayPanel
{
private final Client client;
private final SmokeRuneCrafterPlugin plugin;
private final SmokeRuneCrafterConfig config;
String timeFormat;
private String infoStatus = "Starting...";
@Inject
private SmokeRuneCrafterOverlay(final Client client, final SmokeRuneCrafterPlugin plugin, final SmokeRuneCrafterConfig config)
{
super(plugin);
setPosition(OverlayPosition.BOTTOM_LEFT);
this.client = client;
this.plugin = plugin;
this.config = config;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Smoke Rune Crafter overlay"));
}
@Override
public Dimension render(Graphics2D graphics)
{
if (plugin.botTimer == null)
{
log.debug("Overlay conditions not met, not starting overlay");
return null;
}
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
Duration duration = Duration.between(plugin.botTimer, Instant.now());
timeFormat = (duration.toHours() < 1) ? "mm:ss" : "HH:mm:ss";
tableComponent.addRow("Time running:", formatDuration(duration.toMillis(),timeFormat));
if (plugin.state != null)
{
if (!plugin.state.name().equals("TIMEOUT"))
infoStatus = plugin.state.name();
}
tableComponent.addRow("Status:", infoStatus);
TableComponent tableMarksComponent = new TableComponent();
tableMarksComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableMarksComponent.addRow("Runes:", plugin.totalSmokeRunes + " / " + plugin.runesPH);
tableMarksComponent.addRow("Profit:", plugin.totalProfit + " / " + plugin.profitPH);
TableComponent tableDelayComponent = new TableComponent();
tableDelayComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableDelayComponent.addRow("Sleep delay:", plugin.sleepLength + "ms");
tableDelayComponent.addRow("Tick delay:", String.valueOf(plugin.timeout));
if (!tableComponent.isEmpty())
{
panelComponent.setBackgroundColor(ColorUtil.fromHex("#121212")); //Material Dark default
panelComponent.setPreferredSize(new Dimension(250,250));
panelComponent.setBorder(new Rectangle(5,5,5,5));
panelComponent.getChildren().add(TitleComponent.builder()
.text("Illumine Smoke Runecrafting")
.color(ColorUtil.fromHex("#40C4FF"))
.build());
panelComponent.getChildren().add(tableComponent);
panelComponent.getChildren().add(TitleComponent.builder()
.text("Stats (Total / PH)")
.color(ColorUtil.fromHex("#FFA000"))
.build());
panelComponent.getChildren().add(tableMarksComponent);
panelComponent.getChildren().add(TitleComponent.builder()
.text("Delays")
.color(ColorUtil.fromHex("#F8BBD0"))
.build());
panelComponent.getChildren().add(tableDelayComponent);
}
return super.render(graphics);
}
}

View File

@ -0,0 +1,526 @@
/*
* Copyright (c) 2018, SomeoneWithAnInternetConnection
* Copyright (c) 2018, oplosthee <https://github.com/oplosthee>
* 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.smokerunecrafter;
import com.google.inject.Provides;
import java.time.Duration;
import java.time.Instant;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.ItemID;
import net.runelite.api.MenuEntry;
import net.runelite.api.MenuOpcode;
import net.runelite.api.ObjectID;
import net.runelite.api.Player;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.events.ConfigButtonClicked;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDependency;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.plugins.botutils.BotUtils;
import net.runelite.client.plugins.smokerunecrafter.SmokeRuneCrafterConfig;
import static net.runelite.client.plugins.smokerunecrafter.SmokeRuneCrafterState.*;
import net.runelite.client.ui.overlay.OverlayManager;
import org.pf4j.Extension;
@Extension
@PluginDependency(BotUtils.class)
@PluginDescriptor(
name = "SmokeRuneCrafter Plugin",
enabledByDefault = false,
description = "Illumine - Smoke Runecrafting plugin",
tags = {"illumine", "runecrafting", "bot"},
type = PluginType.UTILITY
)
@Slf4j
public class SmokeRuneCrafterPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private SmokeRuneCrafterConfig config;
@Inject
private BotUtils utils;
@Inject
private ConfigManager configManager;
@Inject
private OverlayManager overlayManager;
@Inject
private SmokeRuneCrafterOverlay overlay;
MenuEntry targetMenu;
Instant botTimer;
Player player;
SmokeRuneCrafterState state;
ExecutorService executorService;
LocalPoint beforeLoc = new LocalPoint(0, 0);
GameObject bankChest;
GameObject mysteriousRuins;
GameObject fireAltar;
Widget bankItem;
Set<Integer> DUEL_RINGS = Set.of(ItemID.RING_OF_DUELING2, ItemID.RING_OF_DUELING3, ItemID.RING_OF_DUELING4, ItemID.RING_OF_DUELING5, ItemID.RING_OF_DUELING6, ItemID.RING_OF_DUELING7, ItemID.RING_OF_DUELING8);
Set<Integer> REQUIRED_ITEMS = Set.of(ItemID.AIR_TALISMAN, ItemID.AIR_RUNE, ItemID.PURE_ESSENCE);
boolean startBot;
boolean setTalisman;
long sleepLength;
int tickLength;
int timeout;
int coinsPH;
int beforeEssence;
int totalEssence;
int beforeAirRunes;
int totalAirRunes;
int beforeTalisman;
int totalTalisman;
int totalSmokeRunes;
int totalDuelRings;
int runesPH;
int profitPH;
int totalProfit;
int smokeRunesCost;
int pureEssenceCost;
int airTalismanCost;
int duelRingCost;
int airRuneCost;
int beforeSmokeRunes;
int currentSmokeRunes;
@Provides
SmokeRuneCrafterConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(SmokeRuneCrafterConfig.class);
}
@Override
protected void startUp()
{
}
@Override
protected void shutDown()
{
startBot = false;
}
@Subscribe
private void onConfigButtonPressed(ConfigButtonClicked configButtonClicked)
{
if (!configButtonClicked.getGroup().equalsIgnoreCase("SmokeRuneCrafter"))
{
return;
}
log.info("button {} pressed!", configButtonClicked.getKey());
switch (configButtonClicked.getKey())
{
case "startButton":
if (!startBot)
{
log.info("starting Smoke Runecrafting plugin");
startBot = true;
initCounters();
state = null;
targetMenu = null;
setTalisman = false;
botTimer = Instant.now();
executorService = Executors.newSingleThreadExecutor();
overlayManager.add(overlay);
smokeRunesCost = utils.getOSBItem(ItemID.SMOKE_RUNE).getOverall_average();
pureEssenceCost = utils.getOSBItem(ItemID.PURE_ESSENCE).getOverall_average();
airTalismanCost = utils.getOSBItem(ItemID.AIR_TALISMAN).getOverall_average();
duelRingCost = utils.getOSBItem(ItemID.RING_OF_DUELING8).getOverall_average();
airRuneCost = utils.getOSBItem(ItemID.AIR_RUNE).getOverall_average();
log.info("Item prices set to at - Smoke Runes: {}gp, Pure Essence: {}gp, Air Talisman: {}gp, " +
"Ring of Dueling {}gp, Air Runes: {}gp", smokeRunesCost, pureEssenceCost, airTalismanCost, duelRingCost, airRuneCost);
}
else
{
log.info("stopping Smoke Runecrafting plugin");
startBot = false;
botTimer = null;
executorService.shutdown();
overlayManager.remove(overlay);
}
break;
}
}
private void initCounters()
{
timeout = 0;
coinsPH = 0;
beforeEssence = 0;
totalEssence = 0;
beforeAirRunes = 0;
totalAirRunes = 0;
beforeTalisman = 0;
totalTalisman = 0;
beforeSmokeRunes = 0;
totalSmokeRunes = 0;
totalDuelRings = 0;
runesPH = 0;
profitPH = 0;
totalProfit = 0;
currentSmokeRunes = 0;
}
private int itemTotals(int itemID, int beforeAmount, boolean stackableItem)
{
int currentAmount = utils.getInventoryItemCount(itemID, stackableItem);
return (beforeAmount > currentAmount) ? beforeAmount - currentAmount : 0;
}
private void updateTotals()
{
totalEssence += itemTotals(ItemID.PURE_ESSENCE, beforeEssence, false);
beforeEssence = utils.getInventoryItemCount(ItemID.PURE_ESSENCE, false);
totalAirRunes += itemTotals(ItemID.AIR_RUNE, beforeAirRunes, true);
beforeAirRunes = utils.getInventoryItemCount(ItemID.AIR_RUNE, true);
totalTalisman += itemTotals(ItemID.AIR_TALISMAN, beforeTalisman, true);
beforeTalisman = utils.getInventoryItemCount(ItemID.AIR_TALISMAN, true);
currentSmokeRunes = utils.getInventoryItemCount(ItemID.SMOKE_RUNE, true);
if (beforeSmokeRunes < currentSmokeRunes)
totalSmokeRunes += currentSmokeRunes;
beforeSmokeRunes = currentSmokeRunes;
if(!utils.isItemEquipped(DUEL_RINGS) || utils.isItemEquipped(Set.of(ItemID.RING_OF_DUELING1)))
totalDuelRings++;
}
public void updateStats()
{
updateTotals();
runesPH = (int) getPerHour(totalSmokeRunes);
totalProfit = (totalSmokeRunes * smokeRunesCost) - ((totalEssence * pureEssenceCost) + (totalAirRunes * airRuneCost) +
(totalTalisman * airTalismanCost) + (totalDuelRings * duelRingCost));
profitPH = (int) getPerHour(totalProfit);
}
public long getPerHour(int quantity)
{
Duration timeSinceStart = Duration.between(botTimer, Instant.now());
if (!timeSinceStart.isZero())
{
return (int) ((double) quantity * (double) Duration.ofHours(1).toMillis() / (double) timeSinceStart.toMillis());
}
return 0;
}
private void sleepDelay()
{
sleepLength = utils.randomDelay(config.sleepWeightedDistribution(), config.sleepMin(), config.sleepMax(), config.sleepDeviation(), config.sleepTarget());
log.info("Sleeping for {}ms", sleepLength);
utils.sleep(sleepLength);
}
private int tickDelay()
{
tickLength = (int) utils.randomDelay(config.tickDelayWeightedDistribution(), config.tickDelayMin(), config.tickDelayMax(), config.tickDelayDeviation(), config.tickDelayTarget());
log.info("tick delay for {} ticks", tickLength);
return tickLength;
}
private void handleMouseClick()
{
executorService.submit(() ->
{
try
{
sleepDelay();
utils.clickRandomPointCenter(-100, 100);
}
catch (RuntimeException e)
{
e.printStackTrace();
}
});
}
private void teleportCastleWars()
{
if (utils.isItemEquipped(DUEL_RINGS) || utils.isItemEquipped(Set.of(ItemID.RING_OF_DUELING1)))
{
targetMenu = new MenuEntry("", "", 3, MenuOpcode.CC_OP.getId(), -1,
25362455, false);
handleMouseClick();
}
else
{
log.info("Need to teleport but don't have a ring of dueling");
}
}
private SmokeRuneCrafterState getDuelRingState()
{
if(utils.inventoryContains(DUEL_RINGS))
{
return EQUIP_DUEL_RING;
}
if(utils.bankContainsAnyOf(DUEL_RINGS))
{
bankItem = utils.getBankItemWidgetAnyOf(DUEL_RINGS);
return WITHDRAW_ITEM;
}
return OUT_OF_ITEM; //out of duel rings
}
private SmokeRuneCrafterState getRequiredItemState()
{
if ((!utils.inventoryContains(ItemID.AIR_TALISMAN) && !utils.bankContains(ItemID.AIR_TALISMAN, 1)) ||
(!utils.inventoryContains(ItemID.AIR_RUNE) && !utils.bankContains(ItemID.AIR_RUNE, 26)) ||
(!utils.inventoryContains(ItemID.PURE_ESSENCE) && !utils.bankContains(ItemID.PURE_ESSENCE, 10)))
{
bankItem = null;
return OUT_OF_ITEM;
}
if (!utils.inventoryContains(ItemID.AIR_TALISMAN))
{
bankItem = utils.getBankItemWidget(ItemID.AIR_TALISMAN);
return WITHDRAW_ITEM;
}
if (!utils.inventoryContains(ItemID.AIR_RUNE))
{
bankItem = utils.getBankItemWidget(ItemID.AIR_RUNE);
return WITHDRAW_ALL_ITEM;
}
if (!utils.inventoryContains(ItemID.PURE_ESSENCE))
{
bankItem = utils.getBankItemWidget(ItemID.PURE_ESSENCE);
return WITHDRAW_ALL_ITEM;
}
return OUT_OF_ITEM;
}
private SmokeRuneCrafterState getState()
{
if (timeout > 0)
{
utils.handleRun(20,30);
return TIMEOUT;
}
if (utils.iterating)
{
return ITERATING;
}
if (utils.isMoving(beforeLoc) || player.getAnimation() == 714) //teleport animation
{
return MOVING;
}
mysteriousRuins = utils.findNearestGameObject(34817); //Mysterious Ruins
fireAltar = utils.findNearestGameObject(ObjectID.ALTAR_34764);
bankChest = utils.findNearestGameObject(ObjectID.BANK_CHEST_4483);
if (mysteriousRuins != null)
{
if (utils.inventoryContainsAllOf(REQUIRED_ITEMS))
{
return ENTER_MYSTERIOUS_RUINS;
}
else
{
return (utils.isItemEquipped(DUEL_RINGS) || utils.isItemEquipped(Set.of(ItemID.RING_OF_DUELING1))) ?
TELEPORT_CASTLE_WARS : OUT_OF_ITEM;
}
}
if (fireAltar != null)
{
if (utils.inventoryContainsAllOf(REQUIRED_ITEMS))
{
return (setTalisman) ? USE_FIRE_ALTAR : SET_TALISMAN;
}
else
{
return (utils.isItemEquipped(DUEL_RINGS) || utils.isItemEquipped(Set.of(ItemID.RING_OF_DUELING1))) ?
TELEPORT_CASTLE_WARS : OUT_OF_ITEM;
}
}
if (bankChest != null)
{
if (!utils.isBankOpen())
{
updateStats();
return OPEN_BANK;
}
if (utils.isBankOpen())
{
if (utils.inventoryContainsAllOf(REQUIRED_ITEMS) && utils.isItemEquipped(DUEL_RINGS))
{
updateStats();
return TELEPORT_DUEL_ARENA;
}
if (utils.inventoryFull())
{
return DEPOSIT_ALL;
}
if(!utils.isItemEquipped(DUEL_RINGS))
{
return getDuelRingState();
}
if(utils.inventoryContainsExcept(REQUIRED_ITEMS))
{
return DEPOSIT_ALL_EXCEPT;
}
return getRequiredItemState();
}
}
return OUT_OF_AREA;
}
@Subscribe
private void onGameTick(GameTick event)
{
if (!startBot)
{
return;
}
player = client.getLocalPlayer();
if (client != null && player != null && client.getGameState() == GameState.LOGGED_IN)
{
state = getState();
log.debug(state.name());
switch (state)
{
case TIMEOUT:
timeout--;
break;
case ITERATING:
break;
case MOVING:
timeout = tickDelay();
break;
case ENTER_MYSTERIOUS_RUINS:
targetMenu = new MenuEntry("", "", 34817, MenuOpcode.GAME_OBJECT_FIRST_OPTION.getId(),
mysteriousRuins.getSceneMinLocation().getX(), mysteriousRuins.getSceneMinLocation().getY(), false);
handleMouseClick();
timeout = tickDelay();
break;
case TELEPORT_CASTLE_WARS:
teleportCastleWars();
timeout = tickDelay();
break;
case SET_TALISMAN:
WidgetItem airTalisman = utils.getInventoryWidgetItem(ItemID.AIR_TALISMAN);
targetMenu = new MenuEntry("Use", "Use", ItemID.AIR_TALISMAN, MenuOpcode.ITEM_USE.getId(),
airTalisman.getIndex(), 9764864, false);
handleMouseClick();
setTalisman = true;
break;
case USE_FIRE_ALTAR:
targetMenu = new MenuEntry("Use", "<col=ff9040>Air talisman<col=ffffff> -> <col=ffff>Altar",
fireAltar.getId(), MenuOpcode.ITEM_USE_ON_GAME_OBJECT.getId(), fireAltar.getSceneMinLocation().getX(),
fireAltar.getSceneMinLocation().getY(), false);
handleMouseClick();
timeout = tickDelay();
break;
case OPEN_BANK:
targetMenu = new MenuEntry("", "", bankChest.getId(), MenuOpcode.GAME_OBJECT_FIRST_OPTION.getId(),
bankChest.getSceneMinLocation().getX(), bankChest.getSceneMinLocation().getY(), false);
handleMouseClick();
timeout = tickDelay();
break;
case TELEPORT_DUEL_ARENA:
targetMenu = new MenuEntry("", "", 2, MenuOpcode.CC_OP.getId(), -1,
25362455, false);
handleMouseClick();
timeout = tickDelay();
break;
case DEPOSIT_ALL:
utils.depositAll();
break;
case DEPOSIT_ALL_EXCEPT:
utils.depositAllExcept(REQUIRED_ITEMS);
break;
case EQUIP_DUEL_RING:
WidgetItem item = utils.getInventoryWidgetItem(DUEL_RINGS);
if (item != null)
{
targetMenu = new MenuEntry("", "", 9, MenuOpcode.CC_OP_LOW_PRIORITY.getId(),
item.getIndex(), 983043, false);
handleMouseClick();
}
break;
case WITHDRAW_ITEM:
utils.withdrawItem(bankItem);
break;
case WITHDRAW_ALL_ITEM:
utils.withdrawAllItem(bankItem);
break;
case OUT_OF_ITEM:
utils.sendGameMessage("Out of required items. Stopping.");
if(config.logout())
utils.logout();
startBot = false;
break;
}
beforeLoc = player.getLocalLocation();
}
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (!startBot || targetMenu == null)
{
return;
}
if (utils.getRandomEvent()) //for random events
{
log.info("SmokeRuneCrafter plugin not overriding due to random event");
return;
}
else
{
event.setMenuEntry(targetMenu);
targetMenu = null; //this allow the player to interact with the client without their clicks being overridden
}
}
}

View File

@ -0,0 +1,21 @@
package net.runelite.client.plugins.smokerunecrafter;
public enum SmokeRuneCrafterState
{
DEPOSIT_ALL,
DEPOSIT_ALL_EXCEPT,
ENTER_MYSTERIOUS_RUINS,
EQUIP_DUEL_RING,
ITERATING,
MOVING,
OPEN_BANK,
OUT_OF_AREA,
OUT_OF_ITEM,
SET_TALISMAN,
TELEPORT_CASTLE_WARS,
TELEPORT_DUEL_ARENA,
TIMEOUT,
USE_FIRE_ALTAR,
WITHDRAW_ALL_ITEM,
WITHDRAW_ITEM;
}