Scalar components
A scalar component stores one number, boolean, or string directly in an archetype column:
local Health <const> = tecs.ecs.newScalarComponent({
name = "Health",
kind = "number",
default = 100,
})
local entity <const> = world:spawn(Health(75))
world:set(entity, Health, 50)
print(world:get(entity, Health)) -- 50Use this storage when the component means exactly one primitive value. Use a tag for presence alone and a table or FFI component for a structured value.
Values and constructor tokens
world:get and archetype columns return the raw primitive. Health(75) instead returns a small component token for spawn and the two-argument world:set form:
world:set(entity, Health(25))
assert(world:get(entity, Health) == 25)The token does not compare equal to its primitive value. Treat it as an input to component APIs, not as stored data.
Calling world:set(entity, Health) writes the registered default. When no default exists, the kind supplies 0, false, or an empty string.
Column updates
Scalar columns follow ordinary query and dirty rules:
local living <const> = world:newQuery({
include = {Health},
type = "logic",
})
for archetype, length in living:iter() do
local health <const> = archetype:getMut(Health)
for row = 1, length do
health[row] = math.max(0, health[row] - 1)
end
endDo not split one coherent value into many scalar components only to pursue column density. A position normally belongs in one structured component rather than separate X and Y components.
Typed module exports
Scalar registration has no container record to carry its value type. State the type on a module export:
local record combat
Health: tecs.ecs.ScalarComponent<number>
end
combat.Health = tecs.ecs.newScalarComponent({
name = "Health",
kind = "number",
default = 100,
})
return combat