Feature: Data-Driven Item Definitions — Anatomy, Points, Grips, Feed Systems #4
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Status: DESIGN IN DISCUSSION (Zach + Lantern, 2026-10-21). Migrated out of the addon packaging proposal (#3) at Zach's direction: none of this is packaging format — it's the item/framework feature design that addon data expresses. The packaging proposal keeps only pack layout, keys, manifest, load order, and merging; everything about what an item definition contains lives here.
The idea
Modding is data-driven for the most part. An author writes config files that tell the game how to create an item. Zach's description of the intent:
The framework supplies behavior; the definition supplies every interactive point and moving part as data. A new weapon on an existing framework is pure data. A new kind of weapon (Zach's example: laser guns — beam behavior isn't projectile behavior) needs a new framework, which is what the addon script tier is for.
Materials
Materials live in the item JSON as a slot array: each entry names a model material slot, a shared base material/shader by key, and the values to plug in (albedo, metallic, roughness, texture key...). A slot with no entry — or an item with no materials at all — gets a generic object-space universal tiling material (object-space detail, no UVs required) so any model still shows surface detail up close. (Example in the #3 attachment's item JSON.)
Grips
Grip poses are data tables: per grip, a
rootpos/rot (the object root's offset) plus abonestable of pos/rot per finger bone, everything relative to the wrist (Hand) bone, side-less bone names mirrored by the engine; unlisted bones keep rest pose + procedural curl. Primary, secondary, and manipulation grips share the shape. Grips are optional — no grips data means the procedural default grab (curl to collider). When authored, grips are tool-generated from a posed reference hand (see Gizmo authoring), never hand-typed.Anatomy points
A weapon/item definition declares its interactive points: accepted magazine types, mag insert (position, orientation, depth), bolt/slide location, lever states (pos/rot per state — safety safe/fire, selectors), chamber location (where the chambered round renders), barrel exit (muzzle pos + direction). Points are the general mechanism for any item with moving parts, not just weapons.
Points have shapes
Points carry config in the name
Functionality is built from the point's name, and the name can carry parameters. Zach's example, a crate:
container.bodyin the .blend is just the part/mesh, not a point — butpoint.container.lid.pivot: rotlock(x=+30)is a point: a lid pivot, rotation locked to the X axis, max +30° from its origin. So gizmo names form a small grammar (dotted path +: key=valueparams) that the build tool must parse and validate strictly — a typo'd parameter should be a build error, never a silent runtime no-op.Gizmo authoring
Points are placed visually in Blender: one generic gizmo model (a clear orientation/alignment visual, sourced from the open-licensed free Resonite Assets) is inserted into the workspace once per point as instances of the single shared model, each instance named for its point — filesize cost per point is just a transform. The build tool reads the named instances' transforms into the item JSON and excludes gizmos from the exported model (authoring-only, never shipped). Working naming proposal (Lantern, open): instance names mirror the JSON path they feed —
point.mag_insert,point.chamber,part.safety.safe,grip.primary— so the tool needs no mapping table.Feed systems: one system, three shapes
Open work
rotlock-style parameter vocabulary. Splits in two: game-side vocabulary with the game ideas (game-planning), format-side grammar with the addon format (#3).The project currently has two different key formats for item definitions: the one #3 proposes and the one in the code skeletons. It's worth picking one before
ItemRegistryand the snapshot save are implemented, because save files store these keys forever. That's the same reasoning #12 applies toda_*names.coolpistolsexample<modid>.<tier>.<dotted path>deadair.data.items.mag_9x18_8src/core/registry.gd:6-7,src/core/save_game.gd:9,src/items/item_definition.gd:14,src/items/item_instance.gd:21<modid>.item.<category>.<name>deadair.item.weapons.1911The shape of a definition differs too:
"model": "coolpistols.asset.models.pm_custom").src/items/item_definition.gd, it's aResourcethat exportsworld_scene: PackedScene(line 29) andtype_data: Resource(line 26, whose comment already calls that shape undecided).A Resource that holds a
PackedScenedoesn't fit the zip tier, which per #3 carries JSON data plus raw assets that runtime loaders build. It also bypasses the key-based AssetLoader that #3 relies on.Suggestion:
ItemDefinitionhold keys (model_key: String) that the AssetLoader resolves at instantiation time.deadair.data.items.1911), so the first real implementation doesn't inherit the other format.