# Language Basics

This page is the “data modeling” side of CSL: primitives, structs/classes, and the patterns you’ll use to represent game state cleanly.

{% hint style="info" %}
If you’re brand new, start with [Getting Started with CSL](/scripting/syntax.md). This page assumes you already know how to declare variables and write `proc`/`method`.
{% endhint %}

## Primitive types

### Numbers and bools

* Signed integers: `s8`, `s16`, `s32`, `s64` (alias: `int` == `s64`)
* Unsigned integers: `u8`, `u16`, `u32`, `u64` (alias: `uint` == `u64`)
* Floats: `f32` (alias: `float`), `f64`
* Booleans: `bool`

```go
health: int = 100;
speed: float = 6.5;
is_dead: bool = false;
```

CSL widens numbers when that is safe: smaller signed integers can become wider signed integers, smaller unsigned integers can become wider unsigned integers, unsigned integers can become wider signed integers when the target can hold the full range, and `f32` can become `f64`.

### Strings

`string` is used constantly for IDs, names, and formatting.

```go
item_id := "sword";
log_info("picked up %", {item_id});
```

### Vectors

`v2`, `v3`, `v4` are built-in math/data types:

```go
pos: v2 = {10, 20};
color: v4 = {1, 0, 0, 1};
```

## Enums

Enums are great for readable “mode/state” fields:

```go
Game_Phase :: enum {
    LOBBY;
    RUNNING;
    POST_GAME;
}

phase := Game_Phase.LOBBY;

if phase == .RUNNING {
    // ...
}
```

{% hint style="info" %}
Enum values are commonly referenced with the shorthand `.VALUE` when the compiler can infer the enum type.
{% endhint %}

## Structs (value types)

Use structs for “plain data” you want to copy around cheaply (config, small state blobs, descriptors).

```go
Damage_Desc :: struct {
    amount: int;
    knockback: v2;
}

hit := Damage_Desc{amount=10, knockback={2, 1}};
```

Structs can inherit from other structs. Compound literals include inherited fields first:

```go
Base_Stats :: struct {
    health: int;
}

Enemy_Stats :: struct : Base_Stats {
    speed: float;
}

stats: Enemy_Stats = {100, 4.5};
```

### When to use a struct

* A descriptor/config object (`*_Desc`)
* Small, self-contained state you want to copy by value
* Data you want to embed inside another type

### When not to use a struct

* Large mutable state shared across multiple systems (use a class)
* “Identity” objects (players, items, long-lived objects) (use a class)

## Classes (reference types)

Classes are reference types. Create instances with `new(...)`.

```go
Enemy :: class {
    health: int = 50;
    target: v2 = {0, 0};
}

e := new(Enemy);
```

### Inheritance

You can inherit from other structs/classes:

```go
Weapon_Definition :: class {
    id: string;
    name: string;
}

Gun_Definition :: class : Weapon_Definition {
    fire_rate: float;
}
```

Derived classes inherit default field values. They can override inherited defaults with `field = value` in the class body:

```go
Weapon_Definition :: class {
    damage: int = 10;
}

Rocket_Definition :: class : Weapon_Definition {
    damage = 100;
    splash_radius: float = 3.0;
}
```

{% hint style="warning" %}
Use inheritance when there’s a real “is-a” relationship. For most gameplay data, composition (fields) is simpler and easier to maintain.
{% endhint %}

## Arrays, slices, and dynamic arrays

You’ll see three common shapes:

* **Fixed arrays**: `[N]T` (compile-time size)
* **Slices / managed arrays**: `[]T` (a view of an array)
* **Dynamic arrays**: `[..]T` (resizable list)

Example:

```go
spawn_points: [4]v2 = {{0,0}, {5,0}, {0,5}, {5,5}};

alive_enemy_ids: [..]int;
alive_enemy_ids.append(123);
alive_enemy_ids.append(456);
```

For a full guide, see [Arrays and Collections](/scripting/arrays-and-collections.md).

## Passing by reference (`ref`)

If a procedure needs to modify a value, use `ref`:

```go
apply_damage :: proc(health: ref int, amount: int) {
    health -= amount;
}

hp := 100;
apply_damage(ref hp, 10);
```

This is especially useful for “layout-style” APIs that progressively cut/shrink a rect:

```go
draw_panel :: proc(rect: ref Rect) {
    header := rect.cut_top(50);
    draw_header(header);
    // rect is now the remaining area for content
}
```

## Casting

Use `expr.(T)` or `cast(T)expr`:

```go
f := 12.7;
i := f.(int);       // 12
f2 := cast(float)i; // 12.0
```

When the target type is already known, `expr.()` and `cast expr` infer the target type.

## Type polymorphism (generic-style procs)

CSL supports polymorphic procedures using `$` to deduce types at the callsite:

```go
min :: proc(a: $T, b: T) -> T {
    if a < b return a;
    return b;
}

a := min(10, 20);       // T == int
b := min(1.25, 3.5);    // T == float
```

## Types as values (`typeid`)

`typeid` is a value that represents a type at runtime and/or for polymorphic calls:

```go
default_of :: proc($T: typeid) -> T {
    t: T;
    return t;
}

zero := default_of(int);
empty := default_of(string);
```

`value.#type` returns the runtime type of a class value. Use it before downcasting from a base class when the exact derived type matters.

## Practical modeling guidelines

* **Per-player state lives on `Player`.** If it should differ between players, it shouldn’t be global.
* **Prefer small structs for descriptors** and store runtime state in classes/components.
* **Keep server-authoritative data authoritative.** If it affects gameplay, don’t compute it only on the client.

For player-specific patterns, see [Adding Player Logic](/scripting/player-model.md). For the ECS side of the world, see [Entities and Components](/scripting/entities-and-components.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.allout.game/scripting/types-and-structures.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
