From 1c159c929a8ee3301cfb1b1902356214b2d23bd1 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle Date: Fri, 15 May 2020 06:33:15 -0700 Subject: [PATCH 1/2] item stats - Fix revitalisation potion prayer bonus --- .../itemstats/potions/PrayerPotion.java | 12 +- .../itemstats/potions/SuperRestore.java | 2 +- .../plugins/itemstats/ItemStatEffectTest.java | 119 ++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java index a0d17db24b..6611b8ac35 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/PrayerPotion.java @@ -35,12 +35,20 @@ import static net.runelite.client.plugins.itemstats.stats.Stats.PRAYER; public class PrayerPotion extends StatBoost { + private static final double BASE_PERC = .25; private final int delta; + private final double perc; public PrayerPotion(int delta) + { + this(delta, BASE_PERC); + } + + PrayerPotion(int delta, double perc) { super(PRAYER, false); this.delta = delta; + this.perc = perc; } private static final int RING_SLOT = EquipmentInventorySlot.RING.getSlotIdx(); @@ -93,9 +101,9 @@ public class PrayerPotion extends StatBoost } } - double perc = hasHolyWrench ? .27 : .25; + double percent = hasHolyWrench ? perc + .02 : perc; int max = getStat().getMaximum(client); - return (((int) (max * perc)) * (delta >= 0 ? 1 : -1)) + delta; + return (((int) (max * percent)) * (delta >= 0 ? 1 : -1)) + delta; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java index b63cd0c2c9..543e3838cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java @@ -56,7 +56,7 @@ public class SuperRestore implements Effect StatsChanges changes = new StatsChanges(0); SimpleStatBoost calc = new SimpleStatBoost(null, false, perc(percR, delta)); - PrayerPotion prayer = new PrayerPotion(delta); + PrayerPotion prayer = new PrayerPotion(delta, percR); changes.setStatChanges(Stream.concat( Stream.of(prayer.effect(client)), Stream.of(superRestoreStats) 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 new file mode 100644 index 0000000000..3a20ba9723 --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemstats/ItemStatEffectTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020, TheStonedTurtle + * 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; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.Skill; +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import org.mockito.Mock; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ItemStatEffectTest +{ + private static final ImmutableMap REVITALISATION_TABLE; + + static + { + // https://oldschool.runescape.wiki/w/Revitalisation_(+)#Maximum_stat_restoration + REVITALISATION_TABLE = new ImmutableMap.Builder() + .put(1, 11) .put(50, 26) + .put(3, 11) .put(53, 26) + .put(4, 12) .put(54, 27) + .put(6, 12) .put(56, 27) + .put(7, 13) .put(57, 28) + .put(9, 13) .put(59, 28) + .put(10, 14) .put(60, 29) + .put(13, 14) .put(63, 29) + .put(14, 15) .put(64, 30) + .put(16, 15) .put(66, 30) + .put(17, 16) .put(67, 31) + .put(19, 16) .put(69, 31) + .put(20, 17) .put(70, 32) + .put(23, 17) .put(73, 32) + .put(24, 18) .put(74, 33) + .put(26, 18) .put(76, 33) + .put(27, 19) .put(77, 34) + .put(29, 19) .put(79, 34) + .put(30, 20) .put(80, 35) + .put(33, 20) .put(83, 35) + .put(34, 21) .put(84, 36) + .put(36, 21) .put(86, 36) + .put(37, 22) .put(87, 37) + .put(39, 22) .put(89, 37) + .put(40, 23) .put(90, 38) + .put(43, 23) .put(93, 38) + .put(44, 24) .put(94, 39) + .put(46, 24) .put(96, 39) + .put(47, 25) .put(97, 40) + .put(49, 25) .put(99, 40) + .build(); + } + + @Mock + private Client client; + + private final ItemStatChanges itemStats = new ItemStatChanges(); + + @Before + public void prepare() + { + when(client.getBoostedSkillLevel(any(Skill.class))) + .thenReturn(0); + } + + @Test + public void testRevitalisationPlus() + { + final Effect item = itemStats.get(ItemID.REVITALISATION_1_20957); + matchWikiTable(REVITALISATION_TABLE, item); + } + + private void matchWikiTable(final ImmutableMap table, final Effect item) + { + for (final Map.Entry entry : table.entrySet()) + { + final int level = entry.getKey(); + final int theoretical = entry.getValue(); + + when(client.getRealSkillLevel(any(Skill.class))) + .thenReturn(level); + + final StatChange[] changes = item.calculate(client).getStatChanges(); + for (final StatChange change : changes) + { + assertEquals(theoretical, change.getTheoretical()); + } + } + } +} From 4836080e56a6523a1b5a686b16a82a9182a393a0 Mon Sep 17 00:00:00 2001 From: TheStonedTurtle Date: Fri, 15 May 2020 07:10:29 -0700 Subject: [PATCH 2/2] item stats - Fix sanfew serum restore bonuses --- .../plugins/itemstats/ItemStatChanges.java | 2 +- .../itemstats/potions/SuperRestore.java | 4 +- .../plugins/itemstats/ItemStatEffectTest.java | 62 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) 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 682e2b08cb..6391628e4d 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 @@ -158,7 +158,7 @@ public class ItemStatChanges add(heal(RUN_ENERGY, 20), SUPER_ENERGY1, SUPER_ENERGY2, SUPER_ENERGY3, SUPER_ENERGY4); add(new SuperRestore(.25, 8), SUPER_RESTORE1, SUPER_RESTORE2, SUPER_RESTORE3, SUPER_RESTORE4, BLIGHTED_SUPER_RESTORE1, BLIGHTED_SUPER_RESTORE2, BLIGHTED_SUPER_RESTORE3, BLIGHTED_SUPER_RESTORE4); - add(new SuperRestore(.25, 9), SANFEW_SERUM1, SANFEW_SERUM2, SANFEW_SERUM3, SANFEW_SERUM4); + add(new SuperRestore(.30, 4), SANFEW_SERUM1, SANFEW_SERUM2, SANFEW_SERUM3, SANFEW_SERUM4); add(heal(RUN_ENERGY, 20), STAMINA_POTION1, STAMINA_POTION2, STAMINA_POTION3, STAMINA_POTION4); // Raids potions (+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java index 543e3838cb..38493055d7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemstats/potions/SuperRestore.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.itemstats.potions; +import com.google.common.annotations.VisibleForTesting; import java.util.Comparator; import java.util.stream.Stream; import lombok.RequiredArgsConstructor; @@ -47,7 +48,8 @@ public class SuperRestore implements Effect CONSTRUCTION }; - private final double percR; //percentage restored + @VisibleForTesting + public final double percR; //percentage restored private final int delta; @Override 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 3a20ba9723..8f498a6f46 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 @@ -42,6 +42,8 @@ import org.mockito.junit.MockitoJUnitRunner; public class ItemStatEffectTest { private static final ImmutableMap REVITALISATION_TABLE; + private static final ImmutableMap SUPER_RESTORE_TABLE; + private static final ImmutableMap SANFEW_TABLE; static { @@ -78,6 +80,52 @@ public class ItemStatEffectTest .put(47, 25) .put(97, 40) .put(49, 25) .put(99, 40) .build(); + + // https://oldschool.runescape.wiki/w/Super_restore#Maximum_restoration + SUPER_RESTORE_TABLE = new ImmutableMap.Builder() + .put(1, 8) .put(36, 17) .put(72, 26) + .put(3, 8) .put(39, 17) .put(75, 26) + .put(4, 9) .put(40, 18) .put(76, 27) + .put(7, 9) .put(43, 18) .put(79, 27) + .put(8, 10) .put(44, 19) .put(80, 28) + .put(11, 10) .put(47, 19) .put(83, 28) + .put(12, 11) .put(48, 20) .put(84, 29) + .put(15, 11) .put(51, 20) .put(87, 29) + .put(16, 12) .put(52, 21) .put(88, 30) + .put(19, 12) .put(55, 21) .put(91, 30) + .put(20, 13) .put(56, 22) .put(92, 31) + .put(23, 13) .put(59, 22) .put(95, 31) + .put(24, 14) .put(60, 23) .put(96, 32) + .put(27, 14) .put(63, 23) .put(99, 32) + .put(28, 15) .put(64, 24) + .put(31, 15) .put(67, 24) + .put(32, 16) .put(68, 25) + .put(35, 16) .put(71, 25) + .build(); + + // https://oldschool.runescape.wiki/w/Sanfew_serum#Maximum_restoration + SANFEW_TABLE = new ImmutableMap.Builder() + .put(1, 4) .put(34, 14) .put(67, 24) + .put(3, 4) .put(36, 14) .put(69, 24) + .put(4, 5) .put(37, 15) .put(70, 25) + .put(6, 5) .put(39, 15) .put(73, 25) + .put(7, 6) .put(40, 16) .put(74, 26) + .put(9, 6) .put(43, 16) .put(76, 26) + .put(10, 7) .put(44, 17) .put(77, 27) + .put(13, 7) .put(46, 17) .put(79, 27) + .put(14, 8) .put(47, 18) .put(80, 28) + .put(16, 8) .put(49, 18) .put(83, 28) + .put(17, 9) .put(50, 19) .put(84, 29) + .put(19, 9) .put(53, 19) .put(86, 29) + .put(20, 10) .put(54, 20) .put(87, 30) + .put(23, 10) .put(56, 20) .put(89, 30) + .put(24, 11) .put(57, 21) .put(90, 31) + .put(26, 11) .put(59, 21) .put(93, 31) + .put(27, 12) .put(60, 22) .put(94, 32) + .put(29, 12) .put(63, 22) .put(96, 32) + .put(30, 13) .put(64, 23) .put(97, 33) + .put(33, 13) .put(66, 23) .put(99, 33) + .build(); } @Mock @@ -99,6 +147,20 @@ public class ItemStatEffectTest matchWikiTable(REVITALISATION_TABLE, item); } + @Test + public void testSuperRestore() + { + final Effect item = itemStats.get(ItemID.SUPER_RESTORE1); + matchWikiTable(SUPER_RESTORE_TABLE, item); + } + + @Test + public void testSanfewSerum() + { + final Effect item = itemStats.get(ItemID.SANFEW_SERUM1); + matchWikiTable(SANFEW_TABLE, item); + } + private void matchWikiTable(final ImmutableMap table, final Effect item) { for (final Map.Entry entry : table.entrySet())