World-Builder Guide

Item System Guide

Create items, attacks, loot tables, and entities — the field-by-field JSON reference.

A generic reference for authoring items, attacks, loot tables, and entities in any Fragmented Planes area bundle. The rules and field definitions apply to every bundle you build. Concrete names (mobs, items, elements) come from the sample bundle the Scar purely as examples — replace them with your own.


1. Power Tiers & Drop Rate Caps

Every item and entity has a power_tier. Valid tiers are 1–10. A bundle is free to use any subset — the sample bundle the Scar uses only 1–3.

The federation enforces a maximum drop probability per tier for GLOBAL (transferable) items. The cap is checked twice — by the Editor at authoring time and by the Server at roll time — so a tampered bundle cannot exceed the budget. Soulbound items are unconstrained (they never leave the player, so they don't consume the shared economy budget) and are not checked against this table.

TierGlobal drop-rate capTypical role
10.10Early gear, common valuables
20.05Mid-game equipment, ability stones
30.02Strong gear, rare ability stones
40.01Elite gear
50.005Near end-game
6–100.001End-game / federated rarities
// GLOBAL item — probability must be ≤ its tier cap
{ "item_def_id": "dragon_scale",  "probability": 0.02 }   // tier 3 → ≤ 0.02 ✓
{ "item_def_id": "steel_sword",   "probability": 0.05 }   // tier 2 → ≤ 0.05 ✓

// SOULBOUND item (e.g. a bound consumable/quest item) — uncapped
{ "item_def_id": "health_potion", "probability": 0.25 }   // fine: soulbound

The cap applies per drop-table entry, independently. Listing the same global item on several monsters is allowed — each entry just has to stay under the cap on its own (drops roll independently; see §10).


2. Item Categories

"category": "gear" | "consumable" | "ability" | "quest"
CategoryPurposeCan have attack?Can have stat_bonuses?
gearEquipment (weapons, armor, rings)NoYes
consumablePotions, drinks, herbsNoYes (flat bonuses on use?)
abilitySkill stones that teach attacksYesYes
questQuest items (keys, letters, coins)NoNo

3. Item Classes (Binding)

"class": "soulbound" | "global"
ClassBehavior
soulboundBinds to player on pickup. Cannot be traded.
globalTradeable, stashable. Used for premium/rare gear.

Best practice:


4. Recognized Stats (stat_bonuses)

These are the stats the engine recognizes. All values are additive (the bonus is added directly).

"stat_bonuses": {
    "strength":       // Increases physical damage
    "intelligence":   // Increases magic damage
    "defense":        // Flat damage reduction
    "speed":          // Movement speed (tiles/sec?)
    "hp_max":         // Bonus to max health
    "mp_max":         // Bonus to max mana
    "resistance":     // Flat elemental damage reduction
}

Typical values by tier:

StatTier 1Tier 2Tier 3
strength2–34–58–12
intelligence3–48–10
defense1–33–74–10
speed1–5810
hp_max20–5050+
mp_max1010–4030+
resistance2–45–10

5. Elemental Resistances

Items can grant per-element resistance:

"resistances": {
    "fire": 0.5,   // Take 50% of fire damage
    "dark": 0.3    // Take 30% of dark damage
}

Resistance values are multipliers (same format as entity resistances):

ValueMeaning
0.0Immune (takes no damage)
0.3Strong resistance (70% reduction)
0.5Moderate resistance (50% reduction)
1.0Neutral (no modifier)
2.0Weak (takes 2× damage)

Elements recognized by the engine (with example attacks from the sample bundle):

ElementExample attack
firefireball, fire_slash
iceice_spike
poisonpoison_cloud
holyholy_beam
darkdark_swirl, shadow_stab
windwind_cutter
lightningthunder_strike
earthearth_shaker
waterwater_cascade

6. Damage Types

Every attack has a type field:

"type": "physical" | "magic"
TypeScales WithStat Bonus
physicalCharacter/entity strengthstrength
magicCharacter/entity intelligenceintelligence

7. Attack Blocks (Ability Items)

Ability items contain an embedded attack block. This is the full attack definition — it does NOT reference attacks/attacks.json.

{
    "category": "ability",
    "class": "soulbound",
    "def_id": "fire_slash_stone",
    "name": "Fire Slash Stone",
    "power_tier": 2,
    "sprite_id": "",
    "stat_bonuses": {
        "strength": 1
    },
    "attack": {
        "attack_id": "fire_slash",
        "name": "Fire Slash",
        "type": "physical",
        "element": "fire",
        "scaling_factor": 1.2,
        "hit_sprite_id": "sprite_766_0",
        "qte": { ... }
    }
}

attack vs attacks/attacks.json

Both can coexist with the same attack_id. The one in attacks/attacks.json is the fallback/server-side definition; the one on the item overrides it for the player.

Attack Fields

FieldRequiredDescription
attack_idYesUnique ID matching the attack
nameYesDisplay name
typeYesphysical or magic
elementNoElement for resistance checks
scaling_factorYesDamage multiplier (base_dmg × scaling)
hit_sprite_idYesSprite for the visual effect
qteYesQuick-time event configuration

QTE Configuration

⚠️ Read Monster Design guide §6 for what these numbers actually do. parry_window_ms / dodge_window_ms are ± tolerances around the window centre, not durations or "moments." The model is a continuous leak: full negation happens only inside a tiny perfect dead-zone (parry/4, capped at ±25 ms), then damage ramps to a full hit at the edge (dodge, capped at ±220 ms). A parry is a mirage unless it's near-perfect. The caps clamp only toward harder — authoring wider windows does not make an attack easier. The QTE also telegraphs for up to ~1.5 s with a visible sweep, so it is an anticipation test, not a reaction test. Set parry/dodge at the top level (the client preview ignores per-input overrides).

"qte": {
    "attack_type": "targeted" | "aoe" | "global",
    "inputs": [
        {
            "button": "a" | "b" | "x" | "y",
            "window_start_ms": 100,     // When button press becomes valid
            "window_end_ms": 250,        // When button press window closes
            "dodge_window_ms": 700,      // Optional: moment when button = dodge
            "parry_window_ms": 450       // Optional: moment when button = parry
        }
    ],
    "dodge_window_ms": 800,              // Global dodge timing (if not per-input)
    "parry_window_ms": 300               // Global parry timing (if not per-input)
}
attack_typeBehavior
targetedHits one target. Can be dodged/parried.
aoeHits area around target. Wider dodge window.
globalHits all enemies in the instance. Unavoidable.

Attack Weight (Entity-Only)

In entity phase attacks, "weight": 1 or "weight": 2 determines how often an attack is selected by the AI relative to others. Higher weight = more frequent.


8. Entity Phases & Multi-Phase Bosses

An entity can have one or more phases. Each phase has its own stats, attacks, and a trigger condition.

"phases": [
    {
        "attacks": [ ... ],               // Phase 1 attacks
        "stats": { ... },                  // Phase 1 stats
        "trigger": {}                      // No trigger = phase 1
    },
    {
        "attacks": [ ... ],               // Phase 2 attacks
        "stats": { ... },                  // Phase 2 stats (can be harder)
        "trigger": {
            "hp_pct_below": 30            // Transitions when HP < 30%
        }
    }
]

Trigger Conditions

TriggerEffect
{}No trigger — this is the initial phase
{"hp_pct_below": 30}Transitions to this phase when HP drops below 30%
{"hp_pct_below": 50}Current standard for a second phase

Triggers only exist on phase N+1. The first phase always has "trigger": {}.

Entity Stats

"stats": {
    "power_tier": 1 | 2 | 3,      // Controls drop tier caps
    "hp": 50,                       // Current health (initial)
    "hp_max": 50,                   // Max health
    "damage_min": 5,                // Base damage minimum
    "damage_max": 10,               // Base damage maximum
    "defense": 3,                   // Damage reduction
    "resistance": 0,                // General elemental resist
    "resistances": {                // Per-element multipliers
        "fire": 0.5,                // (same multiplier convention as items)
        "water": 2.0
    },
    "speed": 1,                     // Movement speed
    "aggro_radius": 5,              // Detection range
    "respawn_time": 30              // Seconds until respawn
}

Default stat progression by tier:

StatTier 1Tier 2Tier 3
HP20–5035–8070–120
damage_min3–55–108–15
damage_max6–1012–1816–25
defense0–31–72–10
resistance02–48–10
speed1–21–31–2
aggro_radius5–86–108–10
respawn_time25–3030–4550–60

9. Sprite System

Sprite Descriptors (JSON)

Each sprite PNG needs a companion JSON descriptor:

{
    "sprite_id": "sprite_836_0",
    "image_file": "sprite_836_0.png",
    "columns": 8,
    "rows": 1,
    "frame_width": 64,
    "frame_height": 64,
    "fps": 8
}

Where Sprites Are Referenced

FieldFilePurpose
hit_sprite_idattacks/attacks.json, items.json (ability), entities.jsonVisual effect when attack lands
sprite_iditems.jsonInventory icon
sprite_identities.jsonEntity world sprite
combat_sprite_identities.jsonEntity combat/portrait sprite
avatar_sprite_identities.jsonNPC dialog portrait

Rules


10. Loot Tables

{
    "entity_def_id": "fire_spirit",
    "drops": [
        { "item_def_id": "fire_slash_stone", "probability": 0.1 },
        { "item_def_id": "flame_sword",      "probability": 0.02 },
        { "item_def_id": "energy_drink",      "probability": 0.15 }
    ]
}

Rules

  1. Every entity_def_id referenced in loot tables must exist in entities/entities.json
  2. Every item_def_id referenced must exist in entities/items.json
  3. A global item's drop probability must not exceed its power-tier cap (§1);

soulbound drops are uncapped

  1. Probabilities are independent per slot (each drop rolls separately)
  2. A guaranteed-drop entry (e.g. a forced quest item) uses probability: 1 — this

is only valid for soulbound items, since 1.0 exceeds every global cap

Drop Distribution Guide

Ranges below assume the drop is soulbound (uncapped). For global items, clamp to the tier cap in §1 (e.g. a tier-1 global item maxes at 0.10, not 0.25).

Mob TierShould DropProbability Range
Tier 1 (trash)T1 gear, consumables, quest items0.05–0.25
Tier 2 (elite)T2 gear, ability stones, valuables0.05–0.15
Tier 3 (boss)T3 gear, rare ability stones, specials≤ 0.02 global

Give each mob a chance at low-value filler too (e.g. currency nuggets).


11. Portals (Item-Gated)

{
    "portal_id": "portal_1783181396_1_2966730235",
    "map_id": "map_main",
    "position": { "x": 4, "y": 9 },
    "entry_position": { "x": 11, "y": 2 },
    "target_map_id": "cave_level_1",
    "tile_id": 0,
    "required_item_def_id": "house_key",   // Optional: item required to use
    "prompt": "Use {item} to open the door."
}
FieldDescription
map_idSource map
positionTile position of the portal on source map
entry_positionTile position the player lands on in target map
target_map_idDestination map
required_item_def_idOptional — item needed to activate portal
promptOptional — tooltip shown, {item} is replaced with item name
tile_idVisual tile override (0 = default exit)

12. Spawn Points

{
    "spawn_id": "spawn_1783274848_1_900576479",
    "entity_def_id": "goblin",
    "map_id": "cave_level_1",
    "position": { "x": 4, "y": 12 },
    "max_count": 4,
    "respawn_time": 30,
    "aggro_radius": 10
}
FieldDescription
entity_def_idMust exist in entities.json
map_idMust exist as a map file in maps/
positionSpawn tile position
max_countHow many can exist at once
respawn_timeSeconds between spawn waves (overrides entity stat)
aggro_radiusDetection range (overrides entity stat)

13. Brain (Entity AI)

Defined in each entity, the brain array is a priority-ordered list of behaviors:

"brain": [
    { "do": { "type": "random_step" },      "when": { "type": "chance", "value": 65 } },
    { "do": { "type": "chase_player" },      "when": { "type": "player_within", "value": 10 } },
    { "do": { "type": "follow" },            "when": { "type": "chance", "value": 30 } },
    { "do": { "type": "hold" },              "when": { "type": "always" } }
]

Action Types (do.type)

ActionDescription
holdIdle / wait
chase_playerMove toward the player
random_stepWander randomly
followFollow another entity
patrol_borderWalk the edge of the map
patrol_lineWalk a line; has direction ("e"/"w"/"n"/"s") and length

Condition Types (when.type)

ConditionBehavior
alwaysAlways executes this action
chancePercentage chance per tick; has value (0–100)
player_withinTriggers when player is within value tiles

The first matching condition (checked top to bottom) wins.


14. Scripts (NPC Dialog)

NPCs with no combat (no phases, no brain) use Lua scripts:

{
    "def_id": "grix",
    "name": "Grix",
    "avatar_sprite_id": "dwarf_face",
    "sprite_id": "dwarf_base_1x4",
    "phases": [],
    "script_id": "grix"
}

The script_id maps to scripts/{script_id}.lua.


15. Quick Reference — File Inventory

FileWhat's In It
manifest.jsonArea metadata, entry map, welcome message
attacks/attacks.jsonGlobal attack registry
entities/entities.jsonEntity, NPC, and monster definitions
entities/items.jsonAll items (gear, consumables, abilities, quest)
loot_tables.jsonDrop tables linking entities to items
spawns.jsonSpawn points linking entities to maps+positions
portals.jsonMap connections, optionally item-gated
sprites/*.json / sprites/*.pngSprite descriptors and images
maps/*.jsonMap data
tiles/registry.jsonTile definitions
tilesets/*.json + *.pngTileset descriptors
audio/*.oggMusic / sound effects
scripts/*.luaNPC dialog/behavior scripts

16. Validation Checklist (Before Submitting a Bundle)