From 2f9630084567a9f43b2c5d3931dada500b48b6e2 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Thu, 13 Feb 2025 13:53:08 -0500 Subject: [PATCH] Ghost enemy added, boss for level 10. Levels updated, probably still not final version, but getting close. --- levels/Wicked Quest/10.json | 26 ++++++-- levels/Wicked Quest/11.json | 10 +-- levels/Wicked Quest/12.json | 8 +-- levels/Wicked Quest/13.json | 28 ++++++++- levels/Wicked Quest/3.json | 9 ++- levels/Wicked Quest/4.json | 79 +++++++++++++++++++----- levels/Wicked Quest/5.json | 14 +++++ levels/Wicked Quest/6.json | 42 ++++++++++--- levels/Wicked Quest/7.json | 2 +- levels/Wicked Quest/8.json | 8 +-- levels/Wicked Quest/9.json | 6 +- sounds/ambience/Dark Dust Dispatcher.ogg | 3 + sounds/ghost.ogg | 3 + sounds/ghost_dies.ogg | 3 + sounds/ghost_is_vulnerable.ogg | 3 + src/enemy.py | 37 +++++++++++ 16 files changed, 227 insertions(+), 54 deletions(-) create mode 100644 sounds/ambience/Dark Dust Dispatcher.ogg create mode 100644 sounds/ghost.ogg create mode 100644 sounds/ghost_dies.ogg create mode 100644 sounds/ghost_is_vulnerable.ogg diff --git a/levels/Wicked Quest/10.json b/levels/Wicked Quest/10.json index c0d35f5..2d256c5 100644 --- a/levels/Wicked Quest/10.json +++ b/levels/Wicked Quest/10.json @@ -2,6 +2,7 @@ "level_id": 10, "name": "Cursed Chapel", "description": "An old chapel looms before you, its stained glass windows glowing with an otherworldly light. The sound of organ music echoes from within, though the chapel has been abandoned for centuries.", + "locked": true, "player_start": { "x": 0, "y": 0 @@ -82,7 +83,7 @@ "x_range": [110, 130], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -144,7 +145,7 @@ "x_range": [200, 220], "y": 0, "enemy_type": "ghoul", - "health": 10, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -171,7 +172,7 @@ "x_range": [240, 260], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -254,11 +255,26 @@ "sound": "coin", "collectible": true, "static": true - } + }, + { + "x_range": [400, 415], + "y": 0, + "enemy_type": "ghost", + "health": 16, + "damage": 2, + "attack_range": 1, + "vulnerability_duration": 2000, + "invulnerability_duration": 5000, + "speed_multiplier": 0.8, + "attack_cooldown": 1200, + "attack_pattern": { + "type": "patrol" + } +} ], "boundaries": { "left": 0, - "right": 400 + "right": 420 }, "ambience": "Choir of Doom.ogg", "footstep_sound": "footstep_stone" diff --git a/levels/Wicked Quest/11.json b/levels/Wicked Quest/11.json index 4a454c2..4d54139 100644 --- a/levels/Wicked Quest/11.json +++ b/levels/Wicked Quest/11.json @@ -36,7 +36,7 @@ "x_range": [30, 45], "y": 0, "enemy_type": "ghoul", - "health": 10, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -104,7 +104,7 @@ "x_range": [120, 135], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -160,7 +160,7 @@ "x_range": [205, 220], "y": 0, "enemy_type": "ghoul", - "health": 10, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -216,7 +216,7 @@ "x_range": [275, 290], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -275,7 +275,7 @@ "x_range": [370, 385], "y": 0, "enemy_type": "witch", - "health": 8, + "health": 6, "damage": 2, "attack_range": 1.5, "attack_pattern": { diff --git a/levels/Wicked Quest/12.json b/levels/Wicked Quest/12.json index e453995..b998dd9 100644 --- a/levels/Wicked Quest/12.json +++ b/levels/Wicked Quest/12.json @@ -44,7 +44,7 @@ "x_range": [75, 85], "y": 0, "enemy_type": "ghoul", - "health": 10, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -123,7 +123,7 @@ "x_range": [185, 195], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -200,7 +200,7 @@ "x_range": [305, 315], "y": 0, "enemy_type": "ghoul", - "health": 10, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -244,7 +244,7 @@ "x_range": [385, 405], "y": 0, "enemy_type": "witch", - "health": 8, + "health": 6, "damage": 2, "attack_range": 1.5, "attack_pattern": { diff --git a/levels/Wicked Quest/13.json b/levels/Wicked Quest/13.json index 9ba3621..f8cbbc6 100644 --- a/levels/Wicked Quest/13.json +++ b/levels/Wicked Quest/13.json @@ -263,7 +263,7 @@ "y": 0, "type": "catapult", "fire_interval": 4000, - "range": 45 + "range": 40 }, { "x": 410, @@ -286,7 +286,7 @@ "y": 15, "type": "skull_storm", "damage": 4, - "maximum_skulls": 4, + "maximum_skulls": 5, "frequency": { "min": 1, "max": 3 @@ -304,7 +304,29 @@ } }, { - "x_range": [405, 495], + "x_range": [425, 445], + "y": 0, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, + "attack_pattern": { + "type": "patrol" + } + }, + { + "x_range": [425, 445], + "y": 0, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, + "attack_pattern": { + "type": "patrol" + } + }, + { + "x_range": [455, 495], "y": 0, "enemy_type": "witch", "health": 50, diff --git a/levels/Wicked Quest/3.json b/levels/Wicked Quest/3.json index c2e1e9c..cf173bc 100644 --- a/levels/Wicked Quest/3.json +++ b/levels/Wicked Quest/3.json @@ -144,7 +144,7 @@ "x_range": [101, 111], "y": 0, "enemy_type": "witch", - "health": 3, + "health": 6, "damage": 2, "attack_range": 1, "attack_pattern": { @@ -195,13 +195,12 @@ { "x_range": [146, 166], "y": 0, - "enemy_type": "ghoul", + "enemy_type": "goblin", "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { - "type": "hunter", - "turn_threshold": 5 + "type": "patrol" } }, { @@ -248,6 +247,6 @@ "left": 0, "right": 200 }, - "ambience": "Wayward Ghouls.ogg", + "ambience": "Dark Dust Dispatcher.ogg", "footstep_sound": "footstep_tall_grass" } diff --git a/levels/Wicked Quest/4.json b/levels/Wicked Quest/4.json index 46111a4..d708da8 100644 --- a/levels/Wicked Quest/4.json +++ b/levels/Wicked Quest/4.json @@ -2,6 +2,7 @@ "level_id": 4, "name": "The Abandoned Church", "description": "The graves led you to a decrepit church. The holy ground offers no sanctuary - if anything, the undead seem stronger here.", + "locked": true, "player_start": { "x": 0, "y": 0 @@ -21,7 +22,18 @@ "type": "coffin" }, { - "x_range": [20, 30], + "x_range": [20, 25], + "y": 0, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, + "attack_pattern": { + "type": "patrol" + } + }, + { + "x_range": [25, 30], "y": 0, "enemy_type": "goblin", "health": 4, @@ -122,15 +134,11 @@ "type": "coffin" }, { - "x_range": [120, 130], - "y": 0, - "enemy_type": "ghoul", - "health": 6, - "damage": 2, - "attack_range": 1.5, - "attack_pattern": { - "type": "patrol" - } + "x_range": [115, 118], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true }, { "x": 135, @@ -147,6 +155,13 @@ "collectible": true, "static": true }, + { + "x_range": [155, 160], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, { "x_range": [150, 170], "y": 12, @@ -168,13 +183,12 @@ { "x_range": [175, 185], "y": 0, - "enemy_type": "ghoul", - "health": 6, + "enemy_type": "goblin", + "health": 4, "damage": 2, - "attack_range": 1.5, + "attack_range": 1, "attack_pattern": { - "type": "hunter", - "turn_threshold": 6 + "type": "patrol" } }, { @@ -197,11 +211,44 @@ "y": 3, "sound": "coffin", "type": "coffin" + }, + { + "x_range": [200, 207], + "y": 0, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, + "attack_pattern": { + "type": "patrol" + } + }, + { + "x_range": [208, 215], + "y": 0, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, + "attack_pattern": { + "type": "patrol" + } + }, + { + "x_range": [200, 215], + "y": 0, + "enemy_type": "ghoul", + "health": 6, + "damage": 2, + "attack_range": 1.5, + "attack_pattern": { + "type": "patrol" + } } ], "boundaries": { "left": 0, - "right": 200 + "right": 220 }, "ambience": "Choir of Doom.ogg", "footstep_sound": "footstep_stone" diff --git a/levels/Wicked Quest/5.json b/levels/Wicked Quest/5.json index 380543a..9bb2573 100644 --- a/levels/Wicked Quest/5.json +++ b/levels/Wicked Quest/5.json @@ -22,6 +22,13 @@ "static": true, "zombie_spawn_chance": 15 }, + { + "x_range": [15, 20], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, { "x_range": [20, 35], "y": 0, @@ -128,6 +135,13 @@ "turn_threshold": 5 } }, + { + "x_range": [130, 135], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, { "x": 140, "y": 3, diff --git a/levels/Wicked Quest/6.json b/levels/Wicked Quest/6.json index 2ca0051..603ddfb 100644 --- a/levels/Wicked Quest/6.json +++ b/levels/Wicked Quest/6.json @@ -2,6 +2,7 @@ "level_id": 6, "name": "The Webbed Crypts", "description": "The catacombs open into ancient crypts, their passages choked with massive cobwebs. Something skitters in the darkness above.", + "locked": true, "player_start": { "x": 0, "y": 0 @@ -31,6 +32,13 @@ "turn_threshold": 4 } }, + { + "x_range": [25, 30], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, { "x": 30, "y": 3, @@ -73,13 +81,12 @@ { "x_range": [70, 85], "y": 0, - "enemy_type": "boogie_man", - "health": 8, - "damage": 3, - "attack_range": 2, + "enemy_type": "goblin", + "health": 4, + "damage": 2, + "attack_range": 1, "attack_pattern": { - "type": "hunter", - "turn_threshold": 4 + "type": "patrol" } }, { @@ -127,6 +134,13 @@ "collectible": true, "static": true }, + { + "x_range": [140, 145], + "y": 3, + "sound": "coin", + "collectible": true, + "static": true + }, { "x_range": [130, 145], "y": 0, @@ -149,7 +163,7 @@ "x_range": [160, 180], "y": 0, "enemy_type": "ghoul", - "health": 8, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -184,11 +198,23 @@ "sound": "coffin", "type": "coffin", "item": "extra_life" + }, + { + "x_range": [200, 215], + "y": 0, + "enemy_type": "boogie_man", + "health": 8, + "damage": 3, + "attack_range": 2, + "attack_pattern": { + "type": "hunter", + "turn_threshold": 4 + } } ], "boundaries": { "left": 0, - "right": 200 + "right": 220 }, "ambience": "Escaping the Grave.ogg", "footstep_sound": "footstep_tall_grass" diff --git a/levels/Wicked Quest/7.json b/levels/Wicked Quest/7.json index 6bdd2f0..c51a0a0 100644 --- a/levels/Wicked Quest/7.json +++ b/levels/Wicked Quest/7.json @@ -245,7 +245,7 @@ "x_range": [230, 245], "y": 0, "enemy_type": "ghoul", - "health": 12, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { diff --git a/levels/Wicked Quest/8.json b/levels/Wicked Quest/8.json index a00c0bd..fd0c464 100644 --- a/levels/Wicked Quest/8.json +++ b/levels/Wicked Quest/8.json @@ -25,7 +25,7 @@ "x_range": [20, 40], "y": 0, "enemy_type": "ghoul", - "health": 8, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -77,7 +77,7 @@ "x_range": [90, 110], "y": 0, "enemy_type": "ghoul", - "health": 8, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -134,7 +134,7 @@ "x_range": [155, 175], "y": 0, "enemy_type": "ghoul", - "health": 8, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -161,7 +161,7 @@ "x_range": [200, 220], "y": 0, "enemy_type": "ghoul", - "health": 8, + "health": 6, "damage": 3, "attack_range": 2, "attack_pattern": { diff --git a/levels/Wicked Quest/9.json b/levels/Wicked Quest/9.json index 031b482..2393f40 100644 --- a/levels/Wicked Quest/9.json +++ b/levels/Wicked Quest/9.json @@ -23,7 +23,7 @@ "x_range": [25, 45], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -144,7 +144,7 @@ "x_range": [210, 230], "y": 0, "enemy_type": "boogie_man", - "health": 10, + "health": 8, "damage": 3, "attack_range": 2, "attack_pattern": { @@ -227,7 +227,7 @@ "x_range": [340, 360], "y": 0, "enemy_type": "witch", - "health": 8, + "health": 6, "damage": 2, "attack_range": 1.5, "attack_pattern": { diff --git a/sounds/ambience/Dark Dust Dispatcher.ogg b/sounds/ambience/Dark Dust Dispatcher.ogg new file mode 100644 index 0000000..33ebe2c --- /dev/null +++ b/sounds/ambience/Dark Dust Dispatcher.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57f3b3683b0c00d8b4d664cd2bc2f5131ea378346843870e4099df636b0f0ad7 +size 2256566 diff --git a/sounds/ghost.ogg b/sounds/ghost.ogg new file mode 100644 index 0000000..21163bd --- /dev/null +++ b/sounds/ghost.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:145e4e839c83c4ac9dd1d19e27727ad0843b0653c7a53f95eae0aad8d8292c27 +size 35433 diff --git a/sounds/ghost_dies.ogg b/sounds/ghost_dies.ogg new file mode 100644 index 0000000..4687cee --- /dev/null +++ b/sounds/ghost_dies.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a501b05a9298bcf843367b90f29d7857135f396fb93d39bca68716ea017fe5d6 +size 31992 diff --git a/sounds/ghost_is_vulnerable.ogg b/sounds/ghost_is_vulnerable.ogg new file mode 100644 index 0000000..eb69ef7 --- /dev/null +++ b/sounds/ghost_is_vulnerable.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a67e40aa68bf1a7ed7f1c7af1ecff95882f0cee1b90b1b7eb74b1883590d1f4b +size 11346 diff --git a/src/enemy.py b/src/enemy.py index ab4bb6f..8849448 100644 --- a/src/enemy.py +++ b/src/enemy.py @@ -43,6 +43,20 @@ class Enemy(Object): self.damage = level.player.get_max_health() # Instant death self.health = 1 # Easy to kill self.attackCooldown = 1500 # Slower attack rate + elif enemyType == "ghost": + self.isVulnerable = False + self.vulnerabilityTimer = 0 + self.vulnerabilityDuration = kwargs.get('vulnerability_duration', 3000) # Default 3 seconds + self.invulnerabilityDuration = kwargs.get('invulnerability_duration', 5000) # Default 5 seconds + self.movementSpeed *= kwargs.get('speed_multiplier', 0.8) # Default 80% speed + self.health = kwargs.get('health', 3) # Default 3 HP + self.damage = kwargs.get('damage', 2) # Default 2 damage + self.attackRange = kwargs.get('attack_range', 1) # Use provided or default 1 + self.attackCooldown = kwargs.get('attack_cooldown', 1200) # Default 1.2 seconds + self.attackPattern = kwargs.get('attack_pattern', { + 'type': 'hunter', + 'turn_threshold': 2 + }) elif enemyType == "spider": speedMultiplier = kwargs.get('speed_multiplier', 2.0) self.movementSpeed *= speedMultiplier # Spiders are faster @@ -76,6 +90,25 @@ class Enemy(Object): if not self.isActive or self.health <= 0: return + # Ghost vulnerability state management + if self.enemyType == "ghost": + if self.isVulnerable and (currentTime - self.vulnerabilityTimer > self.vulnerabilityDuration): + # Switch to invulnerable + self.isVulnerable = False + self.vulnerabilityTimer = currentTime + # Change sound back to base ghost sound + if self.channel: + obj_stop(self.channel) + self.channel = obj_play(self.sounds, "ghost", player.xPos, self.xPos) + elif not self.isVulnerable and (currentTime - self.vulnerabilityTimer > self.invulnerabilityDuration): + # Switch to vulnerable + self.isVulnerable = True + self.vulnerabilityTimer = currentTime + # Change to vulnerable sound + if self.channel: + obj_stop(self.channel) + self.channel = obj_play(self.sounds, "ghost_is_vulnerable", player.xPos, self.xPos) + # Check if player has entered territory if not self.hunting: if self.patrolStart <= player.xPos <= self.patrolEnd: @@ -142,6 +175,10 @@ class Enemy(Object): def take_damage(self, amount): """Handle enemy taking damage""" + # Ghost can only take damage when vulnerable + if self.enemyType == "ghost" and not self.isVulnerable: + return + self.health -= amount if self.health <= 0: self.die()