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()

remove the actor from the game

bool IsStale()

returns true if the actor has been flagged for removal, and is no longer valid

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()

provides access to actor's defs properties

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()

returns non-null even if actor isn't an AI; validate with InstanceOf("kexAI") if uncertain

int GameTicks()

how many ticks the actor has existed for

int16& Health()

actor's health

uint& Flags()

bit field of actor flags:

uint SpawnFlags1()

  • 1 <<  0Solid
  • 1 <<  1Projectile Attack 1
  • 1 <<  2Leader
  • 1 <<  3Snap To Floor
  • 1 <<  4Explosion Death
  • 1 <<  5Climb Walls
  • 1 <<  6Projectile Attack 2
  • 1 <<  7No Repeat Explosion
  • 1 <<  8Die On Explosion
  • 1 <<  9Flocker
  • 1 << 13Kamikaze
  • 1 << 14Avoid Players
  • 1 << 15Float In Water On Death
  • 1 << 16Teleport
  • 1 << 17Cast Shadow
  • 1 << 18Teleport Wait
  • 1 << 19Use Strong Attacks
  • 1 << 20Use Weak Attacks
  • 1 << 21Sniper
  • 1 << 22Melt On Death
  • 1 << 23Avoid Water
  • 1 << 24Flying
  • 1 << 25Teleport Avoid Water
  • 1 << 26Teleport Avoid Cliffs
  • 1 << 27Trigger Stuff
  • 1 << 28Cannot Cause A Fight
  • 1 << 29No Wall Collision
  • 1 << 30Screen Shake
  • 1 << 31Respawn Animation

uint SpawnFlags2()

  • 1 <<  0Drop Item Mask 1
  • 1 <<  1Drop Item Mask 2
  • 1 <<  2Drop Item Mask 3
  • 1 <<  3Drop Item Mask 4
  • 1 <<  4Drop Item Mask 5
  • 1 <<  5Drop Item Mask 6
  • 1 <<  6Drop Item Mask 7
  • 1 <<  7Drop Item Mask 8
  • 1 <<  8Drop Item Mask 9
  • 1 <<  9Drop Item Mask 10
  • 1 << 10Drop Item Mask 11
  • 1 << 11Drop Item Mask 12
  • 1 << 12Drop Item Mask 13
  • 1 << 13Drop Item Mask 14
  • 1 << 14Remove on Completion
  • 1 << 15No Blood
  • 1 << 16Hold Trigger Animation
  • 1 << 17Projectile Attack 3
  • 1 << 18Projectile Attack 4
  • 1 << 19Drop Item On Damage
  • 1 << 20No Automap Draw
  • 1 << 21Alternate Moves
  • 1 << 24Projectile Attack 5
  • 1 << 25Projectile Attack 6
  • 1 << 26Mortal Wound Impact
  • 1 << 27Stay In Water
  • 1 << 30Projectile Attack 7
  • 1 << 31Projectile Attack 8

uint SpawnFlags3()

  • 1 <<  1Play Trigger Anim Once
  • 1 <<  2Regenerate From Start
  • 1 <<  3Walk In Straight Line
  • 1 <<  5No Thinker
  • 1 <<  6Avoid Players 2
  • 1 <<  7No Violent Death
  • 1 <<  8Projectile Attack 9
  • 1 <<  9Projectile Attack 10
  • 1 << 10Make Spawn Anim Visible
  • 1 << 11No Draw On Camera

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:

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()

model 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

actors are removed at a distance around 1996.9 * GAME_SCALE from global origin

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 reflect 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 clipFlags = 0 )

tries to find a sector that contains loc from the actor's current location

clipFlags is a bit field of clip flags to disable while traversing the nav mesh during the search:

updates the global CModel, presumably to indicate what, if anything, blocked the path from the actor's current location to loc

void SetSector( uint i )

float& Friction()

float& BounceDamp()

Collision

float& Radius()

float& Height()

collision volume dimensions

float& WallRadius()

float& FloorHeight()

initial global z-coordinate of the floor at the current location, as defined in the map file

modifying the reference value will not change the sector's height (see kWorld::ChangeSectorHeight()), but will persist to subsequent calls to the function, allowing you to change what's considered the "initial" height

float GetFloorHeight()

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

float& CeilingHeight()

float GetCeilingHeight()

global z-coordinate of the 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 )

returns localOffset converted to global coordinates based on actor's Scale(), Origin(), and orientation

for the player, this doesn't take view pitch into account; for other actors, it does take slope tilt into account

float GetTurnYaw( kVec3& v )

offset from current Yaw() to face global point v

float GetAvoidanceAngle( kVec3& v, float f )

float DistanceToPoint( kVec3& v )

float DistanceToPoint( float x, float y, float z )

square of the distance from center of mass (origin + half height) to a global point

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 true if 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 SpawnFx( kStr& s, kVec3& v )

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

void InflictGenericDamage( kActor@ instigator, int amount )

deal amount of damage to this actor

instigator will be passed on to ScriptObject::OnDamage()/OnDeath()

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 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