From cf3f27d9b851f16740c8f16a4848e00a8eee4c3f Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 7 Sep 2025 12:11:52 -0400 Subject: [PATCH] Add ability to switch weapons with number keys. --- files/instructions.txt | 17 +++++++++++++++++ src/__init__.py | 1 + src/catapult.py | 1 + src/coffin.py | 1 + src/enemy.py | 1 + src/game_selection.py | 1 + src/grasping_hands.py | 1 + src/grave.py | 1 + src/item_types.py | 1 + src/level.py | 1 + src/object.py | 1 + src/player.py | 23 +++++++++++++++++++++++ src/powerup.py | 1 + src/projectile.py | 1 + src/save_manager.py | 1 + src/skull_storm.py | 1 + src/stat_tracker.py | 1 + src/survival_generator.py | 1 + src/weapon.py | 1 + wicked_quest.py | 16 ++++++++++++++++ 20 files changed, 73 insertions(+) diff --git a/files/instructions.txt b/files/instructions.txt index afd5f17..53a9062 100644 --- a/files/instructions.txt +++ b/files/instructions.txt @@ -19,6 +19,9 @@ tab or capslock: Toggle run lock. Control: Attack. Space or shift: Hold to run if runlock is disabled. If run lock is enabled, hold to walk. f, z, or /: Throw jack O'lantern. +1: Switch to rusty shovel (if available). +2: Switch to witch's broom (if available). +3: Switch to nunchucks (if available). c: Check bone dust. e: Check currently wielded weapon. h: Check health. @@ -41,8 +44,22 @@ Spider webs can be passed by ducking as you move by them. If you hit a spiderweb, a spider spawns, and you are slowed for 15 seconds. If you are invincible, you are not slowed, but the spider still appears. Running and jumping both move you at 1.5 your normal speed. Items bounce away from you when they are freed from the coffin. You must jump to catch them when they are in range. +You can switch between weapons you've collected using the number keys (1, 2, 3). This allows strategic combat - use different weapons for different situations based on their damage, range, and speed. The game automatically saves your progress when you have collected 200 bone dust. You will hear a message saying the game has been saved, and a wolf will howl. To load a game, use the load option in the main menu. Load only appears if you have saved games. The first save should happen around level 6. +Game Modes + +Story Mode: Traditional level-by-level progression through predefined stages. Your progress is saved, and you can collect extra lives by gathering bone dust. + +Survival Mode: An endless challenge where you face wave after wave of increasingly difficult enemies. Each wave gets progressively harder with stronger enemies, faster spawn rates, and longer levels. In survival mode: +- No saving or loading - each run is a fresh start +- No extra lives are awarded - you rely on your starting lives only +- All enemies use aggressive "hunter" behavior instead of patrol patterns +- Each wave must be completed by defeating all enemies before you can advance +- Bone dust still provides health bonuses but gives bonus score instead of extra lives +- All coffin contents are randomized to ensure fair gameplay +- A detailed statistics report shows your performance at the end of each run + Enemies Goblin: Walks back and forth in his area trying to break your bones. diff --git a/src/__init__.py b/src/__init__.py index 8b13789..139597f 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1,2 @@ + diff --git a/src/catapult.py b/src/catapult.py index d0ae2ab..8966db1 100644 --- a/src/catapult.py +++ b/src/catapult.py @@ -142,3 +142,4 @@ class Catapult(Object): if not player.isInvincible: self.sounds['player_takes_damage'].play() + diff --git a/src/coffin.py b/src/coffin.py index 9137ec4..08ebe74 100644 --- a/src/coffin.py +++ b/src/coffin.py @@ -66,3 +66,4 @@ class CoffinObject(Object): return True return False + diff --git a/src/enemy.py b/src/enemy.py index 6d6cc55..3262b07 100644 --- a/src/enemy.py +++ b/src/enemy.py @@ -289,3 +289,4 @@ class Enemy(Object): # Update stats self.level.player.stats.update_stat('Enemies killed', 1) + diff --git a/src/game_selection.py b/src/game_selection.py index 2dcc4a8..5fa829d 100644 --- a/src/game_selection.py +++ b/src/game_selection.py @@ -93,3 +93,4 @@ def get_level_path(gameDir, levelNum): level_path = os.path.join(base_path, "levels", gameDir, f"{levelNum}.json") return level_path + diff --git a/src/grasping_hands.py b/src/grasping_hands.py index a899fda..3b8a753 100644 --- a/src/grasping_hands.py +++ b/src/grasping_hands.py @@ -126,3 +126,4 @@ class GraspingHands(Object): obj_stop(self.crumbleChannel) self.crumbleChannel = None + diff --git a/src/grave.py b/src/grave.py index 225f6de..2f24d16 100644 --- a/src/grave.py +++ b/src/grave.py @@ -35,3 +35,4 @@ class GraveObject(Object): return False + diff --git a/src/item_types.py b/src/item_types.py index 0eebd98..ca7fa0e 100644 --- a/src/item_types.py +++ b/src/item_types.py @@ -56,3 +56,4 @@ class ItemProperties: return item_type return None + diff --git a/src/level.py b/src/level.py index 3a88210..322a59f 100644 --- a/src/level.py +++ b/src/level.py @@ -503,3 +503,4 @@ class Level: # Play throw sound play_sound(self.sounds['throw_jack_o_lantern']) + diff --git a/src/object.py b/src/object.py index 01fbe0b..b99e992 100644 --- a/src/object.py +++ b/src/object.py @@ -38,3 +38,4 @@ class Object: obj_stop(self.channel) self.channel = None + diff --git a/src/player.py b/src/player.py index bdfc2d2..9ef4da1 100644 --- a/src/player.py +++ b/src/player.py @@ -253,6 +253,28 @@ class Player: if weapon in self.weapons: self.currentWeapon = weapon + def switch_to_weapon(self, weaponIndex): + """Switch to weapon by index (1=shovel, 2=broom, 3=nunchucks)""" + weaponMap = { + 1: "rusty_shovel", + 2: "witch_broom", + 3: "nunchucks" + } + + targetWeaponName = weaponMap.get(weaponIndex) + if not targetWeaponName: + return False + + # Find the weapon in player's inventory + for weapon in self.weapons: + if weapon.name == targetWeaponName: + self.equip_weapon(weapon) + speak(f"Switched to {weapon.name.replace('_', ' ')}") + return True + + # Weapon not found in inventory + return False + def add_item(self, item): """Add an item to inventory""" self.inventory.append(item) @@ -272,3 +294,4 @@ class Player: return None return self.currentWeapon.get_attack_range(self.xPos, self.facingRight) + diff --git a/src/powerup.py b/src/powerup.py index ef2a2e6..185d2e1 100644 --- a/src/powerup.py +++ b/src/powerup.py @@ -129,3 +129,4 @@ class PowerUp(Object): play_sound(self.sounds['get_nunchucks']) player.stats.update_stat('Items collected', 1) + diff --git a/src/projectile.py b/src/projectile.py index 1314510..e4abfd8 100644 --- a/src/projectile.py +++ b/src/projectile.py @@ -30,3 +30,4 @@ class Projectile: enemy.take_damage(self.damage) self.isActive = False # Projectile is destroyed on hit + diff --git a/src/save_manager.py b/src/save_manager.py index d3d2a16..a8fd17c 100644 --- a/src/save_manager.py +++ b/src/save_manager.py @@ -291,3 +291,4 @@ class SaveManager: def has_saves(self): """Check if any save files exist""" return len(self.get_save_files()) > 0 + diff --git a/src/skull_storm.py b/src/skull_storm.py index dd3646c..0d0dcd1 100644 --- a/src/skull_storm.py +++ b/src/skull_storm.py @@ -119,3 +119,4 @@ class SkullStorm(Object): self.sounds['player_takes_damage'].play() speak("Hit by falling skull!") + diff --git a/src/stat_tracker.py b/src/stat_tracker.py index a788271..2b07e62 100644 --- a/src/stat_tracker.py +++ b/src/stat_tracker.py @@ -43,3 +43,4 @@ class StatTracker: """Get a total stat""" return self.total.get(statName, 0) + diff --git a/src/survival_generator.py b/src/survival_generator.py index 1c0f6ba..f166869 100644 --- a/src/survival_generator.py +++ b/src/survival_generator.py @@ -244,3 +244,4 @@ class SurvivalGenerator: obj['x'] = xPos return obj + diff --git a/src/weapon.py b/src/weapon.py index eff9a51..09464fb 100644 --- a/src/weapon.py +++ b/src/weapon.py @@ -70,3 +70,4 @@ class Weapon: return True return False + diff --git a/wicked_quest.py b/wicked_quest.py index 106a01b..1091f0a 100755 --- a/wicked_quest.py +++ b/wicked_quest.py @@ -21,6 +21,8 @@ class WickedQuest: self.gameStartTime = None self.lastThrowTime = 0 self.throwDelay = 250 + self.lastWeaponSwitchTime = 0 + self.weaponSwitchDelay = 200 self.player = None self.currentGame = None self.runLock = False # Toggle behavior of the run keys @@ -216,6 +218,19 @@ class WickedQuest: if keys[pygame.K_e]: speak(f"Wielding {self.currentLevel.player.currentWeapon.name.replace('_', ' ')}") + # Weapon switching (1=shovel, 2=broom, 3=nunchucks) + currentTime = pygame.time.get_ticks() + if currentTime - self.lastWeaponSwitchTime >= self.weaponSwitchDelay: + if keys[pygame.K_1]: + if player.switch_to_weapon(1): + self.lastWeaponSwitchTime = currentTime + elif keys[pygame.K_2]: + if player.switch_to_weapon(2): + self.lastWeaponSwitchTime = currentTime + elif keys[pygame.K_3]: + if player.switch_to_weapon(3): + self.lastWeaponSwitchTime = currentTime + # Handle attack with either CTRL key if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]) and player.start_attack(currentTime): play_sound(self.sounds[player.currentWeapon.attackSound]) @@ -612,3 +627,4 @@ if __name__ == "__main__": game = WickedQuest() game.run() +