Weak points

Usage guide of combat.weakpoints: localized armor, exposure windows and part health for bosses and monsters, the hit and resolve protocol, settings and defaults, service, events, hooks and a worked example.

Source: module-kits:kits/combat_weakpoints/usage/en.mdView Markdown source

Also read offline — CLI: grip-forge docs combat-weakpointsMCP tool: gripforge_docs { "topic": "combat-weakpoints" }

Weak points and armor parts (combat.weakpoints) #

What it is for #

combat.weakpoints gives a boss or a monster body parts that each have their own armor, health and vulnerability window. A hit on a part is absorbed by its armor first, the rest is multiplied (more while the part is exposed) and split between the part and the body; a part that reaches zero is disabled and names the capabilities it takes away (flight, a weapon). The kit only computes: the engine finds which part was hit, applies the damage to the body through the combat system, then confirms with resolve.

Turn it on #

Install the kit in a project and set its settings with the tools below; gripforge kit api combat.weakpoints lists every setting, and gripforge docs combat-weakpoints prints this guide offline.

gripforge_gamekit_install   { project_id: "gkp_…", id: "combat.weakpoints" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "combat.weakpoints",
                              config: { "maxExposure": 10, "parts": [
                                { "id": "core", "maxHealth": 100, "armor": 20, "bodyShare": 0.5, "capabilities": ["flight"] },
                                { "id": "arm", "maxHealth": 50, "armor": 0, "exposedMultiplier": 3 } ] } }

First example #

<!-- test: kits/combat_weakpoints/tests/combat_weakpoints.rs::armor_absorbs_first_and_the_rest_is_split_between_part_and_body --> A boss with a core (armor 20, half of the damage goes to the body) takes a 60-point hit. Nothing is applied until the engine resolves the hit.

combat.weakpoints.request("default", { op: "hit", part: "core", seq: 1, amount: 60 })
  // action.effect: { kind: "hit", armorDamage: 20, partDamage: 40, bodyDamage: 20, disabled: false }
combat.weakpoints.request("default", { op: "resolve", token: <action.token>, success: true })
  // core: health 60, armor 0

Settings and defaults #

SettingDefaultMeaning
maxExposure30{{s_maxExposure}}
parts[{ "id": "core" }]1 to 64 parts with unique ids; the default is one part core (fields below)
parts[]DefaultMeaning
idrequiredthe hit region id your engine's collision query returns
maxHealth100{{p_maxHealth}}
armor25armor points absorbed before any multiplier; they come back only through restoreArmor, up to this value
normalMultiplier1{{p_normalMultiplier}}
exposedMultiplier2{{p_exposedMultiplier}}
bodyShare1{{p_bodyShare}}
capabilities[]up to 16 capability ids removed when the part reaches zero health

Services #

  • combat.weakpoints (service): create(id, config), request(id, command), remove(id), ids(). The instance default uses the installed settings; other instances are created with their own config (or a preset).
  • Commands of request: hit (part, seq, amount; seq must rise with every hit), expose (part, seconds), restoreArmor (part, amount), step (dt), resolve (token, success), preview (command), status, config, save, load. A hit or restoreArmor answers an action with a token and the effect to carry out; it stays pending, and blocks other commands, until resolve(token, success). A failed resolution drops the hit and does not consume its seq. preview shows an outcome without a pending action.
  • The effect of a hit carries armorDamage, partDamage, bodyDamage (the part damage times bodyShare), disabled and disabledCapabilities. The engine applies bodyDamage through the combat system and disables the capabilities itself.

Events #

  • combat.weakpoints.created and combat.weakpoints.removed (an instance appeared or went), combat.weakpoints.changed (a decided command applied, with its op and result; never a read or a step), combat.weakpoints.refused (a hook cancelled a command, with by and reason). The kit listens to no event.

Hooks and modding #

  • combat.weakpoints.create: an instance is about to be created; a tap may change its config or cancel, and create then fails with the reason.
  • combat.weakpoints.request: a decided command (every op except the reads and step) is about to apply; a tap may change the command or cancel, and request then answers { ok: false, cancelled: true, by, reason } with the instance unchanged.

Using it from content #

Every setting is moddable. A combat_weakpoints_presets document { id, extends?, config } names a ready-made set of parts, and create(id, { preset: "<id>" }) takes it (own keys win). A hook document of a game or a mod looks like this:

{ "id": "no_armor_repair", "hook": "combat.weakpoints.request", "match": { "op": "restoreArmor" }, "cancel": true, "reason": "no_repair" }

Script verbs: the action combat_weakpoints_request sends a command to an instance (default default) through the request hook, and the condition combat_weakpoints_exists tells whether an instance exists.

{ "combat_weakpoints_request": { "command": { "op": "expose", "part": "arm", "seconds": 4 } } }
{ "combat_weakpoints_exists": "default" }

When it does not do what you expect #

SymptomCause and fix
A hit changes nothingThe action is still pending: call resolve with its token (the engine confirms what it applied).
A command is refused with "part disabled", "pending" or "stale"The part is at zero health, another action is pending, or the token or seq is old. A seq must be higher than the last accepted hit.
Damage does not use the exposure multiplierThe window ran out: send expose again, and advance time with step (dt in seconds) every fixed frame.

Limits #

  • It does not find which part was hit: your engine's collision query names the part id.
  • It does not damage the body, drive animations or remove abilities by itself: the engine carries out the effect.
  • It has no display module and emits no event of its own beyond the instance events above.

Versions #

Kit combat.weakpoints 1.1.0 (since 2026-10-19: hooks, presets, events and script verbs; 1.0.0 on 2026-10-16). It runs the same Rust rules on KitHost, in WebAssembly and through a native C library.