Merge branch 'fishing-trawler-fixes' into 'master'

Fishing and fishing trawler now use closer-to-empirical formulae.

See merge request 2009scape/2009scape!348
This commit is contained in:
Ceikry 2021-12-17 00:39:45 +00:00
commit b4f3224287
9 changed files with 117 additions and 72 deletions

View file

@ -74,3 +74,4 @@
- Fix granting hp xp on controlled
- Implemented HCIM Rework
< --- ABOVE Released December 15, 2021 https://gitlab.com/2009scape/2009scape/-/tags/Dec-15-2021 ---- >
- Fishing and fishing trawler now use closer-to-empirical formulae.

View file

@ -9,35 +9,34 @@ import java.util.HashMap;
* @author ceikry
*/
public enum Fish {
CRAYFISH(new Item(13435),1,10),
SHRIMP(new Item(317), 1, 10),
SARDINE(new Item(327), 5, 20),
KARAMBWANJI(new Item(3150), 5, 5),
HERRING(new Item(345), 10, 30),
ANCHOVIE(new Item(321), 15, 40),
MACKEREL(new Item(353), 16, 20),
TROUT(new Item(335), 20, 50),
COD(new Item(341), 23, 45),
PIKE(new Item(349), 25, 60),
SLIMY_EEL(new Item(3379), 28, 65),
SALMON(new Item(331), 30, 70),
FROG_SPAWN(new Item(5004), 33, 75),
TUNA(new Item(359), 35, 80),
RAINBOW_FISH(new Item(10138), 38, 80),
CAVE_EEL(new Item(5001), 38, 80),
LOBSTER(new Item(377), 40, 90),
BASS(new Item(363), 46, 100),
SWORDFISH(new Item(371), 50, 100),
LAVA_EEL(new Item(2148), 53, 100),
MONKFISH(new Item(7944), 62, 120),
KARAMBWAN(new Item(3142), 65, 105),
SHARK(new Item(383), 76, 110),
SEA_TURTLE(new Item(395), 79, 38),
MANTA_RAY(new Item(389), 81, 46),
SEAWEED(new Item(401), 16, 1),
CASKET(new Item(405), 16, 10),
OYSTER(new Item(407), 16, 10),
DARK_CRAB(new Item(14937), 85, 130);
CRAYFISH(new Item(13435),1, 10, 0.15, 0.5),
SHRIMP(new Item(317), 1, 10, 0.191, 0.5),
SARDINE(new Item(327), 5, 20, 0.148, 0.374),
KARAMBWANJI(new Item(3150), 5, 5, 0.4, 0.98),
HERRING(new Item(345), 10, 30, 0.129, 0.504),
ANCHOVIE(new Item(321), 15, 40, 0.098, 0.5),
MACKEREL(new Item(353), 16, 20, 0.055, 0.258),
TROUT(new Item(335), 20, 50, 0.246, 0.468),
COD(new Item(341), 23, 45, 0.063, 0.219),
PIKE(new Item(349), 25, 60, 0.14, 0.379),
SLIMY_EEL(new Item(3379), 28, 65, 0.117, 0.216),
SALMON(new Item(331), 30, 70, 0.156, 0.378),
FROG_SPAWN(new Item(5004), 33, 75, 0.164, 0.379),
TUNA(new Item(359), 35, 80, 0.109, 0.205),
RAINBOW_FISH(new Item(10138), 38, 80, 0.113, 0.254),
CAVE_EEL(new Item(5001), 38, 80, 0.145, 0.316),
LOBSTER(new Item(377), 40, 90, 0.16, 0.375),
BASS(new Item(363), 46, 100, 0.078, 0.16),
SWORDFISH(new Item(371), 50, 100, 0.105, 0.191),
LAVA_EEL(new Item(2148), 53, 100, 0.227, 0.379),
MONKFISH(new Item(7944), 62, 120, 0.293, 0.356),
KARAMBWAN(new Item(3142), 65, 105, 0.414, 0.629),
SHARK(new Item(383), 76, 110, 0.121, 0.16),
SEA_TURTLE(new Item(395), 79, 38, 0.0, 0.0),
MANTA_RAY(new Item(389), 81, 46, 0.0, 0.0),
SEAWEED(new Item(401), 16, 1, 0.63, 0.219),
CASKET(new Item(405), 16, 10, 0.63, 0.219),
OYSTER(new Item(407), 16, 10, 0.63, 0.219);
/**
* Constructs a new {@code Fish} {@code Object}.
@ -45,11 +44,16 @@ public enum Fish {
* @param level the level.
* @param experience the experience.
*/
Fish(final Item item, final int level, final double experience, final int... npcs) {
Fish(final Item item, final int level, final double experience, final double lowChance, final double highChance, final int... npcs) {
this.item = item;
this.level = level;
this.experience = experience;
this.npcs = npcs;
// The chances are given in the table based on when the fish can first be caught.
// Linearly extrapolate the success chance at level 1.
// y = (x - x0) * ((y1 - y0) / (x1 - x0)) + y0
this.lowChance = (1 - (double)level)*((highChance - lowChance) / (99.0 - (double)level)) + lowChance;
this.highChance = highChance;
}
public static HashMap<Integer,Fish> fishMap = new HashMap<>();
@ -70,6 +74,9 @@ public enum Fish {
*/
private final double experience;
private final double lowChance;
private final double highChance;
/**
* The npc ids that give this fish.
*/
@ -112,4 +119,8 @@ public enum Fish {
public int[] getNpcs() {
return npcs;
}
public double getSuccessChance(int level) {
return ((double)level - 1.0)*((highChance - lowChance) / (99.0 - 1.0)) + lowChance;
}
}

View file

@ -8,6 +8,8 @@ import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction;
import org.rs09.consts.Items;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
/**
@ -26,8 +28,7 @@ public enum FishingOption {
BARB_HARPOON(new Item(10129), 35, Animation.create(618), null, "harpoon", Fish.TUNA, Fish.SWORDFISH),
BIG_NET(new Item(305), 16, Animation.create(620), null, "net", Fish.MACKEREL, Fish.COD, Fish.BASS, Fish.SEAWEED),
N_HARPOON(new Item(311), 76, Animation.create(618), null, "harpoon", Fish.SHARK),
H_NET(new Item(303), 1, Animation.create(621), null, "net", Fish.MONKFISH),
C_CAGE(new Item(301), 85, Animation.create(619), new Item[]{new Item(14943)}, "cage", Fish.DARK_CRAB),
H_NET(new Item(303), 62, Animation.create(621), null, "net", Fish.MONKFISH),
KBWANJI_NET(new Item(Items.SMALL_FISHING_NET_303), 5, Animation.create(621), null, "net", Fish.KARAMBWANJI),
KARAMBWAN_VES(new Item(Items.KARAMBWAN_VESSEL_3157), 65, Animation.create(1193), new Item[]{new Item(Items.RAW_KARAMBWANJI_3150)}, "fish", Fish.KARAMBWAN);
@ -84,6 +85,12 @@ public enum FishingOption {
this.animation = animation;
this.bait = bait;
this.name = name;
Arrays.sort(fish, new Comparator<Fish>() {
@Override
public int compare(Fish x, Fish y) {
return y.getLevel() - x.getLevel();
}
});
this.fish = fish;
}
@ -91,7 +98,7 @@ public enum FishingOption {
* Method used to get a random {@link Fish}.
* @return the {@link Fish}.
*/
public Fish getRandomFish(final Player player) {
public Fish rollFish(final Player player) {
if (this == BIG_NET) {
switch (RandomFunction.randomize(100)) {
case 0:
@ -102,14 +109,22 @@ public enum FishingOption {
return Fish.SEAWEED;
}
}
if (this == LURE && player.getInventory().contains(10087, 1)) {
return Fish.RAINBOW_FISH;
}
Fish reward = fish[RandomFunction.randomize(fish.length)];
if (reward.getLevel() > player.getSkills().getLevel(Skills.FISHING) || (reward == Fish.RAINBOW_FISH && !player.getInventory().contains(10087, 1))) {
reward = fish[0];
}
return reward;
int visibleLevel = player.getSkills().getLevel(Skills.FISHING);
int invisibleLevel = visibleLevel + player.getFamiliarManager().getBoost(Skills.FISHING);
for(Fish f : fish) {
if(f.getLevel() > player.getSkills().getLevel(Skills.FISHING)) {
continue;
}
if(this == LURE && (player.getInventory().contains(Items.STRIPY_FEATHER_10087, 1) != (f == Fish.RAINBOW_FISH))) {
continue;
}
double chance = f.getSuccessChance(invisibleLevel);
//System.out.printf("rollFish: %s %s %s %s %s\n", player.getName(), f.getItem().getName(), f.getLowChance(), f.getHighChance(), chance);
if(RandomFunction.random(0.0, 1.0) < chance) {
return f;
}
}
return null;
}
/**

View file

@ -13,7 +13,6 @@ public enum FishingSpot {
CAGE_HARPOON(new int[] { 312, 321, 324, 333, 405, 1332, 1399, 3804, 5470, 7046}, FishingOption.CAGE, FishingOption.HARPOON),
NET_HARPOON(new int[] { 313, 322, 334, 406, 1191, 1333, 1405, 1406, 3574, 3575, 5471, 7044 }, FishingOption.BIG_NET, FishingOption.N_HARPOON),
HARPOON_NET(new int[] { 3848, 3849 }, FishingOption.HARPOON, FishingOption.H_NET, FishingOption.BARB_HARPOON),
CRAB_CAGE(new int[] {8665}, FishingOption.C_CAGE),
SPOT_KBWANJI(new int[] {1174}, FishingOption.KBWANJI_NET),
SPOT_KARAMBWAN(new int[] {1177}, FishingOption.KARAMBWAN_VES);
@ -80,4 +79,4 @@ public enum FishingSpot {
return options;
}
}
}

View file

@ -173,11 +173,12 @@ class NetLootDialogue(player: Player? = null): DialoguePlugin(player){
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
val level = player.skills.getLevel(Skills.FISHING)
when(buttonId){
1 -> TrawlerLoot.getLoot(rolls,true).forEach {
1 -> TrawlerLoot.getLoot(level, rolls, true).forEach {
if(!player.bank.add(it)) GroundItemManager.create(it,player)
}
2 -> TrawlerLoot.getLoot(rolls,false).forEach {
2 -> TrawlerLoot.getLoot(level, rolls, false).forEach {
if(!player.bank.add(it)) GroundItemManager.create(it,player)
}
}
@ -235,4 +236,4 @@ class NetRepairDialogue(player: Player? = null) : DialoguePlugin(player){
return intArrayOf(18237583)
}
}
}

View file

@ -54,6 +54,11 @@ class FishingTrawlerSession(var region: DynamicRegion, val activity: FishingTraw
var inactiveTicks = 0
fun start(pl: ArrayList<Player>){
if(RandomFunction.roll(2)) {
region.setMusicId(38)
} else {
region.setMusicId(51)
}
this.players.addAll(pl)
isActive = true
initHoles()
@ -277,4 +282,4 @@ class TrawlerLogoutPlugin : Plugin<Player>{
return Unit
}
}
}

View file

@ -1,5 +1,6 @@
package rs09.game.content.activity.fishingtrawler
import core.game.node.entity.skill.fishing.Fish
import core.game.node.item.Item
import core.game.node.item.WeightedChanceItem
import core.tools.RandomFunction
@ -11,11 +12,36 @@ import org.rs09.consts.Items
*/
object TrawlerLoot {
val junkItems = arrayOf(Items.BROKEN_ARMOUR_698, Items.BROKEN_ARROW_687, Items.OLD_BOOT_685, Items.BROKEN_GLASS_1469, Items.BROKEN_STAFF_689, Items.BUTTONS_688,Items.DAMAGED_ARMOUR_697, Items.RUSTY_SWORD_686, Items.EMPTY_POT_1931, Items.OYSTER_407)
val trawlerFish = arrayOf(Fish.MANTA_RAY, Fish.SEA_TURTLE, Fish.SHARK, Fish.SWORDFISH, Fish.LOBSTER, Fish.TUNA, Fish.ANCHOVIE, Fish.SARDINE, Fish.SHRIMP)
fun rollTrawlerFish(fishLevel: Int): Item {
while(true) {
for(f in trawlerFish) {
if(f.level > fishLevel) {
continue
}
val lo = 0.6133
val hi = 0.7852
//val chance = RandomFunction.getSkillSuccessChance(lo, hi, fishLevel)
val chance = (fishLevel.toDouble() - 15.0)*((hi - lo) / (99.0 - 15.0)) + lo
if(RandomFunction.random(0.0, 1.0) < chance) {
return f.item
}
}
}
}
@JvmStatic
fun getLoot(rolls: Int, skipJunk: Boolean): ArrayList<Item>{
fun getLoot(fishLevel: Int, rolls: Int, skipJunk: Boolean): ArrayList<Item>{
val loot = ArrayList<Item>()
for(i in 0 until rolls){
loot.add(RandomFunction.rollWeightedChanceTable(listOf(*lootTable)))
val item = RandomFunction.rollWeightedChanceTable(listOf(*lootTable))
if(item.id == 0) {
val item = rollTrawlerFish(fishLevel)
loot.add(item)
} else {
loot.add(item)
}
}
if(skipJunk){
val removeList = ArrayList<Item>()
@ -28,15 +54,7 @@ object TrawlerLoot {
}
val lootTable = arrayOf(
WeightedChanceItem(Items.RAW_SHRIMPS_317,1,150),
WeightedChanceItem(Items.RAW_SARDINE_327,1,150),
WeightedChanceItem(Items.RAW_ANCHOVIES_321,1,150),
WeightedChanceItem(Items.RAW_TUNA_359,1,140),
WeightedChanceItem(Items.RAW_LOBSTER_377,1,140),
WeightedChanceItem(Items.RAW_SWORDFISH_371,1,130),
WeightedChanceItem(Items.RAW_SHARK_383,1,120),
WeightedChanceItem(Items.RAW_SEA_TURTLE_395,1,120),
WeightedChanceItem(Items.RAW_MANTA_RAY_389,1,120),
WeightedChanceItem(0,1,1430),
WeightedChanceItem(Items.BROKEN_ARROW_687,1,70),
WeightedChanceItem(Items.BROKEN_GLASS_1469,1,70),
WeightedChanceItem(Items.BROKEN_STAFF_689,1,70),
@ -47,10 +65,10 @@ object TrawlerLoot {
WeightedChanceItem(Items.EMPTY_POT_1931,1,50),
WeightedChanceItem(Items.RUSTY_SWORD_686,1,50),
//Inauthentic rewards
WeightedChanceItem(Items.LOOP_HALF_OF_A_KEY_987,1,40),
WeightedChanceItem(Items.TOOTH_HALF_OF_A_KEY_985,1,40),
WeightedChanceItem(Items.LOOP_HALF_OF_A_KEY_987,1,7),
WeightedChanceItem(Items.TOOTH_HALF_OF_A_KEY_985,1,7),
WeightedChanceItem(Items.CASKET_405,1,60),
WeightedChanceItem(Items.PIRATES_HAT_2651,1,2),
WeightedChanceItem(Items.LUCKY_CUTLASS_7140,1,2)
)
}
}

View file

@ -70,8 +70,9 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption?
stop()
return false
}
if (player.skills.getLevel(Skills.FISHING) < fish!!.level) {
player.dialogueInterpreter.sendDialogue("You need a fishing level of " + fish!!.level + " to catch " + (if (fish == Fish.SHRIMP || fish == Fish.ANCHOVIE) "" else "a") + " " + fish!!.item.name.toLowerCase() + ".".trim { it <= ' ' })
if (player.skills.getLevel(Skills.FISHING) < option!!.level) {
val f = option!!.fish[option!!.fish.size - 1]
player.dialogueInterpreter.sendDialogue("You need a fishing level of " + f.level + " to catch " + (if (f == Fish.SHRIMP || f == Fish.ANCHOVIE) "" else "a") + " " + f.item.name.toLowerCase() + ".".trim { it <= ' ' })
stop()
return false
}
@ -135,7 +136,6 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption?
stop()
return true
}
fish = option!!.getRandomFish(player)
}
}
return player.inventory.freeSlots() == 0
@ -415,10 +415,8 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption?
if (delay == 1) {
return false
}
val level = 1 + player.skills.getLevel(Skills.FISHING) + player.familiarManager.getBoost(Skills.FISHING)
val hostRatio = Math.random() * fish!!.level
val clientRatio = Math.random() * (level * 1.25 - fish!!.level)
return hostRatio < clientRatio
fish = option!!.rollFish(player)
return fish != null
}
companion object {
@ -441,8 +439,5 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption?
* @param option The fishing option.
*/
init {
if (option != null) {
fish = option.getRandomFish(player)
}
}
}

View file

@ -302,7 +302,7 @@ class MiscCommandSet : CommandSet(Command.Privilege.ADMIN){
} else {
args[1].toString().toInt()
}
player.bank.add(*TrawlerLoot.getLoot(rolls,false).toTypedArray())
player.bank.add(*TrawlerLoot.getLoot(player.skills.getLevel(Skills.FISHING), rolls, false).toTypedArray())
}
define("fillbank"){player,_ ->