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`
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
- **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>
> **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
> [The Counter Earth](https://thecounterearth.com).
@@ -71,7 +71,7 @@ into `ReplicatedStorage`, or add it via [Wally](https://wally.run):
```toml
# wally.toml
[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.
+22 -11
View File
@@ -12,6 +12,9 @@ local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
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 -----------------------------------------------------
-- 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"
@@ -416,10 +419,12 @@ local function seedPlayer(player: Player)
player:SetAttribute("EquipSlot_Head", "straw_hat") -- a pre-filled equipment slot
player:SetAttribute("EquipSlot_Back", "reed_satchel") -- equipped for +slots / +carry weight
end
for _, player in Players:GetPlayers() do
seedPlayer(player)
if STAGE.SeedInventory then
for _, player in Players:GetPlayers() do
seedPlayer(player)
end
Players.PlayerAdded:Connect(seedPlayer)
end
Players.PlayerAdded:Connect(seedPlayer)
SurvivorCore.start()
@@ -509,10 +514,12 @@ local function buildReed(position: Vector3)
reed.Parent = Workspace
end
buildTree(Vector3.new(10, 0, 28))
buildTree(Vector3.new(18, 0, 28))
buildReed(Vector3.new(-8, 0, 28))
buildReed(Vector3.new(-12, 0, 28))
if STAGE.WorldContent then
buildTree(Vector3.new(10, 0, 28))
buildTree(Vector3.new(18, 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.
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
-- 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 })
SurvivorCore.Mobs.spawn("husk", CFrame.new(82, 5, 58), { respawn = true })
SurvivorCore.Mobs.spawn("boar", CFrame.new(-30, 5, 18))
if STAGE.Mobs then
SurvivorCore.Mobs.spawn("husk", CFrame.new(70, 5, 45), { respawn = true })
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 —
-- 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")
post.Parent = Workspace
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.
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 SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore"))
local Stage = require(script.Parent.Stage)
local PICKUPS = {
{ 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
local BASE = Vector3.new(0, 4, 16) -- opposite side from the stat test stations
for i, def in PICKUPS do
local x = (i - (#PICKUPS + 1) / 2) * 4
buildPickup(def, BASE + Vector3.new(x, 0, 0))
if Stage.TestStations then
local BASE = Vector3.new(0, 4, 16) -- opposite side from the stat test stations
for i, def in PICKUPS do
local x = (i - (#PICKUPS + 1) / 2) * 4
buildPickup(def, BASE + Vector3.new(x, 0, 0))
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 SurvivorCore = require(ReplicatedStorage:WaitForChild("SurvivorCore"))
local Stage = require(script.Parent.Stage)
local POISON_SOURCE = "TestStation:poison"
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
-- 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)
for i, def in STATIONS do
local x = (i - (#STATIONS + 1) / 2) * 4
buildStation(def, BASE + Vector3.new(x, 0, 0))
if Stage.TestStations then
local BASE = Vector3.new(0, 4, -16)
for i, def in STATIONS do
local x = (i - (#STATIONS + 1) / 2) * 4
buildStation(def, BASE + Vector3.new(x, 0, 0))
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
> 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
+1 -1
View File
@@ -34,7 +34,7 @@ Once published, add it to your game's `wally.toml`:
```toml
[dependencies]
SurvivorCore = "temujincalidius/survivorcore@0.9.0"
SurvivorCore = "temujincalidius/survivorcore@0.10.0"
```
Then:
+5 -3
View File
@@ -55,7 +55,7 @@
<div class="hero-inner">
<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">
v0.9.0 · pre-release
v0.10.0 · pre-release
</a>
<h1>The survival game engine for <span class="accent">Roblox</span></h1>
<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>
</span>
<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>
</div>
</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/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/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>
</section>
@@ -195,7 +197,7 @@
<p>Grab the drop-in model from the latest release, or add it with Wally:</p>
<pre><code># wally.toml
[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>
<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 = {}
SurvivorCore.VERSION = "0.9.0"
SurvivorCore.VERSION = "0.10.0"
-- Foundation
SurvivorCore.Config = Config
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "temujincalidius/survivorcore"
description = "Batteries-included, creator-extensible survival game framework for Roblox."
version = "0.9.0"
version = "0.10.0"
license = "MIT"
authors = ["Samuel Lison"]
registry = "https://github.com/UpliftGames/wally-index"