EverambleGAME API / 1

CONTENT CONTRACT · VERSION 1

Your first item.

Give one handler two different parameter records.

1. Declare the item

The following complete record is extracted from the validated example package's definitions.json (ID core:healing_potion). Its name is a localized text key.

{
  "icon": "core:healing_potion_icon",
  "id": "core:healing_potion",
  "kind": "item",
  "max_stack": 20,
  "name": "core:healing_potion_name",
  "tags": [
    "core:medicine",
    "core:quick_heal"
  ],
  "use": {
    "cooldown_ticks": 50,
    "parameters": {
      "amount": 25
    },
    "reach_mm": 0,
    "script": "core:heal",
    "snapshot": {
      "anchors": [],
      "definitions_from": [
        "core"
      ],
      "radius_mm": 0,
      "variables": []
    },
    "target_scope": "self"
  }
}

2. Return effects

This is the package's scripts/heal.luau. The heal and consume_item effects form one atomic response. A stronger potion changes the amount parameter; the handler stays the same.

--!strict
local Game = require("@hearthwild/game-api")
local Core = require("@package/types")

return function(ctx: Core.HealContext): Game.UseResult
    local event = ctx.event
    local actor = ctx.read.actor(event.target)
    if actor == nil or not actor.alive then
        return {outcome = "rejected", reason = "core:unavailable"}
    end
    if actor.health >= actor.max_health then
        return {outcome = "rejected", reason = "core:already_healthy"}
    end
    return {outcome = "used", effects = {
        {kind = "consume_item", holder = event.actor, item = event.item, count = 1},
        {kind = "heal", target = event.target, amount = ctx.parameters.amount},
    }}
end

3. Test the response

A fixture freezes a snapshot and states the exact expected answer. Parameters come from the item, never from the fixture. This is the package's tests/healing_potion_60.json:

{
  "event": {
    "actor": "a1",
    "item": "core:healing_potion",
    "kind": "item_used",
    "player": "p1",
    "target": "a1"
  },
  "expect": {
    "kind": "result",
    "result": {
      "effects": [
        {
          "count": 1,
          "holder": "a1",
          "item": "core:healing_potion",
          "kind": "consume_item"
        },
        {
          "amount": 25,
          "kind": "heal",
          "target": "a1"
        }
      ],
      "outcome": "used"
    }
  },
  "handler": {
    "item": "core:healing_potion",
    "kind": "item_use"
  },
  "id": "healing_potion_60",
  "owner": {
    "kind": "player",
    "player": "p1"
  },
  "snapshot": {
    "actors": [
      {
        "active_lights": [],
        "alive": true,
        "definition": "core:traveller",
        "health": 60,
        "home": {
          "map": "m1",
          "x_mm": 0,
          "y_mm": 0,
          "z_mm": 0
        },
        "hunger": 100,
        "max_health": 100,
        "max_hunger": 100,
        "max_stamina": 100,
        "position": {
          "map": "m1",
          "x_mm": 0,
          "y_mm": 0,
          "z_mm": 0
        },
        "ref": "a1",
        "stamina": 100,
        "tags": []
      }
    ],
    "clock": {
      "day": 0,
      "minute": 0,
      "season": "core:spring",
      "tick": 1
    },
    "quests": [
      {
        "player": "p1",
        "quest": "core:first_aid_quest",
        "revision": 0,
        "stage": "available"
      }
    ],
    "variables": []
  }
}

4. Validate the package

hearthwild-content validate assets/content/packages/core --target desktop

The loader checks records, references, dependencies and files, then runs every fixture in the game's own interpreter: 98 fixtures pass for this package. Continue with the authoring tools to pack the package or reload it while the game runs.