Initial commit
This commit is contained in:
@ -0,0 +1,17 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Activity {
|
||||
IDLE("Idle"),
|
||||
WOODCUTTING("Woodcutting"),
|
||||
FLETCHING("Fletching"),
|
||||
FEEDING_BRAZIER("Feeding"),
|
||||
FIXING_BRAZIER("Fixing"),
|
||||
LIGHTING_BRAZIER("Lighting");
|
||||
|
||||
private final String actionString;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Immutable
|
||||
public class BossData {
|
||||
@Getter
|
||||
private final int health;
|
||||
|
||||
@Getter
|
||||
private final int world;
|
||||
|
||||
@Getter
|
||||
private final long time;
|
||||
|
||||
@Getter
|
||||
private final int timer;
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
|
||||
* 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 io.reisub.openosrs.wintertodt;
|
||||
|
||||
import net.runelite.client.config.Button;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Range;
|
||||
|
||||
@ConfigGroup("ChaosWintertodtConfig")
|
||||
|
||||
public interface Config extends net.runelite.client.config.Config {
|
||||
@Range(min = 1, max = 99)
|
||||
@ConfigItem(
|
||||
keyName = "minEatHP",
|
||||
name = "Minimum Eat HP",
|
||||
description = "Minimum HP to eat at. i.e. will always eat",
|
||||
position = 0
|
||||
)
|
||||
default int minEatHP() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Range(min = 1, max = 100)
|
||||
@ConfigItem(
|
||||
keyName = "maxEatHP",
|
||||
name = "Maximum Eat HP",
|
||||
description = "Highest HP to consider eating. Value MUST be higher than minimum HP config. If HP drops below this value bot may randomly decide to eat.",
|
||||
position = 1
|
||||
)
|
||||
default int maxEatHP() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "sideSelection",
|
||||
name = "Select side",
|
||||
description = "Choose which side you want to play the game at."
|
||||
)
|
||||
default Side sideSelection() { return Side.EAST; }
|
||||
|
||||
@Range(min = 1, max = 100)
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
keyName = "sideTimeout",
|
||||
name = "Side timeout",
|
||||
description = "Seconds to wait before switching side because of an incapacitated pyromancer."
|
||||
)
|
||||
default int sideTimeout() { return 15; }
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "fletchNearBrazier",
|
||||
name = "Fletch near brazier",
|
||||
description = "Fletch near brazier so we can quickly fix/light the brazier for more experience and points at the cost of taking more damage.",
|
||||
position = 20
|
||||
)
|
||||
default boolean fletchNearBrazier() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "dodgeProjectiles",
|
||||
name = "Dodge projectiles",
|
||||
description = "Attempts to dodge snow fall and exploding braziers.",
|
||||
position = 21
|
||||
)
|
||||
default boolean dodgeProjectiles() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "openCrates",
|
||||
name = "Open crates",
|
||||
description = "Enable to open crates.",
|
||||
position = 22
|
||||
)
|
||||
default boolean openCrates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "hop",
|
||||
name = "Hop",
|
||||
description = "Hop to different worlds after finishing game.",
|
||||
position = 30
|
||||
)
|
||||
default boolean hop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Range(min = 40, max = 100)
|
||||
@ConfigItem(
|
||||
position = 31,
|
||||
keyName = "hopPercentage",
|
||||
name = "Hop percentage",
|
||||
description = "Minimum percentage the boss' health should be at before hopping. Low values risk not getting enough points. 70 is safe, 60 should work, anything lower is very risky."
|
||||
)
|
||||
default int hopPercentage() { return 70; }
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "startButton",
|
||||
name = "Start/Stop",
|
||||
description = "Start the script",
|
||||
position = 100
|
||||
)
|
||||
default Button startButton() {
|
||||
return new Button();
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum InterruptType {
|
||||
COLD("Damaged by Wintertodt Cold"),
|
||||
SNOWFALL("Damaged by Wintertodt Snowfall"),
|
||||
BRAZIER("Brazier Shattered"),
|
||||
INVENTORY_FULL("Inventory full of Bruma Roots"),
|
||||
OUT_OF_ROOTS("Out of Bruma Roots"),
|
||||
FIXED_BRAZIER("Fixed Brazier"),
|
||||
LIT_BRAZIER("Lit Brazier"),
|
||||
BRAZIER_WENT_OUT("Brazier went out"),
|
||||
EAT("You ate"),
|
||||
TOO_COLD("Your hands are too cold");
|
||||
|
||||
private final String interruptSourceString;
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import com.google.gson.*;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.plugins.iutils.game.Game;
|
||||
import okhttp3.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class Scouter {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Game game;
|
||||
|
||||
@Inject
|
||||
public OkHttpClient okHttpClient;
|
||||
|
||||
@Getter
|
||||
private final List<BossData> data = new ArrayList<>(4);
|
||||
|
||||
private Instant lastUpdate;
|
||||
|
||||
public void onGameTick() {
|
||||
if (lastUpdate == null || Duration.between(lastUpdate, Instant.now()).getSeconds() > 2) {
|
||||
lastUpdate = Instant.now();
|
||||
|
||||
getRemoteData();
|
||||
}
|
||||
}
|
||||
|
||||
public BossData getLocalData() {
|
||||
return new BossData(
|
||||
plugin.getBossHealth(),
|
||||
game.client().getWorld(),
|
||||
System.currentTimeMillis() / 1000,
|
||||
plugin.getRespawnTimer()
|
||||
);
|
||||
}
|
||||
|
||||
private void getRemoteData() {
|
||||
try {
|
||||
Request r = new Request.Builder()
|
||||
.url("https://www.wintertodt.com/scouter/")
|
||||
.addHeader("User-Agent", "RuneLite")
|
||||
.addHeader("Authorization", "2")
|
||||
.build();
|
||||
|
||||
okHttpClient.newCall(r).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
log.debug("Error retrieving Wintertodt boss data", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) {
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
JsonArray jsonArray = new Gson().fromJson(Objects.requireNonNull(response.body()).string(), JsonArray.class);
|
||||
parseData(jsonArray);
|
||||
} catch (IOException | JsonSyntaxException ignored) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
|
||||
private void parseData(JsonArray jsonArray) {
|
||||
for (JsonElement jsonElement : jsonArray) {
|
||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||
try {
|
||||
BossData bossData = new BossData(jsonObject.get("a").getAsInt(), jsonObject.get("b").getAsInt(), jsonObject.get("c").getAsLong(), jsonObject.get("d").getAsInt());
|
||||
if (bossData.getWorld() != game.client().getWorld()) {
|
||||
data.add(bossData);
|
||||
}
|
||||
} catch (UnsupportedOperationException ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Side {
|
||||
EAST(new Position(1638, 3996, 0), new Position(1638, 3988, 0)),
|
||||
WEST(new Position(1622, 3996, 0), new Position(1622, 3988, 0));
|
||||
|
||||
private final Position positionNearBrazier;
|
||||
private final Position positionNearRoots;
|
||||
}
|
@ -0,0 +1,472 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.util.Util;
|
||||
import io.reisub.openosrs.util.tasks.Eat;
|
||||
import io.reisub.openosrs.util.tasks.KittenTask;
|
||||
import io.reisub.openosrs.wintertodt.tasks.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.events.*;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.iutils.iUtils;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
import net.runelite.client.plugins.iutils.scripts.iScript;
|
||||
import org.pf4j.Extension;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.runelite.api.AnimationID.*;
|
||||
import static net.runelite.api.ItemID.BRUMA_KINDLING;
|
||||
import static net.runelite.api.ItemID.BRUMA_ROOT;
|
||||
|
||||
@Extension
|
||||
@PluginDependency(Util.class)
|
||||
@PluginDependency(iUtils.class)
|
||||
@PluginDescriptor(
|
||||
name = "Chaos Wintertodt",
|
||||
description = "Plays the Wintertodt minigame",
|
||||
enabledByDefault = false
|
||||
)
|
||||
@Slf4j
|
||||
public class Wintertodt extends iScript {
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
public static final int WINTERTODT_REGION = 6462;
|
||||
public static final int WINTERTODT_HEALTH_PACKED_ID = 25952277;
|
||||
public static final int WINTERTODT_GAME_TIMER_ID = 25952259;
|
||||
|
||||
@Getter
|
||||
private Activity currentActivity = Activity.IDLE;
|
||||
|
||||
@Getter
|
||||
private Activity previousActivity = Activity.IDLE;
|
||||
|
||||
@Getter
|
||||
private int respawnTimer;
|
||||
|
||||
@Getter
|
||||
private int bossHealth;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean tooCold;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Instant lastHop;
|
||||
|
||||
@Getter
|
||||
private final List<WintertodtProjectile> projectiles = new ArrayList<>();
|
||||
|
||||
private List<Task> tasks;
|
||||
private KittenTask kittenTask;
|
||||
private Hop hopTask;
|
||||
private Scouter scouter;
|
||||
private int fmLevel, wcLevel, fletchLevel;
|
||||
private Instant lastActionTime;
|
||||
private int previousTimerValue;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Provides
|
||||
Config provideConfig(ConfigManager configManager) {
|
||||
return configManager.getConfig(Config.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loop() {
|
||||
for (Task t : tasks) {
|
||||
if (t.validate()) {
|
||||
log.info(t.getStatus());
|
||||
t.execute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
game.sleepDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
log.info("Starting Chaos Wintertodt");
|
||||
|
||||
fmLevel = game.baseLevel(Skill.FIREMAKING);
|
||||
wcLevel = game.baseLevel(Skill.WOODCUTTING);
|
||||
fletchLevel = game.baseLevel(Skill.FLETCHING);
|
||||
|
||||
if (config.hop()) scouter = injector.getInstance(Scouter.class);
|
||||
|
||||
Eat eatTask = injector.getInstance(Eat.class);
|
||||
eatTask.setInterval(config.minEatHP(), config.maxEatHP());
|
||||
|
||||
kittenTask = KittenTask.getInstance(injector);
|
||||
|
||||
tasks = new ArrayList<>();
|
||||
tasks.add(eatTask);
|
||||
tasks.add(kittenTask);
|
||||
if (config.dodgeProjectiles()) {
|
||||
tasks.add(injector.getInstance(DodgeProjectile.class));
|
||||
}
|
||||
tasks.add(injector.getInstance(OpenInventory.class));
|
||||
tasks.add(injector.getInstance(EatWhileWaiting.class));
|
||||
tasks.add(injector.getInstance(OpenCrates.class));
|
||||
tasks.add(injector.getInstance(GoToBank.class));
|
||||
tasks.add(injector.getInstance(HandleBank.class));
|
||||
tasks.add(injector.getInstance(GoToWintertodt.class));
|
||||
if (config.hop()) {
|
||||
hopTask = injector.getInstance(Hop.class);
|
||||
tasks.add(hopTask);
|
||||
}
|
||||
tasks.add(injector.getInstance(MoveToBrazier.class));
|
||||
tasks.add(injector.getInstance(Fix.class));
|
||||
tasks.add(injector.getInstance(Light.class));
|
||||
tasks.add(injector.getInstance(Fletch.class));
|
||||
tasks.add(injector.getInstance(ChangeSide.class));
|
||||
tasks.add(injector.getInstance(Burn.class));
|
||||
tasks.add(injector.getInstance(Chop.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
log.info("Stopping Chaos Wintertodt");
|
||||
if (tasks != null) {
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
KittenTask.handleKitten = false;
|
||||
scouter = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onConfigButtonPressed(ConfigButtonClicked configButtonClicked) {
|
||||
if (configButtonClicked.getKey().equals("startButton")) {
|
||||
execute();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onStatChanged(StatChanged event) {
|
||||
Skill skill = event.getSkill();
|
||||
int level = event.getLevel();
|
||||
|
||||
if (skill == Skill.FIREMAKING && level > fmLevel) {
|
||||
setActivity(Activity.IDLE);
|
||||
fmLevel = event.getLevel();
|
||||
} else if (skill == Skill.WOODCUTTING && level > wcLevel) {
|
||||
setActivity(Activity.IDLE);
|
||||
wcLevel = event.getLevel();
|
||||
} else if (skill == Skill.FLETCHING && level > fletchLevel) {
|
||||
setActivity(Activity.IDLE);
|
||||
fletchLevel = event.getLevel();
|
||||
} else if (skill == Skill.FIREMAKING && currentActivity == Activity.LIGHTING_BRAZIER) {
|
||||
setActivity(Activity.IDLE);
|
||||
} else if (skill == Skill.CONSTRUCTION && currentActivity == Activity.FIXING_BRAZIER) {
|
||||
setActivity(Activity.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onGameTick(GameTick event) {
|
||||
if (!isInWintertodtRegion() || game.client().getGameState() != GameState.LOGGED_IN) return;
|
||||
|
||||
if (scouter != null) {
|
||||
scouter.onGameTick();
|
||||
}
|
||||
|
||||
if (hopTask != null) {
|
||||
hopTask.onGameTick();
|
||||
}
|
||||
|
||||
parseBossHealth();
|
||||
//parseRespawnTime();
|
||||
|
||||
checkActionTimeout();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onChatMessage(ChatMessage chatMessage) {
|
||||
if (kittenTask != null) {
|
||||
kittenTask.onChatMessage(chatMessage);
|
||||
}
|
||||
|
||||
if (!isInWintertodtRegion()) return;
|
||||
|
||||
ChatMessageType chatMessageType = chatMessage.getType();
|
||||
if (chatMessageType != ChatMessageType.GAMEMESSAGE && chatMessageType != ChatMessageType.SPAM) return;
|
||||
|
||||
MessageNode messageNode = chatMessage.getMessageNode();
|
||||
final InterruptType interruptType;
|
||||
|
||||
if (messageNode.getValue().startsWith("You carefully fletch the root")) {
|
||||
setActivity(Activity.FLETCHING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (messageNode.getValue().startsWith("The cold of")) {
|
||||
interruptType = InterruptType.COLD;
|
||||
} else if (messageNode.getValue().startsWith("The freezing cold attack")) {
|
||||
interruptType = InterruptType.SNOWFALL;
|
||||
} else if (messageNode.getValue().startsWith("The brazier is broken and shrapnel")) {
|
||||
interruptType = InterruptType.BRAZIER;
|
||||
} else if (messageNode.getValue().startsWith("You have run out of bruma roots")) {
|
||||
interruptType = InterruptType.OUT_OF_ROOTS;
|
||||
} else if (messageNode.getValue().startsWith("Your inventory is too full")) {
|
||||
interruptType = InterruptType.INVENTORY_FULL;
|
||||
} else if (messageNode.getValue().startsWith("You fix the brazier")) {
|
||||
interruptType = InterruptType.FIXED_BRAZIER;
|
||||
} else if (messageNode.getValue().startsWith("You light the brazier.")) {
|
||||
interruptType = InterruptType.LIT_BRAZIER;
|
||||
} else if (messageNode.getValue().startsWith("The brazier has gone out.")) {
|
||||
interruptType = InterruptType.BRAZIER_WENT_OUT;
|
||||
} else if (messageNode.getValue().startsWith("You eat")) {
|
||||
interruptType = InterruptType.EAT;
|
||||
} else if (messageNode.getValue().startsWith("Your hands are too cold")) {
|
||||
interruptType = InterruptType.TOO_COLD;
|
||||
tooCold = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean wasInterrupted = false;
|
||||
|
||||
switch (interruptType) {
|
||||
case EAT:
|
||||
case LIT_BRAZIER:
|
||||
case INVENTORY_FULL:
|
||||
case OUT_OF_ROOTS:
|
||||
case BRAZIER_WENT_OUT:
|
||||
case FIXED_BRAZIER:
|
||||
wasInterrupted = true;
|
||||
break;
|
||||
case COLD:
|
||||
case BRAZIER:
|
||||
case SNOWFALL:
|
||||
if (currentActivity != Activity.WOODCUTTING && currentActivity != Activity.IDLE) {
|
||||
wasInterrupted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (wasInterrupted) {
|
||||
setActivity(Activity.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onAnimationChanged(AnimationChanged event) {
|
||||
if (game.client().getGameState() != GameState.LOGGED_IN || !isInWintertodtRegion()) return;
|
||||
|
||||
if (event.getActor() != game.client().getLocalPlayer()) return;
|
||||
|
||||
int animId = game.localPlayer().animation();
|
||||
switch (animId) {
|
||||
case WOODCUTTING_BRONZE:
|
||||
case WOODCUTTING_IRON:
|
||||
case WOODCUTTING_STEEL:
|
||||
case WOODCUTTING_BLACK:
|
||||
case WOODCUTTING_MITHRIL:
|
||||
case WOODCUTTING_ADAMANT:
|
||||
case WOODCUTTING_RUNE:
|
||||
case WOODCUTTING_GILDED:
|
||||
case WOODCUTTING_DRAGON:
|
||||
case WOODCUTTING_DRAGON_OR:
|
||||
case WOODCUTTING_INFERNAL:
|
||||
case WOODCUTTING_3A_AXE:
|
||||
case WOODCUTTING_CRYSTAL:
|
||||
case WOODCUTTING_TRAILBLAZER:
|
||||
setActivity(Activity.WOODCUTTING);
|
||||
break;
|
||||
case FLETCHING_BOW_CUTTING:
|
||||
setActivity(Activity.FLETCHING);
|
||||
break;
|
||||
case LOOKING_INTO:
|
||||
setActivity(Activity.FEEDING_BRAZIER);
|
||||
break;
|
||||
case FIREMAKING:
|
||||
setActivity(Activity.LIGHTING_BRAZIER);
|
||||
break;
|
||||
case CONSTRUCTION:
|
||||
case CONSTRUCTION_IMCANDO:
|
||||
setActivity(Activity.FIXING_BRAZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onItemContainerChanged(ItemContainerChanged event) {
|
||||
final ItemContainer container = event.getItemContainer();
|
||||
|
||||
if (!isInWintertodtRegion() || container != game.client().getItemContainer(InventoryID.INVENTORY)) return;
|
||||
|
||||
int logs = (int) game.inventory().withId(BRUMA_ROOT).count();
|
||||
int kindling = (int) game.inventory().withId(BRUMA_KINDLING).count();
|
||||
|
||||
if (logs == 0 && currentActivity == Activity.FLETCHING) {
|
||||
setActivity(Activity.IDLE);
|
||||
} else if (logs == 0 && kindling == 0 && currentActivity == Activity.FEEDING_BRAZIER) {
|
||||
setActivity(Activity.IDLE);
|
||||
} else if (shouldStartFeeding() && (currentActivity == Activity.WOODCUTTING || currentActivity == Activity.FLETCHING)) {
|
||||
setActivity(Activity.IDLE);
|
||||
} else if (shouldStartFletching() && currentActivity == Activity.WOODCUTTING) {
|
||||
setActivity(Activity.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Subscribe
|
||||
private void onVarbitChanged(VarbitChanged varbitChanged) {
|
||||
int timerValue = game.client().getVar(Varbits.WINTERTODT_TIMER);
|
||||
if (timerValue != previousTimerValue) {
|
||||
respawnTimer = timerValue * 30 / 50;
|
||||
previousTimerValue = timerValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onProjectileMoved(ProjectileMoved event) {
|
||||
Projectile projectile = event.getProjectile();
|
||||
|
||||
if (projectile.getInteracting() != null) return;
|
||||
|
||||
if (projectile.getId() == 501) {
|
||||
int x = game.client().getBaseX() + event.getPosition().getSceneX();
|
||||
int y = game.client().getBaseY() + event.getPosition().getSceneY();
|
||||
int cycles = projectile.getEndCycle() - projectile.getStartMovementCycle();
|
||||
|
||||
// we don't care about any of the projectiles that don't go to our play area
|
||||
if (y >= 4001) return;
|
||||
|
||||
if (cycles == 200) {
|
||||
projectiles.add(new WintertodtProjectile(x, y, true, Instant.now()));
|
||||
} else if ((x == 1638 && y == 3997) || (x == 1619 && y == 3997)) {
|
||||
if (cycles == 120) {
|
||||
projectiles.add(new WintertodtProjectile(x, y, false, Instant.now()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInWintertodtRegion() {
|
||||
return game.localPlayer().position().regionID() == WINTERTODT_REGION;
|
||||
}
|
||||
|
||||
public boolean bossIsUp() {
|
||||
return isInWintertodtRegion()
|
||||
&& getBossHealth() > 0
|
||||
&& getRespawnTimer() <= 0;
|
||||
}
|
||||
|
||||
public boolean shouldStartFletching() {
|
||||
long rootCount = game.inventory().withName("Bruma root").count();
|
||||
long kindlingCount = game.inventory().withName("Bruma kindling").count();
|
||||
|
||||
return rootCount * 2 + kindlingCount >= getBossHealth();
|
||||
}
|
||||
|
||||
public boolean shouldStartFeeding() {
|
||||
long burnablesCount = game.inventory().withNamePart("Bruma").count();
|
||||
|
||||
return burnablesCount >= getBossHealth();
|
||||
}
|
||||
|
||||
public Side getNearestSide() {
|
||||
Position playerPos = game.localPlayer().position();
|
||||
if (playerPos.distanceTo(Side.EAST.getPositionNearBrazier()) > playerPos.distanceTo(Side.WEST.getPositionNearBrazier())) {
|
||||
return Side.WEST;
|
||||
} else {
|
||||
return Side.EAST;
|
||||
}
|
||||
}
|
||||
|
||||
public Side getFurthestSide() {
|
||||
Position playerPos = game.localPlayer().position();
|
||||
if (playerPos.distanceTo(Side.EAST.getPositionNearBrazier()) < playerPos.distanceTo(Side.WEST.getPositionNearBrazier())) {
|
||||
return Side.WEST;
|
||||
} else {
|
||||
return Side.EAST;
|
||||
}
|
||||
}
|
||||
|
||||
private void setActivity(Activity action) {
|
||||
if (action == Activity.IDLE && currentActivity != Activity.IDLE) {
|
||||
previousActivity = currentActivity;
|
||||
}
|
||||
|
||||
currentActivity = action;
|
||||
|
||||
if (action != Activity.IDLE) {
|
||||
lastActionTime = Instant.now();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkActionTimeout() {
|
||||
if (currentActivity == Activity.IDLE) return;
|
||||
|
||||
int animId = game.localPlayer().animation();
|
||||
if (animId != IDLE || lastActionTime == null) return;
|
||||
|
||||
Duration timeout = Duration.ofSeconds(3);
|
||||
Duration sinceAction = Duration.between(lastActionTime, Instant.now());
|
||||
|
||||
if (sinceAction.compareTo(timeout) >= 0) {
|
||||
setActivity(Activity.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseBossHealth() {
|
||||
Widget healthWidget = game.client.getWidget(WINTERTODT_HEALTH_PACKED_ID);
|
||||
|
||||
if (healthWidget != null) {
|
||||
Pattern regex = Pattern.compile("\\d+");
|
||||
Matcher bossHealthMatcher = regex.matcher(healthWidget.getText());
|
||||
|
||||
if (bossHealthMatcher.find()) {
|
||||
bossHealth = Integer.parseInt(bossHealthMatcher.group(0));
|
||||
if (bossHealth > 0) {
|
||||
respawnTimer = -1;
|
||||
}
|
||||
} else {
|
||||
bossHealth = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseRespawnTime() {
|
||||
Widget timerWidget = game.client.getWidget(WINTERTODT_GAME_TIMER_ID);
|
||||
|
||||
if (timerWidget != null) {
|
||||
Pattern regex = Pattern.compile("\\d:\\d+");
|
||||
Matcher timerMatcher = regex.matcher(timerWidget.getText());
|
||||
|
||||
if (timerMatcher.find()) {
|
||||
String[] time = timerMatcher.group(0).split(":");
|
||||
String minutes = time[0];
|
||||
String seconds = time[1];
|
||||
|
||||
respawnTimer = Integer.parseInt(minutes) * 60 + Integer.parseInt(seconds);
|
||||
} else {
|
||||
respawnTimer = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package io.reisub.openosrs.wintertodt;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.plugins.iutils.scene.Area;
|
||||
import net.runelite.client.plugins.iutils.scene.RectangularArea;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class WintertodtProjectile {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final boolean aoe;
|
||||
|
||||
@Getter
|
||||
private final Instant start;
|
||||
|
||||
public Area getDamageArea() {
|
||||
if (aoe) {
|
||||
return new RectangularArea(x-1, y-1, x+1, y+1);
|
||||
} else {
|
||||
if (x == 1638) {
|
||||
return new RectangularArea(x,y-1, x+3, y+2);
|
||||
} else {
|
||||
return new RectangularArea(x-1, y-1, x+2, y+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Side;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ItemID.BRUMA_KINDLING;
|
||||
import static net.runelite.api.ItemID.BRUMA_ROOT;
|
||||
|
||||
public class Burn extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.bossIsUp()) return false;
|
||||
|
||||
if (plugin.getPreviousActivity() == Activity.WOODCUTTING && !game.inventory().full() && !plugin.shouldStartFeeding()) return false;
|
||||
|
||||
return plugin.getCurrentActivity() == Activity.IDLE
|
||||
&& game.inventory().withId(BRUMA_ROOT, BRUMA_KINDLING).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (plugin.getNearestSide() == Side.WEST
|
||||
&& !game.localPlayer().position().equals(new Position(1622, 3996, 0))) {
|
||||
walking.walkTo(new Position(1622, 3996, 0));
|
||||
game.tick();
|
||||
game.sleepDelay();
|
||||
}
|
||||
|
||||
game.objects().withName("Burning brazier").within(15).findFirst().ifPresent((brazier) -> {
|
||||
brazier.interact("Feed");
|
||||
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.FEEDING_BRAZIER || !game.objects().withName("Burning brazier").within(10).exists(), 10);
|
||||
game.tick();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Feeding brazier";
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import static net.runelite.api.NpcID.INCAPACITATED_PYROMANCER;
|
||||
|
||||
public class ChangeSide extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
private Instant lastIncap;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Changing side";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.bossIsUp()) {
|
||||
lastIncap = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (game.npcs().within(6).withId(INCAPACITATED_PYROMANCER).exists()
|
||||
&& !game.objects().withName("Burning brazier").within(15).exists()) {
|
||||
if (lastIncap == null) {
|
||||
lastIncap = Instant.now();
|
||||
}
|
||||
} else {
|
||||
lastIncap = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return lastIncap != null
|
||||
&& Duration.between(lastIncap, Instant.now()).getSeconds() > config.sideTimeout()
|
||||
&& plugin.getCurrentActivity() == Activity.IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
lastIncap = null;
|
||||
|
||||
walking.walkTo(plugin.getFurthestSide().getPositionNearBrazier());
|
||||
game.tick();
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class Chop extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.bossIsUp()) return false;
|
||||
|
||||
return plugin.getCurrentActivity() == Activity.IDLE
|
||||
&& !plugin.shouldStartFeeding()
|
||||
&& !plugin.shouldStartFletching()
|
||||
&& plugin.getBossHealth() > 4
|
||||
&& !game.inventory().full();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Position nearRoots = plugin.getNearestSide().getPositionNearRoots();
|
||||
Position nearRoots2 = new Position(nearRoots.x, nearRoots.y+1, nearRoots.z);
|
||||
|
||||
if (!game.localPlayer().position().equals(nearRoots) && !game.localPlayer().position().equals(nearRoots2)) {
|
||||
if (calc.random(0, 10) == 5) {
|
||||
walking.walkTo(nearRoots2);
|
||||
} else {
|
||||
walking.walkTo(nearRoots);
|
||||
}
|
||||
game.tick();
|
||||
game.sleepDelay();
|
||||
}
|
||||
|
||||
game.objects().withName("Bruma roots").nearestFirst().findFirst().ifPresent(roots -> {
|
||||
roots.interact("Chop");
|
||||
});
|
||||
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.WOODCUTTING, 20);
|
||||
game.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Chopping bruma roots";
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import io.reisub.openosrs.wintertodt.WintertodtProjectile;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class DodgeProjectile extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
private WintertodtProjectile projectile;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Dodging projectile";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (plugin.getProjectiles().isEmpty()) return false;
|
||||
|
||||
Instant now = Instant.now();
|
||||
for (Iterator<WintertodtProjectile> it = plugin.getProjectiles().listIterator(); it.hasNext();) {
|
||||
WintertodtProjectile p = it.next();
|
||||
|
||||
if (now.isAfter(p.getStart().plusSeconds(4))) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p.getDamageArea().contains(game.localPlayer().position())) {
|
||||
projectile = p;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Position safePosition = findSafePosition(game.localPlayer().position());
|
||||
|
||||
if (safePosition != null) {
|
||||
walking.walkTo(safePosition);
|
||||
game.tick();
|
||||
}
|
||||
|
||||
game.waitUntil(() -> Instant.now().isAfter(projectile.getStart().plusSeconds(4)));
|
||||
game.sleepDelay();
|
||||
}
|
||||
|
||||
private Position findSafePosition(Position startPosition) {
|
||||
Position safePosition = startPosition;
|
||||
|
||||
while (projectile.getDamageArea().contains(safePosition)) {
|
||||
safePosition = safePosition.south();
|
||||
}
|
||||
if (walking.reachable(safePosition)) return safePosition;
|
||||
|
||||
safePosition = startPosition;
|
||||
|
||||
while (projectile.getDamageArea().contains(safePosition)) {
|
||||
safePosition = safePosition.north();
|
||||
}
|
||||
if (walking.reachable(safePosition)) return safePosition;
|
||||
|
||||
safePosition = startPosition;
|
||||
|
||||
while (projectile.getDamageArea().contains(safePosition)) {
|
||||
safePosition = safePosition.west();
|
||||
}
|
||||
if (walking.reachable(safePosition)) return safePosition;
|
||||
|
||||
safePosition = startPosition;
|
||||
|
||||
while (projectile.getDamageArea().contains(safePosition)) {
|
||||
safePosition = safePosition.east();
|
||||
}
|
||||
if (walking.reachable(safePosition)) return safePosition;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.api.Skill;
|
||||
|
||||
import static net.runelite.api.ItemID.BRUMA_KINDLING;
|
||||
import static net.runelite.api.ItemID.BRUMA_ROOT;
|
||||
|
||||
public class EatWhileWaiting extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Eating";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
int missingHP = game.baseLevel(Skill.HITPOINTS) - game.modifiedLevel(Skill.HITPOINTS);
|
||||
|
||||
return plugin.isInWintertodtRegion()
|
||||
&& (plugin.getRespawnTimer() > 0 || plugin.getBossHealth() <= 4 && !game.inventory().withId(BRUMA_ROOT, BRUMA_KINDLING).exists())
|
||||
&& game.inventory().withAction("Eat", "Drink").exists()
|
||||
&& missingHP > calc.random(9, 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.inventory().withAction("Eat", "Drink").findFirst().ifPresent(inventoryItem -> {
|
||||
if (inventoryItem.actions().contains("Eat")) {
|
||||
inventoryItem.interact("Eat");
|
||||
} else {
|
||||
inventoryItem.interact("Drink");
|
||||
}
|
||||
game.tick(calc.random(3, 5));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class Fix extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Fixing brazier";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.bossIsUp()) return false;
|
||||
|
||||
int distance = plugin.getCurrentActivity() == Activity.IDLE ? 8 : 2;
|
||||
|
||||
return game.objects().within(distance).withAction("Fix").exists()
|
||||
&& plugin.getCurrentActivity() != Activity.FIXING_BRAZIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
int distance = plugin.getCurrentActivity() == Activity.IDLE ? 8 : 2;
|
||||
|
||||
game.objects().within(distance).withAction("Fix").findFirst().ifPresent((brazier) -> {
|
||||
brazier.interact("Fix");
|
||||
game.tick();
|
||||
});
|
||||
|
||||
if (distance == 2) {
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.FIXING_BRAZIER || !game.objects().within(distance).withAction("Fix").exists(), 3);
|
||||
} else {
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.FIXING_BRAZIER || !game.objects().within(distance).withAction("Fix").exists(), 6);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ItemID.BRUMA_ROOT;
|
||||
import static net.runelite.api.ItemID.KNIFE;
|
||||
|
||||
public class Fletch extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.bossIsUp()) return false;
|
||||
|
||||
if (plugin.getPreviousActivity() == Activity.WOODCUTTING && !game.inventory().full() && !plugin.shouldStartFletching()) return false;
|
||||
|
||||
return plugin.getCurrentActivity() == Activity.IDLE
|
||||
&& !plugin.shouldStartFeeding()
|
||||
&& game.inventory().withId(BRUMA_ROOT).exists();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (config.fletchNearBrazier()) {
|
||||
Position nearBrazier = plugin.getNearestSide().getPositionNearBrazier();
|
||||
if (!game.localPlayer().position().equals(nearBrazier) && !game.localPlayer().position().equals(nearBrazier.south())) {
|
||||
walking.walkTo(nearBrazier);
|
||||
}
|
||||
}
|
||||
|
||||
game.tick();
|
||||
game.inventory().withId(KNIFE).findFirst().ifPresent((knife) -> {
|
||||
game.inventory().withId(BRUMA_ROOT).findFirst().ifPresent(knife::useOn);
|
||||
});
|
||||
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.FLETCHING, 5);
|
||||
game.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Cutting roots into kindlings";
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.iutils.game.iObject;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ItemID.BRUMA_KINDLING;
|
||||
import static net.runelite.api.ItemID.BRUMA_ROOT;
|
||||
import static net.runelite.api.ObjectID.DOORS_OF_DINH;
|
||||
|
||||
public class GoToBank extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.isInWintertodtRegion()) return false;
|
||||
|
||||
if (game.inventory().withAction("Eat", "Drink").findAny().isEmpty() && game.modifiedLevel(Skill.HITPOINTS) <= 10) return true;
|
||||
|
||||
return game.inventory().withAction("Eat", "Drink").count() <= 1
|
||||
&& (plugin.getRespawnTimer() > 0 || (plugin.getBossHealth() <= 4 && !game.inventory().withId(BRUMA_ROOT, BRUMA_KINDLING).exists()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
iObject doorsOfDinh = game.objects().withId(DOORS_OF_DINH).first();
|
||||
if (doorsOfDinh == null) return;
|
||||
|
||||
Position target = new Position(1630, 3970, 0);
|
||||
|
||||
if (game.localPlayer().position().y > doorsOfDinh.position().y && game.localPlayer().position().distanceTo(doorsOfDinh.position()) > 8) {
|
||||
walking.walkTo(target.areaWithin(calc.random(1, 9)));
|
||||
game.tick();
|
||||
}
|
||||
|
||||
game.waitUntil(() -> !plugin.bossIsUp(), 200);
|
||||
|
||||
doorsOfDinh.interact("Enter");
|
||||
game.tick();
|
||||
game.waitUntil(() -> game.localPlayer().position().y < 3965, 20);
|
||||
|
||||
final Position bank = new Position(1639, 3944, 0);
|
||||
walking.walkTo(bank.areaWithin(calc.random(1, 4)));
|
||||
game.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Going to the bank";
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Side;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.game.iObject;
|
||||
import net.runelite.client.plugins.iutils.scene.Area;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ObjectID.DOORS_OF_DINH;
|
||||
|
||||
public class GoToWintertodt extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
return !plugin.isInWintertodtRegion()
|
||||
&& game.inventory().withAction("Eat", "Drink").count() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
iObject doorsOfDinh = game.objects().withId(DOORS_OF_DINH).first();
|
||||
if (doorsOfDinh == null) return;
|
||||
|
||||
Position target = new Position(1630, 3962, 0);
|
||||
|
||||
if (game.localPlayer().position().y < doorsOfDinh.position().y && game.localPlayer().position().distanceTo(doorsOfDinh.position()) > 7) {
|
||||
walking.walkTo(target.areaWithin(calc.random(1, 9)));
|
||||
game.tick();
|
||||
}
|
||||
|
||||
doorsOfDinh.interact("Enter");
|
||||
game.tick();
|
||||
game.waitUntil(() -> game.localPlayer().position().y > 3965, 20);
|
||||
|
||||
Side side = config.sideSelection();
|
||||
|
||||
if (plugin.getBossHealth() > 0) {
|
||||
iObject roots = game.objects().withName("Bruma roots").nearest(game.localPlayer().position());
|
||||
roots.interact("Chop");
|
||||
} else {
|
||||
final Area wintertodtSpot = plugin.getRespawnTimer() >= 5 ? side.getPositionNearBrazier() : side.getPositionNearRoots().areaWithin(1);
|
||||
walking.walkTo(wintertodtSpot);
|
||||
}
|
||||
game.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Going to Wintertodt area";
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.iutils.game.iObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ItemID.*;
|
||||
|
||||
public class HandleBank extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
private iObject bankObj;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
bankObj = game.objects().withAction("Bank").nearest();
|
||||
|
||||
return !plugin.isInWintertodtRegion()
|
||||
&& bank != null
|
||||
&& game.localPlayer().position().distanceTo(bankObj.position()) < calc.random(5, 7)
|
||||
&& (!config.openCrates() || !game.inventory().withId(SUPPLY_CRATE).exists())
|
||||
&& game.inventory().withAction("Eat", "Drink").count() <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (!bank.isOpen()) {
|
||||
bankObj.interact("Bank");
|
||||
game.tick();
|
||||
|
||||
game.waitUntil(() -> bank.isOpen(), 15);
|
||||
}
|
||||
|
||||
bank.depositExcept(false,
|
||||
BRONZE_AXE,
|
||||
IRON_AXE,
|
||||
STEEL_AXE,
|
||||
BLACK_AXE,
|
||||
MITHRIL_AXE,
|
||||
ADAMANT_AXE,
|
||||
RUNE_AXE,
|
||||
DRAGON_AXE,
|
||||
HAMMER,
|
||||
KNIFE,
|
||||
TINDERBOX,
|
||||
CAKE,
|
||||
_23_CAKE,
|
||||
SLICE_OF_CAKE,
|
||||
SALMON,
|
||||
RAW_KARAMBWANJI);
|
||||
game.tick();
|
||||
|
||||
int quantity = 10 + (game.baseLevel(Skill.HITPOINTS) - game.modifiedLevel(Skill.HITPOINTS)) / 12;
|
||||
|
||||
bank.withdraw(SALMON, quantity, false);
|
||||
game.waitUntil(() -> game.inventory().withAction("Eat", "Drink").count() > 1, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Banking";
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.BossData;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Scouter;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.game.WorldService;
|
||||
import net.runelite.client.util.WorldUtil;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
import net.runelite.http.api.worlds.WorldResult;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
public class Hop extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
@Inject
|
||||
public Scouter scouter;
|
||||
|
||||
@Inject
|
||||
public WorldService worldService;
|
||||
|
||||
private Instant lastAttempt;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Hopping to other world";
|
||||
}
|
||||
|
||||
private BossData best;
|
||||
private net.runelite.api.World quickHopTargetWorld;
|
||||
private int displaySwitcherAttempts = 0;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.isInWintertodtRegion()) return false;
|
||||
if (plugin.bossIsUp()) return false;
|
||||
|
||||
best = findBestWorld();
|
||||
|
||||
return best.getWorld() != game.client().getWorld()
|
||||
&& (lastAttempt == null || Duration.between(lastAttempt, Instant.now()).getSeconds() >= 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
WorldResult worldResult = worldService.getWorlds();
|
||||
if (worldResult == null) return;
|
||||
|
||||
World world = worldResult.findWorld(best.getWorld());
|
||||
if (world == null) return;
|
||||
|
||||
final net.runelite.api.World rsWorld = game.client().createWorld();
|
||||
rsWorld.setActivity(world.getActivity());
|
||||
rsWorld.setAddress(world.getAddress());
|
||||
rsWorld.setId(world.getId());
|
||||
rsWorld.setPlayerCount(world.getPlayers());
|
||||
rsWorld.setLocation(world.getLocation());
|
||||
rsWorld.setTypes(WorldUtil.toWorldTypes(world.getTypes()));
|
||||
|
||||
if (game.client().getGameState() == GameState.LOGIN_SCREEN) {
|
||||
game.client().changeWorld(rsWorld);
|
||||
return;
|
||||
}
|
||||
|
||||
quickHopTargetWorld = rsWorld;
|
||||
displaySwitcherAttempts = 0;
|
||||
lastAttempt = Instant.now();
|
||||
}
|
||||
|
||||
public void onGameTick() {
|
||||
if (quickHopTargetWorld == null) return;
|
||||
|
||||
if (game.client().getWidget(WidgetInfo.WORLD_SWITCHER_LIST) == null) {
|
||||
game.client().openWorldHopper();
|
||||
if (++displaySwitcherAttempts >= 5) {
|
||||
logWarn("Failed to hop after 5 attempts");
|
||||
displaySwitcherAttempts = 0;
|
||||
quickHopTargetWorld = null;
|
||||
}
|
||||
} else {
|
||||
game.client().hopToWorld(quickHopTargetWorld);
|
||||
plugin.setLastHop(Instant.now());
|
||||
quickHopTargetWorld = null;
|
||||
}
|
||||
}
|
||||
|
||||
private BossData findBestWorld() {
|
||||
List<BossData> dataList = scouter.getData();
|
||||
|
||||
BossData best = scouter.getLocalData();
|
||||
|
||||
for (BossData data : dataList) {
|
||||
// ignore data older than 5 seconds
|
||||
if (System.currentTimeMillis() - (data.getTime() * 1000) >= 5000) continue;
|
||||
|
||||
if (best.getHealth() > 0) {
|
||||
if (data.getHealth() >= config.hopPercentage() && data.getHealth() < best.getHealth()) {
|
||||
best = data;
|
||||
}
|
||||
} else {
|
||||
if (data.getHealth() >= config.hopPercentage()) {
|
||||
best = data;
|
||||
} else if (data.getHealth() <= 0 && data.getTimer() < best.getTimer()) {
|
||||
best = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.NpcID.INCAPACITATED_PYROMANCER;
|
||||
|
||||
public class Light extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Lighting the brazier";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.isInWintertodtRegion()) return false;
|
||||
|
||||
int distance = plugin.getCurrentActivity() == Activity.IDLE ? 8 : 2;
|
||||
|
||||
return game.objects().within(distance).withAction("Light").exists()
|
||||
&& (plugin.getBossHealth() > 0 || plugin.getRespawnTimer() == 0)
|
||||
&& plugin.getCurrentActivity() != Activity.LIGHTING_BRAZIER
|
||||
&& !game.npcs().within(6).withId(INCAPACITATED_PYROMANCER).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
int distance = plugin.getCurrentActivity() == Activity.IDLE ? 8 : 2;
|
||||
|
||||
game.objects().within(distance).withAction("Light").findFirst().ifPresent((brazier) -> {
|
||||
brazier.interact("Light");
|
||||
game.tick();
|
||||
});
|
||||
|
||||
if (distance == 2) {
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.LIGHTING_BRAZIER || !game.objects().within(distance).withAction("Light").exists(), 3);
|
||||
} else {
|
||||
game.waitUntil(() -> plugin.getCurrentActivity() == Activity.LIGHTING_BRAZIER || !game.objects().within(distance).withAction("Light").exists(), 6);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Activity;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.scene.Position;
|
||||
|
||||
public class MoveToBrazier extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Moving near brazier";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
if (!plugin.isInWintertodtRegion()) return false;
|
||||
|
||||
if (plugin.isTooCold()
|
||||
|| (game.localPlayer().position().equals(new Position(1634, 3987, 0)) && plugin.getPreviousActivity() == Activity.FLETCHING)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return plugin.getRespawnTimer() > 0
|
||||
&& !game.localPlayer().position().equals(plugin.getNearestSide().getPositionNearBrazier())
|
||||
&& !game.localPlayer().isMoving();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
plugin.setTooCold(false);
|
||||
walking.walkTo(plugin.getNearestSide().getPositionNearBrazier());
|
||||
game.tick();
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Config;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.client.plugins.iutils.game.iObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static net.runelite.api.ItemID.*;
|
||||
|
||||
public class OpenCrates extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Inject
|
||||
public Config config;
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
iObject bankObj = game.objects().withAction("Bank").nearest();
|
||||
|
||||
return !plugin.isInWintertodtRegion()
|
||||
&& game.localPlayer().position().distanceTo(bankObj.position()) < calc.random(5, 7)
|
||||
&& config.openCrates()
|
||||
&& game.inventory().withId(SUPPLY_CRATE).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.inventory().withId(SUPPLY_CRATE).forEach((crate) -> {
|
||||
crate.interact("Open");
|
||||
game.tick();
|
||||
game.sleepDelay();
|
||||
});
|
||||
|
||||
game.inventory().withId(PYROMANCER_BOOTS, PYROMANCER_GARB, PYROMANCER_HOOD, PYROMANCER_ROBE).forEach((outfit) -> {
|
||||
outfit.interact("Wear");
|
||||
game.tick(calc.random(2, 4));
|
||||
game.sleepDelay();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Opening supply crates";
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package io.reisub.openosrs.wintertodt.tasks;
|
||||
|
||||
import io.reisub.openosrs.util.Task;
|
||||
import io.reisub.openosrs.wintertodt.Wintertodt;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class OpenInventory extends Task {
|
||||
@Inject
|
||||
public Wintertodt plugin;
|
||||
|
||||
@Override
|
||||
public String getStatus() {
|
||||
return "Opening inventory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() {
|
||||
return game.client().getGameState() == GameState.LOGGED_IN
|
||||
&& !bank.isOpen()
|
||||
&& (game.widget(WidgetInfo.INVENTORY) == null || game.widget(WidgetInfo.INVENTORY).hidden());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.sleepDelay();
|
||||
game.openInterface(3);
|
||||
game.tick();
|
||||
}
|
||||
}
|
52
wintertodt/wintertodt.gradle.kts
Normal file
52
wintertodt/wintertodt.gradle.kts
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 = "0.0.1"
|
||||
|
||||
project.extra["PluginName"] = "Chaos Wintertodt" // This is the name that is used in the external plugin manager panel
|
||||
project.extra["PluginDescription"] = "Plays the Wintertodt game" // This is the description that is used in the external plugin manager panel
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":util"))
|
||||
}
|
||||
|
||||
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-Description" to project.extra["PluginDescription"],
|
||||
"Plugin-Dependencies" to
|
||||
arrayOf(
|
||||
nameToId("Chaos Util"),
|
||||
nameToId("iUtils")
|
||||
).joinToString(),
|
||||
"Plugin-License" to project.extra["PluginLicense"]
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user