Wiki source code of Combat System
Version 1.1 by Adam Janus on 2026/01/20 12:43
Hide last authors
| author | version | line-number | content |
|---|---|---|---|
| |
1.1 | 1 | = **Combat System – Technical Design 0.3** = |
| 2 | |||
| 3 | == **1. Introduction** == | ||
| 4 | |||
| 5 | The system revolves around player-crafted and player-wielded weapons. Weapons and enemies define **what** they do and **when** they do it. | ||
| 6 | A targeting mechanic inspired by **Mordhau** provides readable yet deep combat. It supports encounters with **multiple** enemies (not full hordes), maintaining clarity and intent. | ||
| 7 | |||
| 8 | === **1.1 Disclaimer** === | ||
| 9 | |||
| 10 | Hereby document is not completed. Further development of the document requires validation by prototyping. | ||
| 11 | |||
| 12 | ---- | ||
| 13 | |||
| 14 | == **2. Damage Delivery** == | ||
| 15 | |||
| 16 | === **2.1 Targeting ** === | ||
| 17 | |||
| 18 | Each enemy actor contains a reference component within its class. Targeting is an automatic, 3 step process with the goal of selecting said reference component as current target. | ||
| 19 | |||
| 20 | 1. **Visibility check: **To be considered a target, enemy reference point must be visible and not obstructed by any collider. | ||
| 21 | 1. **Range check:** System verifies if enemy is at distance **<=** to **2*CurrentWeaponRange** | ||
| 22 | 1. **Corsair proximity check: **Form previously filtered enemies system selects final one based on corsair proximity to reference component. The parent of the selected component is set as the current target. | ||
| 23 | |||
| 24 | === **2.2 Types of attack and their selection** === | ||
| 25 | |||
| 26 | Selection of Attack type is based on relative position to target reference component. Screen space around and divide it into 4 segments. Left, Right, top and Center+Bottom. | ||
| 27 | |||
| 28 | [[image:1768909366378-449.png]] | ||
| 29 | |||
| 30 | |||
| 31 | Based on, in which segment cursor is present at the moment of entering attack input, respectable attack is performed by PC. | ||
| 32 | |||
| 33 | |||
| 34 | ~1. Left & Right - Directional attack | ||
| 35 | |||
| 36 | 2. Top - Overhead attack | ||
| 37 | |||
| 38 | 3. Center+Bottom - Stab (forward thrust) | ||
| 39 | |||
| 40 | |||
| 41 | All of those attacks are based on animation. Each animation must guide the weapon through the center of the screen. | ||
| 42 | |||
| 43 | ==== **2.2.1 Directional attack ** ==== | ||
| 44 | |||
| 45 | To define direction of attack, upon attack input, the system draws a **2D OnScreen Vector **originating at the center of the corsair. This vector ends at the center of the Reference component of the current target. | ||
| 46 | |||
| 47 | [[image:1768909366379-510.png]] | ||
| 48 | |||
| 49 | |||
| 50 | This vector is translated into direction and rotation of attack animation. It is achieved by blending 2 out of 8 attack animations. [[image:1768909366379-927.png]] | ||
| 51 | |||
| 52 | //Note: each arrow represents one animation.// | ||
| 53 | |||
| 54 | ==== **2.2.2 Overhead attack ** ==== | ||
| 55 | |||
| 56 | Overhead attack animation, on contrary to directional attack, is consistent. That means that if the cursor is present in a respectable segment, then upon attack the same animation is always played. | ||
| 57 | |||
| 58 | ==== **2.2.3 Stab Attack ** ==== | ||
| 59 | |||
| 60 | Stab attack follows the same principles as overhead attack. | ||
| 61 | \\//Note: Bottom-to-top animation is not stab animations, it's used only for blend purposes only. // | ||
| 62 | |||
| 63 | ---- | ||
| 64 | |||
| 65 | |||
| 66 | === **2.3 Attack Phases** === | ||
| 67 | |||
| 68 | Every attack consists of three phases (durations are defined per weapon): | ||
| 69 | |||
| 70 | * **Wind-Up** - First phase of attack, weapon is prepared for swing. Phase is triggered by input down. | ||
| 71 | * **Swing** — The actual striking phase. Animation of performing attack. Phase is triggered by input key release. | ||
| 72 | * **Recovery** — Last phase of attack, animation of retracting weapon into default position. Phase is triggered automatically. Serves a role of delay in between attacks. | ||
| 73 | |||
| 74 | If the player enters and holds the attack input, then the weapon is locked in the Wind-up phase. As the player moves the cursor Vector of attack remains unchanged. If the player wants to change the Vector of attack, they must cancel the attack by entering respectable input or force the PC into another state that does not allow for performing the attack. | ||
| 75 | |||
| 76 | ---- | ||
| 77 | |||
| 78 | === **2.4 Conditions for performing an attack & State machine** === | ||
| 79 | |||
| 80 | In order to enter pc must: | ||
| 81 | |||
| 82 | * Be in respectable State; idle, walking or crouching | ||
| 83 | * Have sufficient stamina | ||
| 84 | * Wield Weapon Actor | ||
| 85 | * | ||
| 86 | |||
| 87 | **Wind-up phase** | ||
| 88 | If player successfully wind-up an attack, they enter a wind-up state. Once in windup state a player may walk and crouch but if PC enters any other state e.g. running, then entering state cancels Win-up. Wind-up state can be interrupted by any state. | ||
| 89 | |||
| 90 | |||
| 91 | **Swing phase** | ||
| 92 | |||
| 93 | During the Swing phase, only walking and crouching is possible. PC can’t enter any other state. | ||
| 94 | |||
| 95 | |||
| 96 | **Recovery phase ** | ||
| 97 | During the Recovery phase, only walking and crouching is possible.PC can’t enter any other state. | ||
| 98 | \\//Note: Description above describes intended result, not expected code. // | ||
| 99 | |||
| 100 | ---- | ||
| 101 | |||
| 102 | |||
| 103 | === **2.5 Movement Impact on Strikes** === | ||
| 104 | |||
| 105 | Weapons are positioned relative to the PC’s camera transform. The player may move the camera at all times. | ||
| 106 | While the **animation **of the strike remains the same, its **world transform** updates with camera motion, preserving precise collision but allowing nuanced control. | ||
| 107 | |||
| 108 | ---- | ||
| 109 | |||
| 110 | === **2.6 Time–Damage Curve** === | ||
| 111 | |||
| 112 | **Time–Damage** is a **multiplier** defined by a curve: | ||
| 113 | |||
| 114 | * **X-axis:** normalized time of Swing phase (0–1). E.g. if swing lasts for 2.0 sec then at X = 0.2 swing is at 0.4 time. | ||
| 115 | * **Y-axis:** damage multiplier. | ||
| 116 | The curve **must match** the weapon’s animation timing and approximate blade velocity. | ||
| 117 | |||
| 118 | **Examples:** | ||
| 119 | |||
| 120 | * **Stab:** near-linear rise with a sharp falloff at the end (peak speed near impact). | ||
| 121 | \\[[image:1768909366380-652.png]] | ||
| 122 | * **Swing:** bell-shaped (≈ normal distribution) with a mid-swing peak. | ||
| 123 | \\[[image:1768909366380-304.png]] | ||
| 124 | |||
| 125 | |||
| 126 | **Important:** The curve is an **editable variable** per child of the weapon parent (per weapon instance/child class). | ||
| 127 | |||
| 128 | ---- | ||
| 129 | |||
| 130 | == **3. Weapons Role in combat system** == | ||
| 131 | |||
| 132 | |||
| 133 | === **3.1 Composition of weapon ** === | ||
| 134 | |||
| 135 | Weapons are composed of Mesh and Damage Colliders. Mesh is a visual representation of weapon and diegetic reference point for players during combat. Collider's role is to define value and type of damage upon successful delivery. Lastly, the weapon holds respectable UX functionality. | ||
| 136 | |||
| 137 | |||
| 138 | ==== **3.1.1 Colliders Types and role ** ==== | ||
| 139 | |||
| 140 | Each weapon has a set amount of colliders covering the entirety of the weapons mesh. Those colliders are divided into following categories holding special effect: | ||
| 141 | |||
| 142 | * **Cutting **- % bonus to damage against unarmored bone | ||
| 143 | * **Crushing **- % bonus to damage to armored bone durability | ||
| 144 | * **Piercing** - % bonus to armour penetration | ||
| 145 | * **Blunt **- No special effect. | ||
| 146 | |||
| 147 | Each collider outside of special effects hold following variables: | ||
| 148 | |||
| 149 | |||
| 150 | * **Base Damage** - Base value used for calculating Delivered damage | ||
| 151 | * **Armor Penetration **- Value of armour ignored upon successful damage delivery | ||
| 152 | * **On-hit effect **- effect applied on enemy at every hit, e.g. bleed, freeze, stun etc. | ||
| 153 | |||
| 154 | Weapons also have actor variable outside of colliders: | ||
| 155 | |||
| 156 | * **Weight **- mass of the weapon in equipment | ||
| 157 | * **Range** - maximum reach of the attack (resemblance a distance between end of most distant form handle collider and pivot point.) | ||
| 158 | * **Handling **- It sets the duration of the wind-up and recovery phase. | ||
| 159 | * **Block cost **- Cost of raising guard and per tick cost of keeping guard up. | ||
| 160 | * **Attack cost **- Cost of performing an attack. | ||
| 161 | |||
| 162 | **Important: **All values of variables above will be described in balance sheets and instances of weapons. It’s a functionality that must be present in parent class. | ||
| 163 | |||
| 164 | |||
| 165 | ==== **3.1.3 Collider structure of weapon** ==== | ||
| 166 | |||
| 167 | The philosophy of overlaying colliders onto weapons mesh is very literal. All blades = Cutting colliders, Spikes = Piercing colliders, Heads = Crushing collider, Lastly all parts of weapon that are not lethal by design like: handles, guards and pommels shall be overlaid | ||
| 168 | |||
| 169 | [[image:1768909366380-349.png]] | ||
| 170 | |||
| 171 | **Red **- Cutting cloider | ||
| 172 | **Blue **- Smashing collider | ||
| 173 | |||
| 174 | **Green **- Piercing collider | ||
| 175 | |||
| 176 | **Yellow **- Blund collider | ||
| 177 | |||
| 178 | |||
| 179 | **Important: **Weapons meshes shall be designed with 1 singular endpoint. | ||
| 180 | |||
| 181 | === **3.1.4 Categories & types** === | ||
| 182 | |||
| 183 | Weapons fall into three functional categories: | ||
| 184 | |||
| 185 | * **One-Handed** — usable alone or paired with an off-hand tool (e.g., sword + shield, nadziak + net). | ||
| 186 | * **Two-Handed** — require both hands, cannot be paired (e.g., war hammer, halberd). | ||
| 187 | * **Off-Hand** — supportive, tactical tools complementing one-handed weapons (e.g., shield, whip, net). | ||
| 188 | |||
| 189 | Further, One and Two-Handed weapons are divided into three types: | ||
| 190 | |||
| 191 | * **Hammers** | ||
| 192 | * **Swords** | ||
| 193 | * **Axes** | ||
| 194 | |||
| 195 | ---- | ||
| 196 | |||
| 197 | == **4. Damage Avoidance** == | ||
| 198 | |||
| 199 | Combat readability emphasizes **timing**. Each enemy attack is a **single primary vector**, encouraging deliberate responses. | ||
| 200 | |||
| 201 | The player has two defensive actions: **Blocking** and **Dodging**. | ||
| 202 | Blocking is **easier** to time but **more stamina-heavy** than dodging. | ||
| 203 | |||
| 204 | === **4.1 Blocking** === | ||
| 205 | |||
| 206 | Blocking is a boolean state with a **wind-up** (like attacks): | ||
| 207 | |||
| 208 | * On input, **Block Wind-Up** starts after delay | ||
| 209 | * **Stamina costs:** upfront activation **and** per-tick drain while blocking. | ||
| 210 | * Additional cost Upon blocked impact | ||
| 211 | * If stamina is insufficient, blocking **cannot** be initiated or is **interrupted**. | ||
| 212 | |||
| 213 | === **4.2 Dodging** === | ||
| 214 | |||
| 215 | * ((( | ||
| 216 | **Dodge:** briefly disables the PC’s hitbox and moves the PC along a vector adjacent to current movement. | ||
| 217 | |||
| 218 | * If stationary, only the hitbox disable applies (no displacement). | ||
| 219 | \\ | ||
| 220 | ))) | ||
| 221 | |||
| 222 | ---- | ||
| 223 | |||
| 224 | == **4. Armor System In context of combat system ** == | ||
| 225 | |||
| 226 | === | ||
| 227 | **4.1 Player Armor** === | ||
| 228 | |||
| 229 | Flat reduction model: damage received is reduced by the player’s current **Armor** value. | ||
| 230 | |||
| 231 | === **4.2 Enemy Armor** === | ||
| 232 | |||
| 233 | Enemy bodies have **Armored** and **Non-Armored** bones. | ||
| 234 | Armored bones store: | ||
| 235 | |||
| 236 | * **Armor Durability (HP):** reduced by each point of blocked damage; at 0 the zone becomes **non-armored**. | ||
| 237 | * **Armor Effectiveness:** flat reduction **before** penetration. | ||
| 238 | |||
| 239 | **Example:** | ||
| 240 | |||
| 241 | * Attack deals **10** damage with **2** armor penetration. | ||
| 242 | * Target: **Armor Effectiveness = 3**, **Durability = 15**. | ||
| 243 | * Effective reduction = 3 (Armor effectiveness) - 2 (armor penetration) = 1 (Final reduction value) | ||
| 244 | * Damage to health = 10 (base damage value) − 1 (Final reduction value) | ||
| 245 | ~= 9 (Value of delivered damage to enemy). | ||
| 246 | * Durability reduced by = 15 (base durability of Target/Damage receiver) - 1 (Final reduction value) = 15 ( post damage value of durability of Target/Damage receiver) | ||
| 247 | |||
| 248 | ---- | ||
| 249 | |||
| 250 | == **6. Instance Editables** == | ||
| 251 | |||
| 252 | === **6.1 Weapon Instance Editables** === | ||
| 253 | |||
| 254 | |||
| 255 | |**Parameter Name**|**Type**|**Description** | ||
| 256 | |**Wind-Up Duration**|Float|Duration of the Wind-Up phase for this weapon instance. Each weapon defines its own timing. | ||
| 257 | |**Swing Duration**|Float|Duration of the Swing phase during which the attack deals damage. Defined per weapon. | ||
| 258 | |**Recovery Duration**|Float|Duration of the Recovery phase before another attack can start. Defined per weapon. | ||
| 259 | |**Time–Damage Curve**|CurveFloat|Damage multiplier curve sampled across normalized Swing time (0–1). Editable per weapon child class. | ||
| 260 | |**Range**|Float|Maximum reach of the weapon; defines attack distance and target validation distance (2× Range in targeting). | ||
| 261 | |**Weight**|Float|Mass of the weapon in equipment. Used by combat and inventory systems. | ||
| 262 | |**Handling**|Float|Defines Wind-Up and Recovery duration scaling (weapon handling characteristics). | ||
| 263 | |**Block Cost**|Float|Stamina cost for raising guard and per-tick cost of keeping guard up (per weapon instance). | ||
| 264 | |||
| 265 | ---- | ||
| 266 | |||
| 267 | === **6.2 Weapon Collider Instance Editables** === | ||
| 268 | |||
| 269 | //(Explicit collider-level variables described in section 3.1.1)// | ||
| 270 | |||
| 271 | |**Parameter Name**|**Type**|**Description** | ||
| 272 | |**Collider Type**|Enum (Cutting / Crushing / Piercing / Blunt)|Defines the damage specialization bonus and interaction with armor/bone types. | ||
| 273 | |**Base Damage**|Float|Core damage value used for calculating delivered damage. | ||
| 274 | |**Armor Penetration**|Float|Amount of armor ignored when this collider hits an armored bone. | ||
| 275 | |**On-Hit Effect**|Enum / Tag|Effect applied on every successful hit from this collider (bleed, freeze, stun, etc.). | ||
| 276 | |||
| 277 | ---- | ||
| 278 | |||
| 279 | === **6.3 Blocking & Dodging Instance Editables** === | ||
| 280 | |||
| 281 | |**Parameter Name**|**Type**|**Description** | ||
| 282 | |**Block Wind-Up Delay**|Float|Delay before block becomes active. //(Referenced as “after delay” in blocking description.)// | ||
| 283 | |**Block Activation Cost**|Float|Up-front stamina cost for initiating a block (per weapon). | ||
| 284 | |**Block Upkeep Cost**|Float|Per-tick stamina drain while blocking (per weapon). | ||
| 285 | |||
| 286 | ---- |