Skip to content

Commit db6a418

Browse files
committed
feat(fishing): Enhance fishing mechanics with improved rod durability and escape chances
1 parent a1314ec commit db6a418

4 files changed

Lines changed: 120 additions & 72 deletions

File tree

cogs/admin/Admin.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import os
1212
import traceback
1313
from typing import Optional, List
14-
from cogs.Help import HelpPaginator
1514

1615
logger = CogLogger('Admin')
1716

@@ -401,10 +400,13 @@ async def shop_list(self, ctx, shop_type: str):
401400
pages.append(embed)
402401

403402
if len(pages) > 1:
404-
view = HelpPaginator(pages, ctx.author)
405-
view.update_buttons()
406-
message = await ctx.reply(embed=pages[0], view=view)
407-
view.message = message
403+
# Simple pagination without complex view for now
404+
for i, page in enumerate(pages):
405+
page.set_footer(text=f"Page {i+1}/{len(pages)}")
406+
if i == 0:
407+
await ctx.reply(embed=page)
408+
else:
409+
await ctx.send(embed=page)
408410
else:
409411
await ctx.reply(embed=pages[0])
410412

cogs/bronx/AI.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __init__(self, bot):
5050
⚠️ THESE ARE THE ONLY VALID COMMANDS - DO NOT INVENT OTHERS ⚠️
5151
5252
🤖 AI COMMANDS:
53-
• `.ai <message>` - Chat with BronxBot AI (aliases: `.chat`, `.aiask`, `.ask`, `.bronxai`)
53+
• `.ai <message>` - Chat with BronxBot AI (aliases: `.chat`, `.aiask`, `.bronxai`)
5454
• `.ai --thinking <message>` - Shows AI reasoning process
5555
• `.aiclear` - Clear conversation history (aliases: `.clearai`, `.resetai`, `.clearconvo`, `.resetconvo`)
5656
• `.aistatus` - Check AI service status [Admin] (aliases: `.aiinfo`, `.checkai`)
@@ -105,7 +105,7 @@ def __init__(self, bot):
105105
• `.serverinfo` - Server information (aliases: `.si`, `.guildinfo`)
106106
• `.uptime` - How long bot has been running
107107
• `.botinfo` - Bot statistics and info
108-
• `.poll <question>` - Create yes/no poll (aliases: `.ask`, `.yn`)
108+
• `.poll <question>` - Create yes/no poll (aliases: `.ask`, `.yn`, `.yesno`)
109109
• `.multipoll <question> <option1> <option2>...` - Multi-option poll
110110
• `.timestamp [style]` - Generate Discord timestamps
111111
• `.hexcolor [code]` - Show color preview
@@ -149,7 +149,7 @@ def __init__(self, bot):
149149
⚠️ IMPORTANT: Commands can be used with their aliases interchangeably ⚠️
150150
151151
Main Command = Aliases:
152-
• `.ai` = `.chat`, `.aiask`, `.ask`, `.bronxai`
152+
• `.ai` = `.chat`, `.aiask`, `.bronxai`
153153
• `.balance` = `.bal`, `.money`
154154
• `.pay` = `.give`, `.send`
155155
• `.deposit` = `.dep`, `.d`
@@ -163,7 +163,7 @@ def __init__(self, bot):
163163
• `.avatar` = `.av`
164164
• `.userinfo` = `.ui`, `.whois`
165165
• `.serverinfo` = `.si`, `.guildinfo`
166-
• `.poll` = `.ask`, `.yn`
166+
• `.poll` = `.ask`, `.yn`, `.yesno`
167167
• `.emojisteal` = `.steal`
168168
• `.cleanup` = `.cu`
169169
• `.calculate` = `.calc`, `.math`
@@ -558,7 +558,7 @@ def validate_response_for_hallucinations(self, response: str) -> str:
558558
"""Check response for potential command hallucinations and warn if found"""
559559
# List of valid commands and their aliases
560560
valid_commands = [
561-
'ai', 'chat', 'aiask', 'ask', 'bronxai', 'aiclear', 'clearai', 'resetai',
561+
'ai', 'chat', 'aiask', 'bronxai', 'aiclear', 'clearai', 'resetai',
562562
'clearconvo', 'resetconvo', 'aistatus', 'aiinfo', 'checkai',
563563
'balance', 'bal', 'money', 'pay', 'give', 'send', 'deposit', 'dep', 'd',
564564
'withdraw', 'with', 'w', 'daily', 'beg', 'rob', 'work', 'job', 'choosejob',
@@ -590,14 +590,14 @@ def validate_response_for_hallucinations(self, response: str) -> str:
590590

591591
return response
592592

593-
@commands.command(name='ai', aliases=['chat', 'aiask', 'ask', 'bronxai'])
593+
@commands.command(name='ai', aliases=['chat', 'aiask', 'bronxai'])
594594
@commands.cooldown(1, 30, commands.BucketType.user)
595595
async def ai_chat(self, ctx, *, prompt: str):
596596
"""Chat with BronxBot AI powered by Deepseek-8B
597597
598598
Usage: .ai <your message>
599599
Usage: .ai --thinking <your message> (shows AI reasoning process)
600-
Aliases: .chat, .aiask, .ask, .bronxai
600+
Aliases: .chat, .aiask, .bronxai
601601
Example: .ai What's the weather like in the Bronx?
602602
Example: .ai --thinking Explain quantum physics
603603
"""

cogs/economy/fishing/fishing_core.py

Lines changed: 80 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,25 @@ async def set_active_rod_manual(self, user_id: int, rod_id: str) -> bool:
122122
self.logger.error(f"Failed to set active rod: {e}")
123123
return False
124124

125-
async def check_rod_durability(self, durability: float) -> bool:
126-
"""Check if rod survives this fishing attempt"""
127-
break_chance = 1 - durability
128-
return random.random() > break_chance
125+
async def check_rod_durability(self, durability: float, rod_price: int = 0) -> bool:
126+
"""Check if rod survives this fishing attempt - Improved durability system"""
127+
# Ensure minimum 95% durability (0.95 = 5% break chance maximum)
128+
durability = max(0.95, min(0.998, durability)) # Cap durability at 99.8%
129+
130+
base_break_chance = 1 - durability
131+
132+
# High-end rods get durability bonuses (10-20% break chance reduction)
133+
if rod_price >= 100000: # Ultra expensive rods
134+
base_break_chance *= 0.80 # 20% break chance reduction
135+
elif rod_price >= 50000: # Very expensive rods
136+
base_break_chance *= 0.85 # 15% break chance reduction
137+
elif rod_price >= 20000: # Expensive rods
138+
base_break_chance *= 0.90 # 10% break chance reduction
139+
140+
# Cap maximum break chance at 10% (was unlimited)
141+
final_break_chance = min(0.10, base_break_chance)
142+
143+
return random.random() > final_break_chance
129144

130145
async def select_fish_from_rarity(self, rarity: str):
131146
"""Select a random fish from the given rarity category"""
@@ -139,18 +154,32 @@ async def select_fish_from_rarity(self, rarity: str):
139154
return random.choice(fish_list)
140155

141156
async def check_fish_escape(self, fish_template, rod_power: int):
142-
"""Check if fish escapes - More generous for expensive rods"""
157+
"""Check if fish escapes - Implements weight rule and balanced escape chances"""
143158
base_escape_chance = fish_template.get("escape_chance", 0.1)
144159

145-
# Reduce escape chance based on rod power (more generous scaling)
146-
power_reduction = min(0.8, (rod_power - 1) * 0.15) # Up to 80% reduction
147-
final_escape_chance = max(0.01, base_escape_chance * (1 - power_reduction))
148-
149-
# Generate fish weight
160+
# Generate fish weight first
150161
min_weight = fish_template.get("min_weight", 0.1)
151162
max_weight = fish_template.get("max_weight", 1.0)
152163
fish_weight = random.uniform(min_weight, max_weight)
153164

165+
# WEIGHT RULE: Fish under 100kg (220 lbs) CANNOT escape - guaranteed catch!
166+
if fish_weight < 100.0:
167+
return False, fish_weight # Fish cannot escape
168+
169+
# For fish over 100kg, apply escape chance calculations
170+
# Reduce escape chance based on rod power (limited scaling)
171+
power_reduction = min(0.30, (rod_power - 1) * 0.05) # Max 30% reduction (was 80%)
172+
final_escape_chance = max(0.01, base_escape_chance * (1 - power_reduction))
173+
174+
# Value-based escape penalties for high-value fish
175+
fish_value = fish_template.get("base_value", 0)
176+
if fish_value >= 1000000: # 1M+ coins
177+
final_escape_chance = min(0.99, final_escape_chance + 0.50)
178+
elif fish_value >= 100000: # 100K+ coins
179+
final_escape_chance = min(0.98, final_escape_chance + 0.30)
180+
elif fish_value >= 50000: # 50K+ coins
181+
final_escape_chance = min(0.95, final_escape_chance + 0.20)
182+
154183
# Check if fish escapes
155184
escaped = random.random() < final_escape_chance
156185

@@ -250,6 +279,7 @@ async def fish(self, ctx):
250279
rod_multiplier = rod.get("multiplier", 1.0)
251280
rod_durability = rod.get("durability", 0.95)
252281
rod_power = rod.get("power", 1)
282+
rod_price = rod.get("price", 0)
253283
bait_rates = current_bait.get("catch_rates", {})
254284

255285
# Display suspense message
@@ -279,7 +309,7 @@ async def fish(self, ctx):
279309
await asyncio.sleep(random.uniform(2.5, 4.5))
280310

281311
# Check rod durability first
282-
if not await self.check_rod_durability(rod_durability):
312+
if not await self.check_rod_durability(rod_durability, rod_price):
283313
# Rod breaks!
284314
break_embed = discord.Embed(
285315
title="💥 Rod Broke!",
@@ -310,31 +340,43 @@ async def fish(self, ctx):
310340
# Determine what fish is hooked
311341
adjusted_rates = self._apply_rod_multiplier_properly(bait_rates, rod_multiplier)
312342

313-
total_weight = sum(adjusted_rates.values())
314-
if total_weight == 0:
315-
await message.edit(embed=discord.Embed(
316-
title="🌊 No Bite",
317-
description="Nothing seems interested in your bait...",
318-
color=0x6495ed
319-
))
320-
return
321-
322-
# Roll for fish rarity
323-
roll = random.random() * total_weight
324-
cumulative = 0
325-
caught_rarity = "junk"
326-
327-
for rarity, weight in adjusted_rates.items():
328-
cumulative += weight
329-
if roll <= cumulative:
330-
caught_rarity = rarity
331-
break
332-
333-
# Select specific fish
334-
fish_template = await self.select_fish_from_rarity(caught_rarity)
335-
if not fish_template:
343+
# BEGINNER ROD SAFETY NET: 10% chance to catch ANY fish, even ultra-rare ones
344+
beginner_luck = False
345+
if rod.get("_id", "").lower() in ["basic_rod", "beginner_rod"]:
346+
if random.random() < 0.10: # 10% chance
347+
beginner_luck = True
348+
# Pick from ALL rarities equally
349+
all_rarities = list(self.fish_database.keys())
350+
caught_rarity = random.choice(all_rarities)
351+
fish_template = await self.select_fish_from_rarity(caught_rarity)
352+
353+
if not beginner_luck:
354+
# Normal fishing logic
355+
total_weight = sum(adjusted_rates.values())
356+
if total_weight == 0:
357+
await message.edit(embed=discord.Embed(
358+
title="🌊 No Bite",
359+
description="Nothing seems interested in your bait...",
360+
color=0x6495ed
361+
))
362+
return
363+
364+
# Roll for fish rarity
365+
roll = random.random() * total_weight
366+
cumulative = 0
336367
caught_rarity = "junk"
368+
369+
for rarity, weight in adjusted_rates.items():
370+
cumulative += weight
371+
if roll <= cumulative:
372+
caught_rarity = rarity
373+
break
374+
375+
# Select specific fish
337376
fish_template = await self.select_fish_from_rarity(caught_rarity)
377+
if not fish_template:
378+
caught_rarity = "junk"
379+
fish_template = await self.select_fish_from_rarity(caught_rarity)
338380

339381
# Check if fish escapes
340382
escaped, fish_weight = await self.check_fish_escape(fish_template, rod_power)
@@ -408,6 +450,10 @@ async def fish(self, ctx):
408450
color=config['color']
409451
)
410452

453+
# Add BEGINNER'S LUCK message if this was a miracle catch
454+
if beginner_luck:
455+
success_embed.description += f"\n\n🍀 **BEGINNER'S LUCK!** 🍀\n*Your basic rod defied the odds!*"
456+
411457
if fish_count > 1:
412458
success_embed.description += f"\n*(You have **{fish_count}x** of this fish)*"
413459

cogs/economy/fishing/fishing_data.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -190,23 +190,23 @@ def _load_fish_database(self):
190190
{"name": "Mahi-Mahi", "min_weight": 5.0, "max_weight": 25.0, "base_value": 1200, "escape_chance": 0.38}
191191
],
192192
"rare": [
193-
{"name": "Giant Squid", "min_weight": 100.0, "max_weight": 800.0, "base_value": 7500, "escape_chance": 0.70},
194-
{"name": "Blue Whale", "min_weight": 50000.0, "max_weight": 150000.0, "base_value": 45000, "escape_chance": 0.85},
195-
{"name": "Colossal Octopus", "min_weight": 200.0, "max_weight": 1000.0, "base_value": 12750, "escape_chance": 0.75},
196-
{"name": "Megalodon", "min_weight": 5000.0, "max_weight": 15000.0, "base_value": 33000, "escape_chance": 0.80}
193+
{"name": "Giant Squid", "min_weight": 100.0, "max_weight": 800.0, "base_value": 7500, "escape_chance": 0.85},
194+
{"name": "Blue Whale", "min_weight": 50000.0, "max_weight": 150000.0, "base_value": 25000, "escape_chance": 0.88},
195+
{"name": "Colossal Octopus", "min_weight": 200.0, "max_weight": 1000.0, "base_value": 12750, "escape_chance": 0.85},
196+
{"name": "Megalodon", "min_weight": 5000.0, "max_weight": 15000.0, "base_value": 20000, "escape_chance": 0.88}
197197
],
198198
"epic": [
199-
{"name": "Leviathan", "min_weight": 1000.0, "max_weight": 5000.0, "base_value": 75000, "escape_chance": 0.90},
200-
{"name": "Kraken", "min_weight": 2000.0, "max_weight": 8000.0, "base_value": 120000, "escape_chance": 0.92},
201-
{"name": "Sea Dragon", "min_weight": 500.0, "max_weight": 3000.0, "base_value": 90000, "escape_chance": 0.88}
199+
{"name": "Leviathan", "min_weight": 1000.0, "max_weight": 5000.0, "base_value": 45000, "escape_chance": 0.90},
200+
{"name": "Kraken", "min_weight": 2000.0, "max_weight": 8000.0, "base_value": 65000, "escape_chance": 0.92},
201+
{"name": "Sea Dragon", "min_weight": 500.0, "max_weight": 3000.0, "base_value": 55000, "escape_chance": 0.92}
202202
],
203203
"legendary": [
204-
{"name": "Ancient Leviathan", "min_weight": 10000.0, "max_weight": 50000.0, "base_value": 500000, "escape_chance": 0.95},
205-
{"name": "Primordial Kraken", "min_weight": 15000.0, "max_weight": 75000.0, "base_value": 750000, "escape_chance": 0.96}
204+
{"name": "Ancient Leviathan", "min_weight": 10000.0, "max_weight": 50000.0, "base_value": 180000, "escape_chance": 0.94},
205+
{"name": "Primordial Kraken", "min_weight": 15000.0, "max_weight": 75000.0, "base_value": 250000, "escape_chance": 0.95}
206206
],
207207
"mythical": [
208-
{"name": "World Serpent", "min_weight": 100000.0, "max_weight": 500000.0, "base_value": 2500000, "escape_chance": 0.98},
209-
{"name": "Ocean God", "min_weight": 200000.0, "max_weight": 1000000.0, "base_value": 5000000, "escape_chance": 0.99}
208+
{"name": "World Serpent", "min_weight": 100000.0, "max_weight": 500000.0, "base_value": 750000, "escape_chance": 0.96},
209+
{"name": "Ocean God", "min_weight": 200000.0, "max_weight": 1000000.0, "base_value": 1200000, "escape_chance": 0.99}
210210
],
211211
"ancient": [
212212
{"name": "Fossil Megalodon", "min_weight": 25000.0, "max_weight": 100000.0, "base_value": 1500000, "escape_chance": 0.97},
@@ -217,20 +217,20 @@ def _load_fish_database(self):
217217
{"name": "Celestial Whale", "min_weight": 300000.0, "max_weight": 800000.0, "base_value": 6000000, "escape_chance": 0.997}
218218
],
219219
"cosmic": [
220-
{"name": "Stellar Whale", "min_weight": 500000.0, "max_weight": 2000000.0, "base_value": 10000000, "escape_chance": 0.9985},
221-
{"name": "Galactic Kraken", "min_weight": 1000000.0, "max_weight": 5000000.0, "base_value": 20000000, "escape_chance": 0.9992}
220+
{"name": "Stellar Whale", "min_weight": 500000.0, "max_weight": 2000000.0, "base_value": 3500000, "escape_chance": 0.9985},
221+
{"name": "Galactic Kraken", "min_weight": 1000000.0, "max_weight": 5000000.0, "base_value": 5500000, "escape_chance": 0.9992}
222222
],
223223
"transcendent": [
224-
{"name": "Reality Bender", "min_weight": 1.0, "max_weight": 10000000.0, "base_value": 40000000, "escape_chance": 0.9997},
225-
{"name": "Dimension Walker", "min_weight": 0.001, "max_weight": 1000000000.0, "base_value": 100000000, "escape_chance": 0.99995}
224+
{"name": "Reality Bender", "min_weight": 1.0, "max_weight": 10000000.0, "base_value": 8000000, "escape_chance": 0.9997},
225+
{"name": "Dimension Walker", "min_weight": 0.001, "max_weight": 1000000000.0, "base_value": 15000000, "escape_chance": 0.99995}
226226
],
227227
"void": [
228-
{"name": "Void Leviathan", "min_weight": 0.0, "max_weight": 1.0, "base_value": 200000000, "escape_chance": 0.99997},
229-
{"name": "Nothingness Fish", "min_weight": -1.0, "max_weight": 0.0, "base_value": 300000000, "escape_chance": 0.99999}
228+
{"name": "Void Leviathan", "min_weight": 0.0, "max_weight": 1.0, "base_value": 25000000, "escape_chance": 0.99997},
229+
{"name": "Nothingness Fish", "min_weight": -1.0, "max_weight": 0.0, "base_value": 40000000, "escape_chance": 0.99999}
230230
],
231231
"celestial": [
232-
{"name": "Moon Fish", "min_weight": 384400.0, "max_weight": 7342000.0, "base_value": 120000000, "escape_chance": 0.9999},
233-
{"name": "Solar Flare Eel", "min_weight": 1989000000.0, "max_weight": 1989000000000.0, "base_value": 400000000, "escape_chance": 0.99999}
232+
{"name": "Moon Fish", "min_weight": 384400.0, "max_weight": 7342000.0, "base_value": 18000000, "escape_chance": 0.9999},
233+
{"name": "Solar Flare Eel", "min_weight": 1989000000.0, "max_weight": 1989000000000.0, "base_value": 50000000, "escape_chance": 0.99999}
234234
],
235235
"mutated": [
236236
{"name": "Three-Eyed Bass", "min_weight": 2.0, "max_weight": 15.0, "base_value": 10000, "escape_chance": 0.48},
@@ -316,7 +316,7 @@ def resolve_bait_alias(self, bait_input: str) -> str:
316316
return None
317317

318318
def apply_rod_multiplier(self, bait_rates, rod_multiplier):
319-
"""Apply rod multiplier to favor higher rarities - Fixed version"""
319+
"""Apply rod multiplier to favor higher rarities - NERFED VERSION per balance changes"""
320320
if rod_multiplier <= 1.0:
321321
return bait_rates.copy()
322322

@@ -330,13 +330,13 @@ def apply_rod_multiplier(self, bait_rates, rod_multiplier):
330330

331331
if rarity in rarity_order:
332332
rarity_index = rarity_order.index(rarity)
333-
# Apply multiplier effect based on rarity tier
333+
# Apply multiplier effect based on rarity tier - MASSIVELY NERFED
334334
if rarity_index >= 15: # Ultra rare fish (subatomic, super, etc.)
335-
multiplier_effect = 1 + ((rod_multiplier - 1) * 0.8) # 80% of rod power
336-
elif rarity_index >= 10: # High tier fish (divine, cosmic, etc.)
337-
multiplier_effect = 1 + ((rod_multiplier - 1) * 1.2) # 120% of rod power
338-
elif rarity_index >= 6: # Mid-high tier (epic, legendary, etc.)
339-
multiplier_effect = 1 + ((rod_multiplier - 1) * 1.5) # 150% of rod power
335+
multiplier_effect = 1 + ((rod_multiplier - 1) * 0.10) # Only 10% of rod power (was 80%)
336+
elif rarity_index >= 10: # Very rare fish (divine, cosmic, etc.)
337+
multiplier_effect = 1 + ((rod_multiplier - 1) * 0.15) # Only 15% of rod power (was 120%)
338+
elif rarity_index >= 6: # High tier fish (epic, legendary, etc.)
339+
multiplier_effect = 1 + ((rod_multiplier - 1) * 0.25) # Only 25% of rod power (was 150%)
340340
elif rarity_index >= 3: # Mid tier (uncommon, rare)
341341
multiplier_effect = 1 + ((rod_multiplier - 1) * 1.0) # Normal rod power
342342
else: # Low tier (junk, tiny, small, common)

0 commit comments

Comments
 (0)