Backported probabilistic runes. Can now toggle between revision 581, 573 and 570 behavior via runecrafting_formula_revision in server config

This commit is contained in:
Avi Weinstock 2023-10-27 12:41:17 +00:00 committed by Ryan
parent a74583b13b
commit fee56ae528
6 changed files with 84 additions and 19 deletions

View file

@ -9,19 +9,19 @@ import core.game.node.item.Item;
* @date 01/11/2013
*/
public enum Rune {
AIR(Runes.AIR_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99 }),
MIND(Runes.MIND_RUNE.transform(), 2, 5.5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98 }),
WATER(Runes.WATER_RUNE.transform(), 5, 6, new int[] { 1, 19, 38, 57, 76, 95 }),
EARTH(Runes.EARTH_RUNE.transform(), 9, 6.5, new int[] { 1, 26, 52, 78 }),
FIRE(Runes.FIRE_RUNE.transform(), 14, 7, new int[] { 1, 35, 70 }),
BODY(Runes.BODY_RUNE.transform(), 20, 7.5, new int[] { 1, 46, 92 }),
COSMIC(Runes.COSMIC_RUNE.transform(), 27, 8, new int[] { 1, 59 }),
CHAOS(Runes.CHAOS_RUNE.transform(), 35, 8.5, new int[] { 1, 74 }),
ASTRAL(Runes.ASTRAL_RUNE.transform(), 40, 8.7, new int[] { 1, 82 }),
NATURE(Runes.NATURE_RUNE.transform(), 44, 9, new int[] { 1, 91 }),
LAW(Runes.LAW_RUNE.transform(), 54, 9.5),
DEATH(Runes.DEATH_RUNE.transform(), 65, 10),
BLOOD(Runes.BLOOD_RUNE.transform(), 77, 10.5),
AIR(Runes.AIR_RUNE.transform(), 1, 5, new int[] { 1, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }),
MIND(Runes.MIND_RUNE.transform(), 2, 5.5, new int[] { 1, 14, 28, 42, 56, 70, 84, 98, 112 }),
WATER(Runes.WATER_RUNE.transform(), 5, 6, new int[] { 1, 19, 38, 57, 76, 95, 114 }),
EARTH(Runes.EARTH_RUNE.transform(), 9, 6.5, new int[] { 1, 26, 52, 78, 104 }),
FIRE(Runes.FIRE_RUNE.transform(), 14, 7, new int[] { 1, 35, 70, 105 }),
BODY(Runes.BODY_RUNE.transform(), 20, 7.5, new int[] { 1, 46, 92, 138 }),
COSMIC(Runes.COSMIC_RUNE.transform(), 27, 8, new int[] { 1, 59, 118 }),
CHAOS(Runes.CHAOS_RUNE.transform(), 35, 8.5, new int[] { 1, 74, 148 }),
ASTRAL(Runes.ASTRAL_RUNE.transform(), 40, 8.7, new int[] { 1, 82, 164 }),
NATURE(Runes.NATURE_RUNE.transform(), 44, 9, new int[] { 1, 91, 182 }),
LAW(Runes.LAW_RUNE.transform(), 54, 9.5, new int[] { 1, 110, }),
DEATH(Runes.DEATH_RUNE.transform(), 65, 10, new int[] { 1, 131 }),
BLOOD(Runes.BLOOD_RUNE.transform(), 77, 10.5, new int[] { 1, 154 }),
SOUL(Runes.SOUL_RUNE.transform(), 90, 11);
/**

View file

@ -1,6 +1,7 @@
package content.global.skill.runecrafting;
import content.global.handlers.item.equipment.fistofguthixgloves.FOGGlovesManager;
import core.ServerConstants;
import core.game.container.impl.EquipmentContainer;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.player.Player;
@ -333,6 +334,12 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
return 1;
}
int rcLevel = player.getSkills().getLevel(Skills.RUNECRAFTING);
int runecraftingFormulaRevision = ServerConstants.RUNECRAFTING_FORMULA_REVISION;
boolean lumbridgeDiary = player.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE).isComplete(1);
return RuneCraftPulse.getMultiplier(rcLevel, rune, runecraftingFormulaRevision, lumbridgeDiary);
}
public static int getMultiplier(int rcLevel, Rune rune, int runecraftingFormulaRevision, boolean lumbridgeDiary) {
int[] multipleLevels = rune.getMultiple();
int i = 0;
for (int level : multipleLevels) {
@ -341,17 +348,18 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
}
}
if(multipleLevels.length > i) {
if(multipleLevels.length > i && runecraftingFormulaRevision >= 573) {
int a = Math.max(multipleLevels[i-1], rune.getLevel());
int b = multipleLevels[i];
double chance = ((double)rcLevel - (double)a) / ((double)b - (double)a);
player.debug(String.format("%d %d %d, %f", a, b, rcLevel, chance));
if(RandomFunction.random(0.0, 1.0) < chance) {
i += 1;
if(b <= 99 || runecraftingFormulaRevision >= 581) {
double chance = ((double)rcLevel - (double)a) / ((double)b - (double)a);
if(RandomFunction.random(0.0, 1.0) < chance) {
i += 1;
}
}
}
if (player.getAchievementDiaryManager().getDiary(DiaryType.LUMBRIDGE).isComplete(1)
if (lumbridgeDiary
&& new ArrayList<>(Arrays.asList(Rune.AIR, Rune.WATER, Rune.FIRE, Rune.EARTH)).contains(rune)
&& RandomFunction.getRandom(10) == 0) { //approximately 10% chance
i += 1;

View file

@ -317,5 +317,8 @@ class ServerConstants {
@JvmField
var FORCE_HALLOWEEN_RANDOMS = false
@JvmField
var RUNECRAFTING_FORMULA_REVISION = 581
}
}

View file

@ -163,6 +163,7 @@ object ServerConfigParser {
ServerConstants.NEW_PLAYER_ANNOUNCEMENT = data.getBoolean("world.new_player_announcement", true)
ServerConstants.HOLIDAY_EVENT_RANDOMS = data.getBoolean("world.holiday_event_randoms", true)
ServerConstants.FORCE_HALLOWEEN_RANDOMS = data.getBoolean("world.force_halloween_randoms", false)
ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 581).toInt()
val logLevel = data.getString("server.log_level", "VERBOSE").uppercase()
ServerConstants.LOG_LEVEL = parseEnumEntry<LogLevel>(logLevel) ?: LogLevel.VERBOSE

View file

@ -0,0 +1,51 @@
import content.global.skill.runecrafting.RuneCraftPulse;
import content.global.skill.runecrafting.Rune;
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class RunecraftTests {
fun rollRc(rcLevel: Int, rune: Rune, revision: Int, lo: Double, hi: Double) {
var total = 0.0
for(i in 0 until 1000) {
total += RuneCraftPulse.getMultiplier(rcLevel, rune, revision, false)
}
val average = total / 1000.0
Assertions.assertTrue(lo <= average && average <= hi, "rollRc: ${rcLevel} ${rune.name} ${revision}: ${average}")
}
@Test fun testNatureRcMultipliers() {
rollRc(44, Rune.NATURE, 530, 1.0, 1.0);
rollRc(44, Rune.NATURE, 573, 1.0, 1.0);
rollRc(44, Rune.NATURE, 581, 1.0, 1.0);
rollRc(68, Rune.NATURE, 530, 1.0, 1.0);
rollRc(68, Rune.NATURE, 573, 1.45, 1.55);
rollRc(68, Rune.NATURE, 581, 1.45, 1.55);
rollRc(91, Rune.NATURE, 530, 2.0, 2.0);
rollRc(91, Rune.NATURE, 573, 2.0, 2.0);
rollRc(91, Rune.NATURE, 581, 2.0, 2.0);
rollRc(90, Rune.NATURE, 530, 1.0, 1.0);
rollRc(90, Rune.NATURE, 573, 1.95, 2.0);
rollRc(90, Rune.NATURE, 581, 1.95, 2.0);
rollRc(99, Rune.NATURE, 530, 2.0, 2.0);
rollRc(99, Rune.NATURE, 573, 2.0, 2.0);
rollRc(99, Rune.NATURE, 581, 2.0, 2.1);
}
@Test fun testLawRcMultipliers() {
rollRc(54, Rune.LAW, 530, 1.0, 1.0);
rollRc(54, Rune.LAW, 573, 1.0, 1.0);
rollRc(54, Rune.LAW, 581, 1.0, 1.0);
rollRc(77, Rune.LAW, 530, 1.0, 1.0);
rollRc(77, Rune.LAW, 573, 1.0, 1.0);
rollRc(77, Rune.LAW, 581, 1.35, 1.45);
rollRc(99, Rune.LAW, 530, 1.0, 1.0);
rollRc(99, Rune.LAW, 573, 1.0, 1.0);
rollRc(99, Rune.LAW, 581, 1.75, 1.85);
}
}

View file

@ -101,6 +101,8 @@ new_player_announcement = true
holiday_event_randoms = true
#force holiday randoms (can only force one at a time)
force_halloween_randoms = false
# runecrafting formula revision (573 introduced probabilistic multiple runes, 581 extrapolated probabilistic runes past 99)
runecrafting_formula_revision = 581
[paths]
#path to the data folder, which contains the cache subfolder and such