chore(release): v0.10.0

Promote CHANGELOG Unreleased → 0.10.0 (the schema-driven Build page for world
objects, #11) and bump wally.toml + SurvivorCore.VERSION.

Demo: new demo/server/Stage.luau — one switch for what the demo places in the
world (gather field + quest post, mobs, starting inventory, hand-test props).
The test-station prop rows now default OFF: they're scaffolding for working ON
the engine and crowded the spawn area for everyone else.

Collateral: the Build demo video on the docs Demos line and as an 8th site
video tile; the landing page's Studio card now tells the Build story; version
surfaces bumped across site, README and getting-started.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Samuel Lison
2026-08-01 19:29:49 +10:00
co-authored by Claude Opus 4.8
parent f1825c3512
commit 3a0206e566
11 changed files with 84 additions and 29 deletions
+10 -1
View File
@@ -5,7 +5,16 @@ All notable changes to SurvivorCore are recorded here. The format follows
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). At release time, `## Unreleased` [Semantic Versioning](https://semver.org/spec/v2.0.0.html). At release time, `## Unreleased`
is promoted to the new version and `main` is tagged `vX.Y.Z`. is promoted to the new version and `main` is tagged `vX.Y.Z`.
## Unreleased ## 0.10.0 — 2026-08-01
### Changed
- **Demo: one switch for what the world contains** — `demo/server/Stage.luau` toggles the gather
field + quest post, the mobs, the starting inventory and the hand-test prop rows independently.
The **test stations now default OFF**: that labelled row of DAMAGE / FEED / POISON / BLEED
prompts (plus the item pickups) is scaffolding for working *on* the engine, and it crowded the
spawn area for everyone else. Flip any flag on to get that piece back; turn them all off for a
clean stage when filming or when building your own world on the engine. Content *definitions*
register regardless, so the admin plugin's pickers still list the demo's items and mobs.
### Added ### Added
- **Build: no-code world objects** (#11) — select a Part or Model in Studio, answer **"what is this - **Build: no-code world objects** (#11) — select a Part or Model in Studio, answer **"what is this
+2 -2
View File
@@ -14,7 +14,7 @@
</div> </div>
> **Status: v0.9.0 — pre-release.** The core survival loop is in and working; the engine is > **Status: v0.10.0 — pre-release.** The core survival loop is in and working; the engine is
> being grown toward v1.0 and APIs may still shift. Production-tested in > being grown toward v1.0 and APIs may still shift. Production-tested in
> [The Counter Earth](https://thecounterearth.com). > [The Counter Earth](https://thecounterearth.com).
@@ -71,7 +71,7 @@ into `ReplicatedStorage`, or add it via [Wally](https://wally.run):
```toml ```toml
# wally.toml # wally.toml
[dependencies] [dependencies]
SurvivorCore = "temujincalidius/survivorcore@0.9.0" SurvivorCore = "temujincalidius/survivorcore@0.10.0"
``` ```
Working from source? Clone and `rojo serve` the `demo.project.json` place. Working from source? Clone and `rojo serve` the `demo.project.json` place.
+22 -11
View File
@@ -12,6 +12,9 @@ local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage") local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore")) local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore"))
-- What this demo places in the world — see demo/server/Stage.luau to turn any of it off.
local STAGE = require(script.Parent.Stage)
-- 1. Programmatic content ----------------------------------------------------- -- 1. Programmatic content -----------------------------------------------------
-- NOTE: the `icon` ids below are PLACEHOLDERS (the engine's stat icons) so the demo grid -- NOTE: the `icon` ids below are PLACEHOLDERS (the engine's stat icons) so the demo grid
-- isn't empty. A real game registers proper item icons (per-item `icon` or the "ItemIcons" -- isn't empty. A real game registers proper item icons (per-item `icon` or the "ItemIcons"
@@ -416,10 +419,12 @@ local function seedPlayer(player: Player)
player:SetAttribute("EquipSlot_Head", "straw_hat") -- a pre-filled equipment slot player:SetAttribute("EquipSlot_Head", "straw_hat") -- a pre-filled equipment slot
player:SetAttribute("EquipSlot_Back", "reed_satchel") -- equipped for +slots / +carry weight player:SetAttribute("EquipSlot_Back", "reed_satchel") -- equipped for +slots / +carry weight
end end
for _, player in Players:GetPlayers() do if STAGE.SeedInventory then
seedPlayer(player) for _, player in Players:GetPlayers() do
seedPlayer(player)
end
Players.PlayerAdded:Connect(seedPlayer)
end end
Players.PlayerAdded:Connect(seedPlayer)
SurvivorCore.start() SurvivorCore.start()
@@ -509,10 +514,12 @@ local function buildReed(position: Vector3)
reed.Parent = Workspace reed.Parent = Workspace
end end
buildTree(Vector3.new(10, 0, 28)) if STAGE.WorldContent then
buildTree(Vector3.new(18, 0, 28)) buildTree(Vector3.new(10, 0, 28))
buildReed(Vector3.new(-8, 0, 28)) buildTree(Vector3.new(18, 0, 28))
buildReed(Vector3.new(-12, 0, 28)) buildReed(Vector3.new(-8, 0, 28))
buildReed(Vector3.new(-12, 0, 28))
end
-- Reaction juice (per resource type) — pure creator content via the engine's reaction API. -- Reaction juice (per resource type) — pure creator content via the engine's reaction API.
local SWAY = TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, true) local SWAY = TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, true)
@@ -582,9 +589,11 @@ buildWeaponTemplates()
-- Husks live out past their aggro+wander reach of spawn — new players shouldn't get farmed at -- Husks live out past their aggro+wander reach of spawn — new players shouldn't get farmed at
-- the spawn point before they've picked up a weapon (they'll still hunt you in their territory). -- the spawn point before they've picked up a weapon (they'll still hunt you in their territory).
SurvivorCore.Mobs.spawn("husk", CFrame.new(70, 5, 45), { respawn = true }) if STAGE.Mobs then
SurvivorCore.Mobs.spawn("husk", CFrame.new(82, 5, 58), { respawn = true }) SurvivorCore.Mobs.spawn("husk", CFrame.new(70, 5, 45), { respawn = true })
SurvivorCore.Mobs.spawn("boar", CFrame.new(-30, 5, 18)) SurvivorCore.Mobs.spawn("husk", CFrame.new(82, 5, 58), { respawn = true })
SurvivorCore.Mobs.spawn("boar", CFrame.new(-30, 5, 18))
end
-- The quest-giver post: offers `slay_husk` (hold E to accept; return to turn in). Any mesh works — -- The quest-giver post: offers `slay_husk` (hold E to accept; return to turn in). Any mesh works —
-- tag it "QuestGiver" + set Quest — this demo just uses a marked wooden post. -- tag it "QuestGiver" + set Quest — this demo just uses a marked wooden post.
@@ -608,7 +617,9 @@ local function buildQuestPost(position: Vector3)
CollectionService:AddTag(post, "QuestGiver") CollectionService:AddTag(post, "QuestGiver")
post.Parent = Workspace post.Parent = Workspace
end end
buildQuestPost(Vector3.new(8, 0, 8)) if STAGE.WorldContent then
buildQuestPost(Vector3.new(8, 0, 8))
end
-- Flourish hooks: print quest + achievement milestones to the output. -- Flourish hooks: print quest + achievement milestones to the output.
SurvivorCore.Hooks.on("quest:completed", function(ctx) SurvivorCore.Hooks.on("quest:completed", function(ctx)
+7 -4
View File
@@ -14,6 +14,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace") local Workspace = game:GetService("Workspace")
local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore")) local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore"))
local Stage = require(script.Parent.Stage)
local PICKUPS = { local PICKUPS = {
{ label = "PICK UP Stone Axe", item = "stone_axe", amount = 1, color = Color3.fromRGB(120, 130, 140) }, { label = "PICK UP Stone Axe", item = "stone_axe", amount = 1, color = Color3.fromRGB(120, 130, 140) },
@@ -67,8 +68,10 @@ local function buildPickup(def: any, position: Vector3)
end) end)
end end
local BASE = Vector3.new(0, 4, 16) -- opposite side from the stat test stations if Stage.TestStations then
for i, def in PICKUPS do local BASE = Vector3.new(0, 4, 16) -- opposite side from the stat test stations
local x = (i - (#PICKUPS + 1) / 2) * 4 for i, def in PICKUPS do
buildPickup(def, BASE + Vector3.new(x, 0, 0)) local x = (i - (#PICKUPS + 1) / 2) * 4
buildPickup(def, BASE + Vector3.new(x, 0, 0))
end
end end
+27
View File
@@ -0,0 +1,27 @@
--!nonstrict
--[[
Demo stage toggles ONE place to control what the demo places in the world.
The demo furnishes a world so the engine has something to DO out of the box. Turn any of it
off for a CLEAN STAGE: filming, screenshots, or building your own world on top of the engine
without the demo's furniture in shot.
Content DEFINITIONS (items, recipes, quests, achievements, mob types) are always registered
regardless — so the admin plugin's pickers still list `reed_bush`, `husk`, `boar` and friends,
and you can point your own objects at real content. These flags only control what gets PLACED
in the world and what the player starts with.
Set them all to false and pressing Play gives you an empty baseplate.
]]
return {
WorldContent = true, -- the gather field (trees + reeds) and the quest post
Mobs = true, -- the husks + the boar
SeedInventory = true, -- the starting items, hotbar pins and worn equipment
-- OFF by default: these are hand-test scaffolding (a labelled row of DAMAGE / FEED / POISON /
-- BLEED prompts, plus item pickups) for exercising the stat and inventory APIs. Useful when
-- you're working ON the engine, but they crowd the spawn area for everyone else. Flip on when
-- you want to poke the survival systems by hand.
TestStations = false,
}
+7 -4
View File
@@ -16,6 +16,7 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace") local Workspace = game:GetService("Workspace")
local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore")) local SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore"))
local Stage = require(script.Parent.Stage)
local POISON_SOURCE = "TestStation:poison" local POISON_SOURCE = "TestStation:poison"
local BLEED_SOURCE = "TestStation:bleed" local BLEED_SOURCE = "TestStation:bleed"
@@ -149,8 +150,10 @@ end
-- (The engine syncs the "Health" stat to the Humanoid + resets stats on respawn now, so the -- (The engine syncs the "Health" stat to the Humanoid + resets stats on respawn now, so the
-- DAMAGE part's real damage shows on the HUD and death/respawn comes out clean on its own.) -- DAMAGE part's real damage shows on the HUD and death/respawn comes out clean on its own.)
local BASE = Vector3.new(0, 4, -16) if Stage.TestStations then
for i, def in STATIONS do local BASE = Vector3.new(0, 4, -16)
local x = (i - (#STATIONS + 1) / 2) * 4 for i, def in STATIONS do
buildStation(def, BASE + Vector3.new(x, 0, 0)) local x = (i - (#STATIONS + 1) / 2) * 4
buildStation(def, BASE + Vector3.new(x, 0, 0))
end
end end
+1 -1
View File
@@ -31,7 +31,7 @@ This is the [Builder / Admin plugin](https://github.com/TemujinCalidius/Survivor
> Studio forgets the old panel's dock position **once** — the new window opens floating; dock it > Studio forgets the old panel's dock position **once** — the new window opens floating; dock it
> wherever you like and Studio remembers from then on. > wherever you like and Studio remembers from then on.
> 📹 **Demos:** [HUD, survival stats & the admin plugin](https://makertube.net/w/xqX7wfRpTqd9L9BkozCS1P) · [no-code item & gatherable creation](https://makertube.net/w/mCneurjoY3Av6yi48VsGQE) · [no-code weapon, ammo & mob creation](https://makertube.net/w/tyn8JEMG3CaMbTXid8osdU) · [no-code quest & achievement creation](https://makertube.net/w/uSGJ2MHEFjSSKxMiJBJ6Y5) · [SurvivorCore Studio — the no-code admin window](https://makertube.net/w/g4oySJeXD4Th7f1zYEu9Bz) > 📹 **Demos:** [HUD, survival stats & the admin plugin](https://makertube.net/w/xqX7wfRpTqd9L9BkozCS1P) · [no-code item & gatherable creation](https://makertube.net/w/mCneurjoY3Av6yi48VsGQE) · [no-code weapon, ammo & mob creation](https://makertube.net/w/tyn8JEMG3CaMbTXid8osdU) · [no-code quest & achievement creation](https://makertube.net/w/uSGJ2MHEFjSSKxMiJBJ6Y5) · [SurvivorCore Studio — the no-code admin window](https://makertube.net/w/g4oySJeXD4Th7f1zYEu9Bz) · [Build — a plain Part into a working iron node](https://makertube.net/w/2kkyPbDWqoyuKcgbiCGwQG)
## Install ## Install
+1 -1
View File
@@ -34,7 +34,7 @@ Once published, add it to your game's `wally.toml`:
```toml ```toml
[dependencies] [dependencies]
SurvivorCore = "temujincalidius/survivorcore@0.9.0" SurvivorCore = "temujincalidius/survivorcore@0.10.0"
``` ```
Then: Then:
+5 -3
View File
@@ -55,7 +55,7 @@
<div class="hero-inner"> <div class="hero-inner">
<img class="hero-logo" src="assets/img/logo-256.png" alt="SurvivorCore logo" width="112" height="112" /> <img class="hero-logo" src="assets/img/logo-256.png" alt="SurvivorCore logo" width="112" height="112" />
<a class="badge" href="https://github.com/TemujinCalidius/SurvivorCore/releases/latest"> <a class="badge" href="https://github.com/TemujinCalidius/SurvivorCore/releases/latest">
v0.9.0 · pre-release v0.10.0 · pre-release
</a> </a>
<h1>The survival game engine for <span class="accent">Roblox</span></h1> <h1>The survival game engine for <span class="accent">Roblox</span></h1>
<p class="lede"> <p class="lede">
@@ -152,7 +152,8 @@
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a4 4 0 0 0-5.4 5.4l-6 6 2 2 6-6a4 4 0 0 0 5.4-5.4l-2.3 2.3-2-2 2.3-2.3z"/></svg> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a4 4 0 0 0-5.4 5.4l-6 6 2 2 6-6a4 4 0 0 0 5.4-5.4l-2.3 2.3-2-2 2.3-2.3z"/></svg>
</span> </span>
<h3>SurvivorCore Studio — no-code admin</h3> <h3>SurvivorCore Studio — no-code admin</h3>
<p>One floating window with a sidebar &amp; search: tune <strong>every engine config section</strong> — movement, combat, mobs, loot, even UI theme colours &amp; fonts — as locked deltas that survive engine updates. Create items, weapons, ammo, mobs, quests and achievements from forms, <strong>override code-registered content</strong> field-by-field, and drop any of it into the world. No scripting.</p> <p>One floating window with a sidebar &amp; search: tune <strong>every engine config section</strong> — movement, combat, mobs, loot, even UI theme colours &amp; fonts — as locked deltas that survive engine updates. Create items, weapons, ammo, mobs, quests and achievements from forms, and <strong>override code-registered content</strong> field-by-field. No scripting.</p>
<p>Then <strong>Build</strong> turns your own geometry into game content: select any Part or Model, answer <em>“what is this object?”</em>, and fill a form — it becomes a gatherable node, a creature or a quest giver. The form is generated from the engine's own component schema, so <strong>every component gets a setup form for free</strong>, with no UI code behind it.</p>
</article> </article>
</div> </div>
</section> </section>
@@ -180,6 +181,7 @@
<div class="video"><iframe src="https://makertube.net/videos/embed/oVJwYUhCKxA2ZvgvocdhwZ" title="Hunting &amp; loot bags demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>Hunting &amp; loot bags</span></div> <div class="video"><iframe src="https://makertube.net/videos/embed/oVJwYUhCKxA2ZvgvocdhwZ" title="Hunting &amp; loot bags demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>Hunting &amp; loot bags</span></div>
<div class="video"><iframe src="https://makertube.net/videos/embed/g4oySJeXD4Th7f1zYEu9Bz" title="SurvivorCore Studio admin panel demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>SurvivorCore Studio</span></div> <div class="video"><iframe src="https://makertube.net/videos/embed/g4oySJeXD4Th7f1zYEu9Bz" title="SurvivorCore Studio admin panel demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>SurvivorCore Studio</span></div>
<div class="video"><iframe src="https://makertube.net/videos/embed/sJmS6L15jRmwxhQCE4Zgmi" title="Player trading demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>Player trading</span></div> <div class="video"><iframe src="https://makertube.net/videos/embed/sJmS6L15jRmwxhQCE4Zgmi" title="Player trading demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>Player trading</span></div>
<div class="video"><iframe src="https://makertube.net/videos/embed/2kkyPbDWqoyuKcgbiCGwQG" title="Build — no-code world objects demo" loading="lazy" allowfullscreen sandbox="allow-same-origin allow-scripts allow-popups allow-fullscreen"></iframe><span>Build: no-code objects</span></div>
</div> </div>
</section> </section>
@@ -195,7 +197,7 @@
<p>Grab the drop-in model from the latest release, or add it with Wally:</p> <p>Grab the drop-in model from the latest release, or add it with Wally:</p>
<pre><code># wally.toml <pre><code># wally.toml
[dependencies] [dependencies]
SurvivorCore = "temujincalidius/survivorcore@0.9.0"</code></pre> SurvivorCore = "temujincalidius/survivorcore@0.10.0"</code></pre>
<p class="muted">…or drop <code>SurvivorCore.rbxm</code> into <code>ReplicatedStorage</code>.</p> <p class="muted">…or drop <code>SurvivorCore.rbxm</code> into <code>ReplicatedStorage</code>.</p>
<p> <p>
<a class="btn btn-ghost" href="https://github.com/TemujinCalidius/SurvivorCore/releases/latest">Latest release ↗</a> <a class="btn btn-ghost" href="https://github.com/TemujinCalidius/SurvivorCore/releases/latest">Latest release ↗</a>
+1 -1
View File
@@ -74,7 +74,7 @@ local EngineConfig = require(script.shared.EngineConfig)
local SurvivorCore = {} local SurvivorCore = {}
SurvivorCore.VERSION = "0.9.0" SurvivorCore.VERSION = "0.10.0"
-- Foundation -- Foundation
SurvivorCore.Config = Config SurvivorCore.Config = Config
+1 -1
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "temujincalidius/survivorcore" name = "temujincalidius/survivorcore"
description = "Batteries-included, creator-extensible survival game framework for Roblox." description = "Batteries-included, creator-extensible survival game framework for Roblox."
version = "0.9.0" version = "0.10.0"
license = "MIT" license = "MIT"
authors = ["Samuel Lison"] authors = ["Samuel Lison"]
registry = "https://github.com/UpliftGames/wally-index" registry = "https://github.com/UpliftGames/wally-index"