From af22ca5e7ac2b873dd3e1f268ef05e3d630c1501 Mon Sep 17 00:00:00 2001 From: BrainFart17 Date: Mon, 6 Apr 2026 16:39:09 -0700 Subject: [PATCH 1/3] Update fishing mechanics for better parity with TU 31 --- Minecraft.World/FishingHelper.cpp | 47 +++++++++++++++++-------------- Minecraft.World/FishingHelper.h | 35 +++++++---------------- Minecraft.World/FishingHook.cpp | 31 ++++++++++++++------ Minecraft.World/FishingHook.h | 2 ++ 4 files changed, 61 insertions(+), 54 deletions(-) diff --git a/Minecraft.World/FishingHelper.cpp b/Minecraft.World/FishingHelper.cpp index b9903c9b..efcf9272 100644 --- a/Minecraft.World/FishingHelper.cpp +++ b/Minecraft.World/FishingHelper.cpp @@ -4,21 +4,22 @@ #include "../Minecraft.World/FishingHelper.h" #include "../Minecraft.World/ItemInstance.h" #include "../Minecraft.World/EnchantmentHelper.h" -#include #include "net.minecraft.world.item.h" +#include + FishingHelper* FishingHelper::getInstance() { static FishingHelper instance; return &instance; } -FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishingJunkArray(12), fishingTreasuresArray(5) +FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishingJunkArray(11), fishingTreasuresArray(5) { // Source: https://github.com/WangTingZheng/mcp940/tree/master/src/minecraft/assets/minecraft/loot_tables/gameplay - catchTypeArray[0] = new CatchTypeWeighedItem(CatchType::JUNK, -2, 10 ); - catchTypeArray[1] = new CatchTypeWeighedItem(CatchType::TREASURE, 2, 5 ); - catchTypeArray[2] = new CatchTypeWeighedItem(CatchType::FISH, -1, 85); + catchTypeArray[0] = new CatchTypeWeighedItem(CatchType::FISH, 8); // 850 + catchTypeArray[1] = new CatchTypeWeighedItem(CatchType::JUNK, 100 ); + catchTypeArray[2] = new CatchTypeWeighedItem(CatchType::TREASURE, 5 ); // 50 fishingTreasuresArray[0] = new CatchWeighedItem(Item::bow_Id, 1, 0, 1); fishingTreasuresArray[1] = new CatchWeighedItem(Item::book_Id, 1, 0, 1); @@ -32,34 +33,38 @@ FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishing fishingFishArray[2] = new CatchWeighedItem(Item::fish_raw_Id, 1, 2, 2); // Clownfish fishingFishArray[3] = new CatchWeighedItem(Item::fish_raw_Id, 1, 3, 13); // Pufferfish - fishingJunkArray[3] = new CatchWeighedItem(Item::leather_Id, 1, 0, 10); + fishingJunkArray[0] = new CatchWeighedItem(Item::leather_Id, 1, 0, 10); fishingJunkArray[1] = new CatchWeighedItem(Item::bone_Id, 1, 0, 10); - fishingJunkArray[6] = new CatchWeighedItem(Item::potion_Id, 1, 0, 10); // Water bottle - fishingJunkArray[2] = new CatchWeighedItem(Item::bowl_Id, 1, 0, 10); + fishingJunkArray[2] = new CatchWeighedItem(Item::potion_Id, 1, 0, 10); // Water bottle + fishingJunkArray[3] = new CatchWeighedItem(Item::bowl_Id, 1, 0, 10); fishingJunkArray[4] = new CatchWeighedItem(Item::boots_leather_Id, 1, 0, 10); fishingJunkArray[5] = new CatchWeighedItem(Item::rotten_flesh_Id, 1, 0, 10); - fishingJunkArray[7] = new CatchWeighedItem(Tile::tripWireSource_Id, 1, 0, 10); - fishingJunkArray[8] = new CatchWeighedItem(Item::stick_Id, 1, 0, 5); - fishingJunkArray[9] = new CatchWeighedItem(Item::string_Id, 1, 0, 5); - fishingJunkArray[10] = new CatchWeighedItem(Item::fishingRod_Id, 1, 0, 2); - fishingJunkArray[11] = new CatchWeighedItem(Item::dye_powder_Id, 10, 0, 1); // 10 ink sacs + fishingJunkArray[6] = new CatchWeighedItem(Tile::tripWireSource_Id, 1, 0, 10); + fishingJunkArray[7] = new CatchWeighedItem(Item::stick_Id, 1, 0, 5); + fishingJunkArray[8] = new CatchWeighedItem(Item::string_Id, 1, 0, 5); + fishingJunkArray[9] = new CatchWeighedItem(Item::fishingRod_Id, 1, 0, 2); + fishingJunkArray[10] = new CatchWeighedItem(Item::dye_powder_Id, 10, 0, 1); // 10 ink sacs } -CatchType FishingHelper::getRandCatchType(int luck, Random* random) +CatchType FishingHelper::getRandCatchType(int fishMod, int junkMod, int treasureMod, Random* random) { CatchTypeWeighedItem* catchTypeWeighedItem = nullptr; - catchTypeArray.calcWeights(luck); // Recalculate the weights based on the luck level of the player + ((CatchTypeWeighedItem*)catchTypeArray[0])->modWeight(fishMod); + ((CatchTypeWeighedItem*)catchTypeArray[1])->modWeight(junkMod); + ((CatchTypeWeighedItem*)catchTypeArray[2])->modWeight(treasureMod); + // Recalculate the weights based on the luck level of the player catchTypeWeighedItem = static_cast(WeighedRandom::getRandomItem(random, catchTypeArray)); + + return catchTypeWeighedItem->getType(); } CatchWeighedItem* FishingHelper::getRandCatch(CatchType catchType, Random* random) { - CatchWeighedItem* catchWeighedItem = nullptr; switch (catchType) { case CatchType::FISH: return static_cast(WeighedRandom::getRandomItem(random, fishingFishArray)); case CatchType::TREASURE: - return static_cast(WeighedRandom::getRandomItem(random, fishingTreasuresArray));; + return static_cast(WeighedRandom::getRandomItem(random, fishingTreasuresArray)); case CatchType::JUNK: return static_cast(WeighedRandom::getRandomItem(random, fishingJunkArray)); } @@ -75,11 +80,11 @@ std::shared_ptr FishingHelper::handleCatch(CatchWeighedItem* weigh itemInstance->setAuxValue((int) (itemInstance->getMaxDamage() * ((double) random->nextInt(901) + 100.0) / 1000.0)); // 10% to 100% damage } else if (itemInstance->id == Item::fishingRod_Id && catchType == CatchType::TREASURE) { - itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0)); // 0% to 25% damage + itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage itemInstance = EnchantmentHelper::enchantItem(random, itemInstance, 30); } else if (itemInstance->id == Item::bow_Id) { - itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0)); // 0% to 25% damage + itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage itemInstance = EnchantmentHelper::enchantItem(random, itemInstance, 30); } else if (itemInstance->id == Item::book_Id) { @@ -89,9 +94,9 @@ std::shared_ptr FishingHelper::handleCatch(CatchWeighedItem* weigh return itemInstance; } -std::shared_ptr FishingHelper::getCatch(int luck, Random* random) +std::shared_ptr FishingHelper::getCatch(int fishMod, int junkMod, int treasureMod, Random* random) { - CatchType catchType = getRandCatchType(luck, random); + CatchType catchType = getRandCatchType(fishMod, junkMod, treasureMod, random); CatchWeighedItem* catchWeighedItem = getRandCatch(catchType, random); return handleCatch(catchWeighedItem, catchType, random); } \ No newline at end of file diff --git a/Minecraft.World/FishingHelper.h b/Minecraft.World/FishingHelper.h index 9a32b044..7bc2d2e0 100644 --- a/Minecraft.World/FishingHelper.h +++ b/Minecraft.World/FishingHelper.h @@ -19,10 +19,9 @@ class CatchTypeWeighedItem : public WeighedRandomItem { int weight; public: - CatchTypeWeighedItem(CatchType type, int quality, int weight) : WeighedRandomItem(weight) + CatchTypeWeighedItem(CatchType type, int weight) : WeighedRandomItem(weight) { this->type = type; - this->quality = quality; this->weight = weight; } @@ -31,24 +30,10 @@ class CatchTypeWeighedItem : public WeighedRandomItem { return type; } - void calcWeight(int luck) { - int newWeight = this->weight + this->quality * luck; - if (newWeight < 0) { - newWeight = 0; - } - this->randomWeight = newWeight; + void modWeight(int mod) { + this->randomWeight = this->weight + mod; } -}; -class CatchTypeWeighedItems : public WeighedRandomItemArray { - public: - using WeighedRandomItemArray::WeighedRandomItemArray; - void calcWeights(int luck) { - for (unsigned int i = 0; i < this->length; i++) { - CatchTypeWeighedItem* catchTypeWeighedItem = static_cast(this->data[i]); - catchTypeWeighedItem->calcWeight(luck); - } - } }; class CatchWeighedItem : public WeighedRandomItem { @@ -83,20 +68,20 @@ class FishingHelper private: FishingHelper(); - CatchTypeWeighedItems catchTypeArray; + WeighedRandomItemArray catchTypeArray; WeighedRandomItemArray fishingFishArray; WeighedRandomItemArray fishingJunkArray; WeighedRandomItemArray fishingTreasuresArray; + + CatchType getRandCatchType(int level, Random* random); + CatchWeighedItem* getRandCatch(CatchType catchType, Random* random); + std::shared_ptr handleCatch(CatchWeighedItem* weighedCatch, CatchType catchType, Random* random); + CatchType getRandCatchType(int fishMod, int junkMod, int treasureMod, Random* random); public: // Setup singleton FishingHelper(const FishingHelper&) = delete; FishingHelper& operator=(const FishingHelper&) = delete; static FishingHelper* getInstance(); - std::shared_ptr getCatch(int luck, Random* random); - private: - CatchType getRandCatchType(int level, Random* random); - CatchWeighedItem* getRandCatch(CatchType catchType, Random* random); - std::shared_ptr handleCatch(CatchWeighedItem* weighedCatch, CatchType catchType, Random* random); - + std::shared_ptr getCatch(int fishMod, int junkMod, int treasureMod, Random* random); }; \ No newline at end of file diff --git a/Minecraft.World/FishingHook.cpp b/Minecraft.World/FishingHook.cpp index 9ff420ef..951c77c1 100644 --- a/Minecraft.World/FishingHook.cpp +++ b/Minecraft.World/FishingHook.cpp @@ -33,9 +33,10 @@ void FishingHook::_init() nibble = 0; // TU 31: Fishing rod now has a random nibble timer between 5 and 30 seconds, instead of a 1/500 chance every tick (plus modifiers). Source: https://minecraft.wiki/w/Fishing - nibbleTimer = random->nextInt(501) + 100; + nibbleTimer = random->nextInt(801) + 100; lureTime = 0; hookedIn = nullptr; + previousItem = nullptr; lSteps = 0; lx = 0.0; @@ -178,14 +179,20 @@ void FishingHook::tick() if (!level->isClientSide) { + std::shared_ptr selectedItem = owner->getSelectedItem(); - if (owner->removed || !owner->isAlive() || selectedItem == nullptr || selectedItem->getItem() != Item::fishingRod || distanceToSqr(owner) > 32 * 32) + if (this->previousItem == nullptr) { + this->previousItem = selectedItem; + } + if (owner->removed || !owner->isAlive() || selectedItem == nullptr || selectedItem->getItem() != Item::fishingRod || distanceToSqr(owner) > 32 * 32 || selectedItem != this->previousItem) { remove(); owner->fishing = nullptr; return; } + this->previousItem = selectedItem; + if (hookedIn != nullptr) { if (hookedIn->removed) hookedIn = nullptr; @@ -341,6 +348,10 @@ void FishingHook::tick() nibbleTimer--; } + else if (!(level->canSeeSky(Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { + // Don't minus the nibbleTimer if the hook is under a roof + } + else { if (random->nextInt(4) == 0) { nibbleTimer -= 2; @@ -360,7 +371,7 @@ void FishingHook::tick() // if the lure effect causes the nibble timer to go below 0, reset the timer and lure time to recalculate next tick. Source: https://minecraft.wiki/w/Fishing if (nibbleTimer < 0) { - nibbleTimer = random->nextInt(501) + 100; + nibbleTimer = random->nextInt(801) + 100; lureTime = 0; } } @@ -369,9 +380,8 @@ void FishingHook::tick() // below 0 due to the random chance of the rain decreasing the timer by 2 instead of 1. if (nibbleTimer == 0 || nibbleTimer == -1) { - // TU 31: Increase the nibble time to between 1 and 2 seconds. https://minecraft.wiki/w/Fishing - nibble = random->nextInt(21) + 20; - nibbleTimer = random->nextInt(501) + 100; + nibble = random->nextInt(11) + 30; + nibbleTimer = random->nextInt(801) + 100; lureTime = 0; yd -= 0.2f; playSound(eSoundType_RANDOM_SPLASH, 0.25f, 1 + (random->nextFloat() - random->nextFloat()) * 0.4f); @@ -462,8 +472,13 @@ int FishingHook::retrieve() std::shared_ptr selectedItemSeaLuck = owner->getSelectedItem(); // TODO: Take into account luck potion effect when calculating luck level once it's implemented - int luckLevel = EnchantmentHelper::getEnchantmentLevel(65, selectedItemSeaLuck); // Luck of the sea - std::shared_ptr fishingItemInstance = helper->getCatch(luckLevel, random); + int luckSeaLevel = EnchantmentHelper::getEnchantmentLevel(65, selectedItemSeaLuck); // Luck of the sea + int lureSeaLevel = EnchantmentHelper::getEnchantmentLevel(64, selectedItemSeaLuck); // Lure + + int junkMod = (-10 * lureSeaLevel) + (-25 * luckSeaLevel); // Lure reduces by 1% per level, luck of the sea 2.5% per level. + int treasureMod = (- 10 * lureSeaLevel) + (10 * luckSeaLevel); + int fishMod = (-junkMod + -treasureMod, 100); // Fish chance is affected my junkMod and treasureMod + std::shared_ptr fishingItemInstance = helper->getCatch(fishMod, junkMod, treasureMod, random); std::shared_ptr ie = std::make_shared(this->Entity::level, x, y, z, fishingItemInstance); double xa = owner->x - x; diff --git a/Minecraft.World/FishingHook.h b/Minecraft.World/FishingHook.h index c9eaebd5..b49a5770 100644 --- a/Minecraft.World/FishingHook.h +++ b/Minecraft.World/FishingHook.h @@ -2,6 +2,7 @@ using namespace std; #include "Entity.h" +#include "../Minecraft.World/ItemInstance.h" class Player; @@ -27,6 +28,7 @@ private: int nibble; int nibbleTimer; int lureTime; + shared_ptr previousItem; public: shared_ptr hookedIn; From e17e26ff99ce8f4471f947f6967a18ecbdb63f2c Mon Sep 17 00:00:00 2001 From: BrainFart17 Date: Tue, 7 Apr 2026 08:00:13 -0700 Subject: [PATCH 2/3] Fix bugs and improve fishing mechanics parity with TU 31 - Based fishing mechanics off of decompiled java 1.7.2 instead of 1.12. - Added check for sky access - Switching between different fishing rods now reels the line back in - Fixed duplicate assignment in fishingTreasuresArray - Remove testing weights from catchTypeArray - Make lureLevel and luckLevel member variables of FishingHook that are calculated upon initialization instead of recalculating every tick. - Changed random nibbleTimer range from 5 - 30 secs to 5 - 45 secs - Fixed out of order and incorrect assignments of fishingJunkArray - Values are now clamped to prevent unintended behavior - Lure now affects loot rates. --- Minecraft.World/FishingHelper.cpp | 6 +++--- Minecraft.World/FishingHelper.h | 7 ++++--- Minecraft.World/FishingHook.cpp | 32 +++++++++++++++++++------------ Minecraft.World/FishingHook.h | 4 ++++ 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Minecraft.World/FishingHelper.cpp b/Minecraft.World/FishingHelper.cpp index efcf9272..86b73a67 100644 --- a/Minecraft.World/FishingHelper.cpp +++ b/Minecraft.World/FishingHelper.cpp @@ -17,16 +17,16 @@ FishingHelper* FishingHelper::getInstance() FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishingJunkArray(11), fishingTreasuresArray(5) { // Source: https://github.com/WangTingZheng/mcp940/tree/master/src/minecraft/assets/minecraft/loot_tables/gameplay - catchTypeArray[0] = new CatchTypeWeighedItem(CatchType::FISH, 8); // 850 + catchTypeArray[0] = new CatchTypeWeighedItem(CatchType::FISH, 850); catchTypeArray[1] = new CatchTypeWeighedItem(CatchType::JUNK, 100 ); - catchTypeArray[2] = new CatchTypeWeighedItem(CatchType::TREASURE, 5 ); // 50 + catchTypeArray[2] = new CatchTypeWeighedItem(CatchType::TREASURE, 50 ); fishingTreasuresArray[0] = new CatchWeighedItem(Item::bow_Id, 1, 0, 1); fishingTreasuresArray[1] = new CatchWeighedItem(Item::book_Id, 1, 0, 1); fishingTreasuresArray[2] = new CatchWeighedItem(Item::fishingRod_Id, 1, 0, 1); fishingTreasuresArray[3] = new CatchWeighedItem(Item::nameTag_Id, 1, 0, 1); fishingTreasuresArray[4] = new CatchWeighedItem(Item::saddle_Id, 1, 0, 1); - fishingTreasuresArray[4] = new CatchWeighedItem(Tile::waterLily_Id, 1, 0, 1); + fishingTreasuresArray[5] = new CatchWeighedItem(Tile::waterLily_Id, 1, 0, 1); fishingFishArray[0] = new CatchWeighedItem(Item::fish_raw_Id, 1, 0, 60); // Fish fishingFishArray[1] = new CatchWeighedItem(Item::fish_raw_Id, 1, 1, 25); // Salmon diff --git a/Minecraft.World/FishingHelper.h b/Minecraft.World/FishingHelper.h index 7bc2d2e0..99b91499 100644 --- a/Minecraft.World/FishingHelper.h +++ b/Minecraft.World/FishingHelper.h @@ -1,11 +1,12 @@ #pragma once - +using namespace std; #include "../Minecraft.World/WeighedTreasure.h" #include "../Minecraft.World/ItemInstance.h" #include "net.minecraft.world.item.h" #include #include + enum CatchType { FISH, TREASURE, @@ -15,7 +16,6 @@ enum CatchType { class CatchTypeWeighedItem : public WeighedRandomItem { protected: CatchType type; - int quality; int weight; public: @@ -31,6 +31,8 @@ class CatchTypeWeighedItem : public WeighedRandomItem { } void modWeight(int mod) { + // Modweight doesn't need clamping, this is done in FishingHook.cpp. + // randomWeight can be changed, weight stays the same. randomWeight is set equal to weight upon initialization. this->randomWeight = this->weight + mod; } @@ -74,7 +76,6 @@ class FishingHelper WeighedRandomItemArray fishingJunkArray; WeighedRandomItemArray fishingTreasuresArray; - CatchType getRandCatchType(int level, Random* random); CatchWeighedItem* getRandCatch(CatchType catchType, Random* random); std::shared_ptr handleCatch(CatchWeighedItem* weighedCatch, CatchType catchType, Random* random); CatchType getRandCatchType(int fishMod, int junkMod, int treasureMod, Random* random); diff --git a/Minecraft.World/FishingHook.cpp b/Minecraft.World/FishingHook.cpp index 951c77c1..ea787820 100644 --- a/Minecraft.World/FishingHook.cpp +++ b/Minecraft.World/FishingHook.cpp @@ -15,6 +15,7 @@ #include "../Minecraft.World/EnchantmentHelper.h" #include "../Minecraft.World/Enchantment.h" #include "../Minecraft.World/ItemInstance.h" +#include // 4J - added common ctor code. void FishingHook::_init() @@ -38,6 +39,9 @@ void FishingHook::_init() hookedIn = nullptr; previousItem = nullptr; + lureLevel = 0; + luckLevel = 0; + lSteps = 0; lx = 0.0; ly = 0.0; @@ -67,6 +71,8 @@ FishingHook::FishingHook(Level *level, double x, double y, double z, std::share // 4J Stu - Moved this outside the ctor //owner->fishing = dynamic_pointer_cast( shared_from_this() ); + getEnchantLevels(); + setPos(x, y, z); } @@ -77,6 +83,7 @@ FishingHook::FishingHook(Level *level, std::shared_ptr mob) : Entity( l owner = mob; // 4J Stu - Moved this outside the ctor //owner->fishing = dynamic_pointer_cast( shared_from_this() ); + getEnchantLevels(); moveTo(mob->x, mob->y + 1.62 - mob->heightOffset, mob->z, mob->yRot, mob->xRot); @@ -96,6 +103,14 @@ FishingHook::FishingHook(Level *level, std::shared_ptr mob) : Entity( l shoot(xd, yd, zd, 1.5f, 1); } +void FishingHook::getEnchantLevels() { + if (this->owner == nullptr) return; + std::shared_ptr fishingRod = owner->getSelectedItem(); + // TODO; Account for luck effect once implemented. + this->luckLevel = EnchantmentHelper::getEnchantmentLevel(65, fishingRod); // Luck of the sea + this->lureLevel = EnchantmentHelper::getEnchantmentLevel(64, fishingRod); // Lure +} + void FishingHook::defineSynchedData() { } @@ -349,7 +364,7 @@ void FishingHook::tick() } else if (!(level->canSeeSky(Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { - // Don't minus the nibbleTimer if the hook is under a roof + // Don't minus the nibbleTimer if the hook obstructed from the sky. } else { @@ -364,9 +379,7 @@ void FishingHook::tick() // Only calculate the effect of lure if it hasn't been calculated already. if (lureTime == 0 && owner != nullptr) { - std::shared_ptr selectedItemLureCheck = owner->getSelectedItem(); - int level = EnchantmentHelper::getEnchantmentLevel(64, selectedItemLureCheck); // Lure - lureTime = level * 100; + lureTime = this->lureLevel * 100; nibbleTimer -= lureTime; // if the lure effect causes the nibble timer to go below 0, reset the timer and lure time to recalculate next tick. Source: https://minecraft.wiki/w/Fishing if (nibbleTimer < 0) @@ -470,14 +483,9 @@ int FishingHook::retrieve() { FishingHelper* helper = FishingHelper::getInstance(); - std::shared_ptr selectedItemSeaLuck = owner->getSelectedItem(); - // TODO: Take into account luck potion effect when calculating luck level once it's implemented - int luckSeaLevel = EnchantmentHelper::getEnchantmentLevel(65, selectedItemSeaLuck); // Luck of the sea - int lureSeaLevel = EnchantmentHelper::getEnchantmentLevel(64, selectedItemSeaLuck); // Lure - - int junkMod = (-10 * lureSeaLevel) + (-25 * luckSeaLevel); // Lure reduces by 1% per level, luck of the sea 2.5% per level. - int treasureMod = (- 10 * lureSeaLevel) + (10 * luckSeaLevel); - int fishMod = (-junkMod + -treasureMod, 100); // Fish chance is affected my junkMod and treasureMod + int junkMod = clamp((-10 * this->lureLevel) + (-25 * this->luckLevel), 0, 1000); // Lure reduces by 1% per level, luck of the sea 2.5% per level. + int treasureMod = clamp((-10 * this->lureLevel) + (10 * this->luckLevel), 0, 1000); // Lure reduces by 1% per level, luck of the sea increases by 1% per level. + int fishMod = -junkMod + -treasureMod; // Fish chance is affected by junkMod and treasureMod std::shared_ptr fishingItemInstance = helper->getCatch(fishMod, junkMod, treasureMod, random); std::shared_ptr ie = std::make_shared(this->Entity::level, x, y, z, fishingItemInstance); diff --git a/Minecraft.World/FishingHook.h b/Minecraft.World/FishingHook.h index b49a5770..23af71ab 100644 --- a/Minecraft.World/FishingHook.h +++ b/Minecraft.World/FishingHook.h @@ -28,6 +28,9 @@ private: int nibble; int nibbleTimer; int lureTime; + + int lureLevel; + int luckLevel; shared_ptr previousItem; public: @@ -60,6 +63,7 @@ public: virtual void addAdditonalSaveData(CompoundTag *tag); virtual void readAdditionalSaveData(CompoundTag *tag); virtual float getShadowHeightOffs(); + virtual void getEnchantLevels(); int retrieve(); // 4J Stu - Brought forward from 1.4 From 3781794be340b16ffe22d2d9cd87aaf1c9cb321c Mon Sep 17 00:00:00 2001 From: BrainFart17 Date: Tue, 7 Apr 2026 16:04:52 -0700 Subject: [PATCH 3/3] (fishing) Fix bugs and change random catch type selection - Implement catch type random selection from decompiled java 1.7.2 code instead of using a WeighedRandomItemArray - Fix fishingTreasuresArray length being set to 5 instead of 6 - Remove testing values for nibbleTimer - Cast maxDamage of item to double before applying damage. - Add include for EnchantmentCategory in LureEnchantment.cpp and LuckOfTheSeaEnchantment.cpp. - sky obstruction is now checked before other checks. --- Minecraft.World/FishingHelper.cpp | 55 ++++++++++++--------- Minecraft.World/FishingHelper.h | 32 ++---------- Minecraft.World/FishingHook.cpp | 17 +++---- Minecraft.World/LuckOfTheSeaEnchantment.cpp | 1 + Minecraft.World/LureEnchantment.cpp | 1 + 5 files changed, 43 insertions(+), 63 deletions(-) diff --git a/Minecraft.World/FishingHelper.cpp b/Minecraft.World/FishingHelper.cpp index 86b73a67..518b76d0 100644 --- a/Minecraft.World/FishingHelper.cpp +++ b/Minecraft.World/FishingHelper.cpp @@ -5,7 +5,6 @@ #include "../Minecraft.World/ItemInstance.h" #include "../Minecraft.World/EnchantmentHelper.h" #include "net.minecraft.world.item.h" - #include FishingHelper* FishingHelper::getInstance() @@ -14,13 +13,8 @@ FishingHelper* FishingHelper::getInstance() return &instance; } -FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishingJunkArray(11), fishingTreasuresArray(5) +FishingHelper::FishingHelper() : fishingFishArray(4), fishingJunkArray(11), fishingTreasuresArray(6) { - // Source: https://github.com/WangTingZheng/mcp940/tree/master/src/minecraft/assets/minecraft/loot_tables/gameplay - catchTypeArray[0] = new CatchTypeWeighedItem(CatchType::FISH, 850); - catchTypeArray[1] = new CatchTypeWeighedItem(CatchType::JUNK, 100 ); - catchTypeArray[2] = new CatchTypeWeighedItem(CatchType::TREASURE, 50 ); - fishingTreasuresArray[0] = new CatchWeighedItem(Item::bow_Id, 1, 0, 1); fishingTreasuresArray[1] = new CatchWeighedItem(Item::book_Id, 1, 0, 1); fishingTreasuresArray[2] = new CatchWeighedItem(Item::fishingRod_Id, 1, 0, 1); @@ -46,16 +40,31 @@ FishingHelper::FishingHelper() : catchTypeArray(3), fishingFishArray(4), fishing fishingJunkArray[10] = new CatchWeighedItem(Item::dye_powder_Id, 10, 0, 1); // 10 ink sacs } -CatchType FishingHelper::getRandCatchType(int fishMod, int junkMod, int treasureMod, Random* random) +CatchType FishingHelper::getRandCatchType(int luckLevel, int lureLevel, Random* random) { - CatchTypeWeighedItem* catchTypeWeighedItem = nullptr; - ((CatchTypeWeighedItem*)catchTypeArray[0])->modWeight(fishMod); - ((CatchTypeWeighedItem*)catchTypeArray[1])->modWeight(junkMod); - ((CatchTypeWeighedItem*)catchTypeArray[2])->modWeight(treasureMod); - // Recalculate the weights based on the luck level of the player - catchTypeWeighedItem = static_cast(WeighedRandom::getRandomItem(random, catchTypeArray)); + float randFloat = random->nextFloat(); + float junkChance = 0.1F - (float)luckLevel * 0.025F - (float)lureLevel * 0.01F; // default 10% chance, affected by lure and luck of the sea + float treasureChance = 0.05F + (float)luckLevel * 0.01F - (float)lureLevel * 0.01F; // default 5% chance, affected by lure and luck of the sea + junkChance = clamp(junkChance, 0.0F, 1.0F); + treasureChance = clamp(treasureChance, 0.0F, 1.0F); - return catchTypeWeighedItem->getType(); + if (randFloat < junkChance) + { + return CatchType::JUNK; + } + else + { + randFloat -= junkChance; + + if (randFloat < treasureChance) + { + return CatchType::TREASURE; + } + else + { + return CatchType::FISH; + } + } } CatchWeighedItem* FishingHelper::getRandCatch(CatchType catchType, Random* random) @@ -77,26 +86,26 @@ std::shared_ptr FishingHelper::handleCatch(CatchWeighedItem* weigh ); if ((itemInstance->id == Item::fishingRod_Id && catchType == CatchType::JUNK) || (itemInstance->id == Item::boots_leather_Id)) { - itemInstance->setAuxValue((int) (itemInstance->getMaxDamage() * ((double) random->nextInt(901) + 100.0) / 1000.0)); // 10% to 100% damage + itemInstance->setAuxValue((int) ((double) itemInstance->getMaxDamage() * ((double) random->nextInt(901) + 100.0) / 1000.0)); // 10% to 100% damage } else if (itemInstance->id == Item::fishingRod_Id && catchType == CatchType::TREASURE) { - itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage - itemInstance = EnchantmentHelper::enchantItem(random, itemInstance, 30); + itemInstance->setAuxValue((int)((double) itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage + EnchantmentHelper::enchantItem(random, itemInstance, 30); } else if (itemInstance->id == Item::bow_Id) { - itemInstance->setAuxValue((int)(itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage - itemInstance = EnchantmentHelper::enchantItem(random, itemInstance, 30); + itemInstance->setAuxValue((int)((double) itemInstance->getMaxDamage() * ((double)random->nextInt(251) / 1000.0))); // 0% to 25% damage + EnchantmentHelper::enchantItem(random, itemInstance, 30); } else if (itemInstance->id == Item::book_Id) { - itemInstance = EnchantmentHelper::enchantItem(random, itemInstance, 30); + EnchantmentHelper::enchantItem(random, itemInstance, 30); } return itemInstance; } -std::shared_ptr FishingHelper::getCatch(int fishMod, int junkMod, int treasureMod, Random* random) +std::shared_ptr FishingHelper::getCatch(int luckLevel, int lureLevel, Random* random) { - CatchType catchType = getRandCatchType(fishMod, junkMod, treasureMod, random); + CatchType catchType = getRandCatchType(luckLevel, lureLevel, random); CatchWeighedItem* catchWeighedItem = getRandCatch(catchType, random); return handleCatch(catchWeighedItem, catchType, random); } \ No newline at end of file diff --git a/Minecraft.World/FishingHelper.h b/Minecraft.World/FishingHelper.h index 99b91499..77972e11 100644 --- a/Minecraft.World/FishingHelper.h +++ b/Minecraft.World/FishingHelper.h @@ -13,31 +13,6 @@ enum CatchType { JUNK }; -class CatchTypeWeighedItem : public WeighedRandomItem { - protected: - CatchType type; - int weight; - - public: - CatchTypeWeighedItem(CatchType type, int weight) : WeighedRandomItem(weight) - { - this->type = type; - this->weight = weight; - } - - CatchType getType() - { - return type; - } - - void modWeight(int mod) { - // Modweight doesn't need clamping, this is done in FishingHook.cpp. - // randomWeight can be changed, weight stays the same. randomWeight is set equal to weight upon initialization. - this->randomWeight = this->weight + mod; - } - -}; - class CatchWeighedItem : public WeighedRandomItem { protected: int itemId; @@ -70,19 +45,18 @@ class FishingHelper private: FishingHelper(); - WeighedRandomItemArray catchTypeArray; - WeighedRandomItemArray fishingFishArray; WeighedRandomItemArray fishingJunkArray; WeighedRandomItemArray fishingTreasuresArray; CatchWeighedItem* getRandCatch(CatchType catchType, Random* random); std::shared_ptr handleCatch(CatchWeighedItem* weighedCatch, CatchType catchType, Random* random); - CatchType getRandCatchType(int fishMod, int junkMod, int treasureMod, Random* random); + CatchType getRandCatchType(int luckLevel, int lureLevel, Random* random); public: // Setup singleton FishingHelper(const FishingHelper&) = delete; FishingHelper& operator=(const FishingHelper&) = delete; static FishingHelper* getInstance(); - std::shared_ptr getCatch(int fishMod, int junkMod, int treasureMod, Random* random); + + std::shared_ptr getCatch(int luckLevel, int lureLevel, Random* random); }; \ No newline at end of file diff --git a/Minecraft.World/FishingHook.cpp b/Minecraft.World/FishingHook.cpp index ea787820..1d2de0ad 100644 --- a/Minecraft.World/FishingHook.cpp +++ b/Minecraft.World/FishingHook.cpp @@ -358,14 +358,14 @@ void FishingHook::tick() } else { - // TU 31: Raining affects the nibble timer by random chance rather than being a fixed rate. Source: https://minecraft.wiki/w/Fishing - if (!(level->isRainingAt( Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { - nibbleTimer--; - } - else if (!(level->canSeeSky(Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { + if (!(level->canSeeSky(Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { // Don't minus the nibbleTimer if the hook obstructed from the sky. } + // TU 31: Raining affects the nibble timer by random chance rather than being a fixed rate. Source: https://minecraft.wiki/w/Fishing + else if (!(level->isRainingAt( Mth::floor(x), Mth::floor(y) + 1, Mth::floor(z)))) { + nibbleTimer--; + } else { if (random->nextInt(4) == 0) { @@ -482,12 +482,7 @@ int FishingHook::retrieve() else if (nibble > 0) { FishingHelper* helper = FishingHelper::getInstance(); - - int junkMod = clamp((-10 * this->lureLevel) + (-25 * this->luckLevel), 0, 1000); // Lure reduces by 1% per level, luck of the sea 2.5% per level. - int treasureMod = clamp((-10 * this->lureLevel) + (10 * this->luckLevel), 0, 1000); // Lure reduces by 1% per level, luck of the sea increases by 1% per level. - int fishMod = -junkMod + -treasureMod; // Fish chance is affected by junkMod and treasureMod - std::shared_ptr fishingItemInstance = helper->getCatch(fishMod, junkMod, treasureMod, random); - + std::shared_ptr fishingItemInstance = helper->getCatch(luckLevel, lureLevel, random); std::shared_ptr ie = std::make_shared(this->Entity::level, x, y, z, fishingItemInstance); double xa = owner->x - x; double ya = owner->y - y; diff --git a/Minecraft.World/LuckOfTheSeaEnchantment.cpp b/Minecraft.World/LuckOfTheSeaEnchantment.cpp index 6dd8edaa..9aacda83 100644 --- a/Minecraft.World/LuckOfTheSeaEnchantment.cpp +++ b/Minecraft.World/LuckOfTheSeaEnchantment.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "LuckOfTheSeaEnchantment.h" +#include "EnchantmentCategory.h" LuckOfTheSeaEnchantment::LuckOfTheSeaEnchantment(int id, int frequency) : Enchantment(id, frequency, EnchantmentCategory::fishing_rod) diff --git a/Minecraft.World/LureEnchantment.cpp b/Minecraft.World/LureEnchantment.cpp index d44e76a4..ef7b5b20 100644 --- a/Minecraft.World/LureEnchantment.cpp +++ b/Minecraft.World/LureEnchantment.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "LureEnchantment.h" +#include "EnchantmentCategory.h" LureEnchantment::LureEnchantment(int id, int frequency) : Enchantment(id, frequency, EnchantmentCategory::fishing_rod)