You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is implemented in the fresh MIT-licensed Go server under the replacement program. Its gameplay and content-design decisions remain authoritative. C, CPython, classic packet, file-path, and enum details in the preserved specification are historical evidence only; do not copy, translate, or structurally port GPL implementation code.
Replacement implementation contract
Keep this as the combat-disciplines epic. Its children establish identities in M2, prove the action framework in M3, and implement full disciplines in M5. All runtime ownership belongs to Go services and generated Rust contracts.
The server remains authoritative, consumes versioned compiled content, and exposes bounded generated Game Protocol 1 messages. Pure rules may use a specifically approved typed CEL environment. Starlark is not part of this issue unless the separate residual-scripting decision explicitly approves it.
Required verification
Preserve every observable rule, balance decision, disclosure boundary, and anti-exploit invariant from the specification below.
Add deterministic Go unit/property tests and wrapper-managed scenario coverage at the appropriate integration boundary.
Add bounded malformed-input and persistence-failure cases where this feature accepts content, network, or stored data.
Add Go/Rust protocol conformance fixtures for every new cross-process field; the client must not reconstruct authoritative rules from prose.
Demonstrate that implementation and tests contain no copied GPL source/test material and execute no runtime Python.
Preserved product/design specification and historical implementation notes
Summary
Add a server-authoritative, data-driven combat training system while consolidating Atrinik's overly narrow XP skills into broad disciplines:
Disciplines are the broad skills that gain XP and levels: one Melee Combat skill for all wielded melee weapons, one Archery skill for bows/crossbows/slings, plus separate Unarmed, Throwing, Wizardry, and Divine Magic skills.
Techniques are explicit active moves such as Sweeping Cleave, Lunge, Ricochet Shot, or Pinning Bolt.
Masteries are passive nodes that specialize a discipline or improve one of its techniques.
Weapon profiles say which maneuvers a weapon can plausibly perform and how effective it is at them.
This should provide melee area attacks without making every weapon behave like an axe. A rapier should not gain a circular cleave merely because the character has spent points in a generic perk; it should gain thrusting, lunging, precision, and line-attack options. Axes, greatswords, glaives, and some impact weapons can sweep, but with different target caps, arcs, damage, and recovery. The same vocabulary should extend naturally to bows, crossbows, slings, throwing weapons, unarmed combat, and future monster abilities.
The player-facing fiction is practice and instruction: skill levels represent broad experience in a discipline, functional character milestones grant the bounded shared specialization points owned by #9, active maneuvers are Techniques, and passive refinements are Masteries. A character should not have to re-level from scratch merely because they exchange an axe for a sword or a bow for a crossbow; the profile and selected branches change how that shared experience is expressed. Existing instructors such as Tom Istrad and John Aldman in the Lost Memories tutorial can explain archery and divine magic, while dedicated masters-at-arms can provide respecialization later.
Important terminology: cleave already means something else
Atrinik currently uses cleave as both:
one of the physical attack/damage types (ATNR_CLEAVE, attack_cleave, protect_cleave); and
one of the four current melee weapon skills (SK_CLEAVE_WEAPONS), which this proposal retires in favor of SK_MELEE_COMBAT.
It does not currently mean “hit an area.” attack_cleave 100 only controls how damage is distributed into the target's cleave protection. Area eligibility must not be inferred from attack[ATNR_CLEAVE]: a monster bite can deal cleave damage, a bolt currently deals cleave damage, and a sweeping sword may deal slash damage.
Use sweep for the capability/shape and names such as Sweeping Cleave for particular techniques. Keep attack type, broad XP discipline, and maneuver capability as independent concepts.
What the codebase already provides
Skills and progression
server/src/include/skills.h currently defines four melee weapon skills, unarmed, throwing, and three separate bow/crossbow/sling archery skills.
server/src/include/skillist.h and server/src/server/skill_util.c associate those enum entries with skill_* archetypes under arch/intern/skills/.
link_player_skills() clones every available skill archetype into the player. Skill objects already persist level and XP and are sent to the client.
server/src/server/exp.c levels skill objects and sends UPD_EXTRA updates.
client/src/gui/widgets/skills.c currently renders a flat icon grid with only name, description, level, and XP.
The skill item packet in server/src/socket/item.c carries only level, XP, and description as its skill-specific payload.
There are enum/table entries for two-hand mastery and polearm mastery, but no corresponding skill_two-hand_mastery or skill_polearm_mastery archetypes. init_new_exp_system() therefore leaves them unavailable and link_player_skills() skips them. Two-handed behavior otherwise exists only as FLAG_TWO_HANDED (primarily suppressing shield bonuses). Weapon directory names and the old editor subtype vocabulary are not reliable runtime polearm metadata.
Broad XP disciplines, specialized technique branches
Replace the four wielded-melee XP skills with one SK_MELEE_COMBAT skill and one skill_melee_combat archetype:
Every wielded melee weapon should use SK_MELEE_COMBAT through item_skill. Its attack type and combat profile still decide protections, technique eligibility, shape, effectiveness, and tree branch. Unarmed remains a separate skill because it has a distinct equipment loop and base damage/speed archetype. Throwing also remains separate from archery because thrown inventory objects, strength scaling, recovery, and ammunition behavior are materially different.
Likewise replace SK_BOW_ARCHERY, SK_CROSSBOW_ARCHERY, and SK_SLING_ARCHERY with one SK_ARCHERY skill and skill_archery archetype. bow_get_skill(), all launcher item_skill values, level requirements, item examination, projectiles, XP credit, scripts, editor lists, and tests should use the shared skill. Bow, crossbow, and sling profiles/branches retain distinct firing speed, damage, ammunition, and Techniques.
This is an intentional breaking cleanup: remove the seven superseded skill enum entries and archetypes rather than keeping aliases or hidden compatibility skills. Update all authored weapons, artifacts, fixtures, scripts, plugin-facing skill names, and generated inputs together. If preserving a particular development save is later made a requirement, define a one-time offline conversion policy explicitly; do not blindly sum four nonlinear skill XP totals and inflate character progression.
Melee and ranged action paths
Targeted basic melee runs from the player loop in server/src/types/player.c, through attack_is_melee_range(), skill_attack(), and attack_object().
skill_attack() chooses the equipped weapon's item_skill; living_update_player() uses that skill level to increase WC and damage.
attack_object() owns attack rolls, facing/animation, hitback, and the call into attack_hit(); attack_hit() owns friendship/PvP checks, protection, blocking, final damage, kill processing, and owner credit.
freearr_x/freearr_y, get_map_from_coord(), map-layer iteration, and HEAD() already provide most primitives needed to collect a directional one-tile arc across tiled-map boundaries and deduplicate multipart monsters.
Bows and thrown items create owned projectile objects. Bow skill affects projectile WC and damage in server/src/types/bow.c and server/src/types/arrow.c; common projectile collision is in server/src/types/common/projectile.c.
The shared player.action_attack/action_timer already prevents overlapping attacks and displays recovery to the client. There is no stamina/fatigue resource today.
Spellcasting is currently hardwired to Wizardry
Although content already calls cause light wounds and minor healing “divine magic” and calls holy word/remove depletion “prayers,” all directly cast SPELL objects select SK_WIZARDRY_SPELLS in check_skill_to_fire(). Spell books, scrolls, item requirements, spell-point display, rod checks, map scripts, and merchant dialogue also contain direct Wizardry assumptions.
The current spell path field describes an effect family such as Restoration, Turning, Fire, Wounding, or Death. It does not describe whether the power is arcane or divine. Atrinik also already has gods, worship lookup through determine_god(), holy altars, consecration, priests, temples, and explicit divine tutorial dialogue. Those are sufficient lore foundations for a separate divine discipline, but not yet a complete casting contract.
Useful persistence and content hooks
Unknown authored object fields become key/value pairs, and object key/value differences are saved by get_ob_diff()/object_save(). Stable node selections can therefore be attached to the existing per-character skill objects without inventing a second character database.
Technique definitions and weapon profiles can be authored as collected archetypes and validated into registries during server startup.
MEVENT_SKILL_USED exists for scripts, but the core attack and final-damage paths must remain authoritative C. A pre-attack script event is not sufficient for safe target collection, final damage, cooldowns, XP ownership, or recursion control.
Let weapon shape matter independently of its physical damage type.
Make area attacks deliberate button presses, not an uncontrollable proc on every basic swing.
Use broad Melee Combat and Archery XP while preserving distinct weapon identities through profiles and tree branches.
Split directly cast spells into explicit Wizardry and Divine Magic disciplines instead of routing every spell through Wizardry.
Reuse normal attack rolls, protections, blocking, PvP/friendship rules, kill credit, and damage feedback.
Keep all effects server-authoritative and data-tunable.
Allow the framework to be used by monster AI later, even if the initial content is player-facing.
Make choices reversible and avoid permanently ruining an old character.
Do not add compatibility shims for old clients/saves; update current producers and consumers together.
Proposed player model
Unified specialization points
#9 owns the single connected specialization graph, bounded character-wide point pool, connectivity rules, persistence, and respec transaction. This issue contributes the combat-profile, Technique, Mastery, skill-level prerequisite, and effect definitions placed into that graph.
Functional character-level milestones grant the shared points under #30's cap and pacing. Use-based discipline levels remain prerequisites and scaling inputs: investment can path toward any cluster, but advanced Melee, Archery, Wizardry, Divine Magic, Unarmed, Throwing, or device nodes require actual experience in that discipline.
Do not create per-skill point balances or separate disconnected trees. Persist selected stable node IDs and purchase order in the typed specialization state owned by #9. Skill-level loss, removed nodes, or invalid references must deactivate/refund affected dependent branches deterministically without leaving an invalid build.
Respecialization
Use #9's server-authoritative full-reset and connected-branch refund transaction. Combat Techniques and Masteries must expose enough dependency, cooldown, equipment-profile, and active-action information for that transaction to cancel or deactivate them safely. Do not add a second per-discipline refund path.
No stamina bar in the first version
Techniques should consume the existing shared action recovery and also have per-technique cooldowns. This creates an opportunity cost versus a basic attack without adding a third combat resource and a new HUD/protocol/stat system.
Add an exertion/stamina resource only if target-dummy and encounter playtests show that cooldown/recovery tuning cannot prevent technique spam. Issue #28 will be useful for repeatable damage testing once implemented.
Spellcasting disciplines: Wizardry and Divine Magic
Add SK_DIVINE_SPELLS with a skill_divine_spells archetype and keep SK_WIZARDRY_SPELLS for arcane practice. Give every directly cast spell an explicit casting_skill/tradition in spell_struct (or equivalent validated authored data):
Wizardry covers deliberately arcane formulae such as elemental projection, magical missiles, mind magic, teleportation, transmutation, and arcane summoning.
Divine Magic covers deliberately devotional miracles such as healing, cures, restoration, consecration, holy word/turning, deity-granted protection, and appropriate divine wounding.
Classify every current spell deliberately. Do not infer tradition from spell path: Restoration is usually divine but could support an arcane spell later; Death or Wounding may be divine, arcane, or deity-specific; Protection and Light are not inherently one tradition. Spell path remains the effect/attunement taxonomy, while casting skill owns learning requirement, casting level, scaling, mana cost, XP, tree points, and UI grouping.
Update check_skill_to_fire(), cast_spell(), spell books/scrolls, socket item metadata, SK_level() source context, kill XP, learning failures, requirements, merchants, scripts, tests, and player-facing descriptions to resolve the declared casting skill. Magic devices remain their own skill when a wand/rod/device is the action source; their interaction with a spell's tradition must be stated explicitly rather than accidentally borrowing Wizardry.
Do not require worship for every Divine Magic cast in the first version: the current god system does not yet model a complete faith resource or granted-spell lifecycle. Allow individual divine spells such as consecrate to retain an explicit requires_deity rule, and leave room for deity affinities, denied paths, and deity-specific Masteries later. Wizardry can lean on Intelligence and Divine Magic on Power where attribute scaling is redesigned, but the first required change is correct XP/level ownership rather than a second simultaneous resource rewrite.
Candidate Divine Magic branches are Restoration, Warding, and Turning/Judgment; candidate Wizardry branches can build on elemental, force/missile, control, and utility paths. These use the same Technique/Mastery framework, but weapon-profile requirements do not apply to spells.
Data-driven weapon profiles
Add collected combat_profile_* definitions and let weapon archetypes reference one stable profile, for example:
combat_profile rapier
A validated profile should contain:
capability tags such as sweep, wide_sweep, thrust, reach, stagger, parry, rapid, precision, power_draw, reload, ricochet, or fan_throw;
bounded ratings for the relevant maneuver families (for example sweep efficiency 0–100);
optional target-cap, reach, recovery, and shape modifiers within server-defined safe bounds;
a short player-facing description.
Use shared profiles for families of similar weapons and allow a rare explicit override only when an individual archetype genuinely differs. Validate every reference during collection/startup and expose the resolved capability summary in item examination and the training UI. Do not infer behavior from a file path or display name.
The profile is separate from:
item_skill, which selects the XP discipline;
attack_*, which selects damage types/protections;
FLAG_TWO_HANDED, which remains an equipment fact;
ordinary WC, damage, speed, quality, and condition.
Representative profiles:
Weapon family
Capabilities
Sweep effectiveness
Rapier/estoc
thrust, precision, parry
0
Dagger
thrust, rapid, precision
0
Longsword/scimitar
sweep, parry, thrust
medium
Greatsword
wide_sweep, power, parry
high, with longer recovery
One-handed axe/cleaver
sweep, execute
high
Great axe/bardiche
wide_sweep, execute, power
very high, with longer recovery
Mace/hammer
stagger, crush; some can sweep
low/medium
Spear/pike
thrust, reach, brace
0
Glaive/halberd
reach, sweep
high
Short bow
rapid, mobile
n/a
Long bow
power_draw, precision, volley
n/a
Crossbow
reload, penetration, pin
n/a
Sling
rapid, ricochet, stagger
n/a
This answers the “all weapons can cleave, but some are better” question with a stricter and more legible rule: all weapons can use their discipline's universal fundamentals, but only profiles with a sweep capability can use an area sweep. A rapier is not merely bad at cleaving; it is ineligible and receives equally valuable thrust/precision techniques instead.
First active melee technique: Sweeping Cleave
Sweeping Cleave should be an explicit Technique, initially available to cleave-weapon profiles with sweep or wide_sweep.
Suggested baseline:
attack the primary target/tile plus the immediately clockwise and counter-clockwise adjacent directions (a three-cell forward arc);
primary target: 100% normal weapon damage;
secondary targets: profile-scaled damage, initially about 45–85%;
maximum two secondary victims at baseline;
each victim receives an independent normal attack roll and normal protection/block calculation;
use the equipped weapon's existing damage-type distribution; do not convert damage into ATNR_CLEAVE;
consume one normal attack recovery plus a small technique recovery premium;
use a short per-technique cooldown, initially in the 5–8 second range;
collect and validate targets before applying damage, deduplicate HEAD() objects, then resolve in deterministic order (primary, clockwise, counter-clockwise, distance/tag tie-break);
never cross a wall, change physical linked-map depth, hit a friendly/PvP-invalid target, hit the attacker, or damage one multipart creature more than once;
a secondary strike must not recursively trigger another area technique.
A wide_sweep profile or later Mastery can raise the cap/arc or secondary scalar, but ordinary melee should stay local. Do not turn every swing into a screen-wide damage pulse.
Candidate discipline trees and branches
These are an initial content vocabulary, not a requirement to ship every node at once. Implement the common framework plus one thin vertical slice first, then fill out trees using measured combat data.
Sweeping Blow: a small low-damage arc only for profiles that can plausibly sweep.
Concussive Strike: applies a short attack/movement delay when control succeeds.
Armor Dent: temporary bounded impact-protection or absorb reduction.
Shove: low damage plus one-tile knockback if the destination is valid.
Groundbreaker: high-tier short cone/ring control with conservative damage and boss resistance.
Unarmed — combinations, evasion, control
Flurry of Blows: multiple reduced hits with one proc budget.
Sweeping Kick: adjacent arc with lower weapon-like damage but a small stagger chance.
Guarded Step: brief defense while repositioning one tile.
Counter: a bounded response after a successful block/evade condition.
Shoulder Throw: adjacent displacement/control, heavily restricted against multipart/large/boss targets.
The Melee Combat tree may also contain a small shared-fundamentals branch, but it must not make every profile eligible for every maneuver. A player can earn Melee Combat XP with an axe and then equip a rapier at the same skill level; the rapier's profile and currently selected nodes determine the available actions. This shared progression is intentional and avoids four parallel grinds.
Do not revive SK_TWOHANDS and SK_POLEARMS as separate XP bars. Two-handed and hafted/reach behavior is a cross-cutting weapon profile layered onto Melee Combat. Remove the currently unreachable enum/table entries or repurpose them only if a later design establishes a real independent progression loop.
Archery: bow branch — mobility, power draw, volleys
Quick Shot: reduced recovery/damage, favored by rapid/short-bow profiles.
Power Draw: longer wind-up for higher single-target damage/range, favored by long bows.
Split Shot: consume one explicit ammunition cost policy and fire a bounded fan at separate targets; no duplicate hit on one multipart victim.
Steady Aim: accuracy/damage benefit after standing still and keeping the same target.
Volley: high-tier delayed targeted area with visible warning, target cap, and line/range validation.
Archery: crossbow branch — preparation, penetration, control
The Archery tree may contain a shared-marksman branch for accuracy, target tracking, or ammunition handling, while launcher profiles keep bow draw, crossbow reload, and sling ricochet mechanics distinct. Switching launcher families does not reset Archery XP.
Combat action context and attack refactor
Do not implement techniques by temporarily mutating chosen_skill, damage, direction, or the equipped weapon around repeated calls to attack_object(). That becomes unsafe as soon as an attack has multiple targets or delayed projectiles.
Introduce an explicit combat action context, conceptually containing:
actor / owner
source discipline and skill-level snapshot
equipped weapon/ammunition and weapon profile
technique ID
action ID
primary/secondary target role
damage/accuracy/recovery scalars
allowed proc/on-hit/counter policy
Refactor normal melee and projectile creation to populate this context, while preserving a simple wrapper for ordinary attacks. Owned delayed effects/projectiles must carry the source discipline and relevant snapshot so kill XP does not depend on whichever skill the owner happens to have readied when the projectile lands.
The context should make these policies explicit:
one attack roll and one damage resolution per selected victim;
one kill/XP credit per victim to the source discipline;
no technique triggering itself or another technique recursively;
clear handling of hitback/counters for secondary targets (recommended: no FLAG_HITBACK response to secondary sweep damage unless a technique explicitly opts in);
bounded on-hit effects for multi-hit actions;
one animation/action lock at the actor, normal per-target damage feedback at victims.
Basic attacks, spells, and old callers can use a default context. This is a cleaner foundation than adding one cleave-only loop inside skill_attack().
Target collection rules
Add reusable server helpers for bounded combat shapes: adjacent arc, adjacent ring, line, cone/fan, and selected-radius area. A shape returns stable (object pointer, count) handles before damage begins.
Every helper must:
resolve coordinates with get_map_from_coord() so horizontal tiled-map edges work;
remain on the attacker's current physical depth unless the technique explicitly supports vertical combat;
respect walls and line of effect;
use living-layer iteration and normalize multipart objects with HEAD();
validate object counts before each resolution in case an earlier hit killed/removed a later target;
apply friendship, owner, PvP, invisibility/targetability, and no-harm rules consistently;
cap both scanned cells and accepted targets;
use deterministic ordering so replays/tests and target caps are stable.
Do not reuse persistent cone spell objects for an instantaneous melee sweep; they have different lifetime, movement, and multi-tile-damage semantics.
Authored technique definitions
Add collected technique_* archetypes (or an equivalently validated authored registry) with stable IDs. Definitions should own presentation and bounded tuning data:
stable node/technique ID and display name;
owning discipline;
active Technique versus passive Mastery;
icon and description;
required skill level, cost, prerequisites, ranks, and mutual exclusions;
required/forbidden weapon profile tags;
shape, target cap, scalars, recovery, cooldown, and proc policy selected from server-known enums;
optional sound/effect identifiers.
Startup/collection validation must reject duplicate IDs, missing disciplines/profiles/faces, cycles, impossible prerequisites, out-of-range scalars/caps, and active nodes without an implemented server handler. Arbitrary script or expression execution must not be embedded in node data.
Protocol and client UI
This is an intentional client/server feature and should use explicit protocol support rather than encoding the tree into skill description text.
Add server-authoritative messages for:
the technique/mastery catalog and tree relationships (or a versioned collected resource referenced by digest);
drag/click support for active Techniques in quickslots;
cooldown and unavailable-state overlays;
keyboard/controller-accessible selection and activation.
Add bounded command parsing and update common/toolkit/socket.h, both dispatch tables, packet tests, and protocol documentation together. A dedicated TECHNIQUE client item/action type is preferable to pretending an active technique is a level-bearing SKILL; stable technique IDs should survive reconnects even when transient object tags do not.
Balance and progression rules
Basic attacks remain the zero-cooldown baseline; Techniques trade recovery/cooldown for shape, control, defense, or burst.
Area damage is never full single-target damage to an uncapped number of victims.
Weapon profile effectiveness adjusts a bounded technique scalar; it does not multiply the entire final damage stack without a cap.
Each victim can grant normal kill credit once. Multi-target combat is balanced through damage, recovery, target caps, encounter density, and cooldowns rather than silently deleting legitimate kills.
Follow-through/cooldown refunds are once per action and have minimum cooldown floors.
Protection penetration is capped and never bypasses 100% immunity unless a specific encounter mechanic says so.
Boss/elite control resistance should be explicit; repeated pin/stagger/knockback needs diminishing returns or immunity windows.
PvP needs separate scalar/duration caps where control or burst would otherwise become oppressive.
Split/fan projectile techniques must define whether they consume one or multiple ammunition items, and special ammunition must not be duplicated.
Training-dummy measurements should compare basic sustained attacks, single-target technique rotations, and dense target scenarios. Coordinate this with Add target-dummy DPS testing with timed, per-player results #28 rather than adding a second DPS mechanism here.
Implementation sequence
Phase 0: consolidate XP skills and declare spell traditions
Replace the four wielded-melee skills with SK_MELEE_COMBAT/skill_melee_combat and update every melee weapon item_skill consumer/definition.
Replace bow/crossbow/sling skills with SK_ARCHERY/skill_archery and update launchers, projectiles, requirements, scripts, editor metadata, fixtures, and tests.
Remove the superseded skill archetypes/enums and unreachable two-hand/polearm entries rather than leaving aliases.
Add SK_DIVINE_SPELLS, explicit per-spell casting skill/tradition, and deliberately classify every current spell.
Replace Wizardry hardcoding in casting, learning, item metadata, merchants, scripts, plugins/tests, and XP attribution with declared-skill lookup.
Phase 1: combat-action foundation and one vertical slice
Add sword, thrust/reach, impact, and shared-fundamentals branches to Melee Combat plus the separate Unarmed tree. Profile all current melee weapons, add control-immunity rules, and add player-facing item/profile examination.
Phase 3: complete Archery and Throwing
Add bow, crossbow, sling, and shared-marksman branches to Archery plus the separate Throwing tree. Refactor projectile source context, multi-projectile ammunition handling, and delayed/area targeting once rather than separately per launcher.
Phase 4: spell Masteries and divine content integration
Add initial Wizardry and Divine Magic branches, update John Aldman's tutorial and relevant temples/books/merchants, and validate learning/scaling/XP for direct casts, scrolls, and devices.
Phase 5: content and AI integration
Integrate tutorial instructors and respec NPCs, give selected monsters authored techniques, add encounter telegraphs/effects, and tune progression/trees against the level-cap/mastery decision in #30.
Validation
Server unit tests
profile loading, inheritance/overrides, invalid tags/ratings, and missing references;
consolidated Melee Combat XP/level/WC/damage/requirements across slash, cleave, pierce, and impact weapons;
consolidated Archery XP/level/damage/requirements across bows, crossbows, and slings while preserving launcher behavior;
explicit Wizardry/Divine Magic classification, learning, scaling, mana cost, item metadata, and XP attribution for every spell/action source;
tree graph validation, cycles, prerequisites, point derivation, purchase order, down-level refunds, respec, save/load, and removed-node recovery;
cardinal and diagonal arcs, lines, fans, tiled-map boundaries, wall blocking, physical depth, target caps, and deterministic ordering;
multipart-monster deduplication and object-count invalidation after an earlier target dies;
build both legacy client and server after every wire change.
Content validation
every wieldable melee/ranged/throwing weapon resolves to a valid profile;
every wielded melee weapon uses Melee Combat and every bow/crossbow/sling uses Archery for XP/requirements;
every directly cast spell declares exactly one valid casting skill/tradition; effect path is not used as an implicit fallback;
representative families have sensible capabilities, including explicit non-sweep piercing weapons;
collection and server startup report no invalid profiles/nodes;
editor lists/config understand the new fields and stop presenting stale weapon-subtype semantics as authoritative;
focused tutorial/map checks for any trainer or training-area content.
Acceptance criteria
ATNR_CLEAVE, the retired cleave-weapon XP skill, shared Melee Combat XP, and sweep/AoE capability are documented and implemented as independent concepts.
Slash, cleave, pierce, and impact weapons all gain/use one SK_MELEE_COMBAT XP level; their old skill enums/archetypes and aliases are removed.
Bows, crossbows, and slings all gain/use one SK_ARCHERY XP level; their old skill enums/archetypes and aliases are removed.
Unarmed and Throwing remain separate XP skills with their own trees.
Weapon and launcher profiles/branches preserve meaningful style, eligibility, recovery, ammunition, and effectiveness differences despite shared XP.
Every directly cast spell explicitly selects Wizardry or Divine Magic; spell path is not treated as casting tradition.
Divine Magic has its own skill object, XP/level, requirements, scaling/point ownership, UI grouping, and initial Restoration/Warding/Turning-Judgment direction.
Spell books, scrolls, normal casting, magic devices, socket metadata, merchants, scripts, and delayed spell kills resolve the correct declared/action-source skill without Wizardry fallbacks.
Sweeping Cleave is an explicit active Technique and can hit a bounded forward arc through the normal attack pipeline.
Weapon profiles determine eligibility and effectiveness; a rapier/dagger/spear negative-control set cannot use Sweeping Cleave.
At least one one-handed axe, great axe, sweeping sword, polearm, and impact weapon demonstrate distinct profile behavior.
Secondary targets receive bounded damage, independent attack rolls, correct protections/blocks, no duplicate multipart hits, and no recursive cleaves.
Friendship, ownership, PvP, no-harm, walls, tiled-map edges, and current physical depth are respected.
Proposal: add a classless connected specialization tree with respecs #9's bounded shared specialization points can reach Melee, Archery, magical, divine, support, and hybrid clusters; actual discipline levels gate advanced nodes, and connectivity, purchase order, prerequisites, respec, and level-loss behavior persist safely.
The legacy client displays a real tree with weapon compatibility, points, ranks, prerequisites, quickslot-capable active Techniques, and cooldowns.
Technique use is server-authoritative and packet parsing is bounded.
Delayed projectiles and multi-target actions credit kills/XP to the skill used when the action began, not the owner's later chosen_skill.
Melee Combat's axe/cleaver, sword, thrust/reach, impact, and fundamentals branches; Archery's bow, crossbow, sling, and marksman branches; plus Unarmed and Throwing have approved initial designs. Piercing profiles receive line/precision options rather than forced cleaving.
No stamina resource is added for the MVP; recovery/cooldown playtesting is documented before reconsidering that scope.
Both legacy targets build, focused server tests pass, affected content collects/checks, and protocol/player-facing documentation is updated.
Relevant source areas
server/src/include/skills.h, server/src/include/skillist.h: current narrow weapon/archery disciplines, new broad skills, Divine Magic, and unreachable mastery entries
server/src/server/skill_util.c: skill initialization, player linking, action-source skill selection, and melee wrapper
server/src/server/exp.c: skill levels/XP and point-milestone update hook
server/src/types/player.c: targeted melee loop, action recovery, player persistence lifecycle
Redesign player cap and endgame progression around level-101–115 group encounters #30 defines a proposed level-100 functional skill cap and bounded post-cap mastery/renown. Consolidating four melee and three archery XP bars materially changes skill/character pacing, so this issue's XP contribution, point schedule, and combat-power ceiling should follow that decision.
These GitHub sub-issues are the executable delivery units tracked by atrinik/atrinik#168. Each belongs to one roadmap milestone; this parent remains open until all are complete.
Important
This issue is implemented in the fresh MIT-licensed Go server under the replacement program. Its gameplay and content-design decisions remain authoritative. C, CPython, classic packet, file-path, and enum details in the preserved specification are historical evidence only; do not copy, translate, or structurally port GPL implementation code.
Replacement implementation contract
Keep this as the combat-disciplines epic. Its children establish identities in M2, prove the action framework in M3, and implement full disciplines in M5. All runtime ownership belongs to Go services and generated Rust contracts.
The server remains authoritative, consumes versioned compiled content, and exposes bounded generated Game Protocol 1 messages. Pure rules may use a specifically approved typed CEL environment. Starlark is not part of this issue unless the separate residual-scripting decision explicitly approves it.
Required verification
Preserved product/design specification and historical implementation notes
Summary
Add a server-authoritative, data-driven combat training system while consolidating Atrinik's overly narrow XP skills into broad disciplines:
This should provide melee area attacks without making every weapon behave like an axe. A rapier should not gain a circular cleave merely because the character has spent points in a generic perk; it should gain thrusting, lunging, precision, and line-attack options. Axes, greatswords, glaives, and some impact weapons can sweep, but with different target caps, arcs, damage, and recovery. The same vocabulary should extend naturally to bows, crossbows, slings, throwing weapons, unarmed combat, and future monster abilities.
The player-facing fiction is practice and instruction: skill levels represent broad experience in a discipline, functional character milestones grant the bounded shared specialization points owned by #9, active maneuvers are Techniques, and passive refinements are Masteries. A character should not have to re-level from scratch merely because they exchange an axe for a sword or a bow for a crossbow; the profile and selected branches change how that shared experience is expressed. Existing instructors such as Tom Istrad and John Aldman in the Lost Memories tutorial can explain archery and divine magic, while dedicated masters-at-arms can provide respecialization later.
Important terminology:
cleavealready means something elseAtrinik currently uses
cleaveas both:ATNR_CLEAVE,attack_cleave,protect_cleave); andSK_CLEAVE_WEAPONS), which this proposal retires in favor ofSK_MELEE_COMBAT.It does not currently mean “hit an area.”
attack_cleave 100only controls how damage is distributed into the target's cleave protection. Area eligibility must not be inferred fromattack[ATNR_CLEAVE]: a monster bite can deal cleave damage, a bolt currently deals cleave damage, and a sweeping sword may deal slash damage.Use sweep for the capability/shape and names such as Sweeping Cleave for particular techniques. Keep attack type, broad XP discipline, and maneuver capability as independent concepts.
What the codebase already provides
Skills and progression
server/src/include/skills.hcurrently defines four melee weapon skills, unarmed, throwing, and three separate bow/crossbow/sling archery skills.server/src/include/skillist.handserver/src/server/skill_util.cassociate those enum entries withskill_*archetypes underarch/intern/skills/.link_player_skills()clones every available skill archetype into the player. Skill objects already persist level and XP and are sent to the client.server/src/server/exp.clevels skill objects and sendsUPD_EXTRAupdates.client/src/gui/widgets/skills.ccurrently renders a flat icon grid with only name, description, level, and XP.server/src/socket/item.ccarries only level, XP, and description as its skill-specific payload.There are enum/table entries for
two-hand masteryandpolearm mastery, but no correspondingskill_two-hand_masteryorskill_polearm_masteryarchetypes.init_new_exp_system()therefore leaves them unavailable andlink_player_skills()skips them. Two-handed behavior otherwise exists only asFLAG_TWO_HANDED(primarily suppressing shield bonuses). Weapon directory names and the old editor subtype vocabulary are not reliable runtime polearm metadata.Broad XP disciplines, specialized technique branches
Replace the four wielded-melee XP skills with one
SK_MELEE_COMBATskill and oneskill_melee_combatarchetype:Every wielded melee weapon should use
SK_MELEE_COMBATthroughitem_skill. Its attack type and combat profile still decide protections, technique eligibility, shape, effectiveness, and tree branch. Unarmed remains a separate skill because it has a distinct equipment loop and base damage/speed archetype. Throwing also remains separate from archery because thrown inventory objects, strength scaling, recovery, and ammunition behavior are materially different.Likewise replace
SK_BOW_ARCHERY,SK_CROSSBOW_ARCHERY, andSK_SLING_ARCHERYwith oneSK_ARCHERYskill andskill_archeryarchetype.bow_get_skill(), all launcheritem_skillvalues, level requirements, item examination, projectiles, XP credit, scripts, editor lists, and tests should use the shared skill. Bow, crossbow, and sling profiles/branches retain distinct firing speed, damage, ammunition, and Techniques.This is an intentional breaking cleanup: remove the seven superseded skill enum entries and archetypes rather than keeping aliases or hidden compatibility skills. Update all authored weapons, artifacts, fixtures, scripts, plugin-facing skill names, and generated inputs together. If preserving a particular development save is later made a requirement, define a one-time offline conversion policy explicitly; do not blindly sum four nonlinear skill XP totals and inflate character progression.
Melee and ranged action paths
server/src/types/player.c, throughattack_is_melee_range(),skill_attack(), andattack_object().skill_attack()chooses the equipped weapon'sitem_skill;living_update_player()uses that skill level to increase WC and damage.attack_object()owns attack rolls, facing/animation, hitback, and the call intoattack_hit();attack_hit()owns friendship/PvP checks, protection, blocking, final damage, kill processing, and owner credit.freearr_x/freearr_y,get_map_from_coord(), map-layer iteration, andHEAD()already provide most primitives needed to collect a directional one-tile arc across tiled-map boundaries and deduplicate multipart monsters.server/src/types/bow.candserver/src/types/arrow.c; common projectile collision is inserver/src/types/common/projectile.c.player.action_attack/action_timeralready prevents overlapping attacks and displays recovery to the client. There is no stamina/fatigue resource today.Spellcasting is currently hardwired to Wizardry
Although content already calls cause light wounds and minor healing “divine magic” and calls holy word/remove depletion “prayers,” all directly cast
SPELLobjects selectSK_WIZARDRY_SPELLSincheck_skill_to_fire(). Spell books, scrolls, item requirements, spell-point display, rod checks, map scripts, and merchant dialogue also contain direct Wizardry assumptions.The current spell
pathfield describes an effect family such as Restoration, Turning, Fire, Wounding, or Death. It does not describe whether the power is arcane or divine. Atrinik also already has gods, worship lookup throughdetermine_god(), holy altars, consecration, priests, temples, and explicit divine tutorial dialogue. Those are sufficient lore foundations for a separate divine discipline, but not yet a complete casting contract.Useful persistence and content hooks
get_ob_diff()/object_save(). Stable node selections can therefore be attached to the existing per-character skill objects without inventing a second character database.MEVENT_SKILL_USEDexists for scripts, but the core attack and final-damage paths must remain authoritative C. A pre-attack script event is not sufficient for safe target collection, final damage, cooldowns, XP ownership, or recursion control.Design goals
Proposed player model
Unified specialization points
#9 owns the single connected specialization graph, bounded character-wide point pool, connectivity rules, persistence, and respec transaction. This issue contributes the combat-profile, Technique, Mastery, skill-level prerequisite, and effect definitions placed into that graph.
Functional character-level milestones grant the shared points under #30's cap and pacing. Use-based discipline levels remain prerequisites and scaling inputs: investment can path toward any cluster, but advanced Melee, Archery, Wizardry, Divine Magic, Unarmed, Throwing, or device nodes require actual experience in that discipline.
Do not create per-skill point balances or separate disconnected trees. Persist selected stable node IDs and purchase order in the typed specialization state owned by #9. Skill-level loss, removed nodes, or invalid references must deactivate/refund affected dependent branches deterministically without leaving an invalid build.
Respecialization
Use #9's server-authoritative full-reset and connected-branch refund transaction. Combat Techniques and Masteries must expose enough dependency, cooldown, equipment-profile, and active-action information for that transaction to cancel or deactivate them safely. Do not add a second per-discipline refund path.
No stamina bar in the first version
Techniques should consume the existing shared action recovery and also have per-technique cooldowns. This creates an opportunity cost versus a basic attack without adding a third combat resource and a new HUD/protocol/stat system.
Add an exertion/stamina resource only if target-dummy and encounter playtests show that cooldown/recovery tuning cannot prevent technique spam. Issue #28 will be useful for repeatable damage testing once implemented.
Spellcasting disciplines: Wizardry and Divine Magic
Add
SK_DIVINE_SPELLSwith askill_divine_spellsarchetype and keepSK_WIZARDRY_SPELLSfor arcane practice. Give every directly cast spell an explicitcasting_skill/tradition inspell_struct(or equivalent validated authored data):Classify every current spell deliberately. Do not infer tradition from spell path: Restoration is usually divine but could support an arcane spell later; Death or Wounding may be divine, arcane, or deity-specific; Protection and Light are not inherently one tradition. Spell path remains the effect/attunement taxonomy, while casting skill owns learning requirement, casting level, scaling, mana cost, XP, tree points, and UI grouping.
Update
check_skill_to_fire(),cast_spell(), spell books/scrolls, socket item metadata,SK_level()source context, kill XP, learning failures, requirements, merchants, scripts, tests, and player-facing descriptions to resolve the declared casting skill. Magic devices remain their own skill when a wand/rod/device is the action source; their interaction with a spell's tradition must be stated explicitly rather than accidentally borrowing Wizardry.Do not require worship for every Divine Magic cast in the first version: the current god system does not yet model a complete faith resource or granted-spell lifecycle. Allow individual divine spells such as consecrate to retain an explicit
requires_deityrule, and leave room for deity affinities, denied paths, and deity-specific Masteries later. Wizardry can lean on Intelligence and Divine Magic on Power where attribute scaling is redesigned, but the first required change is correct XP/level ownership rather than a second simultaneous resource rewrite.Candidate Divine Magic branches are Restoration, Warding, and Turning/Judgment; candidate Wizardry branches can build on elemental, force/missile, control, and utility paths. These use the same Technique/Mastery framework, but weapon-profile requirements do not apply to spells.
Data-driven weapon profiles
Add collected
combat_profile_*definitions and let weapon archetypes reference one stable profile, for example:A validated profile should contain:
sweep,wide_sweep,thrust,reach,stagger,parry,rapid,precision,power_draw,reload,ricochet, orfan_throw;Use shared profiles for families of similar weapons and allow a rare explicit override only when an individual archetype genuinely differs. Validate every reference during collection/startup and expose the resolved capability summary in item examination and the training UI. Do not infer behavior from a file path or display name.
The profile is separate from:
item_skill, which selects the XP discipline;attack_*, which selects damage types/protections;FLAG_TWO_HANDED, which remains an equipment fact;Representative profiles:
This answers the “all weapons can cleave, but some are better” question with a stricter and more legible rule: all weapons can use their discipline's universal fundamentals, but only profiles with a sweep capability can use an area sweep. A rapier is not merely bad at cleaving; it is ineligible and receives equally valuable thrust/precision techniques instead.
First active melee technique: Sweeping Cleave
Sweeping Cleave should be an explicit Technique, initially available to cleave-weapon profiles with
sweeporwide_sweep.Suggested baseline:
ATNR_CLEAVE;HEAD()objects, then resolve in deterministic order (primary, clockwise, counter-clockwise, distance/tag tie-break);A
wide_sweepprofile or later Mastery can raise the cap/arc or secondary scalar, but ordinary melee should stay local. Do not turn every swing into a screen-wide damage pulse.Candidate discipline trees and branches
These are an initial content vocabulary, not a requirement to ship every node at once. Implement the common framework plus one thin vertical slice first, then fill out trees using measured combat data.
Melee Combat: axe/cleaver branch — arcs, momentum, execution
wide_sweepprofiles.Melee Combat: sword branch — tempo, cuts, defense
wide_sweepweapons with a long cooldown.Melee Combat: thrust/reach branch — lines, reach, precision (no generic cleave)
thrust/reachand line of effect is clear.Melee Combat: impact branch — stagger, displacement, armor pressure
Unarmed — combinations, evasion, control
The Melee Combat tree may also contain a small shared-fundamentals branch, but it must not make every profile eligible for every maneuver. A player can earn Melee Combat XP with an axe and then equip a rapier at the same skill level; the rapier's profile and currently selected nodes determine the available actions. This shared progression is intentional and avoids four parallel grinds.
Do not revive
SK_TWOHANDSandSK_POLEARMSas separate XP bars. Two-handed and hafted/reach behavior is a cross-cutting weapon profile layered onto Melee Combat. Remove the currently unreachable enum/table entries or repurpose them only if a later design establishes a real independent progression loop.Archery: bow branch — mobility, power draw, volleys
Archery: crossbow branch — preparation, penetration, control
Archery: sling branch — speed, ricochet, concussion
Throwing — weapon-aware fans and heavy throws
fan_throw; bounded projectiles and ammunition consumption.The Archery tree may contain a shared-marksman branch for accuracy, target tracking, or ammunition handling, while launcher profiles keep bow draw, crossbow reload, and sling ricochet mechanics distinct. Switching launcher families does not reset Archery XP.
Combat action context and attack refactor
Do not implement techniques by temporarily mutating
chosen_skill, damage, direction, or the equipped weapon around repeated calls toattack_object(). That becomes unsafe as soon as an attack has multiple targets or delayed projectiles.Introduce an explicit combat action context, conceptually containing:
Refactor normal melee and projectile creation to populate this context, while preserving a simple wrapper for ordinary attacks. Owned delayed effects/projectiles must carry the source discipline and relevant snapshot so kill XP does not depend on whichever skill the owner happens to have readied when the projectile lands.
The context should make these policies explicit:
FLAG_HITBACKresponse to secondary sweep damage unless a technique explicitly opts in);Basic attacks, spells, and old callers can use a default context. This is a cleaner foundation than adding one cleave-only loop inside
skill_attack().Target collection rules
Add reusable server helpers for bounded combat shapes: adjacent arc, adjacent ring, line, cone/fan, and selected-radius area. A shape returns stable
(object pointer, count)handles before damage begins.Every helper must:
get_map_from_coord()so horizontal tiled-map edges work;HEAD();Do not reuse persistent cone spell objects for an instantaneous melee sweep; they have different lifetime, movement, and multi-tile-damage semantics.
Authored technique definitions
Add collected
technique_*archetypes (or an equivalently validated authored registry) with stable IDs. Definitions should own presentation and bounded tuning data:Startup/collection validation must reject duplicate IDs, missing disciplines/profiles/faces, cycles, impossible prerequisites, out-of-range scalars/caps, and active nodes without an implemented server handler. Arbitrary script or expression execution must not be embedded in node data.
Protocol and client UI
This is an intentional client/server feature and should use explicit protocol support rather than encoding the tree into skill description text.
Add server-authoritative messages for:
The client must never send damage, targets beyond the requested aim, rank, or effect values.
Extend/replace the current flat skills widget with:
Add bounded command parsing and update
common/toolkit/socket.h, both dispatch tables, packet tests, and protocol documentation together. A dedicatedTECHNIQUEclient item/action type is preferable to pretending an active technique is a level-bearingSKILL; stable technique IDs should survive reconnects even when transient object tags do not.Balance and progression rules
Implementation sequence
Phase 0: consolidate XP skills and declare spell traditions
SK_MELEE_COMBAT/skill_melee_combatand update every melee weaponitem_skillconsumer/definition.SK_ARCHERY/skill_archeryand update launchers, projectiles, requirements, scripts, editor metadata, fixtures, and tests.SK_DIVINE_SPELLS, explicit per-spell casting skill/tradition, and deliberately classify every current spell.Phase 1: combat-action foundation and one vertical slice
Phase 2: complete Melee Combat and Unarmed
Add sword, thrust/reach, impact, and shared-fundamentals branches to Melee Combat plus the separate Unarmed tree. Profile all current melee weapons, add control-immunity rules, and add player-facing item/profile examination.
Phase 3: complete Archery and Throwing
Add bow, crossbow, sling, and shared-marksman branches to Archery plus the separate Throwing tree. Refactor projectile source context, multi-projectile ammunition handling, and delayed/area targeting once rather than separately per launcher.
Phase 4: spell Masteries and divine content integration
Add initial Wizardry and Divine Magic branches, update John Aldman's tutorial and relevant temples/books/merchants, and validate learning/scaling/XP for direct casts, scrolls, and devices.
Phase 5: content and AI integration
Integrate tutorial instructors and respec NPCs, give selected monsters authored techniques, add encounter telegraphs/effects, and tune progression/trees against the level-cap/mastery decision in #30.
Validation
Server unit tests
Client and protocol tests
Content validation
Acceptance criteria
ATNR_CLEAVE, the retired cleave-weapon XP skill, shared Melee Combat XP, and sweep/AoE capability are documented and implemented as independent concepts.SK_MELEE_COMBATXP level; their old skill enums/archetypes and aliases are removed.SK_ARCHERYXP level; their old skill enums/archetypes and aliases are removed.chosen_skill.Relevant source areas
server/src/include/skills.h,server/src/include/skillist.h: current narrow weapon/archery disciplines, new broad skills, Divine Magic, and unreachable mastery entriesserver/src/server/skill_util.c: skill initialization, player linking, action-source skill selection, and melee wrapperserver/src/server/exp.c: skill levels/XP and point-milestone update hookserver/src/types/player.c: targeted melee loop, action recovery, player persistence lifecycleserver/src/server/living.c: shared Melee Combat skill, WC/damage, spell-point scaling, and two-handed equipment behaviorserver/src/server/attack.c: attack rolls, hitback, protections, final damage, kills/XP, melee range, and future action contextserver/src/types/bow.c,server/src/types/arrow.c,server/src/types/common/projectile.c: archery/throwing damage, source ownership, collision, and delayed creditserver/src/include/spells.h,server/src/include/spellist.h,server/src/server/spell_util.c: explicit spell casting tradition/skill, paths, scaling, and action sourceserver/src/types/spell.c,server/src/types/book_spell.c,server/src/types/scroll.c,server/src/types/rod.c,server/src/types/common/apply.c: casting, learning, devices, requirements, and current Wizardry assumptionsserver/src/include/object.h,server/src/loaders/object.l,server/src/server/object.c: profile fields/key-values and skill-object persistenceserver/src/socket/item.c,server/src/socket/request.c,server/src/socket/server.c: skill payload, action input, cooldown stats, and command dispatchcommon/toolkit/socket.h: shared commands and packet constantsclient/src/gui/widgets/skills.c,client/src/gui/widgets/quickslots.c: current flat skill UI and quickslot behaviorclient/src/client/commands.c,client/src/client/client.c: state parsing and dispatcharch/intern/skills/: replace narrow melee/archery skills and add Divine Magic description/iconarch/intern/spells/: deliberate Wizardry/Divine Magic classification for every directly cast spellarch/items/weapon/: authored weapon skills, damage types, two-handed flags, and future profile referencesarch/dev/editor/conf/: editor support and stale weapon subtype descriptionsmaps/python/Merchant.pyand related scripts/tests: current string/hardcoded Wizardry lookupsmaps/interfaces/quests/lost_memories/quest.xml: existing lore-friendly archery and divine-magic instructors/tutorial integration pointsRelated issues
Proposal: add a classless connected specialization tree with respecs #9 owns the classless connected specialization graph, shared point pool, connectivity, persistence, and respec policy. This issue owns the combat actions and node effects placed into it.
Redesign player cap and endgame progression around level-101–115 group encounters #30 defines a proposed level-100 functional skill cap and bounded post-cap mastery/renown. Consolidating four melee and three archery XP bars materially changes skill/character pacing, so this issue's XP contribution, point schedule, and combat-power ceiling should follow that decision.
Add target-dummy DPS testing with timed, per-player results #28 proposes authoritative target-dummy DPS sessions suitable for technique tuning.
Child issues
These GitHub sub-issues are the executable delivery units tracked by atrinik/atrinik#168. Each belongs to one roadmap milestone; this parent remains open until all are complete.
M2
M3
M4