Weapon mastery

Give each named gun its own saved XP and levels, earned from applied damage, with a damage bonus per level, a service, a hook and HUD variables.

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

Also read offline — CLI: grip-forge docs weapons-masteryMCP tool: gripforge_docs { "topic": "weapons-mastery" }

Weapon experience and upgrades (weapons.mastery) #

What it is for #

weapons.mastery is an optional companion of combat.ranged for action platformers, shooters and RPGs. Every named gun keeps its own experience for each owner. Damage that is actually applied earns XP for the gun that fired it, including a projectile still flying after a weapon switch. Misses, scenery, blocked damage and zero damage earn nothing. Each level multiplies the damage of the next shots. Progress is saved; loading a save never replays rewards. The kit has no screen of its own: it publishes variables for your HUD. Anonymous default guns earn nothing, so declare named guns in combat.ranged.

Turn it on #

gripforge_gamekit_install   { project_id: "gkp_…", id: "weapons.mastery" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "weapons.mastery",
                              config: { "maxLevel": 5, "baseXp": 100, "growth": 1.5, "damagePerLevel": 0.2 } }

It requires game.engine and combat.ranged.

First example #

<!-- test: kits/weapons_mastery/tests/weapons_mastery.rs::a_grant_tells_its_amount_and_every_level_it_crosses --> With the default settings, a script grants 260 XP to the gun rifle of an entity:

{ "service": "weapons.mastery", "method": "grant", "args": ["e1", "rifle", 260] }

The answer is { ok: true, cancelled: false, by: null, reason: null }. The kit emits one mastery.gained (amount 260, totalXp 260, reason script), then one mastery.levelled for level 2 and one for level 3 (damageMultiplier 1.3).

Settings and defaults #

SettingTypeDefaultMeaning
maxLevelinteger 1 to 1005highest level; no XP is awarded at the cap
baseXpnumber100XP from level 1 to level 2
growthnumber 1 to 31.5each level costs ceil(previous cost * growth)
xpPerDamagenumber 0 to 1001XP per point of applied damage; 0 leaves awards to scripts
damagePerLevelnumber 0 to 100.15added to the multiplier for each level after the first (1, 1.15, 1.30…)
trackAllGunsbooleantruefalse: only guns listed in weapon_mastery earn XP
ownerComponentstringmastery.ownerentity component holding a stable owner id

All settings are read live and are moddable. With the defaults, level 2 needs 100 XP, level 3 250, level 4 475, level 5 813. Changing a curve reinterprets the saved total XP.

The weapon_mastery collection overrides maxLevel, baseXp, growth, xpPerDamage and damagePerLevel per gun; omitted fields inherit the settings:

{ "id": "pulse", "maxLevel": 5, "baseXp": 100, "growth": 1.5, "xpPerDamage": 1, "damagePerLevel": 0.2 }

Services, events, variables #

  • weapons.mastery (service) state(entity, gun): { gun, level, totalXp, xp, toNext, damageMultiplier }, or null for an empty or excluded gun.
  • weapons.mastery (service) grant(entity, gun, amount, reason?): needs an existing entity and a positive finite amount; reason defaults to script. Answers { ok, cancelled, by, reason }; a refusal has ok: false and a reason such as invalid_award, max_level or zero_award.
  • mastery.gained (event): an accepted award, with entity, gun, amount, totalXp, reason.
  • mastery.levelled (event): one per level crossed, with entity, gun, level, damageMultiplier.
  • Listens to combat.hit (applied hits carrying a gun id), combat.fired (remembers the gun of each projectile) and projectile.impact (credits that gun, then forgets the shot).
  • Variables for the controlled player's equipped gun: mastery.gun, mastery.level, mastery.xp (progress in the level), mastery.toNext, mastery.damageMultiplier. They read empty or 0 (multiplier 1) when no gun is tracked.

Hooks and modding #

The hook mastery.gain runs before each positive award to a gun below its cap, with { entity, gun, amount, reason }. It can change amount or cancel; a refusal leaves progress unchanged. The kit also taps ranged.fire to multiply the damage of a shot. Set the entity component mastery.owner (or the field named by ownerComponent) to a stable id on successive heroes to keep progression across scenes and respawns; without it, progress belongs to the entity id. A mod that doubles all XP:

{ "schema": "gripforge.mod/1", "id": "double_weapon_xp", "name": "Double weapon XP", "version": "1.0.0",
  "requires": { "weapons.mastery": "^1" },
  "data": { "hooks": { "add": [{ "id": "double_weapon_xp", "hook": "mastery.gain", "mul": { "amount": 2 } }] } } }

Engines #

The rules are one shared implementation for the web and native players; the engine wrappers show only your HUD variables.

When it does not do what you expect #

  • No XP is earned: the gun has no id (declare named guns in combat.ranged), the hit was not applied, xpPerDamage is 0, or trackAllGuns is false and the gun has no weapon_mastery row.
  • state answers null: the gun id is empty or excluded.
  • Progress is lost on a new hero: set the same mastery.owner on each hero entity.

Limits #

No weapon assets, no mandatory screen, no XP for guns without a name.

Versions #

Kit weapons.mastery 1.0.0, requires game.engine@^1 and combat.ranged@^1.1.