Table of Contents
- Script load order
- State machine
- Interface functions
- List of interface functions
- function init(me) [mandatory]
- function postInit(me)
- function update(me, dt) [mandatory]
- function enterState(me)
- function exitState(me)
- function damage(me, attacker, bone, damageType, dmg, hitX, hitY, shot)
- function msg(me, message, value)
- Special interface functions
- function activate(me)
- function animationKey(me, key)
- function canShotHit(me, attacker, bone, damageType, dmg, hitX, hitY, shot) [OSE only]
- function deathNotify(me, ro) [OSE only]
- function dieEaten(me)
- function dieNormal(me)
- function entityDied(me, dead)
- function exitTimer(me) [removed in OSE]
- function hitSurface(me)
- function lightFlare(me)
- function shiftWorlds(me, lastWorld, newWorld)
- function shotHitEntity(me, hit, shot, bone)
- function song(me, songID)
- function songNote(me, noteID)
- function songNoteDone(me, noteID)
- function sporesDropped(me, sporeType)
Almost all entities are scripted. Entity scripts for mods are located in _mods/modname/*.lua
.
Script load order
When an entity named chomper is loaded, the game first looks in
_mods/modname/scripts/chomper.lua
If no such file exists, it falls back to the vanilla scripts:
scripts/entities/chomper.lua
This way you can use entities from the base game out-of-the-box, without copying scripts.
State machine
Each entity is implicitly a state machine. To summarize, an entity can have a current state (e.g. STATE_IDLE) and eventually transition to a new state (e.g. STATE_ATTACK).
When a state transition happens, the enterState()
and exitState()
interface functions are called. This is useful to script simple interactions and behaviors and model the transitions (e.g. animation changes) between states cleanly.
Interface functions
Interface functions are called by the game to notify an entity of certain events. Most of them are optional; the game will try to call it and if that doesn't work, it remembers that and won't call the same function again.
Beware! This means that if your interface function throws an error, it will be considered non-existent and never called again for the entity that caused the error. This is probably not what you want, so have an eye on the error log and fix your code if that happens.
If you get errors like jellysmall : Attempt to call a nil value (???:0) animationKey
this is usually the normal clutter that appears when an interface function (in this case animationKey
) isn't defined.
List of interface functions
me
is the entity currently processed. Functions are optional unless noted otherwise.
function init(me)
[mandatory]
Called once when an entity is spawned. Usually used to set health, textures, attachments, etc.
When a map is loaded, all scripted entities on the map have their init()
function called.
When an entity is spawned dynamically while the map is already going, init()
is called the same way.
Warning: Do not spawn or delete entities in init()
as this may lead to problems. Use postInit()
for that.
function postInit(me)
Useful to set properties that depend on other entities being already inititalized.
When a map is loaded, all entities' init()
is called first, then all entities' postInit()
is called.
When an entity is spawned dynamically while the map is already going, init()
is called first, and postInit()
immediately afterwards.
Compatibility note: postInit()
is not called when an entity is spawned via an SE-node.
function update(me, dt)
[mandatory]
Called once every frame. dt
holds the time (in seconds) since the last frame.
The update()
function does the bulk of the work that defines an entity. Movement, behavior, shot collision, etc. are all handled here.
In order to ensure your code is framerate-independent, make sure you multiply values with dt
as required.
function enterState(me)
Called when the internal state machine transitions to a new state. The new state is already current when the function is called. Use entity_isState(me, STATE_WHATEVER)
or entity_getState(me)
to check the new state. Use entity_getPrevState(me)
to get the previous state.
The state is STATE_DEAD
when an entity has died and is about to be despawned. Once an entity is in this state, it can't be changed anymore.
When an entity's death scene is enabled, STATE_DEATHSCENE
is entered on death, after which the entity always transitions to STATE_DEAD
. No other state is allowed.
function exitState(me)
Called just before enterState()
. At the time of the call, the old state is still current.
Use entity_isState(me, STATE_WHATEVER)
or entity_getState(me)
to check the current state.
There is no way to obtain the next state.
function damage(me, attacker, bone, damageType, dmg, hitX, hitY, shot)
Called when an entity receives damage. The game uses this function to check whether damage should be applied or not.
If the function returns true
, does not exist, or fails, damage is applied.
If the function returns false, damage is not applied.
attacker
is the entity that caused the damage, if available.bone
is the bone that was hit in case the damage was caused by bone collision.damageType
is the type of damage that is about to be applied.dmg
is a positive number holding the amount of damage that will be applied.hitx, hitY
are the world coordinates where the damage was caused, if available.shot
is the shot that caused the damage, if available.
function msg(me, message, value)
Called when a message is received (sent via entity_msg(me, message, value)
. This function is substantially different in OSE and previous versions:
- Pre-OSE: Message is a string, value may can be a number, entity, or node. Due to how entity pointers are encoded in this version, value will always be a number, so message sender and receiver need to agree on how to interpret value, otherwise it'll crash. Communication is unidirectional only, i.e. if you want to answer, you'll have to send a message back.
- OSE: Message handling is variadic, i.e.
msg(me, ...)
receives all parameters from the correspondingentity_msg(me, ...)
call. Values returned frommsg()
are forwarded to and returned byentity_msg()
. This allows for easy bi-directional communication.
Special interface functions
function activate(me)
Called when an entity is activated (default right click).
An entity must previously be made activatable via entity_setActivationType(me, AT_CLICK)
or entity_setActivation(me, AT_CLICK, radius, range)
function animationKey(me, key)
Called when the entity has an animating skeleton and the animation reaches a keyframe. key
is the ID of the keyframe. Use entity_getAnimationName(me)
to get the animation name.
function canShotHit(me, attacker, bone, damageType, dmg, hitX, hitY, shot)
[OSE only]
Same parameters as damage()
.
Called to check whether a shot should actually hit an entity. This function is only called when there is a collision, and is used to decide whether to collide or whether the shot passes through. If the function returns false, the shot passes through. If the function returns true, doesn't exist, or causes an error, the shot hits.
function deathNotify(me, ro)
[OSE only]
An entity has an internal death notification list that stores RenderObjects that want to be notified when the entity is destroyed.
For each entity in this list, deathNotify(me, dead)
is called (me
is the receiver of the notifiation, dead
the thing that is getting destroyed).
Death notifications are set up via entity_addDeathNotify(me, which)
so that me
tells which
when me
is destroyed.
Note that this is a fairly low-level function. Death notification is delivered in all cases, even when an object is despawned by any means.
function dieEaten(me)
Called when me
dies after receiving damage of type DT_AVATAR_BITE or DT_AVATAR_PETBITE and an entity's eat type is not EAT_NONE.
The eat type can be changed via entity_setEatType(me, [EAT_NONE|EAT_DEFAULT|EAT_FILE]).
This is called after enterState()
with STATE_DEAD.
function dieNormal(me)
Called when me
dies and the conditions for dieEaten()
do not apply.
function entityDied(me, dead)
Called when entity dead
dies. This function is only called when entity me
has previously asked to be notified by calling esetv(me, EV_ENTITYDIED, 1)
beforehand.
function exitTimer(me)
[removed in OSE]
Called when an entity's timer (previously set by entity_resetTimer(me)
) has expired.
The internal entity timer was removed in the OSE version as none of the vanilla scripts used this special timer.
function hitSurface(me)
Called when the entity hits solid ground.
function lightFlare(me)
Called when Naija uses the sun form light flare ability. Function will be called only when the distance between Naija and the entity is 2048 or closer.
function shiftWorlds(me, lastWorld, newWorld)
Called when Naija uses the spirit form ability and switches between spirit and normal world. No other world types exist.
function shotHitEntity(me, hit, shot, bone)
Called when a shot shot
fired by me
hits entity hit
. If the hit entity uses skeletal collision, bone
is the bone that was hit.
function song(me, songID)
Called when Naija successfully sings a known song. Function will be called only when the distance between Naija and the entity is 1000 or closer.
function songNote(me, noteID)
Called when Naija starts singing a Note. Function will be called only when the distance between Naija and the entity is 1000 or closer.
function songNoteDone(me, noteID)
Called when Naija stops singing a Note. Function will be called only when the distance between Naija and the entity is 1000 or closer.
function sporesDropped(me, sporeType)
Called when a shot hits solid ground and that shot is set to spawn an entity on impact. sporeType
is 0 when that entity is called "NatureFormFlowers", and 2 otherwise.
Alternatively, call registerSporeDrop(x, y, sporeType)
to trigger this manually -- x, y
is the position where the drop should be registered.
Function will be called only when the distance between the drop point and me
is 1024 or closer.