Skip to content
Acook1e edited this page May 20, 2026 · 4 revisions

Rim Combat

Rim Combat is a melee combat overhaul framework for Skyrim SE/AE built around stamina pressure, posture damage, timed defense, executions, and animation-driven Weapon Arts.

This project is already playable in game and the core combat loop is real, but it is not a finished, full-polish overhaul yet. The current build should be understood as a serious public prototype: strong enough to test, tune, extend, and build content on top of, but still actively growing in scope and presentation.


For Players

What Rim Combat already does

  • Rebuilds melee combat around resource pressure instead of pure stat trading.
  • Adds differentiated stamina consumption for normal attacks, power attacks, weapon classes, and special actions.
  • Adds an exhaustion layer that affects combat flow when stamina is pushed too low.
  • Adds a posture system with posture damage, posture recovery, posture break, and execution entry.
  • Adds block and timed block interactions to create risk/reward defense instead of flat passive mitigation.
  • Adds a functional Weapon Art framework with assignment, HUD support, menu support, and animation-driven effects.
  • Adds a custom stagger extension layer that can cooperate with external poise and stagger mods instead of replacing them outright.
  • Adds prototype executions that already work as gameplay, even though they are not content-complete yet.

What the current release should be considered

This is not being presented as a final, fully polished combat overhaul.

The current release is best understood as:

  • a playable combat prototype
  • a balancing sandbox
  • an animation-driven combat framework
  • a base for future content packs and integration work

The strongest part of the project today is the system loop. The weakest part is still edge-case coverage, presentation polish, NPC coverage, and fully finished content breadth.

Current feature status

System Status
Attack stamina Implemented
Exhaustion Implemented
Posture Implemented
Block / timed block Implemented
Weapon Art menu / HUD / assignment Implemented
Weapon Art progression / persistence Partially complete
Executions Prototype but functional
Special stagger rules Partially complete
In-game settings menu Basic only
NPC Weapon Art logic Not finished
Broad multi-race execution coverage Not finished

What Rim Combat is aiming to become

Rim Combat is meant to grow into a combat overhaul that does not just add flashy moves, but creates a full melee rule set where:

  • stamina matters before, during, and after every commitment
  • posture pressure creates real openings instead of being a cosmetic extra bar
  • blocking becomes an active decision instead of a binary safety state
  • executions become a readable reward state after pressure and break
  • Weapon Arts become modular, data-driven, and animation-authored instead of hardcoded one-offs
  • custom reactions such as knockdown, launch, and other special stagger states can be authored cleanly through animation logic

What is still unfinished

  • The in-game settings menu is still minimal compared to the number of systems already implemented.
  • Weapon Art logic currently focuses on the player side first; NPC-side usage is still incomplete.
  • Executions work, but animation polish, movement control, rotation control, and broader race coverage still need more work.
  • Special stagger has a real runtime path now, but content breadth and animation coverage are still limited.
  • This is not yet the version that should be judged as the final balance target of the project.

Requirements and recommended setup

Core runtime dependencies:

  • SKSE
  • OAR
  • MCO or BFCO

Recommended companion mods:

  • TrueHUD for posture display
  • PrismaUI for the Weapon Art menu and HUD
  • Maxsu Poise for baseline poise behavior
  • Modern Stagger Lock for stable ordinary stagger thresholds

Rim Combat does not currently try to replace the entire external hit-reaction ecosystem by itself. Ordinary stagger behavior is expected to work best when paired with the recommended ecosystem.

Recommended release positioning on Nexus

If this is published as a public base version, the most honest positioning is:

  • a public foundational release
  • focused on the mature melee core first
  • expandable through future animation packs and data updates
  • not yet a definitive 1.0 combat package

That positioning matches the real state of the code much better than calling it a finished overhaul.


For Mod Developers

This section is for animation authors, moveset authors, plugin developers, and anyone who wants to build content on top of Rim Combat.

Runtime model in one page

Rim Combat uses a two-way contract between the plugin and the animation layer:

  1. BehaviorDataInjector registers custom animation events and graph variables.
  2. The plugin writes graph variables such as active Weapon Art ID, Weapon Art state, execution flags, and stagger state.
  3. OAR reads those graph variables and decides which animation package should play.
  4. The selected animations emit Rim Combat payload events back into the game.
  5. The plugin receives those payloads, caches action data, and applies them later inside hit, stagger, posture, stamina, and execution hooks.

In short:

  • plugin -> graph variables -> OAR animation selection
  • animation events -> payloads -> plugin gameplay effects

That split is intentional. The animation layer decides intent and timing. The plugin decides gameplay consequences.

BehaviorDataInjector contract

The current BDI file registers these custom entries:

Events:

  • RimDamage
  • RimStagger
  • RimStamina
  • RimPosture
  • RimWeaponArt
  • RimExecution

Graph variables:

  • RimCombat_StaggerLevel: Int
  • RimCombat_StaggerImmune: Int
  • RimCombat_WeaponArtID: Int
  • RimCombat_WeaponArtState: Int
  • RimCombat_Executable: Bool
  • RimCombat_ExecutionFlag: Int

These are registered in the runtime BDI config so that behaviors and OAR conditions can reference them directly.

Event dispatch behavior

Animation tags and payload text are normalized to lowercase before dispatch.

That means authors should treat the runtime protocol as case-insensitive, but it is still best practice to write payloads in lowercase for clarity.

The central dispatcher currently routes:

  • RimDamage -> damage multiplier cache
  • RimExecution -> execution damage / execution end
  • RimStagger -> target stagger override / stagger immunity / cleanup
  • RimStamina -> custom stamina channel and action cost
  • RimPosture -> posture damage multiplier and unbreakable state
  • RimWeaponArt -> Weapon Art start, end, prepare transition, and optional spell cast

The dispatcher also clears cached attack-scoped state on common stop events such as attackstop and interruptcast.

Payload system overview

The payload system is designed around two kinds of state:

Action-scoped state:

  • attack-local values that should be applied during the current move and then cleared
  • examples: damage multiplier, posture damage multiplier, target stagger override, custom stamina channel

Duration-scoped state:

  • timed states that survive beyond one hit frame and expire by duration
  • examples: posture unbreakable windows and stagger immunity windows

This distinction matters when authoring events. Not every payload should be cleaned with a shared end marker.

Payload reference

RimStamina

Purpose:

  • switches an action to the Rim Combat stamina channel
  • consumes stamina based on attack type and branch state

Accepted payloads:

  • start
  • end
  • consume|AttackType|Side|Multiplier|FallbackMultiplier

Notes:

  • AttackType is interpreted as normal or power.
  • Side can be left, right, or auto.
  • Multiplier is used when the action is in the Weapon Art eligible branch.
  • FallbackMultiplier is used when the action is in the subordinate branch.
  • During the custom stamina channel, the default weaponSwing stamina route is suppressed.

RimDamage

Purpose:

  • applies a cached melee damage multiplier for the current action

Accepted payloads:

  • setmult|Multiplier|FallbackMultiplier
  • end

Notes:

  • The multiplier is cached on the attacker and applied later in melee hit processing.
  • end clears the current cached damage multiplier.

RimPosture

Purpose:

  • applies cached posture damage multipliers
  • grants temporary posture-break immunity windows

Accepted payloads:

  • unbreakable|Duration
  • breakable|Duration
  • damage|Multiplier|FallbackMultiplier
  • end

Notes:

  • unbreakable|Duration is the intended contract for timed posture-break immunity.
  • breakable|Duration is still accepted by the current parser, but it behaves as a compatibility alias into the same timed handling path. New content should prefer unbreakable|Duration.
  • damage|... is action-scoped and should be cleared with end or a stop event.
  • unbreakable is duration-scoped and is not meant to be ended by the action cleanup marker.

RimStagger

Purpose:

  • applies extra stagger levels
  • modifies the stagger level of the current target
  • grants temporary stagger immunity windows

Accepted payloads:

  • end
  • targetset|Level
  • targetmodify|Delta
  • targetend
  • immune|Level|Duration

Notes:

  • targetset and targetmodify are cached per aggressor and applied later in the TryStagger path.
  • If both targetset and targetmodify exist for the same action, the set value takes priority.
  • immune is duration-scoped.
  • targetend is action-scoped cleanup.
  • Common stop events already clear target stagger overrides automatically, and RimWeaponArt end also clears them, but explicit targetend is still recommended for custom branches that do not rely on standard stop timing.

RimExecution

Purpose:

  • applies execution hit damage during an execution sequence
  • signals execution end

Accepted payloads:

  • damage|Multiplier
  • end

RimWeaponArt

Purpose:

  • starts a Weapon Art action
  • manages prepare and enabled states
  • optionally casts a spell payload from the animation

Accepted payloads:

  • start|ManaCost|MinMana
  • end
  • prepareend
  • toprepare
  • cast|SpellName

Notes:

  • start sets the current action into either an eligible branch or a subordinate branch based on the actor's current magicka.
  • If the actor meets MinMana, Rim Combat consumes ManaCost magicka and marks the action as eligible.
  • If the actor does not meet MinMana, the action can still run as subordinate and downstream payloads can use fallback values.
  • start also enables the Rim Combat stamina channel for that action.
  • end clears the current Weapon Art perform state and also clears cached attack-scoped Damage, Stagger target override, Stamina, and Posture data.
  • start should not be placed on frame 0, because MCO/BFCO can double-fire frame-0 events.
  • cast|SpellName now looks up a pre-parsed spell definition from the current Weapon Art instead of passing spell parameters through the animation event.
  • Spell keys are normalized to lowercase before hashing, matching the event dispatcher behavior.
  • stdMagnitude is defined as the spell's standard strength at skill level 25.
  • Final spell strength is currently computed as stdMagnitude * (1 + (SkillMod + SkillPower) / 100) * pow(skillLevel / 25, factor / (factor + 10)).
  • factor must be non-negative. Larger values make the skill curve steeper, while still keeping 25 as the baseline where the curve equals 1.
  • In current testing, CastSpellImmediate does not apply the same skill multiplier again, so the manual magnitude scaling is the effective scaling path.

Eligible vs subordinate Weapon Art branches

One of the key design points in the current payload system is that a Weapon Art does not have to be all-or-nothing.

When RimWeaponArt start|ManaCost|MinMana fires:

  • the plugin checks current magicka
  • the action is marked as eligible if magicka is high enough
  • otherwise it is marked subordinate

Other payloads can then choose between:

  • a stronger eligible value
  • a weaker fallback value

This lets one animation branch stay playable even when the full Weapon Art condition is not met.

Weapon Art registration

Weapon Arts are loaded from JSON files under the runtime Weapon Art directory:

  • dist/SKSE/Plugins/RimCombat/WeaponArt/*.json

Each top-level JSON key is hashed into the runtime Weapon Art ID. That means the key itself is not just a label. It is part of the runtime contract.

If you rename a top-level key after release:

  • the hash changes
  • the OAR condition value changes
  • existing assignments and animation conditions for that art will no longer match

Keep those keys stable.

Required fields per Weapon Art entry:

  • name
  • description
  • weapons
  • availableWeapon
  • consumePoint
  • unlockLevel
  • needPrepare

Optional structured spell field:

  • spells

Optional field:

  • verbose

If verbose is true, the plugin logs the loaded Weapon Art name and its hashed ID. This is the easiest way to get the exact value you need for OAR conditions.

Minimal registration example

{
  "VacuumSlash": {
    "name": "Vacuum Slash",
    "description": "Release a forward cutting wave.",
    "weapons": [],
    "availableWeapon": ["Normal", "Heavy", "Slash"],
    "spells": {
      "windblade": {
        "mod": "RimCombat.esp",
        "formID": "00000800",
        "selfCast": false,
        "effectiveness": 1.0,
        "stdMagnitude": 25.0,
        "skill": "Destruction",
        "factor": 4.0
      }
    },
    "consumePoint": 2,
    "unlockLevel": 0,
    "needPrepare": false,
    "verbose": true
  }
}

Spell definition fields:

  • mod: plugin name used to resolve the spell form
  • formID: spell form ID string, currently parsed as hexadecimal
  • selfCast: whether the spell targets the caster instead of no explicit target
  • effectiveness: direct effectiveness parameter passed to CastSpellImmediate
  • stdMagnitude: standard spell strength at skill level 25
  • skill: skill used for the growth curve and the percent modifier pool
  • factor: non-negative growth sensitivity for the skill curve

Weapon matching rules

availableWeapon is a flag-based rule set.

It supports:

  • weight groups such as Light, Normal, Heavy
  • attack traits such as Slash, Thrust, Blunt, Polearm, Range
  • family traits such as Sword, Axe, Hammer, Katana, Spear, Whip, Bow, and more
  • Unique for explicit per-weapon lists

Important matching behavior:

  • if weight is omitted, that group becomes a wildcard
  • if weapon family is omitted, that group becomes a wildcard
  • if Unique is used, the explicit weapons list is used instead of generic type matching

Weapon Art assignment is persisted per weapon FormID, and the actor's active Weapon Art ID is derived from the equipped right-hand weapon.

Graph variables and OAR

Weapon Arts

Weapon Art animation packages are selected by OAR through two graph variables:

  • RimCombat_WeaponArtID
  • RimCombat_WeaponArtState

State values are:

  • 0 = disabled
  • 1 = prepare
  • 2 = enabled

Typical OAR conditions check both:

  • the art ID matches the desired Weapon Art
  • the state matches prepare or enabled

If needPrepare is true in the Weapon Art definition, enabling that art puts the actor into state 1 first. The animation is then expected to send RimWeaponArt|PrepareEnd to move to state 2.

Executions

Executions use:

  • RimCombat_Executable
  • RimCombat_ExecutionFlag

RimCombat_ExecutionFlag is the practical animation selector. OAR conditions can use a non-zero execution flag to swap into the paired execution package.

Special stagger

Special stagger animation packages use:

  • RimCombat_StaggerLevel

This allows OAR to branch into extra reactions such as knockdown, strikefly, or knockaway while the plugin still handles the gameplay side of stagger routing.

The relationship in plain terms

The plugin should decide state. OAR should decide animation. Animations should decide exact timing. Payloads should decide move-specific gameplay deltas.

That separation is the core design rule of Rim Combat's animation integration.

Recommended authoring pattern

For a normal Weapon Art attack, a clean event sequence usually looks like this:

  1. Use OAR conditions to enter the correct animation package through RimCombat_WeaponArtID and RimCombat_WeaponArtState.
  2. Emit RimWeaponArt|Start|ManaCost|MinMana after frame 0.
  3. Emit move-specific payloads such as RimDamage, RimPosture, RimStamina, or RimStagger at the right action window.
  4. Emit RimWeaponArt|End when the Weapon Art action finishes.
  5. Rely on attackstop or interruptcast cleanup as a fallback, not as your only authoring discipline.

Example payload chain

RimWeaponArt|Start|15|15
RimStamina|Consume|Normal|Auto|1.10|1.00
RimDamage|SetMult|1.25|1.00
RimPosture|Damage|1.40|1.00
RimStagger|TargetSet|5
RimWeaponArt|End

Because the event dispatcher lowercases payloads internally, the runtime will treat these as lowercase.

Best practices for content authors

  • Keep top-level Weapon Art JSON keys stable after release.
  • Use verbose: true while authoring to capture the hashed Weapon Art ID in logs.
  • Prefer unbreakable|Duration over breakable|Duration for new posture content.
  • Treat immune and unbreakable as timed states, not one-hit flags.
  • Treat setmult, damage, targetset, and similar attack modifiers as action-scoped caches that must be cleaned.
  • Do not put RimWeaponArt start on frame 0.
  • If your move branches around the normal stop path, emit explicit cleanup markers instead of assuming the engine will always hit the same stop event.

Closing Position

For players, Rim Combat is already worth testing if you want a more deliberate melee loop built around stamina, posture, defense timing, executions, and Weapon Art integration.

For mod authors, Rim Combat is already useful as a framework: the payload contract is real, the Weapon Art registration path is real, the BDI and OAR integration is real, and the project is now at the stage where external content can start being built on top of it.

The project is not finished. The foundation is.

Clone this wiki locally