(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.
This commit is contained in:
BrainFart17 2026-04-07 16:04:52 -07:00
parent e17e26ff99
commit 3781794be3
5 changed files with 43 additions and 63 deletions

View file

@ -5,7 +5,6 @@
#include "../Minecraft.World/ItemInstance.h"
#include "../Minecraft.World/EnchantmentHelper.h"
#include "net.minecraft.world.item.h"
#include <memory>
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<CatchTypeWeighedItem *>(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<ItemInstance> 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<ItemInstance> FishingHelper::getCatch(int fishMod, int junkMod, int treasureMod, Random* random)
std::shared_ptr<ItemInstance> 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);
}

View file

@ -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<ItemInstance> 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<ItemInstance> getCatch(int fishMod, int junkMod, int treasureMod, Random* random);
std::shared_ptr<ItemInstance> getCatch(int luckLevel, int lureLevel, Random* random);
};

View file

@ -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<ItemInstance> fishingItemInstance = helper->getCatch(fishMod, junkMod, treasureMod, random);
std::shared_ptr<ItemInstance> fishingItemInstance = helper->getCatch(luckLevel, lureLevel, random);
std::shared_ptr<ItemEntity> ie = std::make_shared<ItemEntity>(this->Entity::level, x, y, z, fishingItemInstance);
double xa = owner->x - x;
double ya = owner->y - y;

View file

@ -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)

View file

@ -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)