Jump to content

Recommended Posts

Posted

Besides the fish got away problem there is also the skillup problem.

The code that matters is in line 1108 of file GameObject.cpp and 5282 of Player.cpp

//GameObject.cpp
switch(getLootState())
           {
               case GO_READY:                              // ready for loot
               {
                   // 1) skill must be >= base_zone_skill
                   // 2) if skill == base_zone_skill => 5% chance
                   // 3) chance is linear dependence from (base_zone_skill-skill)

                   uint32 zone, subzone;
                   GetZoneAndAreaId(zone,subzone);

                   int32 zone_skill = sObjectMgr.GetFishingBaseSkillLevel(subzone);
                   if (!zone_skill)
                       zone_skill = sObjectMgr.GetFishingBaseSkillLevel(zone);

                   //provide error, no fishable zone or area should be 0
                   if (!zone_skill)
                       sLog.outErrorDb("Fishable areaId %u are not properly defined in `skill_fishing_base_level`.",subzone);

                   int32 skill = player->GetSkillValue(SKILL_FISHING);
                   int32 chance = skill - zone_skill + 5;
                   int32 roll = irand(1,100);

                   DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i",skill,zone_skill,chance,roll);

                   if (skill >= zone_skill && chance >= roll)
                   {
                       // prevent removing GO at spell cancel
                       player->RemoveGameObject(this,false);
                       SetOwnerGUID(player->GetGUID());

                       //fish catched
                       player->UpdateFishingSkill();

                       //TODO: find reasonable value for fishing hole search
                       GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
                       if (ok)
                       {
                           player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);
                           player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, ok->GetGOInfo()->id);
                           SetLootState(GO_JUST_DEACTIVATED);
                       }
                       else
                           player->SendLoot(GetGUID(),LOOT_FISHING);
                   }
                   else
                   {
                       // fish escaped, can be deleted now
                       SetLootState(GO_JUST_DEACTIVATED);

                       WorldPacket data(SMSG_FISH_ESCAPED, 0);
                       player->GetSession()->SendPacket(&data);
                   }
                   break;
               }
               case GO_JUST_DEACTIVATED:                   // nothing to do, will be deleted at next update
                   break;
               default:
               {
                   SetLootState(GO_JUST_DEACTIVATED);

                   WorldPacket data(SMSG_FISH_NOT_HOOKED, 0);
                   player->GetSession()->SendPacket(&data);
                   break;
               }
           }
           player->FinishSpell(CURRENT_CHANNELED_SPELL);
           return;
       }
//Player.cpp
bool Player::UpdateFishingSkill()
{
   sLog.outDebug("UpdateFishingSkill");
   uint32 SkillValue = GetPureSkillValue(SKILL_FISHING);
   int32 chance = SkillValue < 75 ? 100 : 2500/(SkillValue-50);
   uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING);
   return UpdateSkillPro(SKILL_FISHING,chance*10,gathering_skill_gain);
}

wowwiki explains it like this

Unlike most professions, increasing your fishing skill is completely unrelated to the difficulty of the task. Every time you catch something (even junk) you gain fishing experience towards your next skill level. It works similarly to xp and leveling. The first 75 or so fish caught will be enough fishing experience to gain a skill up every time. The next 75 or so fish caught will give enough fishing experience to gain half of a skill point, etc. It's very standard and you can count the fish between skill ups with extreme accuracy. Knowing this can help alleviate some of the grind. A partial exception is that at some levels you will need a fraction of a fish to level; you might gain the skill point on the 11th fish in one instance, and on the 10th the next (while in reality you needed about 10.5 caught fish to increase). It appears that there might be a random factor of whether a particular fish increments the skill counter, leading to slightly different numbers of fish required from character to character (see El's mentioned in next paragraph).

see http://www.wowwiki.com/Fishing#Increasing_fishing_skill

To fix this two things are needed

1. in GameObject.cpp

else
                   {
                       // fish escaped, can be deleted now
                       SetLootState(GO_JUST_DEACTIVATED);

                       WorldPacket data(SMSG_FISH_ESCAPED, 0);
                       player->GetSession()->SendPacket(&data);
                   }

must be changed to something like

{
   //junk allows skillup too.
   player->UpdateFishingSkill();
   // loot for junk
   player->SendLoot(GetGUID(),LOOT_FISHINGJUNK);
   // dunno if need setlootstate (?)
   // SetLootState(GO_JUST_DEACTIVATED);
}

and this mus be handled in player.cpp correctly where is now

if (loot_type == LOOT_FISHING)
               go->getFishLoot(loot,this);

should be added above:

if ((loot_type == LOOT_FISHINGJUNK)
    //Display junk loot window
    // [url]http://www.wowhead.com/?items=15.0&filter=qu=0;cr=69;crs=1;crv=0[/url]
    // but this is database todo no?
if (loot_type == LOOT_FISHING)
               go->getFishLoot(loot,this);

For correct skil increase something like this would do:

75 because of http://getmangos.eu/community/showthread.php?10914-[Fix]-Fishing-skillups-for-wotlk&highlight=fishing

and 25000 because it wont eat values after the decimal point like 2500 -> *10 does

bool Player::UpdateFishingSkill()
{
   sLog.outDebug("UpdateFishingSkill");
   uint32 SkillValue = GetPureSkillValue(SKILL_FISHING);
   int32 chance = SkillValue < 75 ? 100 : 25000/(SkillValue-75);
   uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING);
   return UpdateSkillPro(SKILL_FISHING,chance,gathering_skill_gain);
}

It is important to know that this is not correct way, since it will allow you to also gain skill with way less fishes fished. But it is good approximation matching the general mangos loot system.

Posted
Besides the fish got away problem there is also the skillup problem.

The code that matters is in line 1108 of file GameObject.cpp and 5282 of Player.cpp

<snip>

and this mus be handled in player.cpp correctly where is now

if (loot_type == LOOT_FISHING)
               go->getFishLoot(loot,this);

should be added above:

if ((loot_type == LOOT_FISHINGJUNK)
    //Display junk loot window
    // [url]http://www.wowhead.com/?items=15.0&filter=qu=0;cr=69;crs=1;crv=0[/url]
    // but this is database todo no?
if (loot_type == LOOT_FISHING)
               go->getFishLoot(loot,this);

I looked into this a few days ago, and tracked it down to more or less the same code and the same changes you suggest, but - just as you say - couldn't see any way to proceed without the database being modified.

I'm not completely incompetent at database work, but I don't really understand the design/model/layout of the database(s) being used in this project, and I don't want to go messing around with that before I do. Is there any established way of drawing attention to this type of, as you put it, "database todo"? Failing that, is there anywhere I could go to learn about the design (etc.) of the database, aside from the too-dry-and-bare-to-really-be-useful-on-this-level UDB Wiki?

For correct skil increase something like this would do:

75 because of http://getmangos.eu/community/showthread.php?10914-[Fix]-Fishing-skillups-for-wotlk&highlight=fishing

and 25000 because it wont eat values after the decimal point like 2500 -> *10 does

bool Player::UpdateFishingSkill()
{
   sLog.outDebug("UpdateFishingSkill");
   uint32 SkillValue = GetPureSkillValue(SKILL_FISHING);
   int32 chance = SkillValue < 75 ? 100 : 25000/(SkillValue-75);
   uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING);
   return UpdateSkillPro(SKILL_FISHING,chance,gathering_skill_gain);
}

It is important to know that this is not correct way, since it will allow you to also gain skill with way less fishes fished. But it is good approximation matching the general mangos loot system.

I see one obvious problem with this code: when calculating 25000 / (SkillValue - 75), SkillValue can be 75, which would lead to division by zero.

Based on the thread you linked to, I think a better - if not necessarily "the correct" - fix for this would be to have a separate case for 'SkillValue >= 375', something like

bool Player::UpdateFishingSkill()
{
   sLog.outDebug("UpdateFishingSkill");
   uint32 SkillValue = GetPureSkillValue(SKILL_FISHING);
   int32 chance;
   uint32 gathering_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_GATHERING);
   if (SkillValue < 75) {
       chance = 1000;
   } else if (SkillValue < 375) {
       chance = 25000/(SkillValue-50);
   } else {
       chance = 25000/(SkillValue-75);
   }
   return UpdateSkillPro(SKILL_FISHING,chance,gathering_skill_gain);
}

which, if I'm understanding things correctly, avoids the "skill chance too high" issue.

(There are obviously several other ways to code the exact same result, some of which might be better; I picked this one just because it's probably the most readable.)

Any obvious problems with this approach?

  • 39 years later...
Posted

Hey

Fishing in revision 88.9, client version: 3.2.2 doesn't work correctly. Announcement "Your fish got away" still happens - it shouldn't be possible after patch 3.1.

You can now fish anywhere, regardless of skill. Every catch has the potential for fishing skill gains, but you are likely to catch worthless junk in areas that are too difficult for your skill.

It works similiar to old fishing, with same skill required for areas, but we catch junk (http://www.wowhead.com/?items=15.0&filter=qu=0;cr=69;crs=1;crv=0) instead of getting an announcement.

  • 3 months later...
Posted

I see one obvious problem with this code: when calculating 25000 / (SkillValue - 75), SkillValue can be 75, which would lead to division by zero.

Yes you are right, there is however a even more simple fix

int32 chance = SkillValue <= 75 ? 1000 : 25000/(SkillValue-75);

That way you will have 100% chance to levelup up to (including) 75 skill points and from 76 onwards the formula would apply. This does match with wowwiki description.

Also i found more information:

- There are 8 common junk items (Driftwood, Empty Clam, Sickly Fish, Tangled Fishing Line, Tattered Cloth, Torn Sail, Weeds and Withered Kelp) and 5 uncommon junk items (Empty Rum Bottle, Old Boot, Rock, Tree Branch and Water Snail).

- With patch 3.3, junk will never be caught from pools. Only fishing skill 1 is required to fish pools effectively.

see http://www.elsanglin.com/3_1_changes.html

from what i see the easiest option for this would be to make something like this

diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index 0bfb0b9..243680a 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -491,17 +491,24 @@ void GameObject::Delete()
        AddObjectToRemoveList();
}

-void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner)
+void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner, bool success)
{
    fishloot->clear();
+    if (success)
+    {
+        uint32 zone, subzone;
+        GetZoneAndAreaId(zone,subzone);

-    uint32 zone, subzone;
-    GetZoneAndAreaId(zone,subzone);
-
-    // if subzone loot exist use it
-    if (!fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true))
-        // else use zone loot (must exist in like case)
-        fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true);
+        // if subzone loot exist use it
+        if (!fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true))
+            // else use zone loot (must exist in like case)
+            fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true);
+    }
+    else
+    {
+        // We caught junk, this is single loottable
+        fishloot->FillLoot(0,LootTemplates_Fishing,loot_owner,true);
+    }
}

void GameObject::SaveToDB()
@@ -1131,35 +1138,27 @@ void GameObject::Use(Unit* user)
                    int32 roll = irand(1,100);

                    DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i",skill,zone_skill,chance,roll);
-
-                    if (skill >= zone_skill && chance >= roll)
-                    {
-                        // prevent removing GO at spell cancel
-                        player->RemoveGameObject(this,false);
-                        SetOwnerGUID(player->GetGUID());
-
-                        //fish catched
-                        player->UpdateFishingSkill();
-
-                        //TODO: find reasonable value for fishing hole search
-                        GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
-                        if (ok)
-                        {
-                            player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);
-                            player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, ok->GetGOInfo()->id);
-                            SetLootState(GO_JUST_DEACTIVATED);
-                        }
-                        else
-                            player->SendLoot(GetGUID(),LOOT_FISHING);
-                    }
-                    else
-                    {
-                        // fish escaped, can be deleted now
-                        SetLootState(GO_JUST_DEACTIVATED);
-
-                        WorldPacket data(SMSG_FISH_ESCAPED, 0);
-                        player->GetSession()->SendPacket(&data);
-                    }
+                    // You can fish everywhere with every skill now.
+                    player->RemoveGameObject(this,false);
+                    SetOwnerGUID(player->GetGUID());
+                    player->UpdateFishingSkill();
+                    // If we fish in a FishingHole we always catch something.
+                    GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
+                    if (ok)
+                    {
+                        // We are fishing in a fishing hole, we always catch something.
+                        player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);
+                        player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, ok->GetGOInfo()->id);
+                        SetLootState(GO_JUST_DEACTIVATED);
+                    }
+                    else
+                    {
+                        // We are fishing in open Water, what we catch depends on our skill.
+                        if (chance >= roll)
+                            player->SendLoot(GetGUID(),LOOT_FISHING);
+                        else
+                            player->SendLoot(GetGUID(),LOOT_FISHINGJUNK);
+                    }
                    break;
                }
                case GO_JUST_DEACTIVATED:                   // nothing to do, will be deleted at next update
diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h
index 0b7914d..b4fa62d 100644
--- a/src/game/LootMgr.h
+++ b/src/game/LootMgr.h
@@ -71,7 +71,8 @@ enum LootType
    LOOT_MILLING                = 8,

    LOOT_FISHINGHOLE            = 20,                       // unsupported by client, sending LOOT_FISHING instead
-    LOOT_INSIGNIA               = 21                        // unsupported by client, sending LOOT_CORPSE instead
+    LOOT_INSIGNIA               = 21,                       // unsupported by client, sending LOOT_CORPSE instead
+    LOOT_FISHINGJUNK            = 22                        // unsupported by client, sending LOOT_FISHING instead
};

class Player;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index fe9fddf..79d813d 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -7583,7 +7583,9 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
            }

            if (loot_type == LOOT_FISHING)
-                go->getFishLoot(loot,this);
+                go->getFishLoot(loot,this,true);
+            if (loot_type == LOOT_FISHINGJUNK)
+                go->getFishLoot(loot,this,false);

            go->SetLootState(GO_ACTIVATED);
        }
@@ -7775,7 +7777,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
    switch(loot_type)
    {
        case LOOT_INSIGNIA:    loot_type = LOOT_SKINNING; break;
-        case LOOT_FISHINGHOLE: loot_type = LOOT_FISHING; break;
+        case LOOT_FISHINGHOLE:
+        case LOOT_FISHINGJUNK: loot_type = LOOT_FISHING; break;
        default: break;
    }

i used zoneid = 0 as template for junk loot since its same everywhere. The entry it database seems also fairly simple since there are only 10 items, but udb syntax escapes me atm. and this isnt right forum for it anyway.

Posted
Yes you are right, there is however a even more simple fix

int32 chance = SkillValue <= 75 ? 1000 : 25000/(SkillValue-75);

That way you will have 100% chance to levelup up to (including) 75 skill points and from 76 onwards the formula would apply. This does match with wowwiki description.

I think that's still wrong.

According to the WoWWiki description, you have a 100% chance up through 75, yes - but then you have on average a 50% chance up through 150.

According to my math, using the above formula you have 100% chance up through 75, then *more* than 100% up through 99, 100% at 100, and less after that - for an average of 163.3785% during 76 through 150.

According to the thread you linked initially, after skill 375, the chance of skill-up increases.

That's why I did three cases; I don't see any way to avoid it and still have the correct chance in all three skill ranges.

Also i found more information:

see http://www.elsanglin.com/3_1_changes.html

Yeah, I found that before, but couldn't find it when I was writing my previous post.

from what i see the easiest option for this would be to make something like this

<snip>

I'm not an expert on this codebase, but at a glance that looks good to me.

i used zoneid = 0 as template for junk loot since its same everywhere. The entry it database seems also fairly simple since there are only 10 items, but udb syntax escapes me atm. and this isnt right forum for it anyway.

Which place would be correct - Developer's Corner -> Database, or the UDB forums themselves? I'm not yet entirely up on the etiquette around here.

Posted

yes you are right, i guess wowwiki isnt specific enough on their wiki page. Well i guess can just use your function.

about database changes i would think udb forums, since mangos always say they have nothing to do with content.

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use