diff --git a/src/catapult.py b/src/catapult.py index c1fcb64..c538705 100644 --- a/src/catapult.py +++ b/src/catapult.py @@ -152,5 +152,5 @@ class Catapult(Object): pumpkin.stop_sound(self.sounds, player.xPos) pumpkin.isActive = False self.activePumpkins.remove(pumpkin) - if not player.isInvincible: + if not player.isInvincible and not getattr(player, '_godMode', False): self.sounds["player_takes_damage"].play() diff --git a/src/grasping_hands.py b/src/grasping_hands.py index 3891e4e..3eb72a0 100644 --- a/src/grasping_hands.py +++ b/src/grasping_hands.py @@ -114,7 +114,7 @@ class GraspingHands(Object): playerCaught = True if playerCaught: - if not player.isInvincible: + if not player.isInvincible and not getattr(player, '_godMode', False): # Player is caught - instant death # Stop the crumbling sound before death if self.crumbleChannel: diff --git a/src/level.py b/src/level.py index 21d7061..c40e233 100644 --- a/src/level.py +++ b/src/level.py @@ -465,6 +465,7 @@ class Level: distance <= 2 and not self.player.isJumping and not self.player.isInvincible + and not getattr(self.player, '_godMode', False) and currentTime - self.lastWarningTime >= self.warningInterval ): if isinstance(obj, GraveObject) and obj.graveItem and not obj.isCollected: @@ -581,7 +582,7 @@ class Level: obj.channel = None obj.isActive = False # Mark grave as inactive after filling continue - elif not self.player.isInvincible: + elif not self.player.isInvincible and not getattr(self.player, '_godMode', False): # Kill player for normal graves or non-ducking collision play_sound(self.sounds[obj.soundName]) speak("You fell in an open grave! Now, it's yours!") diff --git a/src/player.py b/src/player.py index 7d9b017..b331e10 100644 --- a/src/player.py +++ b/src/player.py @@ -225,6 +225,10 @@ class Player: if self.isInvincible and value < old_health: return + # Check for god mode (prevents all damage) + if hasattr(self, '_godMode') and self._godMode and value < old_health: + return + self._health = max(0, value) # Health can't go below 0 if self._health == 0 and old_health > 0: diff --git a/src/powerup.py b/src/powerup.py index efa9952..d127acf 100644 --- a/src/powerup.py +++ b/src/powerup.py @@ -111,7 +111,7 @@ class PowerUp(Object): player.xPos -= 3 if player.xPos > self.xPos else -3 # Only apply debuffs if not invincible and slowdown is enabled - if not player.isInvincible: + if not player.isInvincible and not getattr(player, '_godMode', False): # Check if slowdown is enabled (default is True) shouldSlowDown = True if hasattr(self, "webObject") and hasattr(self.webObject, "slowdownOverride"): diff --git a/src/skull_storm.py b/src/skull_storm.py index bd935b3..3725ecc 100644 --- a/src/skull_storm.py +++ b/src/skull_storm.py @@ -114,7 +114,7 @@ class SkullStorm(Object): # Check if player was hit if abs(player.xPos - skull["x"]) < 1: # Within 1 tile - if not player.isInvincible: + if not player.isInvincible and not getattr(player, '_godMode', False): player.set_health(player.get_health() - self.damage) self.sounds["player_takes_damage"].play() speak(self.hitMessage) diff --git a/wicked_quest.py b/wicked_quest.py index 3e5ccc2..5094f8f 100755 --- a/wicked_quest.py +++ b/wicked_quest.py @@ -34,6 +34,8 @@ class WickedQuest: self.survivalWave = 1 self.survivalScore = 0 + # Console system - no longer needed since we use get_input directly + def initialize_pack_sounds(self): """Initialize pack-specific sound system after game selection.""" if self.currentGame: @@ -48,6 +50,185 @@ class WickedQuest: self.initialize_pack_sounds() return self.soundSystem if self.soundSystem else self.sounds + def process_console_command(self, command): + """Process console commands and execute their effects.""" + command = command.lower().strip() + + if command == "samhain": + # Level selection menu + self.show_level_select_menu() + elif command == "misfits": + # Give 20 HP (but don't exceed max HP) + if self.player: + currentHealth = self.player.get_health() + maxHealth = self.player.get_max_health() + newHealth = min(currentHealth + 20, maxHealth) + self.player._health = newHealth + speak(f"Health restored to {newHealth}") + if 'heal' in self.get_sounds(): + play_sound(self.get_sounds()['heal']) + elif command == "coffinshakers": + # Give extra life + if self.player: + self.player._lives += 1 + speak(f"Extra life granted. You now have {self.player.get_lives()} lives") + if 'get_extra_life' in self.get_sounds(): + play_sound(self.get_sounds()['get_extra_life']) + elif command == "nekromantix": + # Give 100 bone dust + if self.player: + self.player._boneDust += 100 + speak(f"100 bone dust granted. You now have {self.player.get_coins()} bone dust") + if 'coin' in self.get_sounds(): + play_sound(self.get_sounds()['coin']) + elif command == "calabrese": + # Reveal all enemies on current level + if self.currentLevel and self.currentLevel.enemies: + enemyCount = len([enemy for enemy in self.currentLevel.enemies if enemy.isActive]) + if enemyCount > 0: + speak(f"{enemyCount} enemies remaining on this level") + for enemy in self.currentLevel.enemies: + if enemy.isActive: + distance = abs(enemy.xPos - self.player.xPos) + direction = "right" if enemy.xPos > self.player.xPos else "left" + speak(f"{enemy.enemyType} {distance} units to the {direction}") + else: + speak("No active enemies on this level") + else: + speak("No enemies found") + elif command == "balzac": + # Give 200 bone dust + if self.player: + self.player._boneDust = 200 + speak(f"Bone dust set to 200") + if 'coin' in self.get_sounds(): + play_sound(self.get_sounds()['coin']) + elif command == "blitzkid": + # Grant broom and nunchucks weapons with level pack override support + if self.player: + from src.weapon import Weapon + + # Check if player already has broom + hasBroom = any(weapon.originalName == "witch_broom" for weapon in self.player.weapons) + if not hasBroom: + broomWeapon = Weapon.create_witch_broom() + self.player.add_weapon(broomWeapon) + + # Check if player already has nunchucks + hasNunchucks = any(weapon.originalName == "nunchucks" for weapon in self.player.weapons) + if not hasNunchucks: + nunchucksWeapon = Weapon.create_nunchucks() + self.player.add_weapon(nunchucksWeapon) + + # Report what was granted (using display names with overrides) + grantedWeapons = [] + if not hasBroom: + broomName = next((w.name for w in self.player.weapons if w.originalName == "witch_broom"), "witch broom") + grantedWeapons.append(broomName.replace('_', ' ')) + if not hasNunchucks: + nunchucksName = next((w.name for w in self.player.weapons if w.originalName == "nunchucks"), "nunchucks") + grantedWeapons.append(nunchucksName.replace('_', ' ')) + + if grantedWeapons: + speak(f"Granted {', '.join(grantedWeapons)}") + else: + speak("You already have both weapons") + elif command == "creepshow": + # Toggle god mode (invincibility) + if self.player: + if hasattr(self.player, '_godMode'): + self.player._godMode = not self.player._godMode + else: + self.player._godMode = True + + status = "enabled" if getattr(self.player, '_godMode', False) else "disabled" + speak(f"God mode {status}") + elif command == "diemonsterdie": + # Give 100 jack o'lanterns + if self.player: + self.player._jack_o_lantern_count += 100 + speak(f"100 jack o'lanterns granted. You now have {self.player.get_jack_o_lanterns()} jack o'lanterns") + if 'get_jack_o_lantern' in self.get_sounds(): + play_sound(self.get_sounds()['get_jack_o_lantern']) + elif command == "murderland": + # Set jack o'lanterns to exactly 13 (the special number) + if self.player: + self.player._jack_o_lantern_count = 13 + speak("13 jack o'lanterns, this power courses through my soul.") + if 'get_jack_o_lantern' in self.get_sounds(): + play_sound(self.get_sounds()['get_jack_o_lantern']) + elif command == "koffinkats": + # Spawn a coffin with random item at player's current position + if self.player and self.currentLevel: + from src.coffin import CoffinObject + + # Create coffin at player's current position + coffin = CoffinObject( + int(self.player.xPos), # Use player's current x position + self.player.yPos, # Use player's current y position + self.get_sounds(), + self.currentLevel, + item="random" # Random item + ) + + # Add coffin to the level's object list + self.currentLevel.objects.append(coffin) + + speak("Coffin spawned at your location") + if 'coffin' in self.get_sounds(): + play_sound(self.get_sounds()['coffin']) + else: + speak("Unknown command") + + def show_level_select_menu(self): + """Show menu to select and warp to different levels.""" + if not self.currentGame: + speak("No game loaded") + return + + # Find available levels + availableLevels = [] + levelNumber = 1 + while True: + levelPath = get_level_path(self.currentGame, levelNumber) + if not os.path.exists(levelPath): + break + availableLevels.append(levelNumber) + levelNumber += 1 + + if not availableLevels: + speak("No levels found") + return + + # Create menu options + options = [] + for levelNum in availableLevels: + options.append(f"Level {levelNum}") + options.append("Cancel") + + choice = instruction_menu(self.get_sounds(), "Warp to which level?", *options) + + if choice and choice != "Cancel": + # Extract level number from choice + levelNum = int(choice.split()[-1]) + + # Load the selected level + if self.load_level(levelNum): + speak(f"Warped to level {levelNum}") + else: + speak(f"Failed to load level {levelNum}") + + def open_console(self): + """Open the console for input and process the command.""" + from libstormgames import get_input + + # Get console input using libstormgames text input + command = get_input("Enter console command:") + + # Process the command if user didn't cancel + if command is not None: + self.process_console_command(command) + def load_level(self, levelNumber): """Load a level from its JSON file.""" levelFile = get_level_path(self.currentGame, levelNumber) @@ -384,6 +565,13 @@ class WickedQuest: mods = pygame.key.get_mods() altPressed = mods & pygame.KMOD_ALT + # Console activation with grave accent key - only in story mode + if event.key == pygame.K_BACKQUOTE: # Grave accent key (`) + # Open console (only in story mode, not survival) + if hasattr(self, 'currentLevel') and self.currentLevel and self.currentLevel.levelId != 999: + self.open_console() + continue + if event.key == pygame.K_ESCAPE: # Stop all sounds before exiting (consistent with survival mode) pygame.mixer.stop()