Ricochet - Arrow Physics Framework - API Usage

Table of Contents

📌 Introduction

Ricochet - Arrow Physics Framework is a modular system that lets mod creators define custom behaviors, visuals, and sounds for projectiles upon fracture. It provides a simple but flexible JSON-based mapping API to control how each arrow or bolt reacts when hitting different materials or objects.

Creators can assign durability values, fracture probabilities, and sound or impact effects to any projectile type. Filters and modifiers allow fine-grained control based on weapon type, ammunition, material, impact velocity, or even global conditions.

In short, the Ricochet Framework provides a flexible and fully configurable foundation that allows any mod to add fracture behavior to its arrows or bolts, without requiring a direct dependency on the framework.

🔹 Available Filters

Filters let you control when and how arrows or bolts break, based on simple criteria:

These filters make it easy to customize fracture behavior for different situations.

🔹 Modifiers

Modifiers control the visual and sound effects when arrows break. You can choose which effects play, add extra sounds, or spawn broken arrow pieces.

With filters and modifiers, you can make arrow impacts feel varied, realistic, and immersive.

📌 Prerequisites

Before starting this tutorial, and to save time, make sure you have the following skills:

If you're not comfortable with any of these skills or tools, it is recommended to acquire them before following this tutorial.

Great, now that we're all set up, let's dive into using the Ricochet Framework API.

📌 Location of JSON Files

The JSON files should be placed in Data/SKSE/RicochetFramework. The exact organization of these files doesn't matter as long as they remain in this directory. You are free to organize them in subfolders as you see fit.

Similarly, there are no specific rules for naming the files: you are completely free to name them however you like.

In summary: as long as they are in this folder (or sub-folder), everything is fine. The rest is up to you! ✅

📌 Ammo Mapping

AmmoMapping defines how a specific arrow or bolt behaves when it breaks. Each entry specifies the original projectile (ammunition), its durability, the broken item it produces, and the possible broken states with associated effects.

Example: Defining a custom broken state for Falmer Arrows.

{
  "AmmoMapping": [
    {
      "ID": "FalmerArrow",
      "AmmoBase": "Skyrim.esm:0x38341",
      "AmmoBroken": "Broken Feathers.esp:0x809",
      "Durability": 20.0,
      "BrokenStates": [
        {
          "Chances": 50.0,
          "ProjectileSwap": "Broken Feathers.esp:0x827"
        },
        {
          "Chances": 50.0,
          "ProjectileSwap": "Broken Feathers.esp:0x828",
          "ExtraProjectiles": ["Broken Feathers.esp:0x829"]
        }
      ]
    }
  ]
}

🔹 Properties

ID

Description: Unique identifier for this AmmoMapping.
This field is referenced in FractureMapping to link fracture events to this specific arrow or bolt.

Possible Values: String

Example: "FalmerArrow"

AmmoBase

Description: The original projectile this mapping applies to.

Possible Values: FormID (Ammunition)

Example:

"AmmoBase": "Skyrim.esm:0xCEE9E"

AmmoBroken

Description: The object added to the actor's inventory when the broken arrow is picked up.

Possible Values: FormID (Bound Object: any item that can be held in the inventory)

Example:

"AmmoBroken": "Plugin.esp:0x800"

Durability

Description: It is the durability of the arrow, expressed as a percentage. Depending on the impact angle, velocity, and all other parameters provided by the framework, the arrow's durability will also determine whether it should break or not.

Possible Values: Float, EditorID (Global Variable), FormID (Global Variable)

Example:

"Durability": 25.0

BrokenStates

Description: Array of possible outcomes when the projectile breaks.

  • Chances: Probability of this state occurring.
    Possible Values: Float
  • ProjectileSwap: The new projectile spawned.
    Possible Values: FormID (Projectile)
  • ExtraProjectiles: Optional additional pieces spawned when breaking.
    Possible Values: FormID (Projectile)

Example:

"BrokenStates": [
  {
    "Chances": 50.0,
    "ProjectileSwap": "Broken Feathers.esp:0x827"
  },
  {
    "Chances": 50.0,
    "ProjectileSwap": "Broken Feathers.esp:0x828",
    "ExtraProjectiles": [
      "Broken Feathers.esp:0x829"
    ]
  }
]

With Ammo Mapping, mod creators can add fracture behavior and custom visual effects to any arrow or bolt, fully configurable and without creating hard dependencies on the Ricochet Framework.

📌 Fracture Mapping - Structure and Functioning

{
  "FractureMapping": [
    {
      "Priority": 10,
      "Override": false,
      "Filters": {
        "Ammunitions": ["Skyrim.esm:0x38341"]
      },
      "Modifiers": {
        "Fracture": true,
        "AmmoID": "FalmerArrow"
      }
    }
  ]
}

FractureMapping is an array in your JSON file that defines the conditions under which arrows or bolts can break upon impact. Each entry specifies filters that determine when a fracture may occur and, if triggered, which configuration from AmmoMapping should be used to handle the resulting behavior.

This link is established through the AmmoID field, which directly corresponds to the ID value defined in an AmmoMapping entry. When a projectile meets all the fracture conditions, the framework automatically applies the associated AmmoMapping, allowing you to define what broken model to spawn, and whether additional effects or projectiles should be generated.

The elements of FractureMapping are:

📌 Fracture Mapping - Filters

Each filter represents a condition that must be satisfied for the modifiers to be applied. You only need to define the filters you intend to use; it is not required to declare all of them. Filters within the same group are inclusive, meaning all specified filters in that group must be satisfied simultaneously for the effect to trigger.

However, within the arrays of each filter, the values work in OR: For example, if a weapon filter lists multiple specific weapons in the Weapons array and you define multiple projectiles in the Projectiles array, the effect will only apply when at least one of the listed weapons is used and that weapon must have shot at least one of the listed projectiles to satisfy the condition.

The only exception to this OR system is for Global Variables, which must all be validated for the filter to be considered fulfilled. In other words, if multiple Globals are defined, they function in AND, and each condition must be satisfied for the modifiers to apply.

📝 Before moving on to the filter list, here are a few clarifications on the use of FormID and EditorID in the JSON:

Complete List of Filters

Parameter Description and Possible Values
Globales

Description: Defines conditions based on global game variables. Each entry consists of three elements: the global variable (EditorID or FormID), a comparison operator, and a value (integer or float). This is useful for triggering effects only when specific global game states are met.

Possible Values: Array of 3 elements:

  • Global Variable: EditorID (Global Variable), FormID (Global Variable)
  • Comparison: ==, !=, <, >, <=, >=
  • Value: Int, Float

Example:

"Globales": [
  ["My_Custom_GV", "==", 1],
  ["Plugin.esp:0x800", ">=", 100.0]
]

Weapons

Description: Restricts effects to a specific array of weapons. This filter is ideal for applying effects to attacks performed with specific weapon. Only weapon forms are accepted.

Possible Values: FormID (Weapon)

Example:

"Weapons": ["Plugin.esp:0x800", "Plugin.esp:0x801"]
WeaponKeywords

Description: Matches any of the listed keywords against the relevant weapon. Keywords make it possible to group and target weapons sharing a common trait.

Possible Values: EditorID (Keyword), FormID (Keyword)

Example:

"WeaponKeywords": ["WeapTypeBow", "Plugin.esp:0x800"]
Ammunitions

Description: Filters by specific ammunition types. Only ammunition objects (arrows, bolts, etc.) are accepted.

Possible Values: FormID (Ammunition)

Example:

"Ammunitions": ["Plugin.esp:0x800", "Plugin.esp:0x801"]
AmmunitionKeywords

Description: Matches any of the listed keywords against the ammunition used. This allows for easy grouping.

Possible Values: EditorID (Keyword), FormID (Keyword)

Example:

"AmmunitionKeywords": ["VendorItemArrow", "Plugin.esp:0x800"]
Projectiles

Description: Restricts effects to specific projectile forms. Use this to apply special logic depending on the projectile type (e.g., magic bolts, custom arrows).

Possible Values: FormID (Projectile)

Example:

"Projectiles": ["Plugin.esp:0x800", "Plugin.esp:0x801"]
Materials

Description: Checks if the hit object or target actor's material type matches any in the list. Typically used to differentiate surface or skin materials during impact events.

Possible Values: FormID (MaterialType)

Example:

"Materials": ["Skyrim.esm:0x12F34", "Plugin.esp:0x800"]
HitObjects

Description: Filters based on the specific object that was hit. Can reference either a placed reference (RefID) or its base object (BaseID). Only valid for bound objects (e.g., static objects, movable objects, or placed items). Useful for controlling effects when hitting specific environmental assets.

Possible Values: FormID (Reference or Bound Object)

Example:

"HitObjects": ["Plugin.esp:0x800", "Plugin.esp:0x801"]
Percentage

Description: Defines a probability threshold for the effect to trigger. This value can also be driven by a global variable (EditorID or FormID) for dynamic control.

Possible Values: Float, EditorID (Global Variable), FormID (Global Variable)

Example:

"Percentage": 25.0
MinPower

Description: Sets the minimum charge power required for the filter to pass. The value typically ranges from 0.0 to 1.0, where 1.0 represents a fully charged shot (e.g., a fully drawn bow). Can also reference a global variable for adjustable thresholds.

Possible Values: Float (0.0 – 1.0), EditorID (Global Variable), FormID (Global Variable)

Example:

"MinPower": 0.5
MaxPower

Description: Sets the maximum charge power allowed for the filter to pass. The value typically ranges from 0.0 to 1.0, where 1.0 represents a fully charged shot (e.g., a fully drawn bow). Can also reference a global variable for dynamic thresholds.

Possible Values: Float (0.0 – 1.0), EditorID (Global Variable), FormID (Global Variable)

Example:

"MaxPower": 1.0
MinVelocity

Description: Filters by minimum projectile velocity. Only applies when the attack involves a projectile or thrown weapon. Can be set to a global variable for dynamic scaling.

Possible Values: Float, EditorID (Global Variable), FormID (Global Variable)

Example:

"MinVelocity": 1000.0
MaxVelocity

Description: Sets an upper limit for the projectile velocity filter. Useful to restrict effects to slower or faster projectiles only. Can reference a global variable.

Possible Values: Float, EditorID (Global Variable), FormID (Global Variable)

Example:

"MaxVelocity": 1500.0
ArrowSticks

Description: Boolean filter indicating whether the arrow or projectile sticks to the target upon impact. Can be used to trigger specific effects when projectiles embed into the actor or surface.

Possible Values: true, false, EditorID (Global Variable), FormID (Global Variable)

Example:

"ArrowSticks": true
IsActor

Description: Boolean filter checking whether the hit target is an actor (NPC or creature). Useful when you want an effect to apply exclusively to living entities, excluding inanimate objects or static forms. Can also reference a global variable.

Possible Values: true, false, EditorID (Global Variable), FormID (Global Variable)

Example:

"IsActor": true

📌 Fracture Mapping - Modifiers

Once the filters are validated, the following modifiers may be applied.

Parameter Description and Possible Values
AmmoID

Description: Links the projectile to a specific AmmoMapping entry. When the projectile meets all fracture conditions, the framework applies the associated AmmoMapping, defining which broken model to spawn and whether additional effects or projectiles are generated.

Possible Values: String (ID defined in AmmoMapping)

Example:

"AmmoID": "ArrowIron"
Fracture

Description: Boolean flag indicating whether the projectile can fracture upon impact, triggering the associated AmmoMapping effects.

Possible Values: true, false, EditorID (Global Variable), FormID (Global Variable)

Example:

"Fracture": true
ImpactBounce

Description: Determines whether a projectile will physically bounce upon impact. This is a boolean flag rather than a probability value.

Possible Values: true, false, EditorID (Global Variable), FormID (Global Variable)

Example:

"ImpactBounce": true
ImpactSound

Description: Overrides the default impact sound with a custom sound descriptor form.

Possible Values: FormID (Sound Descriptor)

Example:

"ImpactSound": "Plugin.esp:0x800"
ExtraImpactSounds

Description: Array of additional sounds that are played upon impact alongside the primary impact sound.

Possible Values: Array of FormID (Sound Descriptor)

Example:

"ExtraImpactSounds": ["Plugin.esp:0x800", "Plugin.esp:0x801"]
ExtraImpactEffects

Description: Array of additional impact effects applied when the projectile hits. Each effect is played individually; no sound or decal is applied.

Possible Values: Array of FormID (ImpactData)

Example:

"ExtraImpactEffects": ["Plugin.esp:0x800", "Plugin.esp:0x801"]

📌 Testing in the Game

After configuring your JSON files, it is crucial to test your changes in the game to ensure they work as intended. If you encounter a crash when launching the game, it likely means that the structure of one of your JSON files is malformed (possibly an extra comma). Feel free to use tools like JSON Formatter to validate your JSON files or find potential errors.

Once the game is running, be sure to check the RicochetFramework.log file (located in Documents\My Games\Skyrim Special Edition\SKSE) for any errors or issues with your JSON files. Regularly check this file during your testing to identify and quickly correct errors. This will help you refine your configuration and ensure smooth integration into the game.