Elin:Code Analysis/Fishing: Difference between revisions
(Fix number of fish table and example.) |
Hachimitsu (talk | contribs) m (Hachimitsu moved page Elin:Spoiler/Fishing to Elin:Code Analysis/Fishing without leaving a redirect) |
||
(19 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{Spoiler}} | |||
==Calculations== | ==Calculations== | ||
Line 7: | Line 9: | ||
<pre>fishLV = rnd(fishingLevel * 2) + 1</pre> | <pre>fishLV = rnd(fishingLevel * 2) + 1</pre> | ||
*'''fishingLevel''': Your current fishing skill level. | * '''fishingLevel''': Your current fishing skill level. | ||
*'''rnd''': A random number between '''0''' and the value passed into the function. | * '''rnd''': A random number between '''0''' and the value passed into the function. | ||
==== Adjusted Fish LV ==== | |||
The adjusted fish LV is calculated during item creation. It uses multiple calls to the '''rnd''' function and adds a hardcoded value of '''+2''' at the end. The final adjusted level becomes: | |||
<pre>adjustedLV = fishLV + 2 + rnd(rnd(rnd(rnd(Mathf.Min(fishLV * 2, 20)) + 1) + 1) + 1)</pre> | |||
* The adjustment process involves: | |||
** Determining the base '''fishLV''' as '''rnd(fishingLevel * 2) + 1'''. | |||
** Applying multiple calls to the '''rnd''' function: | |||
*** '''rnd''' generates a random number between '''0''' and '''(max - 1)'''. | |||
*** Each call depends on the result of the previous '''rnd''', gradually narrowing down the possible range. | |||
** Adding a hardcoded '''+2''' to ensure the adjusted LV always has an offset. | |||
* '''Note''': While it’s rare, the final result of the multiple calls to '''rnd''' can theoretically be as high as '''19''', resulting in a significant boost to the adjusted LV. | |||
==== Example ==== | |||
If your fishing level is '''10''': | |||
* '''Base LV''': | |||
** '''fishLV = rnd(10 * 2) + 1 = rnd(20) + 1'''. | |||
** Example result: '''10'''. | |||
* '''Adjustments''': | |||
** First '''rnd(20)''' → Result = '''7'''. | |||
** Second '''rnd(7 + 1)''' → Result = '''3'''. | |||
** Third '''rnd(3 + 1)''' → Result = '''2'''. | |||
** Fourth '''rnd(2 + 1)''' → Result = '''0'''. | |||
* '''Final Adjusted LV''': | |||
** '''adjustedLV = 10 + 2 + 0 = 12'''. | |||
====Fish LV Range Table==== | ====Fish LV Range Table==== | ||
Line 24: | Line 50: | ||
!Fishing Level!!Minimum LV!!Maximum LV | !Fishing Level!!Minimum LV!!Maximum LV | ||
|- | |- | ||
|1|| | |1||3||4 | ||
|- | |- | ||
|2|| | |2||3||6 | ||
|- | |- | ||
|3|| | |3||3||8 | ||
|- | |- | ||
|4|| | |4||3||10 | ||
|- | |- | ||
|5|| | |5||3||12 | ||
|- | |- | ||
|6|| | |6||3||14 | ||
|- | |- | ||
|7|| | |7||3||16 | ||
|- | |- | ||
|8|| | |8||3||18 | ||
|- | |- | ||
|9|| | |9||3||20 | ||
|- | |- | ||
|10|| | |10||3||22 | ||
|- | |- | ||
|11|| | |11||3||24 | ||
|- | |- | ||
|12|| | |12||3||26 | ||
|- | |- | ||
|13|| | |13||3||28 | ||
|- | |- | ||
|14|| | |14||3||30 | ||
|- | |- | ||
|15|| | |15||3||32 | ||
|- | |- | ||
|16|| | |16||3||34 | ||
|- | |- | ||
|17|| | |17||3||36 | ||
|- | |- | ||
|18|| | |18||3||38 | ||
|- | |- | ||
|19|| | |19||3||40 | ||
|} | |} | ||
====Code (EA 23. | ====Code (EA 23.41)==== | ||
<syntaxhighlight lang="c#" line="1"> | <syntaxhighlight lang="c#" line="1"> | ||
int num3 = EClass.rnd(num * 2) + 1; | int num3 = EClass.rnd(num * 2) + 1; | ||
thing = ThingGen.Create("fish", -1, num3); | thing = ThingGen.Create("fish", -1, num3); | ||
lv = lv + 2 + EClass.rnd(EClass.rnd(EClass.rnd(EClass.rnd(Mathf.Min(lv * 2, 20)) + 1) + 1) + 1); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 93: | Line 119: | ||
The <code>rnd(2)</code> generates a random number between '''0''' and '''1'''. Adding 1 ensures that you will catch at least '''1''' fish, and the number of fish can either be '''1''' or '''2''', depending on the random result. | The <code>rnd(2)</code> generates a random number between '''0''' and '''1'''. Adding 1 ensures that you will catch at least '''1''' fish, and the number of fish can either be '''1''' or '''2''', depending on the random result. | ||
==== Adding Land Feats ==== | |||
The initial chance of catching one extra fish starts at '''5%'''. | |||
If the land feats include: | |||
* '''Beach (3604)''': Adds '''20%''' to the base chance. | |||
* '''Sea (3605)''': Adds '''20%''' to the base chance. | |||
* '''Fishing Spot (3706)''': Adds '''25%''' to the base chance. | |||
Since only '''Sea (3605)''' or '''Beach (3604)''' can be present at the same time (not both), the total chance is calculated as: | |||
<pre> | |||
chanceForOneMoreFish = 5 | |||
chanceForOneMoreFish += isBeach * 20 + isSea * 20 + isFishingSpot * 25 | |||
</pre> | |||
Where: | |||
* '''isBeach''': A flag (either 0 or 1) indicating whether the land feat is a '''Beach (3604)'''. | |||
* '''isSea''': A flag (either 0 or 1) indicating whether the land feat is '''Sea (3605)'''. | |||
* '''isFishingSpot''': A flag (either 0 or 1) indicating whether the land feat is a '''Fishing Spot (3706)'''. | |||
For example: | |||
* If '''Sea (3605)''' is present, and '''Fishing Spot (3706)''' is also present: | |||
<pre> | |||
chanceForOneMoreFish = 5 + 1 * 20 + 1 * 25 = 50 | |||
</pre> | |||
* If '''Beach (3604)''' is present instead of '''Sea (3605)''': | |||
<pre> | |||
chanceForOneMoreFish = 5 + 1 * 20 + 1 * 25 = 50 | |||
</pre> | |||
==== Checking the Chance to Increase the Number of Fish ==== | |||
The '''chanceForOneMoreFish''' value is compared to a random number generated by the <code>rnd(100)</code> function, which produces a number between '''0''' and '''99''' (inclusive). | |||
If '''chanceForOneMoreFish''' is greater than or equal to the random number, the number of fish will increase by '''1'''. | |||
This check is implemented with: | |||
<pre> | |||
if (chanceForOneMoreFish >= rnd(100)) | |||
</pre> | |||
For example: | |||
* If '''chanceForOneMoreFish = 50''', and the random number generated by <code>rnd(100)</code> is '''50 or less''', you will catch an additional fish. | |||
==== Example with Land Feats ==== | |||
===== Example 1: Fishing Spot (3706) and Sea (3605) ===== | |||
Let's say your fishing level is '''22''', and the fish LV is '''1'''. The base number of fish is calculated as: | |||
<pre> | |||
numberOfFish = rnd(22 / (1 + 10)) + 1 = rnd(2) + 1 | |||
</pre> | |||
This gives '''1 or 2 fish''', depending on the random result. | |||
Now, evaluating the land feats: | |||
* Start with '''chanceForOneMoreFish = 5''' (base chance). | |||
* '''Sea (3605)''' adds '''20'''. | |||
* '''Fishing Spot (3706)''' adds '''25'''. | |||
The new '''chanceForOneMoreFish''' becomes: | |||
<pre> | |||
chanceForOneMoreFish = 5 + 20 + 25 = 50 | |||
</pre> | |||
Next, the random chance is checked: | |||
<pre> | |||
if (chanceForOneMoreFish >= rnd(100)) | |||
</pre> | |||
If the random number generated by <code>rnd(100)</code> is '''50 or less''', the number of fish will increase by '''1'''. Thus: | |||
* '''numberOfFish = numberOfFish + 1''' (if the random check passes). | |||
* If the random number exceeds '''50''', the number of fish remains unchanged. | |||
===== Example 2: Fishing Spot (3706) and Beach (3604) ===== | |||
For the same fishing level and fish LV, the land feats contribute: | |||
* '''Beach (3604)''' adds '''20'''. | |||
* '''Fishing Spot (3706)''' adds '''25'''. | |||
The total '''chanceForOneMoreFish''' remains: | |||
<pre> | |||
chanceForOneMoreFish = 5 + 20 + 25 = 50 | |||
</pre> | |||
The random check behaves the same as above, with the same chance for an additional fish. | |||
====Number of Fish Table==== | ====Number of Fish Table==== | ||
Line 98: | Line 217: | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
!Fish LV!!Minimum Fishing Level for 2 Fish!!Minimum Fishing Level for 3 Fish | ! Fish LV !! Minimum Fishing Level for 2 Fish !! Minimum Fishing Level for 3 Fish !! Minimum Fishing Level for 4+ Fish | ||
|- | |- | ||
|1||22||33 | | 1 || 22 || 33 || 44, etc. | ||
|- | |- | ||
|5||30||45 | | 5 || 30 || 45 || 60, etc. | ||
|- | |- | ||
|10||40||60 | | 10 || 40 || 60 || 80, etc. | ||
|- | |- | ||
|15||50||75 | | 15 || 50 || 75 || 100, etc. | ||
|- | |- | ||
|20||60||90 | | 20 || 60 || 90 || 120, etc. | ||
|- | |- | ||
|25||70||105 | | 25 || 70 || 105 || 140, etc. | ||
|- | |- | ||
|30||80||120 | | 30 || 80 || 120 || 160, etc. | ||
|- | |- | ||
|35||90||135 | | 35 || 90 || 135 || 180, etc. | ||
|- | |- | ||
|40||100||150 | | 40 || 100 || 150 || 200, etc. | ||
|} | |} | ||
====Code (EA 23. | '''Note''': Values for 4+ fish follow the same progression pattern (incrementing by the same interval as earlier columns). | ||
==== Code (EA 23.40) ==== | |||
<syntaxhighlight lang="c#" line="1"> | <syntaxhighlight lang="c#" line="1"> | ||
Line 126: | Line 247: | ||
if (EClass.Branch != null) | if (EClass.Branch != null) | ||
{ | { | ||
num4 += EClass.Branch.Evalue(3604) * 20 + EClass.Branch.Evalue(3706) * 25; | num4 += EClass.Branch.Evalue(3604) * 20 + EClass.Branch.Evalue(3605) * 20 + EClass.Branch.Evalue(3706) * 25; | ||
} | } | ||
if (num4 >= EClass.rnd(100)) | if (num4 >= EClass.rnd(100)) | ||
Line 138: | Line 259: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===Fishing Speed=== | |||
The fishing process involves two key variables: | |||
* '''progress''': Represents the overall duration or percentage of fishing completion, ranging from '''0''' to '''100'''. | |||
* '''hit''': Tracks the number of attempts made during the fishing fight. The following conditions apply: | |||
** '''Increase''': ''hit'' increments on each attempt until either: | |||
*** The fish is caught (when ''hit > random threshold''). | |||
*** Certain random conditions reset ''hit'' to '''0'''. | |||
====Success==== | |||
The formula to calculate the success threshold for catching a fish is: | |||
<pre>successThreshold = Mathf.Clamp(10 - rnd(fishingLevel + 1) / 10, 5, 10)</pre> | |||
* '''fishingLevel''': Your current fishing skill level. | |||
* '''rnd''': A random number between '''0''' and the value passed into the function. | |||
* '''Clamp''': Ensures the value stays between '''5''' (easiest) and '''10''' (hardest). | |||
The actual success logic occurs as follows: | |||
<pre> | |||
if (hit > rnd(successThreshold)) { | |||
hit = 100; | |||
progress = MaxProgress; | |||
} | |||
</pre> | |||
* '''hit''': Tracks the current number of attempts. The fish is caught if ''hit'' exceeds the random roll of the successThreshold. | |||
* '''progress''': Automatically completes when success occurs. | |||
====Example==== | |||
If your fishing level is '''20''', the calculation proceeds as follows: | |||
# <code>rnd(20 + 1)</code> generates a random number between '''0''' and '''20'''. | |||
# This random number is divided by '''10''' and subtracted from '''10'''. | |||
# The result is clamped to the range '''[5, 10]''', determining the successThreshold. | |||
For example: | |||
* If <code>rnd(21) = 10</code>, the calculation is: | |||
<pre>successThreshold = Mathf.Clamp(10 - (10 / 10), 5, 10) = 9</pre> | |||
A random roll of <code>rnd(9)</code> determines the threshold. If ''hit > rnd(9)'', the fish is caught. | |||
====Success Threshold Table==== | |||
{| class="wikitable sortable" | |||
|- | |||
! Fishing Level !! Min successThreshold !! Max successThreshold | |||
|- | |||
| 1 || 10 || 10 | |||
|- | |||
| 5 || 10 || 10 | |||
|- | |||
| 10 || 9 || 10 | |||
|- | |||
| 15 || 9 || 10 | |||
|- | |||
| 20 || 8 || 10 | |||
|- | |||
| 25 || 8 || 10 | |||
|- | |||
| 30 || 7 || 10 | |||
|- | |||
| 35 || 7 || 10 | |||
|- | |||
| 40 || 6 || 10 | |||
|- | |||
| 45 || 6 || 10 | |||
|- | |||
| 50 || 5 || 10 | |||
|- | |||
| 55 || 5 || 10 | |||
|- | |||
| 60 || 5 || 10 | |||
|} | |||
====Reset==== | |||
The formula to determine whether ''hit'' resets is: | |||
<pre>resetThreshold = Mathf.Clamp(10 - rnd(fishingLevel + 1) / 5, 2, 10)</pre> | |||
* '''fishingLevel''': Your current fishing skill level. | |||
* '''rnd''': A random number between '''0''' and the value passed into the function. | |||
* '''Clamp''': Ensures the value stays between '''2''' (easiest threshold to reset) and '''10''' (hardest threshold to reset). | |||
If <code>rnd(resetThreshold)</code> equals '''0''', and ''progress >= 10'', the ''hit'' counter resets to '''0'''. | |||
====Example==== | |||
If your fishing level is '''30''', the calculation proceeds as follows: | |||
# <code>rnd(30 + 1)</code> generates a random number between '''0''' and '''30'''. | |||
# This random number is divided by '''5''' and subtracted from '''10'''. | |||
# The result is clamped to the range '''[2, 10]''', determining the resetThreshold. | |||
For example: | |||
* If <code>rnd(31) = 10</code>, the calculation is: | |||
<pre>resetThreshold = Mathf.Clamp(10 - (10 / 5), 2, 10) = 8</pre> | |||
A second random roll, <code>rnd(8)</code>, is performed. If the result is '''0''', the ''hit'' counter resets. | |||
====Reset Threshold Table==== | |||
{| class="wikitable sortable" | |||
|- | |||
! Fishing Level !! Min resetThreshold !! Max resetThreshold | |||
|- | |||
| 1 || 10 || 10 | |||
|- | |||
| 5 || 9 || 10 | |||
|- | |||
| 10 || 8 || 10 | |||
|- | |||
| 15 || 7 || 10 | |||
|- | |||
| 20 || 6 || 10 | |||
|- | |||
| 25 || 5 || 10 | |||
|- | |||
| 30 || 4 || 10 | |||
|- | |||
| 35 || 3 || 10 | |||
|- | |||
| 40 || 2 || 10 | |||
|- | |||
| 45 || 2 || 10 | |||
|- | |||
| 50 || 2 || 10 | |||
|} | |||
====Code (EA 23.37)==== | |||
<syntaxhighlight lang="c#" line="1"> | |||
public override void OnProgress() | |||
{ | |||
if (this.owner.IsPC && (this.owner.Tool == null || !this.owner.Tool.HasElement(245, 1))) | |||
{ | |||
this.Cancel(); | |||
return; | |||
} | |||
if (this.hit >= 0) | |||
{ | |||
this.owner.renderer.PlayAnime(AnimeID.Fishing, default(Vector3), false); | |||
this.owner.PlaySound("fish_fight", 1f, true); | |||
this.Ripple(); | |||
int a = Mathf.Clamp(10 - EClass.rnd(this.owner.Evalue(245) + 1) / 10, 5, 10); | |||
if (this.hit > EClass.rnd(a)) | |||
{ | |||
this.hit = 100; | |||
this.progress = this.MaxProgress; | |||
} | |||
this.hit++; | |||
return; | |||
} | |||
if (EClass.rnd(Mathf.Clamp(10 - EClass.rnd(this.owner.Evalue(245) + 1) / 5, 2, 10)) == 0 && this.progress >= 10) | |||
{ | |||
this.hit = 0; | |||
} | |||
if (this.progress == 2 || (this.progress >= 8 && this.progress % 6 == 0 && EClass.rnd(3) == 0)) | |||
{ | |||
this.owner.renderer.PlayAnime(AnimeID.Shiver, default(Vector3), false); | |||
this.Ripple(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== Chances and Probability === | |||
Each item or fish has a unique probability of being generated, determined by the following rules and calculations: | |||
{| class="wikitable sortable" | |||
|- | |||
! Roll !! Logic | |||
|- | |||
| Nothing || If this succeeds, no further rolls occur. | |||
|- | |||
| Rare Item || Checked if "Nothing" fails; if this succeeds, no further rolls occur. | |||
|- | |||
| Junk || Checked if both "Nothing" and "Rare Item" fail; if this succeeds, no further rolls occur. | |||
|- | |||
| Fish || The fallback/default roll if all previous rolls fail. | |||
|} | |||
==== Initial Roll: Chance to Catch Nothing ==== | |||
The first roll determines whether the player catches anything at all. If this roll fails, no item or fish is generated, and the function returns <code>null</code>. The chance to catch nothing is calculated as follows: | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(3 + fishingLevel) == 0) | |||
{ | |||
return null; | |||
} | |||
</syntaxhighlight> | |||
* '''Formula''': <code>rnd(3 + fishingLevel)</code> generates a random number between <code>0</code> and <code>(3 + fishingLevel - 1)</code>, inclusive. | |||
* '''Condition''': If the result is <code>0</code>, the roll fails, and nothing is caught. | |||
===== Probability ===== | |||
The probability of catching nothing decreases as the player's fishing level increases: | |||
* '''Maximum Value for the Roll''': <code>3 + fishingLevel</code>, where <code>fishingLevel = c.Evalue(245)</code>. | |||
* '''Chance to Catch Nothing''': | |||
** <code>1 / (3 + fishingLevel)</code> | |||
For example: | |||
* At '''Fishing Level 1''': | |||
** <code>rnd(3 + 1)</code> generates a number between <code>0</code> and <code>3</code>. | |||
** Probability of <code>0</code>: <code>1 / 4</code> (25%). | |||
* At '''Fishing Level 10''': | |||
** <code>rnd(3 + 10)</code> generates a number between <code>0</code> and <code>12</code>. | |||
** Probability of <code>0</code>: <code>1 / 13</code> (~7.69%). | |||
This means that higher fishing levels significantly reduce the chance of failing the roll and increase the likelihood of catching something. | |||
==== Conditional Rolls: Rare Items and Rewards ==== | |||
This section determines whether a rare item or reward is generated. The outermost condition checks if a random roll succeeds. If the condition is met, nested conditions evaluate the type of item to generate. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(20) == 0) | |||
</syntaxhighlight> | |||
* '''Condition''': Pass a random roll: <code>rnd(20) == 0</code>. | |||
If this condition is satisfied, the following rolls determine the item generated: | |||
===== Ancient Book ===== | |||
The Ancient Book is one of the rare items that can be generated during fishing if specific conditions are met. Its generation depends on a random roll after passing the initial check. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(30) == 0) | |||
{ | |||
text = "book_ancient"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': The item is generated if <code>rnd(30) == 0</code>. | |||
* '''Probability''': <code>1 / 30</code>, or approximately 3.33%. | |||
If this condition is satisfied, the Ancient Book is created as the reward. | |||
===== Platinum Coin ===== | |||
The Platinum Coin is another rare item that can be generated during fishing. Its generation depends on a random roll. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(35) == 0) | |||
{ | |||
text = "plat"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': The item is generated if <code>rnd(35) == 0</code>. | |||
* '''Probability''': <code>1 / 35</code> (~2.86%). | |||
If this condition is satisfied, a Platinum Coin is created as the reward. | |||
===== Scratch Card ===== | |||
The Scratch Card is a replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(2) == 0) | |||
{ | |||
text = "scratchcard"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': The item is generated if <code>rnd(2) == 0</code>, replacing the Platinum Coin. | |||
* '''Probability''': <code>1 / 2</code> (50%), but it depends on the successful Platinum Coin roll. | |||
* '''Dependent Probability''': <code>1 / (20 * 35 * 2)</code> (~0.071%). | |||
** Calculated as: | |||
*** Rare Item Roll: <code>1 / 20</code> (5%). | |||
*** Platinum Coin Roll: <code>1 / 35</code> (~2.86%). | |||
*** Scratch Card Roll: <code>1 / 2</code> (50%). | |||
If this condition is satisfied, the Scratch Card replaces the Platinum Coin as the reward. | |||
===== Casino Coin ===== | |||
The Casino Coin is another replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(3) == 0) | |||
{ | |||
text = "casino_coin"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': The item is generated if <code>rnd(3) == 0</code>, replacing the Platinum Coin. | |||
* '''Probability''': <code>1 / 3</code> (~33.33%), but it depends on the successful Platinum Coin roll. | |||
* '''Dependent Probability''': <code>1 / (20 * 35 * 3)</code> (~0.048%). | |||
** Calculated as: | |||
*** Rare Item Roll: <code>1 / 20</code> (5%). | |||
*** Platinum Coin Roll: <code>1 / 35</code> (~2.86%). | |||
*** Casino Coin Roll: <code>1 / 3</code> (~33.33%). | |||
If this condition is satisfied, the Casino Coin replaces the Platinum Coin as the reward. | |||
===== Strange Coin ===== | |||
The Strange Coin is another replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(3) == 0) | |||
{ | |||
text = "gacha_coin"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': The item is generated if <code>rnd(3) == 0</code>, replacing the Platinum Coin. | |||
* '''Probability''': <code>1 / 3</code> (~33.33%), but it depends on the successful Platinum Coin roll. | |||
* '''Dependent Probability''': <code>1 / (20 * 35 * 3)</code> (~0.048%). | |||
** Calculated as: | |||
*** Rare Item Roll: <code>1 / 20</code> (5%). | |||
*** Platinum Coin Roll: <code>1 / 35</code> (~2.86%). | |||
*** Strange Coin Roll: <code>1 / 3</code> (~33.33%). | |||
If this condition is satisfied, the Strange Coin replaces the Platinum Coin as the reward. | |||
===== Statues ===== | |||
Statues are extremely rare items that can be generated after the Platinum Coin roll. Their generation depends on a random roll, with one of seven possible statues being selected. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(50) == 0) | |||
{ | |||
text = "Randomly choose one of these statues: " | |||
"Statue of Earth", | |||
"Statue of Element", | |||
"Statue of Harvest", | |||
"Statue of Healing", | |||
"Statue of Luck", | |||
"Statue of Machine", | |||
"Statue of Wind"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': A statue is generated if <code>rnd(50) == 0</code>. | |||
* '''Probability''': <code>1 / 50</code> (2%), but it depends on the successful Platinum Coin roll. | |||
* '''Dependent Probability''': <code>1 / (20 * 35 * 50)</code> (~0.00286%). | |||
** Calculated as: | |||
*** Rare Item Roll: <code>1 / 20</code> (5%). | |||
*** Platinum Coin Roll: <code>1 / 35</code> (~2.86%). | |||
*** Statue Roll: <code>1 / 50</code> (2%). | |||
If this condition is satisfied, one of the following statues is randomly selected: | |||
* '''Statue of Earth''' | |||
* '''Statue of Element''' | |||
* '''Statue of Harvest''' | |||
* '''Statue of Healing''' | |||
* '''Statue of Luck''' | |||
* '''Statue of Machine''' | |||
* '''Statue of Wind''' | |||
Each statue has an equal probability of being selected from the pool of seven statues. | |||
* '''Probability of a Specific Statue''': <code>1 / 7</code> (~14.29%) of the statue roll. | |||
* '''Dependent Probability for a Specific Statue''': <code>1 / (20 * 35 * 50 * 7)</code> (~0.00041%). | |||
===== Small Medal ===== | |||
The Small Medal is a rare item that can be generated during fishing. Its generation depends on two random rolls: a base roll and a level-dependent threshold check. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(40) == 0 && rnd(40) < fishingLevel / 3 + 10) | |||
{ | |||
text = "medal"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': | |||
** The first roll succeeds if <code>rnd(40) == 0</code> (2.5%). | |||
** The second roll succeeds if <code>rnd(40) < fishingLevel / 3 + 10</code>. | |||
* '''Probability''': | |||
** The first roll has a fixed probability: <code>1 / 40</code> (2.5%). | |||
** The second roll's probability depends on the player's fishing level: | |||
*** Higher fishing levels increase the threshold (<code>fishingLevel / 3 + 10</code>), making it easier to succeed. | |||
* '''Minimum Fishing Level for Consistent Success''': | |||
** To always pass the second roll, the threshold must reach or exceed 40. Solve for: | |||
*** <code>fishingLevel / 3 + 10 >= 40</code>. | |||
*** <code>fishingLevel >= (40 - 10) * 3</code>. | |||
*** <code>fishingLevel >= 90</code>. | |||
** At <code>fishingLevel = 90</code>, the threshold becomes <code>90 / 3 + 10 = 40</code>, ensuring consistent success. | |||
* '''Dependent Probability''': | |||
** Combined probability: <code>(1 / 20) * (1 / 40) * (fishingLevel-dependent threshold)</code>. | |||
** Example for Fishing Level 10: | |||
*** Threshold: <code>10 / 3 + 10 = ~13.33</code>. | |||
*** Second roll succeeds if <code>rnd(40) < 13</code>, or <code>13 / 40</code> (32.5%). | |||
*** Combined Probability: <code>(1 / 20) * (1 / 40) * (13 / 40)</code> (~0.01625%). | |||
==== Junk Items ==== | |||
Junk items are a category of low-value rewards that can be generated during fishing. Their generation depends on a random roll after all higher-priority items (e.g., rare items, medals) have failed to generate. | |||
<syntaxhighlight lang="csharp"> | |||
if (rnd(5 + fishingLevel / 3) == 0) | |||
{ | |||
thing = "Randomly choose one of these junk items: " | |||
"Boots", | |||
"Empty Bottle (1)", | |||
"Empty Bottle (2)", | |||
"Empty Can (1)", | |||
"Empty Can (2)", | |||
"Flotsam from the North", | |||
"Lucky Cat", | |||
"Rubber Duck", | |||
"Rubber Putit", | |||
"Rubber Snail", | |||
"Sandal (1)", | |||
"Sandal (2)", | |||
"Sea Pants"; | |||
} | |||
</syntaxhighlight> | |||
* '''Condition''': Junk items are generated if: | |||
** The rare item roll and all higher-priority rolls fail. | |||
** The following roll succeeds: <code>rnd(5 + fishingLevel / 3) == 0</code>. | |||
* '''Probability''': | |||
** The probability depends on the player's fishing level: | |||
*** <code>1 / (5 + fishingLevel / 3)</code>. | |||
*** Higher fishing levels reduce the chance of junk items being generated, as the denominator increases. | |||
* '''Junk Item Pool''': | |||
** If this roll succeeds, one item is randomly selected from the following list (15 items total): | |||
*** '''Boots''' | |||
*** '''Empty Bottle (1)''' | |||
*** '''Empty Bottle (2)''' | |||
*** '''Empty Can (1)''' | |||
*** '''Empty Can (2)''' | |||
*** '''Flotsam from the North''' | |||
*** '''Lucky Cat''' | |||
*** '''Rubber Duck''' | |||
*** '''Rubber Putit''' | |||
*** '''Rubber Snail''' | |||
*** '''Sandal (1)''' | |||
*** '''Sandal (2)''' | |||
*** '''Sea Pants''' | |||
* '''Probability of a Specific Junk Item''': | |||
** Equal chance for each item in the list: <code>1 / 15</code> (~6.67%) of junk roll success. | |||
===== Example Calculation ===== | |||
* At '''Fishing Level 10''': | |||
** Threshold for junk roll: <code>5 + 10 / 3 = ~8.33</code>. | |||
** Probability of junk roll succeeding: <code>1 / 8</code> (12.5%). | |||
** Probability of a specific junk item: <code>1 / 8 * 1 / 15 = 1 / 120</code> (~0.83%). | |||
==== Fish ==== | |||
The generation of fish happens as the default outcome when all higher-priority rolls fail: | |||
* '''Dependencies''': | |||
** The fish roll occurs if: | |||
*** The "Nothing" roll fails. | |||
*** The "Rare Item" roll fails. | |||
*** The "Junk" roll fails. | |||
===== Probability Context ===== | |||
Since the fish roll occurs as the final fallback, its probability is calculated as: | |||
* '''Probability of Fish Roll''': | |||
<code>1 - P(Nothing) - P(Rare Item) - P(Junk)</code> | |||
* '''Dependent Probabilities''': | |||
** This depends on: | |||
*** Fishing level (affects the probability of "Nothing" and "Junk"). | |||
*** Success/failure of preceding rolls. | |||
===== Example Calculation for Whale ===== | |||
At '''Fishing Level 19''', the '''minimum fishing level''' for the '''Whale''' is 19. If the '''adjustedLV''' is 40 or higher, the '''Whale''' can be caught. | |||
To calculate the probability of catching the '''Whale''': | |||
<syntaxhighlight lang="csharp"> | |||
P(Whale) = 50 / Total Chance of All Eligible Fish | |||
</syntaxhighlight> | |||
If the '''total chance''' for all eligible fish at '''Fishing Level 19''' is '''22050''', then: | |||
<syntaxhighlight lang="csharp"> | |||
P(Whale) = 50 / 22050 = 0.00227 or ~0.227% | |||
</syntaxhighlight> | |||
===== Fish Probability Table (Fish LV 40) ===== | |||
{| class="wikitable sortable" | |||
|- | |||
! Name !! Chance !! Probability (Independent) | |||
|- | |||
| Tadpole || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Bitterling || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Turtle || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Goby || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Muddler || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Goldfish || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Carp || 100 || 100 / 22050 (~0.45%) | |||
|- | |||
| Sweetfish || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Sea Urchin || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Sardine || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Eel || 500 || 500 / 22050 (~2.27%) | |||
|- | |||
| Bass || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Scad || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Arowana || 600 || 600 / 22050 (~2.72%) | |||
|- | |||
| Tilefish || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Tuna || 400 || 400 / 22050 (~1.81%) | |||
|- | |||
| Striped Jack || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Mackerel || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Bonito || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Red Bream || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Black Bass || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Blowfish || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Sea Bream || 500 || 500 / 22050 (~2.27%) | |||
|- | |||
| Flatfish || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Tuna (2) || 500 || 500 / 22050 (~2.27%) | |||
|- | |||
| Sand Borer || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Salmon || 500 || 500 / 22050 (~2.27%) | |||
|- | |||
| Sunfish || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Shark || 100 || 100 / 22050 (~0.45%) | |||
|- | |||
| Deep Sea Fish || 1000 || 1000 / 22050 (~4.54%) | |||
|- | |||
| Ancient Fish || 200 || 200 / 22050 (~0.91%) | |||
|- | |||
| Moonfish || 500 || 500 / 22050 (~2.27%) | |||
|- | |||
| Coelacanth || 100 || 100 / 22050 (~0.45%) | |||
|- | |||
| Whale || 50 || 50 / 22050 (~0.23%) | |||
|} | |||
==== All Probability Table ==== | |||
{| class="wikitable sortable" | |||
|- | |||
! Item !! Probability (Independent) !! Probability (Dependent) !! Notes | |||
|- | |||
| Nothing || <code>1 / (3 + fishingLevel)</code> || N/A || Higher fishing levels reduce the chance of this outcome. | |||
|- | |||
| Rare Item || <code>1 / 20</code> (5%) || <code>1 / 20</code> || Determines if a rare item roll happens. | |||
|- | |||
| Ancient Book || <code>1 / 30</code> (~3.33%) || <code>1 / (20 * 30)</code> (~0.167%) || Requires a rare item roll success, then its own probability. | |||
|- | |||
| Platinum Coin || <code>1 / 35</code> (~2.86%) || <code>1 / (20 * 35)</code> (~0.143%) || Requires a rare item roll success, then its own probability. | |||
|- | |||
| Scratch Card || <code>1 / 2</code> (50%) || <code>1 / (20 * 35 * 2)</code> (~0.071%) || Replaces Platinum Coin if condition is met. | |||
|- | |||
| Casino Coin || <code>1 / 3</code> (33.3%) || <code>1 / (20 * 35 * 3)</code> (~0.048%) || Replaces Platinum Coin if condition is met. | |||
|- | |||
| Strange Coin || <code>1 / 3</code> (33.3%) || <code>1 / (20 * 35 * 3)</code> (~0.048%) || Replaces Platinum Coin if condition is met. | |||
|- | |||
| Statue || <code>1 / 50</code> (2%) || <code>1 / (20 * 35 * 50)</code> (~0.00286%) || Requires a rare item roll success. One of seven statues is randomly selected. | |||
|- | |||
| Specific Statue || <code>1 / 7</code> (~14.29% of Statue Roll) || <code>1 / (20 * 35 * 50 * 7)</code> (~0.00041%) || Probability of obtaining a specific statue. | |||
|- | |||
| Small Medal || Level-dependent || <code>(1 / 20) * (1 / 40) * (fishingLevel threshold)</code> || Requires two successful rolls. Consistent success at fishingLevel >= 90. | |||
|- | |||
| Junk || Level-dependent || <code>1 / (5 + fishingLevel / 3)</code> || Requires rare item roll to fail. Probability decreases with higher fishing levels. | |||
|- | |||
| Specific Junk || <code>1 / 15</code> (~6.67%) || <code>(1 / (5 + fishingLevel / 3)) * (1 / 15)</code> || Probability of obtaining a specific junk item. | |||
|- | |||
| Fish || <code>fishChance / fishTotalChance</code> || <code>1 - P(Nothing) - P(Rare Item) - P(Junk)</code> || Default outcome if all other rolls fail. | |||
|} | |||
==== Code (EA 23.43) ==== | |||
<syntaxhighlight lang="c#" line="1"> | |||
public static Thing Makefish(Chara c) | |||
{ | |||
int num = c.Evalue(245); | |||
if (EClass.rnd(3 + num) == 0) | |||
{ | |||
return null; | |||
} | |||
int[] source = new int[] | |||
{ | |||
233, | |||
235, | |||
236, | |||
236, | |||
236, | |||
1170, | |||
1143, | |||
1144, | |||
727, | |||
728, | |||
237, | |||
869, | |||
1178, | |||
1179, | |||
1180 | |||
}; | |||
int num2 = 1; | |||
string text = ""; | |||
if (c.IsPC || EClass.rnd(20) == 0) | |||
{ | |||
if (EClass.rnd(30) == 0) | |||
{ | |||
text = "book_ancient"; | |||
} | |||
if (EClass.rnd(35) == 0 || EClass.debug.enable) | |||
{ | |||
text = "plat"; | |||
if (EClass.rnd(2) == 0) | |||
{ | |||
text = "scratchcard"; | |||
} | |||
if (EClass.rnd(3) == 0) | |||
{ | |||
text = "casino_coin"; | |||
} | |||
if (EClass.rnd(3) == 0) | |||
{ | |||
text = "gacha_coin"; | |||
} | |||
if (EClass.rnd(50) == 0 || EClass.debug.enable) | |||
{ | |||
text = new string[] | |||
{ | |||
"659", | |||
"758", | |||
"759", | |||
"806", | |||
"828", | |||
"1190", | |||
"1191" | |||
}.RandomItem<string>(); | |||
} | |||
} | |||
if (EClass.rnd(40) == 0 && EClass.rnd(40) < num / 3 + 10) | |||
{ | |||
text = "medal"; | |||
} | |||
} | |||
Thing thing; | |||
if (text != "") | |||
{ | |||
thing = ThingGen.Create(text, -1, -1); | |||
} | |||
else if (EClass.rnd(5 + num / 3) == 0) | |||
{ | |||
thing = ThingGen.Create(source.RandomItem<int>().ToString() ?? "", -1, -1); | |||
} | |||
else | |||
{ | |||
int num3 = EClass.rnd(num * 2) + 1; | |||
thing = ThingGen.Create("fish", -1, num3); | |||
num2 = EClass.rnd(num / (num3 + 10)) + 1; | |||
int num4 = 5; | |||
if (EClass.Branch != null) | |||
{ | |||
num4 += EClass.Branch.Evalue(3604) * 20 + EClass.Branch.Evalue(3605) * 20 + EClass.Branch.Evalue(3706) * 25; | |||
} | |||
if (num4 >= EClass.rnd(100)) | |||
{ | |||
num2++; | |||
} | |||
} | |||
if (thing != null) | |||
{ | |||
thing.SetNum(num2); | |||
thing.SetBlessedState(BlessedState.Normal); | |||
} | |||
return thing; | |||
} | |||
</syntaxhighlight> | |||
[[Category:Elin Spoiler]] | [[Category:Elin Spoiler]] | ||
[[Category:EN]] | [[Category:EN]] |
Latest revision as of 20:10, 2 December 2024
This page does not contain information obtained through legitimate play, but rather through Elin's data analysis, debug mode, and internal file viewing. It may contain serious spoilers or information that may detract from the enjoyment of playing the game. please summarize the content in a way that is easy to understand for people who cannot read the code, rather than posting the code as it is. |
Calculations
Fish LV
The formula to calculate the fish LV that can be caught based on your fishing level:
fishLV = rnd(fishingLevel * 2) + 1
- fishingLevel: Your current fishing skill level.
- rnd: A random number between 0 and the value passed into the function.
Adjusted Fish LV
The adjusted fish LV is calculated during item creation. It uses multiple calls to the rnd function and adds a hardcoded value of +2 at the end. The final adjusted level becomes:
adjustedLV = fishLV + 2 + rnd(rnd(rnd(rnd(Mathf.Min(fishLV * 2, 20)) + 1) + 1) + 1)
- The adjustment process involves:
- Determining the base fishLV as rnd(fishingLevel * 2) + 1.
- Applying multiple calls to the rnd function:
- rnd generates a random number between 0 and (max - 1).
- Each call depends on the result of the previous rnd, gradually narrowing down the possible range.
- Adding a hardcoded +2 to ensure the adjusted LV always has an offset.
- Note: While it’s rare, the final result of the multiple calls to rnd can theoretically be as high as 19, resulting in a significant boost to the adjusted LV.
Example
If your fishing level is 10:
- Base LV:
- fishLV = rnd(10 * 2) + 1 = rnd(20) + 1.
- Example result: 10.
- Adjustments:
- First rnd(20) → Result = 7.
- Second rnd(7 + 1) → Result = 3.
- Third rnd(3 + 1) → Result = 2.
- Fourth rnd(2 + 1) → Result = 0.
- Final Adjusted LV:
- adjustedLV = 10 + 2 + 0 = 12.
Fish LV Range Table
Fishing Level | Minimum LV | Maximum LV |
---|---|---|
1 | 3 | 4 |
2 | 3 | 6 |
3 | 3 | 8 |
4 | 3 | 10 |
5 | 3 | 12 |
6 | 3 | 14 |
7 | 3 | 16 |
8 | 3 | 18 |
9 | 3 | 20 |
10 | 3 | 22 |
11 | 3 | 24 |
12 | 3 | 26 |
13 | 3 | 28 |
14 | 3 | 30 |
15 | 3 | 32 |
16 | 3 | 34 |
17 | 3 | 36 |
18 | 3 | 38 |
19 | 3 | 40 |
Code (EA 23.41)
int num3 = EClass.rnd(num * 2) + 1;
thing = ThingGen.Create("fish", -1, num3);
lv = lv + 2 + EClass.rnd(EClass.rnd(EClass.rnd(EClass.rnd(Mathf.Min(lv * 2, 20)) + 1) + 1) + 1);
Number of Fish
The formula to calculate the number of fish you can catch based on your fishing level:
numberOfFish = rnd(fishingLevel / (fishLV + 10)) + 1
- fishingLevel: Your current fishing skill level.
- fishLV: The fish LV.
- rnd: A random number between 0 and the value passed into the function.
Example
If your fishing level is 22, and the fish LV is determined to be 1, the potential number of fish is calculated as:
rnd(22 / (1 + 10)) + 1
This simplifies to:
rnd(22 / 11) + 1
The rnd(2)
generates a random number between 0 and 1. Adding 1 ensures that you will catch at least 1 fish, and the number of fish can either be 1 or 2, depending on the random result.
Adding Land Feats
The initial chance of catching one extra fish starts at 5%.
If the land feats include:
- Beach (3604): Adds 20% to the base chance.
- Sea (3605): Adds 20% to the base chance.
- Fishing Spot (3706): Adds 25% to the base chance.
Since only Sea (3605) or Beach (3604) can be present at the same time (not both), the total chance is calculated as:
chanceForOneMoreFish = 5 chanceForOneMoreFish += isBeach * 20 + isSea * 20 + isFishingSpot * 25
Where:
- isBeach: A flag (either 0 or 1) indicating whether the land feat is a Beach (3604).
- isSea: A flag (either 0 or 1) indicating whether the land feat is Sea (3605).
- isFishingSpot: A flag (either 0 or 1) indicating whether the land feat is a Fishing Spot (3706).
For example:
- If Sea (3605) is present, and Fishing Spot (3706) is also present:
chanceForOneMoreFish = 5 + 1 * 20 + 1 * 25 = 50
- If Beach (3604) is present instead of Sea (3605):
chanceForOneMoreFish = 5 + 1 * 20 + 1 * 25 = 50
Checking the Chance to Increase the Number of Fish
The chanceForOneMoreFish value is compared to a random number generated by the rnd(100)
function, which produces a number between 0 and 99 (inclusive).
If chanceForOneMoreFish is greater than or equal to the random number, the number of fish will increase by 1.
This check is implemented with:
if (chanceForOneMoreFish >= rnd(100))
For example:
- If chanceForOneMoreFish = 50, and the random number generated by
rnd(100)
is 50 or less, you will catch an additional fish.
Example with Land Feats
Example 1: Fishing Spot (3706) and Sea (3605)
Let's say your fishing level is 22, and the fish LV is 1. The base number of fish is calculated as:
numberOfFish = rnd(22 / (1 + 10)) + 1 = rnd(2) + 1
This gives 1 or 2 fish, depending on the random result.
Now, evaluating the land feats:
- Start with chanceForOneMoreFish = 5 (base chance).
- Sea (3605) adds 20.
- Fishing Spot (3706) adds 25.
The new chanceForOneMoreFish becomes:
chanceForOneMoreFish = 5 + 20 + 25 = 50
Next, the random chance is checked:
if (chanceForOneMoreFish >= rnd(100))
If the random number generated by rnd(100)
is 50 or less, the number of fish will increase by 1. Thus:
- numberOfFish = numberOfFish + 1 (if the random check passes).
- If the random number exceeds 50, the number of fish remains unchanged.
Example 2: Fishing Spot (3706) and Beach (3604)
For the same fishing level and fish LV, the land feats contribute:
- Beach (3604) adds 20.
- Fishing Spot (3706) adds 25.
The total chanceForOneMoreFish remains:
chanceForOneMoreFish = 5 + 20 + 25 = 50
The random check behaves the same as above, with the same chance for an additional fish.
Number of Fish Table
Fish LV | Minimum Fishing Level for 2 Fish | Minimum Fishing Level for 3 Fish | Minimum Fishing Level for 4+ Fish |
---|---|---|---|
1 | 22 | 33 | 44, etc. |
5 | 30 | 45 | 60, etc. |
10 | 40 | 60 | 80, etc. |
15 | 50 | 75 | 100, etc. |
20 | 60 | 90 | 120, etc. |
25 | 70 | 105 | 140, etc. |
30 | 80 | 120 | 160, etc. |
35 | 90 | 135 | 180, etc. |
40 | 100 | 150 | 200, etc. |
Note: Values for 4+ fish follow the same progression pattern (incrementing by the same interval as earlier columns).
Code (EA 23.40)
num2 = EClass.rnd(num / (num3 + 10)) + 1;
int num4 = 5;
if (EClass.Branch != null)
{
num4 += EClass.Branch.Evalue(3604) * 20 + EClass.Branch.Evalue(3605) * 20 + EClass.Branch.Evalue(3706) * 25;
}
if (num4 >= EClass.rnd(100))
{
num2++;
}
if (thing != null)
{
thing.SetNum(num2);
thing.SetBlessedState(BlessedState.Normal);
}
Fishing Speed
The fishing process involves two key variables:
- progress: Represents the overall duration or percentage of fishing completion, ranging from 0 to 100.
- hit: Tracks the number of attempts made during the fishing fight. The following conditions apply:
- Increase: hit increments on each attempt until either:
- The fish is caught (when hit > random threshold).
- Certain random conditions reset hit to 0.
- Increase: hit increments on each attempt until either:
Success
The formula to calculate the success threshold for catching a fish is:
successThreshold = Mathf.Clamp(10 - rnd(fishingLevel + 1) / 10, 5, 10)
- fishingLevel: Your current fishing skill level.
- rnd: A random number between 0 and the value passed into the function.
- Clamp: Ensures the value stays between 5 (easiest) and 10 (hardest).
The actual success logic occurs as follows:
if (hit > rnd(successThreshold)) { hit = 100; progress = MaxProgress; }
- hit: Tracks the current number of attempts. The fish is caught if hit exceeds the random roll of the successThreshold.
- progress: Automatically completes when success occurs.
Example
If your fishing level is 20, the calculation proceeds as follows:
rnd(20 + 1)
generates a random number between 0 and 20.- This random number is divided by 10 and subtracted from 10.
- The result is clamped to the range [5, 10], determining the successThreshold.
For example:
- If
rnd(21) = 10
, the calculation is:
successThreshold = Mathf.Clamp(10 - (10 / 10), 5, 10) = 9
A random roll of rnd(9)
determines the threshold. If hit > rnd(9), the fish is caught.
Success Threshold Table
Fishing Level | Min successThreshold | Max successThreshold |
---|---|---|
1 | 10 | 10 |
5 | 10 | 10 |
10 | 9 | 10 |
15 | 9 | 10 |
20 | 8 | 10 |
25 | 8 | 10 |
30 | 7 | 10 |
35 | 7 | 10 |
40 | 6 | 10 |
45 | 6 | 10 |
50 | 5 | 10 |
55 | 5 | 10 |
60 | 5 | 10 |
Reset
The formula to determine whether hit resets is:
resetThreshold = Mathf.Clamp(10 - rnd(fishingLevel + 1) / 5, 2, 10)
- fishingLevel: Your current fishing skill level.
- rnd: A random number between 0 and the value passed into the function.
- Clamp: Ensures the value stays between 2 (easiest threshold to reset) and 10 (hardest threshold to reset).
If rnd(resetThreshold)
equals 0, and progress >= 10, the hit counter resets to 0.
Example
If your fishing level is 30, the calculation proceeds as follows:
rnd(30 + 1)
generates a random number between 0 and 30.- This random number is divided by 5 and subtracted from 10.
- The result is clamped to the range [2, 10], determining the resetThreshold.
For example:
- If
rnd(31) = 10
, the calculation is:
resetThreshold = Mathf.Clamp(10 - (10 / 5), 2, 10) = 8
A second random roll, rnd(8)
, is performed. If the result is 0, the hit counter resets.
Reset Threshold Table
Fishing Level | Min resetThreshold | Max resetThreshold |
---|---|---|
1 | 10 | 10 |
5 | 9 | 10 |
10 | 8 | 10 |
15 | 7 | 10 |
20 | 6 | 10 |
25 | 5 | 10 |
30 | 4 | 10 |
35 | 3 | 10 |
40 | 2 | 10 |
45 | 2 | 10 |
50 | 2 | 10 |
Code (EA 23.37)
public override void OnProgress()
{
if (this.owner.IsPC && (this.owner.Tool == null || !this.owner.Tool.HasElement(245, 1)))
{
this.Cancel();
return;
}
if (this.hit >= 0)
{
this.owner.renderer.PlayAnime(AnimeID.Fishing, default(Vector3), false);
this.owner.PlaySound("fish_fight", 1f, true);
this.Ripple();
int a = Mathf.Clamp(10 - EClass.rnd(this.owner.Evalue(245) + 1) / 10, 5, 10);
if (this.hit > EClass.rnd(a))
{
this.hit = 100;
this.progress = this.MaxProgress;
}
this.hit++;
return;
}
if (EClass.rnd(Mathf.Clamp(10 - EClass.rnd(this.owner.Evalue(245) + 1) / 5, 2, 10)) == 0 && this.progress >= 10)
{
this.hit = 0;
}
if (this.progress == 2 || (this.progress >= 8 && this.progress % 6 == 0 && EClass.rnd(3) == 0))
{
this.owner.renderer.PlayAnime(AnimeID.Shiver, default(Vector3), false);
this.Ripple();
}
}
Chances and Probability
Each item or fish has a unique probability of being generated, determined by the following rules and calculations:
Roll | Logic |
---|---|
Nothing | If this succeeds, no further rolls occur. |
Rare Item | Checked if "Nothing" fails; if this succeeds, no further rolls occur. |
Junk | Checked if both "Nothing" and "Rare Item" fail; if this succeeds, no further rolls occur. |
Fish | The fallback/default roll if all previous rolls fail. |
Initial Roll: Chance to Catch Nothing
The first roll determines whether the player catches anything at all. If this roll fails, no item or fish is generated, and the function returns null
. The chance to catch nothing is calculated as follows:
if (rnd(3 + fishingLevel) == 0)
{
return null;
}
- Formula:
rnd(3 + fishingLevel)
generates a random number between0
and(3 + fishingLevel - 1)
, inclusive. - Condition: If the result is
0
, the roll fails, and nothing is caught.
Probability
The probability of catching nothing decreases as the player's fishing level increases:
- Maximum Value for the Roll:
3 + fishingLevel
, wherefishingLevel = c.Evalue(245)
. - Chance to Catch Nothing:
1 / (3 + fishingLevel)
For example:
- At Fishing Level 1:
rnd(3 + 1)
generates a number between0
and3
.- Probability of
0
:1 / 4
(25%).
- At Fishing Level 10:
rnd(3 + 10)
generates a number between0
and12
.- Probability of
0
:1 / 13
(~7.69%).
This means that higher fishing levels significantly reduce the chance of failing the roll and increase the likelihood of catching something.
Conditional Rolls: Rare Items and Rewards
This section determines whether a rare item or reward is generated. The outermost condition checks if a random roll succeeds. If the condition is met, nested conditions evaluate the type of item to generate.
if (rnd(20) == 0)
- Condition: Pass a random roll:
rnd(20) == 0
.
If this condition is satisfied, the following rolls determine the item generated:
Ancient Book
The Ancient Book is one of the rare items that can be generated during fishing if specific conditions are met. Its generation depends on a random roll after passing the initial check.
if (rnd(30) == 0)
{
text = "book_ancient";
}
- Condition: The item is generated if
rnd(30) == 0
. - Probability:
1 / 30
, or approximately 3.33%.
If this condition is satisfied, the Ancient Book is created as the reward.
Platinum Coin
The Platinum Coin is another rare item that can be generated during fishing. Its generation depends on a random roll.
if (rnd(35) == 0)
{
text = "plat";
}
- Condition: The item is generated if
rnd(35) == 0
. - Probability:
1 / 35
(~2.86%).
If this condition is satisfied, a Platinum Coin is created as the reward.
Scratch Card
The Scratch Card is a replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition.
if (rnd(2) == 0)
{
text = "scratchcard";
}
- Condition: The item is generated if
rnd(2) == 0
, replacing the Platinum Coin. - Probability:
1 / 2
(50%), but it depends on the successful Platinum Coin roll. - Dependent Probability:
1 / (20 * 35 * 2)
(~0.071%).- Calculated as:
- Rare Item Roll:
1 / 20
(5%). - Platinum Coin Roll:
1 / 35
(~2.86%). - Scratch Card Roll:
1 / 2
(50%).
- Rare Item Roll:
- Calculated as:
If this condition is satisfied, the Scratch Card replaces the Platinum Coin as the reward.
Casino Coin
The Casino Coin is another replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition.
if (rnd(3) == 0)
{
text = "casino_coin";
}
- Condition: The item is generated if
rnd(3) == 0
, replacing the Platinum Coin. - Probability:
1 / 3
(~33.33%), but it depends on the successful Platinum Coin roll. - Dependent Probability:
1 / (20 * 35 * 3)
(~0.048%).- Calculated as:
- Rare Item Roll:
1 / 20
(5%). - Platinum Coin Roll:
1 / 35
(~2.86%). - Casino Coin Roll:
1 / 3
(~33.33%).
- Rare Item Roll:
- Calculated as:
If this condition is satisfied, the Casino Coin replaces the Platinum Coin as the reward.
Strange Coin
The Strange Coin is another replacement item that can be generated after the Platinum Coin roll. Its generation depends on a random roll following the successful Platinum Coin condition.
if (rnd(3) == 0)
{
text = "gacha_coin";
}
- Condition: The item is generated if
rnd(3) == 0
, replacing the Platinum Coin. - Probability:
1 / 3
(~33.33%), but it depends on the successful Platinum Coin roll. - Dependent Probability:
1 / (20 * 35 * 3)
(~0.048%).- Calculated as:
- Rare Item Roll:
1 / 20
(5%). - Platinum Coin Roll:
1 / 35
(~2.86%). - Strange Coin Roll:
1 / 3
(~33.33%).
- Rare Item Roll:
- Calculated as:
If this condition is satisfied, the Strange Coin replaces the Platinum Coin as the reward.
Statues
Statues are extremely rare items that can be generated after the Platinum Coin roll. Their generation depends on a random roll, with one of seven possible statues being selected.
if (rnd(50) == 0)
{
text = "Randomly choose one of these statues: "
"Statue of Earth",
"Statue of Element",
"Statue of Harvest",
"Statue of Healing",
"Statue of Luck",
"Statue of Machine",
"Statue of Wind";
}
- Condition: A statue is generated if
rnd(50) == 0
. - Probability:
1 / 50
(2%), but it depends on the successful Platinum Coin roll. - Dependent Probability:
1 / (20 * 35 * 50)
(~0.00286%).- Calculated as:
- Rare Item Roll:
1 / 20
(5%). - Platinum Coin Roll:
1 / 35
(~2.86%). - Statue Roll:
1 / 50
(2%).
- Rare Item Roll:
- Calculated as:
If this condition is satisfied, one of the following statues is randomly selected:
- Statue of Earth
- Statue of Element
- Statue of Harvest
- Statue of Healing
- Statue of Luck
- Statue of Machine
- Statue of Wind
Each statue has an equal probability of being selected from the pool of seven statues.
- Probability of a Specific Statue:
1 / 7
(~14.29%) of the statue roll. - Dependent Probability for a Specific Statue:
1 / (20 * 35 * 50 * 7)
(~0.00041%).
Small Medal
The Small Medal is a rare item that can be generated during fishing. Its generation depends on two random rolls: a base roll and a level-dependent threshold check.
if (rnd(40) == 0 && rnd(40) < fishingLevel / 3 + 10)
{
text = "medal";
}
- Condition:
- The first roll succeeds if
rnd(40) == 0
(2.5%). - The second roll succeeds if
rnd(40) < fishingLevel / 3 + 10
.
- The first roll succeeds if
- Probability:
- The first roll has a fixed probability:
1 / 40
(2.5%). - The second roll's probability depends on the player's fishing level:
- Higher fishing levels increase the threshold (
fishingLevel / 3 + 10
), making it easier to succeed.
- Higher fishing levels increase the threshold (
- The first roll has a fixed probability:
- Minimum Fishing Level for Consistent Success:
- To always pass the second roll, the threshold must reach or exceed 40. Solve for:
fishingLevel / 3 + 10 >= 40
.fishingLevel >= (40 - 10) * 3
.fishingLevel >= 90
.
- At
fishingLevel = 90
, the threshold becomes90 / 3 + 10 = 40
, ensuring consistent success.
- To always pass the second roll, the threshold must reach or exceed 40. Solve for:
- Dependent Probability:
- Combined probability:
(1 / 20) * (1 / 40) * (fishingLevel-dependent threshold)
. - Example for Fishing Level 10:
- Threshold:
10 / 3 + 10 = ~13.33
. - Second roll succeeds if
rnd(40) < 13
, or13 / 40
(32.5%). - Combined Probability:
(1 / 20) * (1 / 40) * (13 / 40)
(~0.01625%).
- Threshold:
- Combined probability:
Junk Items
Junk items are a category of low-value rewards that can be generated during fishing. Their generation depends on a random roll after all higher-priority items (e.g., rare items, medals) have failed to generate.
if (rnd(5 + fishingLevel / 3) == 0)
{
thing = "Randomly choose one of these junk items: "
"Boots",
"Empty Bottle (1)",
"Empty Bottle (2)",
"Empty Can (1)",
"Empty Can (2)",
"Flotsam from the North",
"Lucky Cat",
"Rubber Duck",
"Rubber Putit",
"Rubber Snail",
"Sandal (1)",
"Sandal (2)",
"Sea Pants";
}
- Condition: Junk items are generated if:
- The rare item roll and all higher-priority rolls fail.
- The following roll succeeds:
rnd(5 + fishingLevel / 3) == 0
.
- Probability:
- The probability depends on the player's fishing level:
1 / (5 + fishingLevel / 3)
.- Higher fishing levels reduce the chance of junk items being generated, as the denominator increases.
- The probability depends on the player's fishing level:
- Junk Item Pool:
- If this roll succeeds, one item is randomly selected from the following list (15 items total):
- Boots
- Empty Bottle (1)
- Empty Bottle (2)
- Empty Can (1)
- Empty Can (2)
- Flotsam from the North
- Lucky Cat
- Rubber Duck
- Rubber Putit
- Rubber Snail
- Sandal (1)
- Sandal (2)
- Sea Pants
- If this roll succeeds, one item is randomly selected from the following list (15 items total):
- Probability of a Specific Junk Item:
- Equal chance for each item in the list:
1 / 15
(~6.67%) of junk roll success.
- Equal chance for each item in the list:
Example Calculation
- At Fishing Level 10:
- Threshold for junk roll:
5 + 10 / 3 = ~8.33
. - Probability of junk roll succeeding:
1 / 8
(12.5%). - Probability of a specific junk item:
1 / 8 * 1 / 15 = 1 / 120
(~0.83%).
- Threshold for junk roll:
Fish
The generation of fish happens as the default outcome when all higher-priority rolls fail:
- Dependencies:
- The fish roll occurs if:
- The "Nothing" roll fails.
- The "Rare Item" roll fails.
- The "Junk" roll fails.
- The fish roll occurs if:
Probability Context
Since the fish roll occurs as the final fallback, its probability is calculated as:
- Probability of Fish Roll:
1 - P(Nothing) - P(Rare Item) - P(Junk)
- Dependent Probabilities:
- This depends on:
- Fishing level (affects the probability of "Nothing" and "Junk").
- Success/failure of preceding rolls.
- This depends on:
Example Calculation for Whale
At Fishing Level 19, the minimum fishing level for the Whale is 19. If the adjustedLV is 40 or higher, the Whale can be caught.
To calculate the probability of catching the Whale:
P(Whale) = 50 / Total Chance of All Eligible Fish
If the total chance for all eligible fish at Fishing Level 19 is 22050, then:
P(Whale) = 50 / 22050 = 0.00227 or ~0.227%
Fish Probability Table (Fish LV 40)
Name | Chance | Probability (Independent) |
---|---|---|
Tadpole | 1000 | 1000 / 22050 (~4.54%) |
Bitterling | 1000 | 1000 / 22050 (~4.54%) |
Turtle | 200 | 200 / 22050 (~0.91%) |
Goby | 1000 | 1000 / 22050 (~4.54%) |
Muddler | 1000 | 1000 / 22050 (~4.54%) |
Goldfish | 200 | 200 / 22050 (~0.91%) |
Carp | 100 | 100 / 22050 (~0.45%) |
Sweetfish | 1000 | 1000 / 22050 (~4.54%) |
Sea Urchin | 200 | 200 / 22050 (~0.91%) |
Sardine | 1000 | 1000 / 22050 (~4.54%) |
Eel | 500 | 500 / 22050 (~2.27%) |
Bass | 1000 | 1000 / 22050 (~4.54%) |
Scad | 1000 | 1000 / 22050 (~4.54%) |
Arowana | 600 | 600 / 22050 (~2.72%) |
Tilefish | 1000 | 1000 / 22050 (~4.54%) |
Tuna | 400 | 400 / 22050 (~1.81%) |
Striped Jack | 1000 | 1000 / 22050 (~4.54%) |
Mackerel | 1000 | 1000 / 22050 (~4.54%) |
Bonito | 1000 | 1000 / 22050 (~4.54%) |
Red Bream | 200 | 200 / 22050 (~0.91%) |
Black Bass | 1000 | 1000 / 22050 (~4.54%) |
Blowfish | 200 | 200 / 22050 (~0.91%) |
Sea Bream | 500 | 500 / 22050 (~2.27%) |
Flatfish | 1000 | 1000 / 22050 (~4.54%) |
Tuna (2) | 500 | 500 / 22050 (~2.27%) |
Sand Borer | 1000 | 1000 / 22050 (~4.54%) |
Salmon | 500 | 500 / 22050 (~2.27%) |
Sunfish | 1000 | 1000 / 22050 (~4.54%) |
Shark | 100 | 100 / 22050 (~0.45%) |
Deep Sea Fish | 1000 | 1000 / 22050 (~4.54%) |
Ancient Fish | 200 | 200 / 22050 (~0.91%) |
Moonfish | 500 | 500 / 22050 (~2.27%) |
Coelacanth | 100 | 100 / 22050 (~0.45%) |
Whale | 50 | 50 / 22050 (~0.23%) |
All Probability Table
Item | Probability (Independent) | Probability (Dependent) | Notes |
---|---|---|---|
Nothing | 1 / (3 + fishingLevel) |
N/A | Higher fishing levels reduce the chance of this outcome. |
Rare Item | 1 / 20 (5%) |
1 / 20 |
Determines if a rare item roll happens. |
Ancient Book | 1 / 30 (~3.33%) |
1 / (20 * 30) (~0.167%) |
Requires a rare item roll success, then its own probability. |
Platinum Coin | 1 / 35 (~2.86%) |
1 / (20 * 35) (~0.143%) |
Requires a rare item roll success, then its own probability. |
Scratch Card | 1 / 2 (50%) |
1 / (20 * 35 * 2) (~0.071%) |
Replaces Platinum Coin if condition is met. |
Casino Coin | 1 / 3 (33.3%) |
1 / (20 * 35 * 3) (~0.048%) |
Replaces Platinum Coin if condition is met. |
Strange Coin | 1 / 3 (33.3%) |
1 / (20 * 35 * 3) (~0.048%) |
Replaces Platinum Coin if condition is met. |
Statue | 1 / 50 (2%) |
1 / (20 * 35 * 50) (~0.00286%) |
Requires a rare item roll success. One of seven statues is randomly selected. |
Specific Statue | 1 / 7 (~14.29% of Statue Roll) |
1 / (20 * 35 * 50 * 7) (~0.00041%) |
Probability of obtaining a specific statue. |
Small Medal | Level-dependent | (1 / 20) * (1 / 40) * (fishingLevel threshold) |
Requires two successful rolls. Consistent success at fishingLevel >= 90. |
Junk | Level-dependent | 1 / (5 + fishingLevel / 3) |
Requires rare item roll to fail. Probability decreases with higher fishing levels. |
Specific Junk | 1 / 15 (~6.67%) |
(1 / (5 + fishingLevel / 3)) * (1 / 15) |
Probability of obtaining a specific junk item. |
Fish | fishChance / fishTotalChance |
1 - P(Nothing) - P(Rare Item) - P(Junk) |
Default outcome if all other rolls fail. |
Code (EA 23.43)
public static Thing Makefish(Chara c)
{
int num = c.Evalue(245);
if (EClass.rnd(3 + num) == 0)
{
return null;
}
int[] source = new int[]
{
233,
235,
236,
236,
236,
1170,
1143,
1144,
727,
728,
237,
869,
1178,
1179,
1180
};
int num2 = 1;
string text = "";
if (c.IsPC || EClass.rnd(20) == 0)
{
if (EClass.rnd(30) == 0)
{
text = "book_ancient";
}
if (EClass.rnd(35) == 0 || EClass.debug.enable)
{
text = "plat";
if (EClass.rnd(2) == 0)
{
text = "scratchcard";
}
if (EClass.rnd(3) == 0)
{
text = "casino_coin";
}
if (EClass.rnd(3) == 0)
{
text = "gacha_coin";
}
if (EClass.rnd(50) == 0 || EClass.debug.enable)
{
text = new string[]
{
"659",
"758",
"759",
"806",
"828",
"1190",
"1191"
}.RandomItem<string>();
}
}
if (EClass.rnd(40) == 0 && EClass.rnd(40) < num / 3 + 10)
{
text = "medal";
}
}
Thing thing;
if (text != "")
{
thing = ThingGen.Create(text, -1, -1);
}
else if (EClass.rnd(5 + num / 3) == 0)
{
thing = ThingGen.Create(source.RandomItem<int>().ToString() ?? "", -1, -1);
}
else
{
int num3 = EClass.rnd(num * 2) + 1;
thing = ThingGen.Create("fish", -1, num3);
num2 = EClass.rnd(num / (num3 + 10)) + 1;
int num4 = 5;
if (EClass.Branch != null)
{
num4 += EClass.Branch.Evalue(3604) * 20 + EClass.Branch.Evalue(3605) * 20 + EClass.Branch.Evalue(3706) * 25;
}
if (num4 >= EClass.rnd(100))
{
num2++;
}
}
if (thing != null)
{
thing.SetNum(num2);
thing.SetBlessedState(BlessedState.Normal);
}
return thing;
}