ConVars
Each name is looked up once, then cached.
| API | Description |
|---|---|
aqua.cvar.get(name) |
float, or nil if missing |
aqua.cvar.get_int(name) |
int, or nil |
aqua.cvar.get_bool(name) |
bool, or nil |
aqua.cvar.type(name) |
"bool"/"int32"/"float32"/… , "invalid" if the tag is unavailable, nil if missing |
aqua.cvar.exists(name) |
bool |
local vol = aqua.cvar.get("volume") or 1.0local sens = aqua.cvar.get("sensitivity")
-- Getters CONVERT, so this is fine even though sv_showimpacts is an int cvar:local impacts = aqua.cvar.get("sv_showimpacts") -- 1.0, not 1.4e-45The getters convert. A convar’s value is a type-tagged union, and each getter
now reads it as its real type and converts - aqua.cvar.get on an int convar
returns 1.0, not the float reinterpretation of the bit pattern.
Before 2026-08-06 they reinterpreted raw bytes, so calling the wrong getter
returned garbage with nothing to indicate it: sv_showimpacts read back as
1.4012984643248e-45 (the float view of 0x00000001) and looked like a broken
or unset convar rather than “enabled”.
One case still behaves the old way: if the type tag fails its runtime
validation, conversion is disabled and the getters reinterpret raw bytes again.
aqua.cvar.type(name) returns "invalid" in that state, so a script that cares
can check for it. It is a fail-closed fallback, not the expected path.