Skip to content

Tier 4: boss zombies, buildables, perma-perks, easter-egg quest framework#170

Open
ikbenignace wants to merge 30 commits into
TheTurkeyDev:masterfrom
ikbenignace:feat/bo2-tier4
Open

Tier 4: boss zombies, buildables, perma-perks, easter-egg quest framework#170
ikbenignace wants to merge 30 commits into
TheTurkeyDev:masterfrom
ikbenignace:feat/bo2-tier4

Conversation

@ikbenignace

Copy link
Copy Markdown
Contributor

Tier 4 — big systems (final tier)

Last tier of the BO2 fidelity effort: the large/foundational systems. Each is a contained, config-driven, documented system; approximations are flagged in-code.

Stacking: builds on #169 (Tier 3) → #168#167#166#165/#164. Merge in order; diff reduces to just the Tier 4 commits once parents land.

What's in this PR

  • Boss zombies — new BOSS round type (config bossRoundEveryX, default off). George Romero (tanky glowing zombie, drops Max Ammo + random perk on death) and Brutus (armored brute that temporarily disables a hit player's perk). Alternate by boss-round index; boss rounds take precedence over dog rounds.
  • Buildables — parts→assembly-station framework (Buildable + BuildableManager + BuildableSign), persisted per arena. Concrete buildable: a Zombie Shield (buy parts at the station, assemble, then it absorbs zombie melee for N hits).
  • Perma-perks — progression persisted in playerdata.json: lifetime revives unlock Perma Jugg (lite) and Perma Quick Revive (lite), auto-applied on game entry.
  • Easter-egg quest framework — generic per-arena multi-step objective engine (Quest/QuestStep/QuestManager + QuestSign) with INTERACT and REACH_ROUND triggers and a completion reward. Map-specific eggs are authored via arenas.json + quest signs.

Testing

Pure logic extracted into testable statics and covered by the JUnit harness (133 tests green, JDK 21 / target 17): boss-round cadence + boss health, buildable completion, perma-perk unlock gate, quest step-matching + advance flow. These are large Bukkit-glue systems — compile-verified throughout; in-game playtest strongly recommended before merge, especially bosses (custom AI), buildables (item/shield handling), and the quest engine (arena authoring).

Approximation notes (documented in-code)

  • George is killable here (canonically electric-stun-only) so boss rounds can end.
  • Brutus perk-disable is a reversible remove+re-grant, not a greyed icon.
  • Quest progress is per-game (only the definition persists); single linear track.

🤖 Generated with Claude Code

Ignace Mella and others added 30 commits June 26, 2026 14:19
…spawn selection, thread-safety)

Cherry-picks/finishes three items from skbeh's PR TheTurkeyDev#155 that were not yet on
master:

* Shift-to-repair barriers (resolves TheTurkeyDev#97): new BarrierRepairListener lets a
  player repair a nearby barrier by holding sneak, alongside the existing
  sign-break repair. Reimplements the PR's listener with a corrected detection
  box - the PR left a "// TODO: incorrect subtract" on its asymmetric bounding
  box; this uses a symmetric cuboid centred on the repair sign.
* Rewrite SpawnManager.getNearestPoints: replaces the manual insertion-sort
  over a parallel POSITIVE_INFINITY distance list with a
  stream/distanceSquared/limit. Extracted to a package-private static for
  testing.
* Thread-safety: activeActions and isEditingASign are now ConcurrentHashMap.
  AsyncPlayerChatEvent reads them off the async chat thread while the main
  thread mutates them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrate from the 20 per-version NMS modules (topping out at an untested
1.21.5) to a single build that runs on Minecraft 26.2 (Java 25 server):

- Build against spigot-api 26.2, targeting Java 17 bytecode (26.2's API is
  Java 17; Java 25 is only needed to run the server). Drop the unused
  server jar and add jsr305 (26.2 no longer ships javax.annotation).
- Replace the 20 NMS support modules with one pure-Bukkit NMSUtil_Modern
  (Lidded + Player#sendBlockDamage). Keep the INMSUtil seam and version
  dispatch so older versions can be re-added later as a module + a case.
- Fix enum/registry renames surfaced by compiling against 26.2:
  Attribute.GENERIC_* -> *, PotionEffectType.SLOW -> SLOWNESS,
  Particle REDSTONE/SPELL_WITCH/CRIT_MAGIC/SMOKE_NORMAL/FIREWORKS_SPARK ->
  DUST/WITCH/ENCHANTED_HIT/SMOKE/FIREWORK, EntityType.FIREWORK ->
  FIREWORK_ROCKET, GameRule.DO_DAYLIGHT_CYCLE -> ADVANCE_TIME.
- Route config-driven Sound/Material lookups through a new Compat helper
  (graceful fallback + warning instead of crashing on a stale name).
- Bump plugin.yml api-version to 1.21.

Fix a ClassCastException that corrupted game state:

Door.closeDoor cast a block to Sign without checking. A wall sign mounted
on a door block pops off when the door opens (block -> air), so closeDoor
threw inside endGame and aborted the entire game-end cleanup, leaving the
player "still in game" with broken teleport-back and rejoin state.

- Door.closeDoor: guard the cast and recreate the sign if it popped off.
- Game.endGame: isolate each door's close so one failure cannot abort the
  rest of the cleanup.
- Guard the remaining unguarded (Sign) casts in SignManager (runs on a
  repeating task) and PlayerChatListener.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 0a: two-phase zombie HP curve (linear to r9, x1.1 compounding after) in
  RoundSpawner.zombieHealth(), wired into both spawners. TDD'd.
- Config foundation: expose every BO2 tunable in config.yml + ConfigSetup
  (board scaling, attack cooldown, kill bonuses, perk rewire multipliers,
  knife round, dog scaling, power-up cap/refresh, PaP re-pack, teleporter).
- Default tweaks: zombieDamage 9->10 (2-hit down), healTime 5->2.5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lat knife

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d, roster+kits

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…efill

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zombies that make no progress for zombieStuckSeconds (default 6) are
teleported to the door-open spawn point nearest the targeted player so
they can resume pathing. Fixes the common "1 zombie left wedged on
geometry" round hang. Pure accumulator SpawnManager.updateStuckTicks is
TDD-covered; both thresholds are config-exposed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ade cap

- Deadshot Daiquiri: perk-gated extra headshot damage multiplier (config).
- Bonus Points power-up: flat points to every player (config, double-points aware).
- Random Perk Bottle power-up: grants a random perk via the Wunderfizz path.
- Grenade/equipment buy-to-cap now config-driven (maxGrenades).
- Fix pre-existing Nuke bug: points were awarded to the picker, not each player.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ption

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Death Machine: temporary minigun for deathMachineDurationSeconds, saves and
  restores the displaced weapon/slot on expiry.
- Bonfire Sale: Fire Sale + global temporary Pack-a-Punch cost override
  (bonfirePaPCost, default 1000) via Game.effectivePaPCost; reset on game reset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… effects

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uildable

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gine)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Server owners can fully disable perma-perks: when false no revive progress is
tracked and no perma-perk effect is applied at game entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Doors stored only Material per block, so closing a door restored fences,
panes, walls and stairs without their connection/shape state (fences rendered
connection arms into air) and recreated price signs as a default wall sign
facing the wrong way. Now the full BlockData is persisted and restored exactly
(no physics, so connections match what was authored), and door signs save +
restore their facing before the [Zombies]/Door text is re-applied. Backward
compatible: legacy saves with only "material" fall back to the old path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Tier 2 last-zombie crawler used 0.35x speed + Slowness IV, leaving it
effectively frozen: it tripped the stuck-zombie teleporter and then could not
move at all after teleporting. Crawler now uses a mild speed cut + Slowness I so
it visibly crawls toward players, and crawlers are exempt from the stuck
teleporter (the hold zombie stays where players left it).

Also adds BO2_FEATURES.md documenting every Tier 0-4 feature, its config keys,
and how to disable each.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Barriers stored only Material per window block, so repairing/rebuilding them
lost orientation and fence/pane connection state. Now the full BlockData is
persisted and restored exactly. Backward compatible: legacy saves (or missing
blockdata) capture the live intact block's data on load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In a solo game the down handler still broadcast the co-op "stand close and
right click to revive" prompt and told the player they "need to be revived",
even though no second player exists. Down messaging now lives in
DownedPlayerManager: solo Quick Revive shows a clear "getting back up in Ns"
self-revive message; the co-op revive prompt only shows when there is actually
another player. Solo with no self-revive still ends the game (Game.playerDowned),
and can be forced off entirely with soloQuickReviveUses: 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant