Implement comprehensive experience and leveling system

**NEW FEATURES:**
- Complete EXP system with Pokemon-style stat calculation
- Level-based stat growth and automatic HP restoration on level up
- Experience gain from catches and battle victories
- Visual level up notifications with stat increases

**EXPERIENCE SOURCES:**
- Successful catches: 5 EXP × caught pet level
- Wild battle victories: 10 EXP × defeated pet level
- Gym battle victories: 20 EXP × defeated pet level (2x multiplier)

**LEVELING MECHANICS:**
- Cubic growth formula: level³ × 4 - 12 (smooth progression)
- Level cap at 100
- Stats recalculated on level up using Pokemon formulas
- Full HP restoration on level up
- Real-time stat increase display

**EXPERIENCE DISPLAY:**
- \!team command now shows "EXP: X to next" for active pets
- Level up messages show exact stat gains
- Experience awarded immediately after catch/victory

**STAT CALCULATION:**
- HP: (2 × base + 31) × level / 100 + level + 10
- Other stats: (2 × base + 31) × level / 100 + 5
- Progressive growth ensures meaningful advancement

**BATTLE INTEGRATION:**
- EXP awarded after wild battles, gym individual battles, and catches
- Different multipliers for different victory types
- First active pet receives all experience

This creates proper RPG progression where pets grow stronger through gameplay,
encouraging both exploration (catches) and combat (battles) for advancement.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
megaproxy 2025-07-14 16:11:20 +01:00
parent 6053161b6e
commit bd455f1be5
4 changed files with 233 additions and 4 deletions

View file

@ -769,6 +769,116 @@ class Database:
rows = await cursor.fetchall()
return [dict(row) for row in rows]
def calculate_exp_for_level(self, level: int) -> int:
"""Calculate total experience needed to reach a level"""
# Using a cubic growth formula: level^3 * 4 - 12
return max(0, (level ** 3) * 4 - 12)
def calculate_level_from_exp(self, exp: int) -> int:
"""Calculate what level a pet should be based on experience"""
level = 1
while self.calculate_exp_for_level(level + 1) <= exp:
level += 1
return min(level, 100) # Cap at level 100
async def award_experience(self, pet_id: int, exp_amount: int) -> Dict:
"""Award experience to a pet and handle leveling up"""
async with aiosqlite.connect(self.db_path) as db:
db.row_factory = aiosqlite.Row
# Get current pet data
cursor = await db.execute("""
SELECT p.*, ps.name as species_name, ps.base_hp, ps.base_attack,
ps.base_defense, ps.base_speed
FROM pets p
JOIN pet_species ps ON p.species_id = ps.id
WHERE p.id = ?
""", (pet_id,))
pet = await cursor.fetchone()
if not pet:
return {"success": False, "error": "Pet not found"}
pet_dict = dict(pet)
old_level = pet_dict["level"]
old_exp = pet_dict["experience"]
new_exp = old_exp + exp_amount
new_level = self.calculate_level_from_exp(new_exp)
result = {
"success": True,
"pet_id": pet_id,
"pet_name": pet_dict["nickname"] or pet_dict["species_name"],
"species_name": pet_dict["species_name"],
"old_level": old_level,
"new_level": new_level,
"old_exp": old_exp,
"new_exp": new_exp,
"exp_gained": exp_amount,
"leveled_up": new_level > old_level,
"levels_gained": new_level - old_level
}
# Update experience
await db.execute("""
UPDATE pets SET experience = ? WHERE id = ?
""", (new_exp, pet_id))
# Handle level up if it occurred
if new_level > old_level:
await self._handle_level_up(db, pet_dict, new_level)
result["stat_increases"] = await self._calculate_stat_increases(pet_dict, old_level, new_level)
await db.commit()
return result
async def _handle_level_up(self, db, pet_dict: Dict, new_level: int):
"""Handle pet leveling up - recalculate stats and HP"""
# Calculate new stats based on level
new_stats = self._calculate_pet_stats(pet_dict, new_level)
# Update pet stats and level
await db.execute("""
UPDATE pets
SET level = ?, max_hp = ?, attack = ?, defense = ?, speed = ?, hp = ?
WHERE id = ?
""", (
new_level,
new_stats["hp"],
new_stats["attack"],
new_stats["defense"],
new_stats["speed"],
new_stats["hp"], # Restore full HP on level up
pet_dict["id"]
))
def _calculate_pet_stats(self, pet_dict: Dict, level: int) -> Dict:
"""Calculate pet stats for a given level"""
# Pokémon-style stat calculation
hp = int((2 * pet_dict["base_hp"] + 31) * level / 100) + level + 10
attack = int((2 * pet_dict["base_attack"] + 31) * level / 100) + 5
defense = int((2 * pet_dict["base_defense"] + 31) * level / 100) + 5
speed = int((2 * pet_dict["base_speed"] + 31) * level / 100) + 5
return {
"hp": hp,
"attack": attack,
"defense": defense,
"speed": speed
}
async def _calculate_stat_increases(self, pet_dict: Dict, old_level: int, new_level: int) -> Dict:
"""Calculate stat increases from leveling up"""
old_stats = self._calculate_pet_stats(pet_dict, old_level)
new_stats = self._calculate_pet_stats(pet_dict, new_level)
return {
"hp": new_stats["hp"] - old_stats["hp"],
"attack": new_stats["attack"] - old_stats["attack"],
"defense": new_stats["defense"] - old_stats["defense"],
"speed": new_stats["speed"] - old_stats["speed"]
}
# Gym Battle System Methods
async def get_gyms_in_location(self, location_id: int, player_id: int = None) -> List[Dict]:
"""Get all gyms in a specific location with optional player progress"""