Implement magazine system and inventory management
- Add level-based magazine system (3 mags at L1, 2 at L3-5, 1 at L6-8) - Replace ammo/chargers with current_ammo/magazines/bullets_per_magazine - Add inventory system for storing and using shop items - Add Magazine item to shop (15 XP, adds 1 magazine) - Auto-migrate existing players from old ammo system - Auto-update magazines when players level up - Fix method name bugs (get_player_level -> calculate_player_level)
This commit is contained in:
@@ -38,14 +38,14 @@ class LevelManager:
|
||||
"""Default fallback level system"""
|
||||
return {
|
||||
"level_calculation": {
|
||||
"method": "total_ducks",
|
||||
"description": "Level based on total ducks interacted with"
|
||||
"method": "xp",
|
||||
"description": "Level based on XP earned"
|
||||
},
|
||||
"levels": {
|
||||
"1": {
|
||||
"name": "Duck Novice",
|
||||
"min_ducks": 0,
|
||||
"max_ducks": 9,
|
||||
"min_xp": 0,
|
||||
"max_xp": 49,
|
||||
"befriend_success_rate": 85,
|
||||
"accuracy_modifier": 5,
|
||||
"duck_spawn_speed_modifier": 1.0,
|
||||
@@ -53,8 +53,8 @@ class LevelManager:
|
||||
},
|
||||
"2": {
|
||||
"name": "Duck Hunter",
|
||||
"min_ducks": 10,
|
||||
"max_ducks": 99,
|
||||
"min_xp": 50,
|
||||
"max_xp": 299,
|
||||
"befriend_success_rate": 75,
|
||||
"accuracy_modifier": 0,
|
||||
"duck_spawn_speed_modifier": 0.8,
|
||||
@@ -65,20 +65,24 @@ class LevelManager:
|
||||
|
||||
def calculate_player_level(self, player: Dict[str, Any]) -> int:
|
||||
"""Calculate a player's current level based on their stats"""
|
||||
method = self.levels_data.get('level_calculation', {}).get('method', 'total_ducks')
|
||||
method = self.levels_data.get('level_calculation', {}).get('method', 'xp')
|
||||
|
||||
if method == 'total_ducks':
|
||||
if method == 'xp':
|
||||
player_xp = player.get('xp', 0)
|
||||
elif method == 'total_ducks':
|
||||
# Fallback to duck-based calculation if specified
|
||||
total_ducks = player.get('ducks_shot', 0) + player.get('ducks_befriended', 0)
|
||||
elif method == 'xp':
|
||||
total_ducks = player.get('xp', 0) // 10 # 10 XP per "duck equivalent"
|
||||
player_xp = total_ducks # Use duck count as if it were XP
|
||||
else:
|
||||
total_ducks = player.get('ducks_shot', 0) + player.get('ducks_befriended', 0)
|
||||
player_xp = player.get('xp', 0)
|
||||
|
||||
# Find the appropriate level
|
||||
levels = self.levels_data.get('levels', {})
|
||||
for level_num in sorted(levels.keys(), key=int, reverse=True):
|
||||
level_data = levels[level_num]
|
||||
if total_ducks >= level_data.get('min_ducks', 0):
|
||||
# Check for XP-based thresholds first, fallback to duck-based
|
||||
min_threshold = level_data.get('min_xp', level_data.get('min_ducks', 0))
|
||||
if player_xp >= min_threshold:
|
||||
return int(level_num)
|
||||
|
||||
return 1 # Default to level 1
|
||||
@@ -102,15 +106,23 @@ class LevelManager:
|
||||
"duck_spawn_speed_modifier": 1.0
|
||||
}
|
||||
|
||||
total_ducks = player.get('ducks_shot', 0) + player.get('ducks_befriended', 0)
|
||||
method = self.levels_data.get('level_calculation', {}).get('method', 'xp')
|
||||
if method == 'xp':
|
||||
current_value = player.get('xp', 0)
|
||||
value_type = "xp"
|
||||
else:
|
||||
current_value = player.get('ducks_shot', 0) + player.get('ducks_befriended', 0)
|
||||
value_type = "ducks"
|
||||
|
||||
# Calculate progress to next level
|
||||
next_level_data = self.get_level_data(level + 1)
|
||||
if next_level_data:
|
||||
ducks_needed = next_level_data.get('min_ducks', 0) - total_ducks
|
||||
threshold_key = f'min_{value_type}' if value_type == 'xp' else 'min_ducks'
|
||||
next_threshold = next_level_data.get(threshold_key, 0)
|
||||
needed_for_next = next_threshold - current_value
|
||||
next_level_name = next_level_data.get('name', f"Level {level + 1}")
|
||||
else:
|
||||
ducks_needed = 0
|
||||
needed_for_next = 0
|
||||
next_level_name = "Max Level"
|
||||
|
||||
return {
|
||||
@@ -120,9 +132,11 @@ class LevelManager:
|
||||
"befriend_success_rate": level_data.get('befriend_success_rate', 75),
|
||||
"accuracy_modifier": level_data.get('accuracy_modifier', 0),
|
||||
"duck_spawn_speed_modifier": level_data.get('duck_spawn_speed_modifier', 1.0),
|
||||
"total_ducks": total_ducks,
|
||||
"ducks_needed_for_next": max(0, ducks_needed),
|
||||
"next_level_name": next_level_name
|
||||
"current_xp": player.get('xp', 0),
|
||||
"total_ducks": player.get('ducks_shot', 0) + player.get('ducks_befriended', 0),
|
||||
"needed_for_next": max(0, needed_for_next),
|
||||
"next_level_name": next_level_name,
|
||||
"value_type": value_type
|
||||
}
|
||||
|
||||
def get_modified_accuracy(self, player: Dict[str, Any]) -> int:
|
||||
@@ -163,4 +177,44 @@ class LevelManager:
|
||||
self.load_levels()
|
||||
new_count = len(self.levels_data.get('levels', {}))
|
||||
self.logger.info(f"Levels reloaded: {old_count} -> {new_count} levels")
|
||||
return new_count
|
||||
return new_count
|
||||
|
||||
def update_player_magazines(self, player: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Update player's magazine count based on their current level"""
|
||||
level_info = self.get_player_level_info(player)
|
||||
level_magazines = level_info.get('magazines', 3)
|
||||
level_bullets_per_mag = level_info.get('bullets_per_magazine', 6)
|
||||
|
||||
# Get current magazine status
|
||||
current_magazines = player.get('magazines', 3)
|
||||
current_ammo = player.get('current_ammo', 6)
|
||||
current_bullets_per_mag = player.get('bullets_per_magazine', 6)
|
||||
|
||||
# Calculate total bullets they currently have
|
||||
total_current_bullets = current_ammo + (current_magazines - 1) * current_bullets_per_mag
|
||||
|
||||
# Update magazine system to level requirements
|
||||
player['magazines'] = level_magazines
|
||||
player['bullets_per_magazine'] = level_bullets_per_mag
|
||||
|
||||
# Redistribute bullets across new magazine system
|
||||
max_total_bullets = level_magazines * level_bullets_per_mag
|
||||
new_total_bullets = min(total_current_bullets, max_total_bullets)
|
||||
|
||||
# Calculate how to distribute bullets
|
||||
if new_total_bullets <= 0:
|
||||
player['current_ammo'] = 0
|
||||
elif new_total_bullets <= level_bullets_per_mag:
|
||||
# All bullets fit in current magazine
|
||||
player['current_ammo'] = new_total_bullets
|
||||
else:
|
||||
# Fill current magazine, save rest for other magazines
|
||||
player['current_ammo'] = level_bullets_per_mag
|
||||
|
||||
return {
|
||||
'old_magazines': current_magazines,
|
||||
'new_magazines': level_magazines,
|
||||
'old_total_bullets': total_current_bullets,
|
||||
'new_total_bullets': new_total_bullets,
|
||||
'current_ammo': player['current_ammo']
|
||||
}
|
||||
Reference in New Issue
Block a user