Turok EX Modding Guide

Scripts kActor

kActor is an internal class that acts as an intermediary between scripts and an actor's native object. If an actor has a script object assigned, it will receive a handle to its associated kActor in its constructor.

Core

void Remove()

bool IsStale()

void MarkPersistentBit( bool bUnmark )

bool IsPersistentMarked()

set and check the actor's persistent bit, respectively

the persistent bit only applies to actors placed in the map file – for actors spawned dynamically during gameplay, MarkPersistentBit() does nothing, and IsPersistentMarked() always returns false

for more information on the persistent bit, see ScriptObject::OnRestore()

int TID()

actor tag ID

kScriptObject@ ScriptObject()

returns a wrapper for the user script object this actor is associated with

kDictMem@ Definition()

int& Type()

actor type ID

this is the number after the actor's type name in defs/actors/, and enumerated in turokActorTypes in scripts/common.txt

bool InstanceOf( kStr& className )

returns whether this actor's associated native object is an instance of className, or a subclass thereof (this refers to kex-prefixed classes, not script classes)

kActor@ CastToActor()

kAI@ CastToAI()

int GameTicks()

how many ticks the actor has existed for

int16& Health()

actor's health

uint& Flags()

bit field of actor flags:

uint SpawnFlags1()

uint SpawnFlags2()

uint SpawnFlags3()

static bit fields corresponding to the tabs of the same names in the editor

some of these are used to initialize other properties when the actor is (re)spawned (e.g., the Sniper flag sets AF_STATIONARY), while other are referenced directly (e.g., the item drop flags in TurokEnemy::DropItem())

int16 SpawnParams( int param )

static properties corresponding to the following editor fields:

  1. Target TID
  2. Trigger Anim (uint8)
  3. Health (initial)
  4. Max Regenerations
  5. Attack Chance (uint8)
  6. Texture (initial) (int8)
  7. Params 2 (int8)
  8. Params 1 (int8)

some classes use these in novel ways (e.g., movers use health and attack chance to control timing)

Display

kRenderModel@ RenderModel()

returns a handle to the actor's render model

int& ModelVariation()

which model variant to use (e.g., regular or cyborg variant of raptor)

kVec3& Scale()

kAnimState& AnimState()

returns a reference to the actor's anim state

float& AnimSpeed()

void RunFxEvent( kStr& effectName )

apply an actor effect, defined in actorfx/*.kafx

todo: link to actorfx reference

Movement

kVec3& Origin()

current location of the actor

kVec3& PrevOrigin()

location of the actor before the last move

for objects in motion, this is the location from the previous tick – the value will get stale when the object comes to rest

kVec3& Movement()

almost the change in location during the last tick, but not quite

for the player, this will be the horizontal offset only, except when in the air or swimming

when swimming, the z component will reflect the attempted offset – it'll still be non-zero when swimming up at the surface or down at the floor

kVec3& Velocity()

attempted delta per tick

For the player, this will always be (0,0,0), except for the z component when in the air. When knocked back by a purlin, it'll also show the entire velocity imparted by the attack.

float& Gravity()

positive is down

only takes effect when in the air

float& StepHeight()

void MoveToPosition( float newX, float newY )

tries to move to the given global horizontal coordinates

will move up and down slopes, but will be stopped by any obstructions along the way

stores collision info in the global CModel if anything was hit along the way

void SetPosition( kVec3& newLoc )

set location to an arbitrary point

if the actor gets stuck in an invalid spot (based on its clip flags), the game will try to find a reasonable place to move it back into bounds

kAngle& Yaw()

kAngle& Pitch()

kAngle& Roll()

orientation of the actor, applied in the order listed

for the player, this reflects where the player is looking

kQuat& Rotation()

orientation of the actor

for the player, this reflects where the player is looking

bool OnGround()

on the ground, on a climbable wall, or swimming along the ground underwater

bool InWater()

swimming underwater

int GetWaterLevel()

info related to water areas (excluding AAF_SHALLOWWATER areas)

possible values are:

int AreaID()

int SectorIndex()

actor's area and sector, respectively

int GetSectorIndexAtLocation( kVec3& loc, uint [unknown] = 0 )

returns the sector that contains loc

void SetSector( uint i )

float& Friction()

float& BounceDamp()

Collision

float& Radius()

float& Height()

float& WallRadius()

float& FloorHeight()

float GetFloorHeight()

float& CeilingHeight()

float GetCeilingHeight()

global z-coordinate of the floor or ceiling at the current location

CeilingHeight()'s value is only updated when the actor enters a new sector, making it coarse and imprecise

bool CheckPosition( kVec3& v )

bool CheckPosition( float f, float f )

float GetWaterHeight()

global z-coordinate of current area's water surface

int& ImpactType()

defines which onImpact sub-block effects use when colliding with this actor

possible values are:

uint& ClipFlags()

bit field of clipping flags:

Sound

void PlaySound( kStr& path )

play a sound by file path

e.g., self.PlaySound( "sounds/shaders/pistol_shot.ksnd" );

void PlaySoundWithLookupID( int ID )

play a sound by ID number, as defined in defs/fileLookup.txt

void StopSound()

stop all sounds this actor is playing, looping or otherwise

void StopLoopingSounds()

stop only looping sounds this actor is playing

Spatial

kVec3 GetTransformedVector( kVec3& localOffset )

multiplies localOffset by Scale(), converts to global coordinates based on orientation (Yaw()? not Rotation(), since it doesn't take player view pitch into account), and returns the result added to Origin()

float GetTurnYaw( kVec3& v )

float GetAvoidanceAngle( kVec3& v, float f )

float DistanceToPoint( kVec3& v )

float DistanceToPoint( float f1, float f2, float f3 )

Targeting

void SetTarget( kActor@ a )

kActor@ GetTarget()

bool CanSee( kActor@ a, uint clipFlags = 0 )

bool CanSee( kPuppet@ a, uint clipFlags = 0 )

performs a raycast to a, and stores the result in the global CModel

returns whether anything was hit between the two actors

clipFlags is a bit field of clip flags to disable (e.g., "collide floors" means the ray should not collide with floors; i.e., the actor should see through floors):

void SetHeadTrackTarget( kActor@ a )

Other Methods

void SpawnProjectile( kStr& s, kVec3& v1, kVec3& v2, float f )

void MeleeObject( kStr& damageType, kVec3& offset, float radius )

inflict damageType on all actors within range of the given offset, according to the following math:

float range = (radius + 1) * 2 * GAME_SCALE;
kVec3 origin = self.GetTransformedVector( offset );
for every actor A in the general vicinity of origin
{
	kVec3 v = A.Origin();     // actor's base
	v.z += A.Height() * 0.5f; // center of mass
	float dist = (v - origin).Unit() - A.Radius();
	if ( dist <= range )
		inflict damageType on A
}

damage types are defined in defs/damageInfo.txt

void SpawnFx( kStr& s, kVec3& v )

void SpawnFx( kStr& s, kVec3& v, kQuat& q )

void InflictGenericDamage( kActor@ a, int i )

void InteractActorsAtPosition( kVec3& position, kStr& callbackFunc,
float arg1 = 0, float arg2 = 0, float arg3 = 0, float arg4 = 0 )

for every actor A in the general vicinity of position, call:

this.callbackFunc( A, arg1, arg2, arg3, arg4 );

the callback function should be defined in the user script (or a parent class) for the actor that called InteractActorsAtPosition(), with the following type signature:
void( kActor@, const float, const float, const float, const float )

bool RandomDecision( int i )

probability of returning true is 1 / 2i-1, except when i is 0, in which case the probability is nearly 0