# Crash BASIC 1.44.0 Release Notes

*~written by Crash-tan~*

## THE "TYPES THAT DO THINGS" UPDATE

`TYPE` used to be a quiet little thing — a bag of named fields and not much
else. This release gives types a life of their own: they can carry **methods**,
and a method knows the object it belongs to through a new implied reference,
`SELF`. No classes, no inheritance, no ceremony — just behavior that lives next
to the data it works on.

---

## Methods: `SUB Type::Method` and `FUNCTION Type::Method`

Bind a sub or function to a type by qualifying its name with `Type::`. Inside
the body, `SELF` is the instance you called it on — read or assign `SELF.field`
and you change that instance **in place**.

```basic
TYPE Player
    health AS INTEGER
END TYPE

SUB Player::TakeDamage(amount)
    SELF.health = SELF.health - amount
END SUB

FUNCTION Player::IsDead()
    IsDead = SELF.health <= 0
END FUNCTION

DIM p AS Player
p.health = 100
CALL p.TakeDamage(30)
IF p.IsDead() THEN PRINT "game over"
```

A method is an ordinary sub or function in every way — the **only** addition is
`SELF`. So everything you already know still applies:

- **Call a SUB method** with `CALL p.TakeDamage(30)` (subs are always called
  with `CALL`).
- **Call a FUNCTION method** in expression position: `x = p.IsDead()`,
  `IF p.IsDead() THEN ...`.
- **Call a method on another method's `SELF`**: `CALL SELF.Recompute()` or
  `x = SELF.Total()` inside a method body.
- **Methods on array elements**: `CALL enemies(i).Hit(5)` and
  `x = enemies(i).GetHP()` work too.
- **Methods as callbacks**: `CALL THREAD p.Run() AS "ai"`,
  `CALL TIMER p.Tick() EVERY 1 SECOND AS "clock"`,
  `CALL RENDER p.Draw() AS "draw"`, and `CALL EVENT p.OnHit() AS "hit"` all bind
  `SELF` to the object you named — even on array elements
  (`CALL THREAD enemies(i).Run() AS "e" & i`).

Type and method names are case-insensitive, like the rest of the language:
`Player`, `player`, and `PLAYER` are the same type; `p.TakeDamage` and
`p.takedamage` call the same method.

---

## `TYPE` is now a real type

To make methods work, `DIM x AS SomeType` now does more than allocate an empty
object:

- It **pre-creates the declared fields** at their type defaults.
- It **tags the instance** with its type, which is how `x.Method()` knows which
  method to run.
- Arrays of a type (`DIM enemies(8) AS Enemy`) give **every element its own
  independent instance**.

Objects stay dynamic — you can still add fields beyond the ones you declared.

**One compatibility note:** because types are now real, using a type name in
`DIM` that was never declared with `TYPE` is a **loud error** instead of
silently creating an untyped object. This catches typos (`DIM p AS Palyer`).
Declare your `TYPE` before the `DIM` that uses it, the same way you define a SUB
before you CALL it. Built-in types (`INTEGER`, `STRING`, `OBJECT`, …) are
unaffected.

---

## Also in this release

- **`ANIMATE` with no frame list now animates.** Inside a `BEHAVIOR`,
  `ANIMATE "name" FRAMERATE n` with no explicit frames is meant to cycle every
  frame in the sheet — it was sitting frozen on a single frame. It now expands
  to the whole sheet as documented. Listing frames explicitly was never
  affected.
- **Bound polygons are client-only in multiplayer.** A mutation-bound polygon
  (`SET POLYGON`) renders and animates on each client, so calling `SET POLYGON`
  or `DESTROY POLYGON` from server-side code in a CrashNet game is now a clear
  error — wrap it in `IF ME.ISCLIENT THEN ... END IF`. Single-player is
  unaffected.
- **Collision detection now uses a sprite's bounding box everywhere.** The
  automatic collision loop (the `FOR ... COLLISION` statement) previously tested
  each sprite's full, unscaled texture rectangle, while the explicit checks
  (and the solid-collision physics) honored a custom `BBOX` and scale. They now
  agree: every collision test point uses the same effective rectangle, so a
  tight `BBOX` or a scaled sprite collides consistently no matter how you ask.
  If you'd been relying on the old full-texture behavior in a `FOR ... COLLISION`
  loop, sprites with a custom `BBOX` or non-default scale will now collide by
  that box instead.

---

## Compatibility

Methods, `SELF`, and the indexed-receiver call forms are all additive — nothing
about existing subs, functions, or calls changed shape. The one behavior change
is the `DIM x AS UndeclaredType` error described above; programs that only use
built-in types or properly-declared `TYPE`s are unaffected.
