Boss encounters: vampire-hunter arena fights#22
Open
partouf wants to merge 22 commits into
Open
Conversation
Every level now ends in a fixed 12x12 boss arena (top chunk band, marked with a new 'B' BossSpawn tile). The boss is a vampire hunter that reuses a human prefab body but swaps in a ranged, keep-distance brain: it self-heals, holds ~3 tiles away, and fires telegraphed volleys of arrows. A red warning overlay flashes on the target line, then a projectile deals heavy damage on hit. The boss is defeated by draining it (GetResistance keeps the player on the melee-drain path until the pool empties). Defeat seals-then-opens the level exit and unlocks the Recruit Ghoul ability. - Boss/BossAttackController/BossProjectile: boss brain, telegraph, projectiles - Human: GetResistance/LoseBlood made virtual; AI extracted into Brain() - ConstructionTypes/ChunkPresets/Map: BossSpawn tile + forced arena template - LevelConstruction/SceneManager: spawn boss, lock exit, reward on defeat - MapExit: respect sealed exit Arena is kept fully passable: MapTest probes the map edges at mid-height, which lands on the arena's bottom row at level 1, so edge walls there would hang generation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The boss AI moved toward the player from level load, so it walked down out of the top arena band and met the player mid-city (~8 tiles in) instead of guarding the end of the level. Now the boss stays idle at its spawn until the player steps into the arena band (tracked via ArenaMinY, set to the top 12-row band), then engages. Its movement is clamped so it never descends below the arena, and it holds fire until the fight has begun. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The arena was overwriting the top 12-row city band, so the playable city shrank by half (level 1 became 12 city rows instead of 24). Now the arena is an ADDITIVE extra band: total height = (level+1)*12 city + 12 arena. Level 1 is 24 city rows + 12 arena = 36 total, exit above everything. - LevelConstruction: cityHeight vs total height; humans/items/difficulty keyed to cityHeight so the sealed arena stays clean and difficulty is unchanged - ChunkPresets: arena is now enclosed (walls + central entrance/exit gap); safe because the mid-height traversability probe now lands in the city - boss ArenaMinY = cityHeight Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The boss could fire while walking away to keep its distance, and shots came out regardless of which way it faced. Now the attack only begins when the boss is engaged and standing still; at that point it turns to face the player (sets facing to the shot direction) and holds position for the whole telegraph + shot via a new IsAttacking flag that suppresses movement. Once the shot is loosed it resumes repositioning. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The boss was only clamped at the arena's bottom edge, so when it chased the player upward it walked straight through the centre exit gap and off the top of the map. Added ArenaMaxY (top row of the arena band) and clamp upward movement to it, matching the existing bottom clamp. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The keep-distance AI made the boss back away from the player, and with the arena clamps it just parked itself in the top exit gap. Replaced it with a random wander within the arena band: mostly random 4-directional steps, with an occasional step toward the player when it has drifted far away so it does not corner itself. It never deliberately retreats. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pure random wander felt aimless. The boss now holds each spot for a randomized dwell (0.8-2.0s) then takes a single step; most steps hunt the player on the dominant axis so it presses the attack, with an occasional random step to stay unpredictable. Combined with the aim-and-plant shooting, it reads as actively trying to corner and kill the player. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two bugs made attacks miss a target that was mid-step even when it visually overlapped the player: - the player bailed out entirely (`if (sheep.isMoving) return;`) when the target was moving - target detection was a zero-length raycast at the tile centre, which whiffs while a target's collider is sliding between tiles Replaced combat target detection with a movement-aware grid lookup (GetAttackTargetAt): a target counts if the tile ahead matches either the tile it is stepping from or to, so melee connects anywhere along its step. The lookup also covers the boss, which isn't in the humans list. Added MovingObject.GetDestinationPosition to expose the step's destination tile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unity 6 deprecated these. Use FindObjectsByType(FindObjectsSortMode.None) where order is irrelevant (destroying all AbilityUI instances) and FindFirstObjectByType for the single-instance lookups (Canvas, AbilityIconSet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At 6 damage an arrow took 60% of the player's starting 10 bloodfill and two hits was a game over before feeding. 3 keeps it threatening but survivable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The from-or-to occupancy check counted a mover's origin tile as occupied for the whole step, so you could still hit the boss on the tile it had almost fully left (e.g. both moving up, you stepping into where it just stood). Now a mover occupies the single tile its interpolated position rounds to: melee connects once it is at least halfway onto a tile and stops on a tile it has mostly vacated. Removed the now-unused GetDestinationPosition accessor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the player enters the arena, play a scripted intro before the fight: - lock player input (GameInput.Locked) while leaving Confirm live for dialogue - pan the camera up to frame the arena (SceneManager owns the camera during the cutscene; normal follow resumes after) - the boss is no longer pre-placed; it spawns at the exit and walks in (Boss.InIntro) to just above the arena centre - show the boss's line in a code-generated dialogue box (BossDialogUI), advanced with Confirm - Boss.BeginFight() then engages the normal hunt brain + attacks, camera pans back to the player, input unlocks SpawnBoss refactored to SpawnBossAt (returns the boss) + SpawnBossForIntro. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The area-denial volley could hit a point-blank player. Now it has a melee blind spot: tiles within MeleeRange (1) of the boss are not telegraphed, and the arrow only arms past that distance, so it flies harmlessly over a player standing in the boss's melee range. Closing to drain the boss is now safe from arrows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
IntroTargetY now uses the recorded 'B' tile position instead of a computed mid-arena value, so the arena template controls where the boss ends up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce BossDefinition (name, dialogue, arena template, and combat/attack tuning) and BossRoster, which picks a random boss for the level from a list (currently a level-1 roster: Vampire Hunter, Zealous Priest, Old Stalker). The chosen definition drives everything: its arena template feeds map generation (ChunkTemplates.BuildArena from supplied rows), its stats configure the Boss body and BossAttackController, and its lines drive the intro dialogue. Add or tweak encounters by editing data, no logic changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A church's holy aura (HolyAura on ChurchH) at the arena entrance could burn the player to death during the boss intro, because the player is frozen and can't step out of it. Burn and ReceivePunch now no-op while GameInput.Locked, so no aura, sun, or attack can kill a player who has no way to react. Normal damage resumes as soon as control returns. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The boss used a random human body every run. BossDefinition now has a BodyPrefab name, resolved against BloodPrefabs by GameObject name (falling back to random if unset/not found), so each roster entry gets a consistent look (Vampire Hunter=Human1, Zealous Priest=Human2, Old Stalker=Human3). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boss bodies now resolve against a dedicated inspector-assigned BossPrefabs array first, then fall back to the civilian BloodPrefabs, then random. Keeps boss art out of the civilian pool while still working before BossPrefabs is populated (the current Human1/2/3 names resolve via the BloodPrefabs fallback). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Human5 was moved into the dedicated BossPrefabs array, so the roster now references it for all three level-1 bosses (they share the one boss body until more boss prefabs are added). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds boss encounters (GitHub issue #16). Every level ends in a boss arena where a vampire hunter fights the player with telegraphed ranged attacks; defeating it unlocks the Recruit Ghoul ability and opens the exit.
What's in it
Arena
(level+1)*12city + 12 arena) — the city is never shortened. Enclosed layout with a central entrance/exit gap; humans and items stay in the city.The boss (
Boss : Human)Area-denial attack (
BossAttackController+BossProjectile)Intro cutscene (
SceneManager.BossIntroRoutine)BossDialogUI, advance with Confirm), then the fight begins and the camera returns.Also
FindObjectOfType/FindObjectsOfTypecalls.docs/mechanics.md.Notes
🤖 Generated with Claude Code