Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c442261d9 |
36
src/level.py
36
src/level.py
@@ -10,7 +10,6 @@ from src.grasping_hands import GraspingHands
|
||||
from src.grave import GraveObject
|
||||
from src.object import Object
|
||||
from src.player import Player
|
||||
from src.projectile import Projectile
|
||||
from src.powerup import PowerUp
|
||||
from src.skull_storm import SkullStorm
|
||||
|
||||
@@ -200,8 +199,8 @@ class Level:
|
||||
self.objects.append(gameObject)
|
||||
enemyCount = len(self.enemies)
|
||||
coffinCount = sum(1 for obj in self.objects if hasattr(obj, "isBroken"))
|
||||
player.stats.update_stat("Enemies remaining", enemyCount)
|
||||
player.stats.update_stat("Coffins remaining", coffinCount)
|
||||
player.stats.set_stat("Enemies remaining", enemyCount, level_only=True)
|
||||
player.stats.set_stat("Coffins remaining", coffinCount, level_only=True)
|
||||
|
||||
def update_audio(self):
|
||||
"""Update all audio and entity state."""
|
||||
@@ -310,16 +309,22 @@ class Level:
|
||||
def handle_combat(self, currentTime):
|
||||
"""Handle combat interactions between player and enemies"""
|
||||
# Only get attack range if attack is active
|
||||
if self.player.currentWeapon and self.player.currentWeapon.is_attack_active(currentTime):
|
||||
attackRange = self.player.currentWeapon.get_attack_range(self.player.xPos, self.player.facingRight)
|
||||
if self.player.currentWeapon and self.player.currentWeapon.is_attack_active():
|
||||
# Calculate attack range manually
|
||||
if self.player.facingRight:
|
||||
attackRange = (self.player.xPos, self.player.xPos + self.player.currentWeapon.range_value)
|
||||
else:
|
||||
attackRange = (self.player.xPos - self.player.currentWeapon.range_value, self.player.xPos)
|
||||
|
||||
# Check for enemy hits
|
||||
for enemy in self.enemies:
|
||||
if enemy.isActive and enemy.xPos >= attackRange[0] and enemy.xPos <= attackRange[1]:
|
||||
# Only damage and play sound if this is a new hit for this attack
|
||||
if self.player.currentWeapon.register_hit(enemy, currentTime):
|
||||
play_sound(self.sounds[self.player.currentWeapon.hitSound])
|
||||
enemy.take_damage(self.player.currentWeapon.damage)
|
||||
# Use libstormgames weapon hit detection
|
||||
if self.player.currentWeapon.can_hit_target(enemy.xPos, self.player.xPos, self.player.facingRight, id(enemy)):
|
||||
damage = self.player.currentWeapon.hit_target(id(enemy))
|
||||
if damage > 0:
|
||||
play_sound(self.sounds[self.player.currentWeapon.hit_sound])
|
||||
enemy.take_damage(damage)
|
||||
|
||||
# Check for coffin hits
|
||||
for obj in self.objects:
|
||||
@@ -516,13 +521,16 @@ class Level:
|
||||
|
||||
# Check for enemy hits
|
||||
for enemy in self.enemies:
|
||||
if enemy.isActive and abs(proj.x - enemy.xPos) < 1:
|
||||
proj.hit_enemy(enemy)
|
||||
if enemy.isActive and proj.check_collision(enemy.xPos, 1.0):
|
||||
damage = proj.hit()
|
||||
enemy.take_damage(damage)
|
||||
self.projectiles.remove(proj)
|
||||
# Calculate volume and pan for splat sound based on final position
|
||||
volume, left, right = calculate_volume_and_pan(self.player.xPos, proj.x)
|
||||
proj_pos = proj.get_position()
|
||||
proj_x = proj_pos if isinstance(proj_pos, (int, float)) else proj_pos[0]
|
||||
volume, left, right = calculate_volume_and_pan(self.player.xPos, proj_x)
|
||||
if volume > 0: # Only play if within audible range
|
||||
obj_play(self.sounds, "pumpkin_splat", self.player.xPos, proj.x, loop=False)
|
||||
obj_play(self.sounds, "pumpkin_splat", self.player.xPos, proj_x, loop=False)
|
||||
break
|
||||
|
||||
def throw_projectile(self):
|
||||
@@ -532,6 +540,6 @@ class Level:
|
||||
speak("No jack o'lanterns to throw!")
|
||||
return
|
||||
|
||||
self.projectiles.append(Projectile(proj_info["type"], proj_info["start_x"], proj_info["direction"]))
|
||||
self.projectiles.append(Projectile(proj_info["type"], proj_info["start_x"], proj_info["direction"], speed=0.2, damage=5, max_range=12))
|
||||
# Play throw sound
|
||||
play_sound(self.sounds["throw_jack_o_lantern"])
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
import pygame
|
||||
from libstormgames import *
|
||||
from src.stat_tracker import StatTracker
|
||||
from src.weapon import Weapon
|
||||
|
||||
|
||||
class Player:
|
||||
@@ -27,7 +25,7 @@ class Player:
|
||||
self._lives = 1
|
||||
self.distanceSinceLastStep = 0
|
||||
self.stepDistance = 0.5
|
||||
self.stats = StatTracker()
|
||||
self.stats = StatTracker({"Bone dust": 0, "Enemies killed": 0, "Coffins broken": 0, "Items collected": 0, "Total time": 0, "levelsCompleted": 0})
|
||||
self.sounds = sounds
|
||||
|
||||
# Footstep tracking
|
||||
@@ -67,10 +65,10 @@ class Player:
|
||||
Weapon(
|
||||
name="rusty_shovel",
|
||||
damage=2,
|
||||
range=2,
|
||||
attackSound="player_shovel_attack",
|
||||
hitSound="player_shovel_hit",
|
||||
attackDuration=200, # 200ms attack duration
|
||||
range_value=2,
|
||||
attack_sound="player_shovel_attack",
|
||||
hit_sound="player_shovel_hit",
|
||||
attack_duration=200, # 200ms attack duration
|
||||
)
|
||||
)
|
||||
|
||||
@@ -106,7 +104,7 @@ class Player:
|
||||
if currentTime >= self.webPenaltyEndTime:
|
||||
self.moveSpeed *= 2 # Restore speed
|
||||
if self.currentWeapon:
|
||||
self.currentWeapon.attackDuration *= 0.5 # Restore attack speed
|
||||
self.currentWeapon.attack_duration *= 0.5 # Restore attack speed
|
||||
del self.webPenaltyEndTime
|
||||
|
||||
# Check invincibility status
|
||||
@@ -166,7 +164,7 @@ class Player:
|
||||
|
||||
def get_step_distance(self):
|
||||
"""Get step distance based on current speed"""
|
||||
weaponBonus = self.currentWeapon.speedBonus if self.currentWeapon else 1.0
|
||||
weaponBonus = self.currentWeapon.stat_bonuses.get("speed", 1.0) if self.currentWeapon else 1.0
|
||||
totalMultiplier = weaponBonus
|
||||
|
||||
if self.isRunning or self.isJumping:
|
||||
@@ -176,7 +174,7 @@ class Player:
|
||||
|
||||
def get_step_interval(self):
|
||||
"""Get minimum time between steps based on current speed"""
|
||||
weaponBonus = self.currentWeapon.speedBonus if self.currentWeapon else 1.0
|
||||
weaponBonus = self.currentWeapon.stat_bonuses.get("speed", 1.0) if self.currentWeapon else 1.0
|
||||
totalMultiplier = weaponBonus
|
||||
|
||||
if self.isRunning or self.isJumping:
|
||||
@@ -199,7 +197,7 @@ class Player:
|
||||
def get_current_speed(self):
|
||||
"""Calculate current speed based on state and weapon"""
|
||||
baseSpeed = self.moveSpeed
|
||||
weaponBonus = self.currentWeapon.speedBonus if self.currentWeapon else 1.0
|
||||
weaponBonus = self.currentWeapon.stat_bonuses.get("speed", 1.0) if self.currentWeapon else 1.0
|
||||
|
||||
if self.isJumping or self.isRunning:
|
||||
return baseSpeed * self.runMultiplier * weaponBonus
|
||||
@@ -207,7 +205,7 @@ class Player:
|
||||
|
||||
def get_current_jump_duration(self):
|
||||
"""Calculate current jump duration based on weapon bonus"""
|
||||
weaponBonus = self.currentWeapon.jumpDurationBonus if self.currentWeapon else 1.0
|
||||
weaponBonus = self.currentWeapon.stat_bonuses.get("jump_duration", 1.0) if self.currentWeapon else 1.0
|
||||
return int(self.jumpDuration * weaponBonus)
|
||||
|
||||
def set_footstep_sound(self, soundName):
|
||||
@@ -304,14 +302,21 @@ class Player:
|
||||
|
||||
def start_attack(self, currentTime):
|
||||
"""Attempt to start an attack with the current weapon"""
|
||||
if self.currentWeapon and self.currentWeapon.start_attack(currentTime):
|
||||
self.isAttacking = True
|
||||
self.lastAttackTime = currentTime
|
||||
return True
|
||||
if self.currentWeapon and self.currentWeapon.can_attack():
|
||||
damage = self.currentWeapon.attack()
|
||||
if damage > 0:
|
||||
self.isAttacking = True
|
||||
self.lastAttackTime = currentTime
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_attack_range(self, currentTime):
|
||||
"""Get the current attack's range based on position and facing direction"""
|
||||
if not self.currentWeapon or not self.currentWeapon.is_attack_active(currentTime):
|
||||
if not self.currentWeapon or not self.currentWeapon.is_attack_active():
|
||||
return None
|
||||
return self.currentWeapon.get_attack_range(self.xPos, self.facingRight)
|
||||
|
||||
# Calculate attack range based on position and facing direction
|
||||
if self.facingRight:
|
||||
return (self.xPos, self.xPos + self.currentWeapon.range_value)
|
||||
else:
|
||||
return (self.xPos - self.currentWeapon.range_value, self.xPos)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import pygame
|
||||
from libstormgames import *
|
||||
from src.object import Object
|
||||
from src.weapon import Weapon
|
||||
|
||||
|
||||
class PowerUp(Object):
|
||||
@@ -100,7 +99,16 @@ class PowerUp(Object):
|
||||
|
||||
self.check_for_nunchucks(player)
|
||||
elif self.item_type == "witch_broom":
|
||||
broomWeapon = Weapon.create_witch_broom()
|
||||
broomWeapon = Weapon(
|
||||
name="witch_broom",
|
||||
damage=3,
|
||||
range_value=3,
|
||||
attack_sound="player_broom_attack",
|
||||
hit_sound="player_broom_hit",
|
||||
cooldown=500,
|
||||
attack_duration=200,
|
||||
stat_bonuses={"speed": 1.17, "jump_duration": 1.25}
|
||||
)
|
||||
player.add_weapon(broomWeapon)
|
||||
player.equip_weapon(broomWeapon)
|
||||
elif self.item_type == "spiderweb":
|
||||
@@ -112,7 +120,7 @@ class PowerUp(Object):
|
||||
# Half speed and double attack time for 15 seconds
|
||||
player.moveSpeed *= 0.5
|
||||
if player.currentWeapon:
|
||||
player.currentWeapon.attackDuration *= 2
|
||||
player.currentWeapon.attack_duration *= 2
|
||||
# Set timer for penalty removal
|
||||
player.webPenaltyEndTime = pygame.time.get_ticks() + 15000
|
||||
|
||||
@@ -135,11 +143,19 @@ class PowerUp(Object):
|
||||
and "guts" in player.collectedItems
|
||||
and not any(weapon.name == "nunchucks" for weapon in player.weapons)
|
||||
):
|
||||
nunchucksWeapon = Weapon.create_nunchucks()
|
||||
nunchucksWeapon = Weapon(
|
||||
name="nunchucks",
|
||||
damage=6,
|
||||
range_value=4,
|
||||
attack_sound="player_nunchuck_attack",
|
||||
hit_sound="player_nunchuck_hit",
|
||||
cooldown=250,
|
||||
attack_duration=100
|
||||
)
|
||||
player.add_weapon(nunchucksWeapon)
|
||||
player.equip_weapon(nunchucksWeapon)
|
||||
basePoints = nunchucksWeapon.damage * 1000
|
||||
rangeModifier = nunchucksWeapon.range * 500
|
||||
rangeModifier = nunchucksWeapon.range_value * 500
|
||||
player.scoreboard.increase_score(basePoints + rangeModifier)
|
||||
play_sound(self.sounds["get_nunchucks"])
|
||||
player.stats.update_stat("Items collected", 1)
|
||||
|
||||
227
wicked_quest.py
227
wicked_quest.py
@@ -10,7 +10,6 @@ from src.level import Level
|
||||
from src.object import Object
|
||||
from src.player import Player
|
||||
from src.game_selection import select_game, get_level_path
|
||||
from src.save_manager import SaveManager
|
||||
from src.survival_generator import SurvivalGenerator
|
||||
|
||||
|
||||
@@ -28,7 +27,7 @@ class WickedQuest:
|
||||
self.player = None
|
||||
self.currentGame = None
|
||||
self.runLock = False # Toggle behavior of the run keys
|
||||
self.saveManager = SaveManager()
|
||||
self.saveManager = SaveManager("wicked-quest")
|
||||
self.survivalGenerator = None
|
||||
self.lastBroomLandingTime = 0 # Timestamp to prevent ducking after broom landing
|
||||
self.survivalWave = 1
|
||||
@@ -75,7 +74,7 @@ class WickedQuest:
|
||||
del self.player.webPenaltyEndTime # Remove the penalty timer
|
||||
self.player.moveSpeed *= 2 # Restore normal speed
|
||||
if self.player.currentWeapon:
|
||||
self.player.currentWeapon.attackDuration *= 0.5 # Restore normal attack speed
|
||||
self.player.currentWeapon.attack_duration *= 0.5 # Restore normal attack speed
|
||||
|
||||
# Pass existing player to new level
|
||||
pygame.event.clear()
|
||||
@@ -112,28 +111,32 @@ class WickedQuest:
|
||||
def load_game_menu(self):
|
||||
"""Display load game menu with available saves using instruction_menu"""
|
||||
save_files = self.saveManager.get_save_files()
|
||||
|
||||
|
||||
if not save_files:
|
||||
messagebox("No save files found.")
|
||||
return None
|
||||
|
||||
# Create menu options
|
||||
|
||||
# Create menu options with save info
|
||||
options = []
|
||||
save_infos = []
|
||||
for save_file in save_files:
|
||||
options.append(save_file['display_name'])
|
||||
|
||||
save_info = self.saveManager.get_save_info(save_file)
|
||||
save_infos.append(save_info)
|
||||
display_name = save_info.get("metadata", {}).get("display_name", "Unknown Save")
|
||||
options.append(display_name)
|
||||
|
||||
options.append("Cancel")
|
||||
|
||||
|
||||
# Use instruction_menu for consistent behavior
|
||||
choice = instruction_menu(self.get_sounds(), "Select a save file to load:", *options)
|
||||
|
||||
|
||||
if choice == "Cancel" or choice is None:
|
||||
return None
|
||||
else:
|
||||
# Find the corresponding save file
|
||||
for save_file in save_files:
|
||||
if save_file['display_name'] == choice:
|
||||
return save_file
|
||||
for i, option in enumerate(options[:-1]): # Exclude "Cancel"
|
||||
if option == choice:
|
||||
return save_infos[i]
|
||||
return None
|
||||
|
||||
def auto_save(self):
|
||||
@@ -141,36 +144,167 @@ class WickedQuest:
|
||||
# Don't save in survival mode
|
||||
if hasattr(self, 'currentLevel') and self.currentLevel and self.currentLevel.levelId == 999:
|
||||
return False
|
||||
|
||||
|
||||
if not self.player.can_save():
|
||||
return False
|
||||
|
||||
|
||||
# Spend the bone dust
|
||||
if not self.player.spend_save_bone_dust(200):
|
||||
return False
|
||||
|
||||
# Automatically create save
|
||||
try:
|
||||
success, message = self.saveManager.create_save(
|
||||
self.player,
|
||||
self.currentLevel.levelId,
|
||||
self.gameStartTime,
|
||||
self.currentGame
|
||||
)
|
||||
|
||||
if success:
|
||||
try:
|
||||
if 'save' in self.get_sounds():
|
||||
play_sound(self.get_sounds()['save'])
|
||||
else:
|
||||
print("Save sound not found in sounds dictionary")
|
||||
except Exception as e:
|
||||
print(f"Error playing save sound: {e}")
|
||||
pass # Continue if save sound fails to play
|
||||
else:
|
||||
print(f"Save failed: {message}")
|
||||
|
||||
return success
|
||||
# Create save data structure
|
||||
save_data = {
|
||||
"player_state": self._serialize_player_state(),
|
||||
"game_state": {
|
||||
"currentLevel": self.currentLevel.levelId,
|
||||
"currentGame": self.currentGame,
|
||||
"gameStartTime": self.gameStartTime,
|
||||
},
|
||||
}
|
||||
|
||||
# Create metadata for display
|
||||
metadata = {
|
||||
"display_name": f"{self.currentGame} Level {self.currentLevel.levelId}",
|
||||
"level": self.currentLevel.levelId,
|
||||
"game": self.currentGame
|
||||
}
|
||||
|
||||
save_path = self.saveManager.create_save(save_data, metadata)
|
||||
|
||||
try:
|
||||
if 'save' in self.get_sounds():
|
||||
play_sound(self.get_sounds()['save'])
|
||||
else:
|
||||
print("Save sound not found in sounds dictionary")
|
||||
except Exception as e:
|
||||
print(f"Error playing save sound: {e}")
|
||||
pass # Continue if save sound fails to play
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error during save: {e}")
|
||||
return False
|
||||
|
||||
def _serialize_player_state(self):
|
||||
"""Serialize player state for saving"""
|
||||
return {
|
||||
"xPos": self.player.xPos,
|
||||
"yPos": self.player.yPos,
|
||||
"health": self.player._health,
|
||||
"maxHealth": self.player._maxHealth,
|
||||
"lives": self.player._lives,
|
||||
"coins": self.player._coins,
|
||||
"saveBoneDust": self.player._saveBoneDust,
|
||||
"jackOLanternCount": self.player._jack_o_lantern_count,
|
||||
"shinBoneCount": self.player.shinBoneCount,
|
||||
"inventory": self.player.inventory,
|
||||
"collectedItems": self.player.collectedItems,
|
||||
"weapons": self._serialize_weapons(self.player.weapons),
|
||||
"currentWeaponName": self.player.currentWeapon.name if self.player.currentWeapon else None,
|
||||
"stats": self.player.stats.to_dict(),
|
||||
"scoreboard": self._serialize_scoreboard(self.player.scoreboard),
|
||||
}
|
||||
|
||||
def _serialize_weapons(self, weapons):
|
||||
"""Serialize weapons for saving"""
|
||||
serialized = []
|
||||
for weapon in weapons:
|
||||
serialized.append({
|
||||
"name": weapon.name,
|
||||
"damage": weapon.damage,
|
||||
"range": weapon.range,
|
||||
"attackSound": weapon.attack_sound,
|
||||
"hitSound": weapon.hit_sound,
|
||||
"attackDuration": weapon.attack_duration,
|
||||
"speedBonus": getattr(weapon, "speedBonus", 1.0),
|
||||
"jumpDurationBonus": getattr(weapon, "jumpDurationBonus", 1.0),
|
||||
})
|
||||
return serialized
|
||||
|
||||
def _serialize_scoreboard(self, scoreboard):
|
||||
"""Serialize scoreboard for saving"""
|
||||
return {
|
||||
"currentScore": getattr(scoreboard, "currentScore", 0),
|
||||
"highScores": getattr(scoreboard, "highScores", []),
|
||||
}
|
||||
|
||||
def _restore_player_state(self, player_state):
|
||||
"""Restore player state from save data"""
|
||||
# Restore basic attributes
|
||||
self.player.xPos = player_state["xPos"]
|
||||
self.player.yPos = player_state["yPos"]
|
||||
self.player._health = player_state["health"]
|
||||
self.player._maxHealth = player_state["maxHealth"]
|
||||
self.player._lives = player_state["lives"]
|
||||
self.player._coins = player_state["coins"]
|
||||
self.player._saveBoneDust = player_state["saveBoneDust"]
|
||||
self.player._jack_o_lantern_count = player_state["jackOLanternCount"]
|
||||
self.player.shinBoneCount = player_state["shinBoneCount"]
|
||||
self.player.inventory = player_state["inventory"]
|
||||
self.player.collectedItems = player_state["collectedItems"]
|
||||
|
||||
# Restore weapons
|
||||
self.player.weapons = self._deserialize_weapons(player_state["weapons"])
|
||||
|
||||
# Restore current weapon
|
||||
current_weapon_name = player_state.get("currentWeaponName")
|
||||
if current_weapon_name:
|
||||
for weapon in self.player.weapons:
|
||||
if weapon.name == current_weapon_name:
|
||||
self.player.currentWeapon = weapon
|
||||
break
|
||||
|
||||
# Restore stats
|
||||
if "stats" in player_state:
|
||||
self.player.stats = StatTracker.from_dict(player_state["stats"])
|
||||
else:
|
||||
self.player.stats = StatTracker()
|
||||
|
||||
# Restore scoreboard
|
||||
if "scoreboard" in player_state:
|
||||
self.player.scoreboard = self._deserialize_scoreboard(player_state["scoreboard"])
|
||||
else:
|
||||
self.player.scoreboard = Scoreboard()
|
||||
|
||||
def _deserialize_weapons(self, weapon_data):
|
||||
"""Deserialize weapons from save data"""
|
||||
from src.weapon import Weapon
|
||||
|
||||
weapons = []
|
||||
for data in weapon_data:
|
||||
# Handle backward compatibility for old saves
|
||||
speedBonus = data.get("speedBonus", 1.0)
|
||||
jumpDurationBonus = data.get("jumpDurationBonus", 1.0)
|
||||
|
||||
# For old saves, restore proper bonuses for specific weapons
|
||||
if data["name"] == "witch_broom" and speedBonus == 1.0:
|
||||
speedBonus = 1.17
|
||||
jumpDurationBonus = 1.25
|
||||
|
||||
weapon = Weapon(
|
||||
name=data["name"],
|
||||
damage=data["damage"],
|
||||
range=data["range"],
|
||||
attackSound=data["attackSound"],
|
||||
hitSound=data["hitSound"],
|
||||
attackDuration=data["attackDuration"],
|
||||
speedBonus=speedBonus,
|
||||
jumpDurationBonus=jumpDurationBonus,
|
||||
)
|
||||
weapons.append(weapon)
|
||||
return weapons
|
||||
|
||||
def _deserialize_scoreboard(self, scoreboard_data):
|
||||
"""Deserialize scoreboard from save data"""
|
||||
scoreboard = Scoreboard()
|
||||
if "currentScore" in scoreboard_data:
|
||||
scoreboard.currentScore = scoreboard_data["currentScore"]
|
||||
if "highScores" in scoreboard_data:
|
||||
scoreboard.highScores = scoreboard_data["highScores"]
|
||||
return scoreboard
|
||||
|
||||
def handle_input(self):
|
||||
"""Process keyboard input for player actions."""
|
||||
keys = pygame.key.get_pressed()
|
||||
@@ -257,7 +391,7 @@ class WickedQuest:
|
||||
|
||||
# Handle attack with either CTRL key
|
||||
if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]) and player.start_attack(currentTime):
|
||||
play_sound(self.get_sounds()[player.currentWeapon.attackSound])
|
||||
play_sound(self.get_sounds()[player.currentWeapon.attack_sound])
|
||||
|
||||
# Handle jumping
|
||||
if (keys[pygame.K_w] or keys[pygame.K_UP]) and not player.isJumping:
|
||||
@@ -291,14 +425,14 @@ class WickedQuest:
|
||||
seconds = (timeTaken % 60000) // 1000
|
||||
|
||||
# Update time in stats
|
||||
self.currentLevel.player.stats.update_stat('Total time', timeTaken, levelOnly=True)
|
||||
self.currentLevel.player.stats.set_stat('Total time', timeTaken, level_only=True)
|
||||
|
||||
report = [f"Time taken: {minutes} minutes and {seconds} seconds"]
|
||||
|
||||
# Add all level stats
|
||||
for key in self.currentLevel.player.stats.level:
|
||||
if key != 'Total time': # Skip time since we already displayed it
|
||||
report.append(f"{key}: {self.currentLevel.player.stats.get_level_stat(key)}")
|
||||
report.append(f"{key}: {self.currentLevel.player.stats.get_stat(key)}")
|
||||
|
||||
report.append(f"Score: {int(self.currentLevel.levelScore)}")
|
||||
|
||||
@@ -324,7 +458,7 @@ class WickedQuest:
|
||||
# Add all total stats
|
||||
for key in self.currentLevel.player.stats.total:
|
||||
if key not in ['Total time', 'levelsCompleted']: # Skip these
|
||||
report.append(f"Total {key}: {self.currentLevel.player.stats.get_total_stat(key)}")
|
||||
report.append(f"Total {key}: {self.currentLevel.player.stats.get_stat(key, from_total=True)}")
|
||||
|
||||
report.append(f"Final Score: {self.player.scoreboard.get_score()}")
|
||||
|
||||
@@ -350,7 +484,7 @@ class WickedQuest:
|
||||
# Add all total stats
|
||||
for key in self.currentLevel.player.stats.total:
|
||||
if key not in ['Total time', 'levelsCompleted']: # Skip these
|
||||
report.append(f"Total {key}: {self.currentLevel.player.stats.get_total_stat(key)}")
|
||||
report.append(f"Total {key}: {self.currentLevel.player.stats.get_stat(key, from_total=True)}")
|
||||
|
||||
if self.currentLevel.player.scoreboard.check_high_score():
|
||||
pygame.event.clear()
|
||||
@@ -479,24 +613,25 @@ class WickedQuest:
|
||||
elif choice == "load_game":
|
||||
selected_save = self.load_game_menu()
|
||||
if selected_save:
|
||||
success, save_data = self.saveManager.load_save(selected_save['filepath'])
|
||||
if success:
|
||||
try:
|
||||
save_data, metadata = self.saveManager.load_save(selected_save['filepath'])
|
||||
|
||||
# Load the saved game
|
||||
self.currentGame = save_data['game_state']['currentGame']
|
||||
self.gameStartTime = save_data['game_state']['gameStartTime']
|
||||
current_level = save_data['game_state']['currentLevel']
|
||||
# Initialize pack-specific sound system
|
||||
self.initialize_pack_sounds()
|
||||
|
||||
|
||||
# Load the level
|
||||
if self.load_level(current_level):
|
||||
# Restore player state
|
||||
self.saveManager.restore_player_state(self.player, save_data)
|
||||
self._restore_player_state(save_data['player_state'])
|
||||
self.game_loop(current_level)
|
||||
else:
|
||||
messagebox("Failed to load saved level.")
|
||||
else:
|
||||
messagebox(f"Failed to load save: {save_data}")
|
||||
except Exception as e:
|
||||
messagebox(f"Failed to load save: {e}")
|
||||
elif choice == "play":
|
||||
self.currentGame = select_game(self.get_sounds())
|
||||
if self.currentGame is None:
|
||||
|
||||
Reference in New Issue
Block a user