Skip to content

Add roaming named elites and counterplay-driven rare combat encounters #23

Description

@zoeyrose

Architecture amendment — one authored content source (2026-08-13)

Initiative atrinik/atrinik#357 supersedes every future live-branch instruction below. atrinik/content@main is the sole mutable authored content source for replacement and Classic targets. Future authored changes land only on main; supported Classic artifacts are deterministically derived from the same immutable main revision. Do not create, restore, author, backport, validate, or publish through a live 1.x branch.

Exact historical 1.x commits, tags, releases, assets, preserved local snapshots, provenance, parity records, and comparisons remain valid immutable evidence. This amendment changes no other feature, balance, lore, compatibility, licensing, validation, or ownership acceptance criterion.

Important

The gameplay/authored-content decisions in this issue are preserved. This revision changes only the technical implementation path for the fresh MIT Go/Rust replacement program. atrinik/content remains separately/mixed licensed data; MIT engine/tooling code does not relicense the corpus.

Camp-spot and static-actor amendment (2026-08-23)

This issue now coordinates with content#241 — preserve camp-spot identity
during dynamic spawn migration
.
The earlier statement that the Fahrgorm and Thrakir tiles become merely
ordinary eligible spawn points is superseded by the following product rule:

  • Their physical locations remain authored, recognizable camp sites with a
    stable site identity and the original family/region/level/schedule context.
    The dynamic system may select safe positions within that bounded footprint,
    but it must preserve the camp's local feel.
  • The old map-local 90/10 named-template blocks are removed. A preserved site
    instead supplies a higher bounded named-variant affinity for appropriate
    profiles, still subject to one authoritative global cap, reservation,
    cooldown, persistence, and no-reroll rules. This is a hotspot bias, not a
    guaranteed named spawn or an independent local cap.
  • New camp sites may use the same stable site/profile contract. Names remain
    regionally and level appropriate rather than becoming a global adjective or
    stat-affix lottery.
  • Story NPCs such as King Rhun, bespoke bosses, quest/gate actors, and named
    monsters whose location-specific identity or special-key drop is required
    for progression remain explicit. They are not roaming candidates merely
    because they share a source archetype. Use stable semantic exclusions and
    fail closed when reward ownership is uncertain.

Add camp-site classification and hotspot tuning to the audit, migration,
frequency/cap tests, and player-facing playtest evidence. Preserve exact
quest/key/unique reward behavior, and never place those objects in repeatable
roaming named loot.

Replacement implementation contract

Preserve roaming-elite scheduling, persistence, encounter, reward, disclosure,
and authored-world decisions. Use Go spawn scheduling/world persistence,
encounter ledger, common timed actions/AI, compiled content, and structured Rust
presentation rather than map Python.

Common migration gates

  • Stable authored identities and behavior remain the source of truth; localized/rendered text and filesystem order are never identity.
  • Content is parsed, validated, transacted, and compiled by released content-toolkit; production Go/Rust consumers do not add private source parsers.
  • Runtime authority belongs to native Go services and bounded compiled definitions/CEL; Starlark is considered only through the residual go/no-go issue.
  • Verification uses deterministic compiler/conformance fixtures and wrapper-managed Go-server/Rust-client scenarios.
  • Verified original past work by an approved MIT provenance grantor may be copied, migrated, translated, or relicensed under MIT only through the merged complete-history provenance directive; all asset/data notices remain exact.

Content release-line scope

This future feature targets content@main and the canonical replacement stack. It is not automatically backported to content@1.x; any separately approved classic maintenance uses a linked pull request under #45, preserves the same gameplay/content decision and attribution, and validates only compatible classic consumers.

Preserved product/design specification and historical implementation notes

Summary

Add a server-authoritative, data-driven system that lets an ordinary spawn-point monster be replaced by a rare named variant anywhere that monster archetype is eligible. Use Fahrgorm and Thrakir as the first roaming named minibosses, preserve the authored context of the spawn they take over, give each a readable combat mechanic, and reward the encounter with a distinctive drop.

This should create occasional "something unusual is here" moments during ordinary exploration without requiring map authors to duplicate a named template at every spawn point.

In this issue, rare named replacement describes how an encounter appears. It is separate from the veteran/elite/boss group-size rank proposed in atrinik/server#30. Fahrgorm and Thrakir should initially be soloable veteran/miniboss encounters; future roaming variants may have higher encounter ranks.

What already exists

The current maps implement almost exactly this idea, but at one fixed spawn point per monster:

  • maps/shattered_islands/world_3_68 at (12, 11) gives an evil treant template weight 90 and Fahrgorm weight 10.
  • maps/shattered_islands/world_3_69 at (4, 2) gives a night-only lost soul template weight 90 and Thrakir weight 10.
  • Fahrgorm embeds a rand_drop with container 25 for the Bow of Accuracy: 1/25 per Fahrgorm kill.
  • Thrakir embeds a rand_drop with container 30 for the Ring of the Ghost: 1/30 per Thrakir kill.

server/src/types/spawn_point.c already supplies the useful primitives:

  1. It treats object_int1 on nested type-83 templates as a weight.
  2. It selects one weighted template when a spawn point is empty.
  3. It checks the selected template's spawn_time.
  4. It copies the selected monster, generates its ordinary randomitems, copies explicit inventory, and resolves RANDOM_DROP using the object's weight_limit/container denominator.
  5. It links the result back to the spawn point through SPAWN_POINT_INFO.

The authored world currently contains 131 treant_evil placements and 54 lost_soul placements. Copying the current 90/10 blocks into all 185 placements would be noisy, hard to rebalance, and easy for future maps to omit.

The engine also already has building blocks for more interesting fights:

  • monster ability objects and spell selection in server/src/types/monster.c;
  • multiple attack movement modes;
  • faction/ally signaling among nearby and linked spawn points;
  • attack types, protections, blocking, absorption, movement/backstab attack-roll modifiers, and status effects;
  • map messages, sounds, effect objects, and EVENT_DEATH hooks.

Proposed design

1. Add authored rare-variant profiles

Create a collected, validated content registry (exact syntax is an implementation choice) with stable variant IDs. A profile should describe:

  • stable ID and display name;
  • one or more eligible source archetypes, initially treant_evil and lost_soul;
  • replacement chance;
  • encounter rank and intended party size;
  • global active limit and respawn/cooldown policy;
  • relative level/stat modifiers rather than one fixed absolute level;
  • added abilities, behavior, visual treatment, sound, and inventory;
  • special-drop table;
  • optional region/map/difficulty constraints.

The ordinary spawn template must remain the source of contextual properties: position, authored level, spawn_time, terrain flags, faction, peaceful/aggressive state, and spawn-point ownership. Apply the named profile as an overlay after an eligible ordinary template is selected. This lets Fahrgorm replace a level-15 Eld Woods evil treant as a level-appropriate named threat instead of becoming the current fixed level-6 monster everywhere.

Unknown object fields already survive as key/value data, so a small archetype marker such as elite_pool treant and map/spawn overrides such as no_rare_variant 1 can remain data-driven. Do not identify eligibility by display name.

Migrate the inline Fahrgorm and Thrakir weighted alternatives to profiles. Their original tiles remain ordinary eligible spawn points rather than privileged hard-coded locations.

2. Define eligibility and safety rules

A replacement roll should happen only after the ordinary weighted template has been selected and found time-eligible.

Default eligibility should include spawn-point monsters whose source archetype opts into a named-variant pool. Provide explicit map, spawn-point, and template opt-outs. Automatically exclude or require explicit opt-in for:

  • quest/gate monsters carrying progression keys or quest containers;
  • one-time/script-owned encounters;
  • tutorial and protected settlement areas;
  • static monsters not owned by a spawn point;
  • a template already carrying a unique/named encounter identity.

Preserve the base template's schedule. Thrakir may therefore take over any eligible lost-soul spawn only while that source lost soul is allowed to exist.

3. Make named identity genuinely unique and non-exploitable

A stable variant ID should have an authoritative server-side state:

  • maximum active instances, initially one Fahrgorm and one Thrakir server-wide;
  • reservation before generation and release on death, legitimate despawn, failed insertion, or map teardown;
  • a configurable cooldown/window before the next appearance;
  • enough persisted scheduling state that a restart or repeatedly unloading/reloading maps cannot be used as a free reroll;
  • no second reward or duplicate reservation from multipart objects, owner indirection, or repeated death callbacks.

Do not reroll merely because a map was loaded. A genuine spawn lifecycle should consume the roll. Add debug/operator diagnostics for variant selection, rejection reason, reservation, spawn, death, and cooldown without broadcasting exact coordinates to all players by default.

4. Tune occurrence and loot as one economy

The current local design composes two rolls:

  • Fahrgorm: 10% named chance × 1/25 drop = 0.4% special items per generic spawn cycle at that point.
  • Thrakir: 10% named chance × 1/30 drop = about 0.333% per generic spawn cycle at that point.

A much smaller world-wide replacement chance followed by the unchanged 1/25 or 1/30 drop can become excessively rare. Conversely, rolling independently across 185 placements without a global limit can create many copies at once.

Set an explicit target for:

  • expected named encounters per active-play hour/server population;
  • expected named kills per special item;
  • maximum concurrent encounters;
  • minimum/maximum time between sightings.

For the MVP, retain a chance at the signature item but give every kill useful baseline value (for example a themed material, token, or above-normal treasure). Consider a tradeable component or bounded bad-luck protection later rather than making players win two opaque lotteries indefinitely.

5. Give each named variant counterplay, not only bigger stats

Each initial profile should add one signature mechanic with a clear tell, a short response window, and a meaningful failure cost that is not an unavoidable one-shot.

Suggested first encounters:

  • Fahrgorm — forest rally / crushing roots: on aggro or at an HP threshold, visibly warns before a directional or local-area root/slam and calls nearby allied trees. Players can step out of the marked direction/area or interrupt/stagger the windup.
  • Thrakir — soul-drain windup: visibly faces and warns before a drain cone/line. Players can sidestep, break line of sight, or interrupt; failure causes damage/drain but remains recoverable.

The MVP can use ordinary map text, sounds, facing, and existing effect objects/spells, avoiding a new wire command. If readable ground telegraphs cannot be represented reliably with existing effects, design one small server/client telegraph primitive and use it for all future encounters.

An authored ability description should support at least:

  • trigger: aggro, interval, or HP threshold;
  • windup duration and cue;
  • existing spell/effect to execute;
  • target/shape;
  • interrupt/stagger rule;
  • cooldown and maximum uses.

This creates a reusable base for later bosses instead of embedding one-off checks for these two names in monster.c.

Follow-on combat proposals

These should reuse the same encounter/ability data rather than become unrelated name checks:

  1. Pack leaders and morale: rare captains rally nearby allies; killing or interrupting the leader can make remaining ordinary monsters hesitate, scatter, or lose a buff. Existing ally signaling and run_away behavior are useful starting points.
  2. HP-threshold phases: let authored encounters change movement, vulnerabilities, or ability sets at clear thresholds. Keep early variants to one transition so the fight remains legible.
  3. Role-based variant families: add a small curated roster such as bulwark, skirmisher, healer, summoner, and artillery, each with a visible behavior and counter. Do not create opaque random stat affixes.
  4. Regional hunt clues: rumors, hunter NPCs, notice boards, or a command can announce the region and approximate freshness of a sighting without revealing the exact tile. This avoids requiring players to patrol hundreds of maps blindly.
  5. Collection and achievement hooks: stable variant IDs can later feed the data-driven achievements in Implement data-driven per-character achievements server#31 and a bestiary/collection log without using mutable display names.
  6. Risk/reward repair: use named encounters and targeted protection drops to make dangerous caster/group routes competitive with the currently dominant passive-tree progression, as identified in the gameplay playtest notes.

Rollout

Phase 1: reusable engine primitive and two examples

  • Add and validate the rare-variant/profile format.
  • Add server-side selection, reservation, cooldown, scaling overlay, and diagnostics.
  • Migrate Fahrgorm and Thrakir from their map-local 90/10 templates.
  • Implement one telegraphed ability and one special drop profile for each.
  • Add a minimal regional-sighting clue.
  • Update the farming analyzer and Atrinik bot so roaming names are not modeled as guaranteed coordinate-local rerolls.

Phase 2: curated world roster

Audit monster families and add a small number of regionally appropriate named variants across level bands. Prefer distinctive mechanics and targeted rewards over a large combinatorial affix system.

Phase 3: broader encounter vocabulary

Generalize proven windup, interrupt, pack, and phase primitives for dungeon bosses and the encounter ranks proposed by atrinik/server#30. Add collection/achievement integration after the underlying stable IDs and kill-credit rules exist.

Acceptance criteria

  • A collected, validated profile can make an opted-in spawn-point archetype produce a named replacement without editing every map placement.
  • Fahrgorm can replace eligible evil-treant spawns and Thrakir can replace eligible time-valid lost-soul spawns across the world.
  • The replacement preserves the selected source template's position, schedule, level context, faction, aggression, terrain, and spawn ownership unless the profile explicitly overrides a documented field.
  • Each initial variant has at most one active server-wide instance and correct reservation cleanup on all success/failure/despawn/death paths.
  • Map unload/reload and server restart cannot be exploited for unlimited fresh rolls.
  • Quest, scripted, settlement/tutorial, static, and already-named encounters follow documented eligibility/opt-out rules.
  • Profile stat scaling is relative and produces appropriate threats at representative low-, mid-, and high-level source spawns.
  • Fahrgorm and Thrakir each have a visible, avoidable or interruptible signature mechanic; neither is only an HP/damage multiplier.
  • Signature-drop odds and the composed spawn-plus-drop rate are documented and covered by deterministic tests.
  • Every named kill gives worthwhile baseline rewards without duplicating quest/key/one-drop items.
  • Players have an in-world way to learn the approximate region and freshness of a sighting.
  • Existing EVENT_DEATH, faction, XP, party credit, loot/corpse, and spawn-respawn behavior remain correct.
  • Current map-local Fahrgorm/Thrakir definitions and coordinate assumptions in tools/tests are migrated rather than maintained as a second path.
  • Content authors can add a variant and ability without adding a name-specific branch to C.
  • The feature remains distinct from, but can reuse, Redesign player cap and endgame progression around level-101–115 group encounters server#30's encounter-rank vocabulary.

Validation

  • Add deterministic unit tests around spawn_point.c for eligibility, weighted-base selection, replacement probability, time windows, relative scaling, uniqueness, cooldown, failed insertion, death/despawn cleanup, and reload/restart behavior.
  • Test RANDOM_DROP composition and duplicate prevention, including party kills, summoned/projectile owners, and zero-XP/no-loot cases.
  • Add focused tests for windup timing, interrupt/stagger, line/area targeting, threshold triggers, and destroyed targets/maps during a pending ability.
  • Seed or inject the gameplay RNG in statistical tests; do not use flaky live randomness assertions.
  • Run the map checker on migrated maps, collect affected authored resources, build the server, and run focused/server checks.
  • Runtime-smoke low-, mid-, and high-level replacements, two simultaneous players searching/killing, map unload/reload, restart during cooldown, and each special-drop path.
  • Update and run tools/farming_analyzer.py, tools/atrinik_bot, and their tests for non-coordinate-local named encounters.

Relevant source/content areas

  • server/src/types/spawn_point.c: weighted selection, time checks, generation, random drops, spawn ownership
  • server/src/types/monster.c: spell abilities, movement, ally signaling
  • server/src/server/attack.c: damage, death event, XP, faction and kill/loot credit
  • server/src/server/living.c: level-relative monster stat calculation
  • server/src/loaders/object.l: authored key/value loading
  • arch/special/spawn_point.arc and the new authored variant/ability source
  • arch/mobs/undead/lost_soul/ and arch/mobs/plants/treant/
  • maps/shattered_islands/world_3_68 and maps/shattered_islands/world_3_69
  • tools/farming_analyzer.py, tools/atrinik_bot/, and related tests

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Fields

    Priority

    None yet

    Start date

    None yet

    Target date

    None yet

    Effort

    None yet

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions