mirror of
https://github.com/TemujinCalidius/SurvivorCore.git
synced 2026-08-14 00:58:01 +00:00
151 lines
8.2 KiB
Markdown
151 lines
8.2 KiB
Markdown
# No-code content authoring
|
||
|
||
> 📹 **Demos:** [creating quests & achievements](https://makertube.net/w/uSGJ2MHEFjSSKxMiJBJ6Y5) · [creating mobs, weapons & ammo](https://makertube.net/w/tyn8JEMG3CaMbTXid8osdU) · [creating an item + gatherable](https://makertube.net/w/mCneurjoY3Av6yi48VsGQE) · [hunting, butchering & loot bags](https://makertube.net/w/oVJwYUhCKxA2ZvgvocdhwZ)
|
||
|
||
The engine ships **zero** items, resources, or recipes — your game supplies them. You can do this
|
||
two ways, and they coexist:
|
||
|
||
1. **From code** — `SurvivorCore.Items.register{…}`, `SurvivorCore.Resources.register{…}`,
|
||
`SurvivorCore.Recipes.register{…}` before `start()` (see the demo `Boot.server.luau`).
|
||
2. **No-code, as instances** — author content in the place and the engine loads it at `start()`.
|
||
The **admin plugin's Content widget** writes exactly this for you.
|
||
|
||
## The `SurvivorCoreContent` folder
|
||
|
||
At `start()`, the engine reads `ReplicatedStorage.SurvivorCoreContent` and registers any defs found:
|
||
|
||
```
|
||
ReplicatedStorage
|
||
└─ SurvivorCoreContent
|
||
├─ Items (Folder)
|
||
│ └─ berry (Configuration) ← child Name = item id
|
||
│ • name = "Wild Berries" ← attributes = def fields
|
||
│ • stack = 20
|
||
│ • weight = 0.05
|
||
│ • category = "consumable"
|
||
├─ Weapons (Folder) ← items with category="weapon" (loaded into the Items registry)
|
||
│ └─ wood_club (Configuration)
|
||
│ • category = "weapon"
|
||
│ • toolType = "club" (lets the hotbar equip it)
|
||
│ • weaponKind = "melee" ("melee" | "bow")
|
||
│ • weaponDamage = 20
|
||
├─ Arrows (Folder) ← items with category="ammo" (loaded into the Items registry)
|
||
│ └─ heavy_arrow (Configuration)
|
||
│ • category = "ammo"
|
||
│ • ammoDamage = 1.4 (× the bow's damage)
|
||
│ • ammoDrop = 2 (× gravity = the curve)
|
||
│ • ammoRange = 140
|
||
├─ Resources (Folder)
|
||
│ └─ berry_bush (Configuration)
|
||
│ • item = "berry"
|
||
│ • hp = 4
|
||
│ • requireTool = "" (blank = bare-hand)
|
||
│ • yieldMin = 1
|
||
│ • yieldMax = 3
|
||
├─ Mobs (Folder)
|
||
│ └─ husk (Configuration)
|
||
│ • faction = "hostile" ("hostile" | "passive" | "neutral")
|
||
│ • health = 60
|
||
│ • aggroRange = 40
|
||
│ • carcassItem = "raw_meat" (hunting: blank = no carcass; see docs/mobs.md)
|
||
│ • carcassTool = "knife"
|
||
├─ Quests (Folder) ← flat single-objective quests (normalized at load)
|
||
│ └─ gather_reeds (Configuration)
|
||
│ • name = "Gather Reeds"
|
||
│ • objectiveType = "gather" ("gather" | "craft" | "kill" | "use")
|
||
│ • objectiveTarget = "reed"
|
||
│ • objectiveCount = 3
|
||
│ • rewardItem = "berry"
|
||
│ • rewardCount = 2
|
||
│ • autoStart = true
|
||
├─ Achievements (Folder) ← flat counter + threshold defs
|
||
│ └─ husk_slayer (Configuration)
|
||
│ • name = "Husk Slayer"
|
||
│ • counter = "kills_husk" (see docs/achievements.md for the counter catalogue)
|
||
│ • threshold = 3
|
||
├─ Tools (Folder) ← Tool templates the hotbar equips (named by item id)
|
||
├─ MobModels (Folder) ← rigged mob templates Mobs.spawn clones (named by mob id)
|
||
├─ Carcasses (Folder) ← carcass models spawned on mob death (named by mob id)
|
||
└─ LootBag (Model/Part) ← the death loot-bag look (optional; placeholder otherwise)
|
||
```
|
||
|
||
Each child's **Name is the id**; its **attributes are the def fields**
|
||
([`Registry.loadFromFolder`](../src/foundation/Registry.luau) copies them verbatim). This is the
|
||
same instance-config pattern the survival stats use.
|
||
|
||
## The admin plugin Content widget
|
||
|
||
Open Studio → the **SurvivorCore** toolbar → **Content**. Seven builders:
|
||
|
||
- **Items** — create an item by id, then set Name / Max stack / Weight / Category / Tool type /
|
||
Icon / Description.
|
||
- **Weapons** — create a weapon by id, then set Kind (melee/bow) / Damage / Range / Cooldown, plus
|
||
bow Draw time / Arrow speed / Max range / Ammo item. (Weapons are items with `category = "weapon"`;
|
||
they live in their own folder so this editor never collides with the Items editor.) **+ Tool model**
|
||
drops a starter `Tool` (a Handle carrying the weapon's `ToolType`/`WeaponKind`) into the world so you
|
||
can build the held look on it; move the finished Tool under `SurvivorCoreContent.Tools` (named by the
|
||
weapon id) and the hotbar clones it when the weapon is equipped.
|
||
- **Arrows / Ammo** — create an arrow type by id, then set Damage × / Drop (curve) × / Max range /
|
||
Speed × / Carry weight. A bow's *Ammo item* points at one of these. (Arrows are items with
|
||
`category = "ammo"`, in their own folder — see [combat.md](combat.md).)
|
||
- **Gatherables** — create a resource by id, then set Yields item / HP (gathers) / Tool required /
|
||
Yield min / Yield max. **+ Add to World** drops a tagged `Gatherable` node.
|
||
- **Mobs** — create a mob type by id, then set Faction / Health / Speeds / Aggro / Leash / Attack.
|
||
**+ Add to World** drops a tagged `Mob` placeholder rig (swap in your own model later).
|
||
- **Quests** — create a quest by id, then set Name / Description / Objective (type, target, count) /
|
||
Reward (item, count) / Auto-start / Requires / Turn in. **+ Quest giver** drops a tagged
|
||
`QuestGiver` post offering it (see [quests.md](quests.md)). Multi-objective chains stay
|
||
code-authored, like recipes.
|
||
- **Achievements** — create an achievement by key, then set Name / Description / Counter /
|
||
Threshold / Icon — counters are the engine's auto-derived progression counters
|
||
(see [achievements.md](achievements.md)).
|
||
|
||
Each edit is one Studio **undo** step. Behind the scenes it creates/edits the
|
||
`SurvivorCoreContent` instances above, so pressing Play registers your content with no code.
|
||
|
||
## Overrides — tune code-registered defs without code
|
||
|
||
The authoring folders above can't touch a def that was registered **from code** (the engine's
|
||
loader skips already-registered ids — code wins). The **`Overrides`** folder can:
|
||
|
||
```text
|
||
SurvivorCoreContent/
|
||
└─ Overrides (Folder) ← mirrors the category folders above
|
||
└─ Items (Folder)
|
||
└─ berry (Configuration) ← name of a CODE-registered def
|
||
• name = "Sweet Berries" (ONLY the fields you change)
|
||
• stack = 99
|
||
```
|
||
|
||
At `start()` the engine **field-merges** each override's attributes onto the registered def —
|
||
before components bind and before the client data caches publish, so tooltips/recipes/gatherables
|
||
all see the merged values. Rules:
|
||
|
||
- **Deltas-only**: an override carries only the attributes it changes; anything absent inherits
|
||
the code value. Deleting the override restores the pristine code def on the next Play.
|
||
- The **id can't be renamed** by an override, and an id matching **no registered def warns in
|
||
Output on Play** (`override 'x' matches no registered def`) — your typo backstop.
|
||
- **Quest caveat**: a code-registered quest with nested objective/reward tables ignores the flat
|
||
`objective*`/`reward*` override fields (name/description/autoStart/requires/turnIn still merge).
|
||
Overrides of no-code quests merge fully.
|
||
|
||
The admin plugin's category pages author these for you (**+ Override**, blue pill, blank = inherit)
|
||
— see [admin-plugin.md](admin-plugin.md).
|
||
|
||
## Binding a world object
|
||
|
||
A creator builds any mesh, tags it **`Gatherable`** (CollectionService), and sets a `Resource`
|
||
attribute to a resource id (e.g. `"berry_bush"`). The node inherits item/HP/tool/yield from the def.
|
||
See [harvesting.md](harvesting.md) for the full attribute list and the per-type **reaction** hooks
|
||
(shake / fell / etc.).
|
||
|
||
For creatures, tag a rigged Model (Humanoid + PrimaryPart) **`Mob`** and set `MobType` to a mob id
|
||
(e.g. `"husk"`); it inherits faction/health/speed/ranges from the def. See [mobs.md](mobs.md) and
|
||
[combat.md](combat.md).
|
||
|
||
## Tools
|
||
|
||
For a tool item, set `toolType` (e.g. `"axe"`) and `category = "tool"`. To give it a custom look,
|
||
place a `Tool` named by the item id under `SurvivorCoreContent.Tools`; otherwise the engine equips a
|
||
plain default. Trees etc. require the matching `RequireTool`.
|