diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java index bd97701644..b54b3c6ee6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/ItemStatChanges.java @@ -33,6 +33,7 @@ import lombok.extern.slf4j.Slf4j; import static net.runelite.api.ItemID.*; import static net.runelite.client.plugins.itemstats.Builders.*; import net.runelite.client.plugins.itemstats.food.Anglerfish; +import net.runelite.client.plugins.itemstats.potions.AncientBrew; import net.runelite.client.plugins.itemstats.potions.GauntletPotion; import net.runelite.client.plugins.itemstats.potions.PrayerPotion; import net.runelite.client.plugins.itemstats.potions.SaradominBrew; @@ -196,6 +197,7 @@ public class ItemStatChanges CASTLEWARS_BREW4, CASTLEWARS_BREW3, CASTLEWARS_BREW2, CASTLEWARS_BREW1); add(combo(2, boost(ATTACK, perc(0.15, 5)), boost(STRENGTH, perc(0.15, 5))), SUPER_COMBAT_POTION4_23543, SUPER_COMBAT_POTION3_23545, SUPER_COMBAT_POTION2_23547, SUPER_COMBAT_POTION1_23549 /* LMS */); + add(new AncientBrew(), ANCIENT_BREW1, ANCIENT_BREW2, ANCIENT_BREW3, ANCIENT_BREW4); // Regular overload (NMZ) add(combo(5, boost(ATTACK, perc(.15, 5)), boost(STRENGTH, perc(.15, 5)), boost(DEFENCE, perc(.15, 5)), boost(RANGED, perc(.15, 5)), boost(MAGIC, perc(.15, 5)), heal(HITPOINTS, -50)), OVERLOAD_1, OVERLOAD_2, OVERLOAD_3, OVERLOAD_4); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/AncientBrew.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/AncientBrew.java new file mode 100644 index 0000000000..08e705dcb0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/AncientBrew.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 Hydrox6 + * 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.itemstats.potions; + +import lombok.NoArgsConstructor; +import net.runelite.api.Client; +import net.runelite.client.plugins.itemstats.BoostedStatBoost; +import static net.runelite.client.plugins.itemstats.Builders.perc; +import net.runelite.client.plugins.itemstats.CappedStatBoost; +import net.runelite.client.plugins.itemstats.Effect; +import net.runelite.client.plugins.itemstats.SimpleStatBoost; +import net.runelite.client.plugins.itemstats.StatChange; +import net.runelite.client.plugins.itemstats.StatsChanges; +import net.runelite.client.plugins.itemstats.stats.Stat; +import static net.runelite.client.plugins.itemstats.stats.Stats.ATTACK; +import static net.runelite.client.plugins.itemstats.stats.Stats.DEFENCE; +import static net.runelite.client.plugins.itemstats.stats.Stats.MAGIC; +import static net.runelite.client.plugins.itemstats.stats.Stats.PRAYER; +import static net.runelite.client.plugins.itemstats.stats.Stats.STRENGTH; +import java.util.Comparator; +import java.util.stream.Stream; + +@NoArgsConstructor +public class AncientBrew implements Effect +{ + private static final Stat[] LOWERED_STATS = { + ATTACK, STRENGTH, DEFENCE + }; + private static final CappedStatBoost PRAYER_BOOST = new CappedStatBoost(PRAYER, perc(.1, 2), perc(.05, 0)); + private static final SimpleStatBoost MAGIC_BOOST = new SimpleStatBoost(MAGIC, true, perc(.05, 2)); + private static final BoostedStatBoost MELEE_DRAIN = new BoostedStatBoost(null, false, perc(.1, -2)); + + @Override + public StatsChanges calculate(Client client) + { + StatsChanges changes = new StatsChanges(0); + changes.setStatChanges(Stream.of( + Stream.of(PRAYER_BOOST.effect(client)), + Stream.of(MAGIC_BOOST.effect(client)), + Stream.of(LOWERED_STATS) + .filter(stat -> 1 < stat.getValue(client)) + .map(stat -> + { + MELEE_DRAIN.setStat(stat); + return MELEE_DRAIN.effect(client); + })) + .reduce(Stream::concat) + .orElseGet(Stream::empty) + .toArray(StatChange[]::new)); + changes.setPositivity(Stream.of(changes.getStatChanges()) + .map(StatChange::getPositivity) + .max(Comparator.naturalOrder()).get()); + return changes; + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java index 8f498a6f46..b75313dd3e 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java @@ -178,4 +178,42 @@ public class ItemStatEffectTest } } } + + @Test + public void testAncientBrew() + { + final Effect ancientBrew = new ItemStatChanges().get(ItemID.ANCIENT_BREW4); + + assertEquals(4, skillChange(Skill.PRAYER, 99, 99, ancientBrew)); + assertEquals(11, skillChange(Skill.PRAYER, 99, 90, ancientBrew)); + assertEquals(11, skillChange(Skill.PRAYER, 99, 0, ancientBrew)); + assertEquals(2, skillChange(Skill.PRAYER, 50, 50, ancientBrew)); + assertEquals(7, skillChange(Skill.PRAYER, 50, 40, ancientBrew)); + assertEquals(0, skillChange(Skill.PRAYER, 1, 1, ancientBrew)); + assertEquals(1, skillChange(Skill.PRAYER, 1, 0, ancientBrew)); + } + + private int skillChange(Skill skill, int maxValue, int currentValue, Effect effect) + { + if (effect == null) + { + throw new IllegalArgumentException("Applied effect is null"); + } + + when(client.getRealSkillLevel(skill)).thenReturn(maxValue); + when(client.getBoostedSkillLevel(skill)).thenReturn(currentValue); + final StatsChanges statsChanges = effect.calculate(client); + + for (final StatChange statChange : statsChanges.getStatChanges()) + { + if (!statChange.getStat().getName().equals(skill.getName())) + { + continue; + } + + return statChange.getRelative(); + } + + return 0; + } }