2013-04-04 22:35:38 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
# include "g_local.h"
//==========================================================
/*QUAKED target_give (1 0 0) (-8 -8 -8) (8 8 8)
Gives the activator all the items pointed to .
*/
void Use_Target_Give ( gentity_t * ent , gentity_t * other , gentity_t * activator ) {
gentity_t * t ;
trace_t trace ;
if ( ! activator - > client ) {
return ;
}
if ( ! ent - > target ) {
return ;
}
memset ( & trace , 0 , sizeof ( trace ) ) ;
t = NULL ;
while ( ( t = G_Find ( t , FOFS ( targetname ) , ent - > target ) ) ! = NULL ) {
if ( ! t - > item ) {
continue ;
}
Touch_Item ( t , activator , & trace ) ;
// make sure it isn't going to respawn or show any events
t - > nextthink = 0 ;
trap_UnlinkEntity ( t ) ;
}
}
void SP_target_give ( gentity_t * ent ) {
ent - > use = Use_Target_Give ;
}
//==========================================================
/*QUAKED target_remove_powerups (1 0 0) (-8 -8 -8) (8 8 8)
takes away all the activators powerups .
Used to drop flight powerups into death puts .
*/
void Use_target_remove_powerups ( gentity_t * ent , gentity_t * other , gentity_t * activator ) {
if ( ! activator - > client ) {
return ;
}
if ( activator - > client - > ps . powerups [ PW_REDFLAG ] ) {
Team_ReturnFlag ( TEAM_RED ) ;
} else if ( activator - > client - > ps . powerups [ PW_BLUEFLAG ] ) {
Team_ReturnFlag ( TEAM_BLUE ) ;
} else if ( activator - > client - > ps . powerups [ PW_NEUTRALFLAG ] ) {
Team_ReturnFlag ( TEAM_FREE ) ;
}
memset ( activator - > client - > ps . powerups , 0 , sizeof ( activator - > client - > ps . powerups ) ) ;
}
void SP_target_remove_powerups ( gentity_t * ent ) {
ent - > use = Use_target_remove_powerups ;
}
//==========================================================
/*QUAKED target_delay (1 0 0) (-8 -8 -8) (8 8 8) NO_RETRIGGER
NO_RETRIGGER - Keeps the delay from resetting the time if it is
activated again while it is counting down to an event .
" wait " seconds to pause before firing targets .
" random " delay variance , total delay = delay + / - random seconds
*/
void Think_Target_Delay ( gentity_t * ent ) {
G_UseTargets ( ent , ent - > activator ) ;
}
void Use_Target_Delay ( gentity_t * ent , gentity_t * other , gentity_t * activator ) {
if ( ent - > nextthink > level . time & & ( ent - > spawnflags & 1 ) )
{ //Leave me alone, I am thinking.
return ;
}
G_ActivateBehavior ( ent , BSET_USE ) ;
ent - > nextthink = level . time + ( ent - > wait + ent - > random * crandom ( ) ) * 1000 ;
ent - > think = Think_Target_Delay ;
ent - > activator = activator ;
}
void SP_target_delay ( gentity_t * ent ) {
// check delay for backwards compatability
if ( ! G_SpawnFloat ( " delay " , " 0 " , & ent - > wait ) ) {
G_SpawnFloat ( " wait " , " 1 " , & ent - > wait ) ;
}
if ( ! ent - > wait ) {
ent - > wait = 1 ;
}
ent - > use = Use_Target_Delay ;
}
//==========================================================
/*QUAKED target_score (1 0 0) (-8 -8 -8) (8 8 8)
" count " number of points to add , default 1
The activator is given this many points .
*/
void Use_Target_Score ( gentity_t * ent , gentity_t * other , gentity_t * activator ) {
AddScore ( activator , ent - > r . currentOrigin , ent - > count ) ;
}
void SP_target_score ( gentity_t * ent ) {
if ( ! ent - > count ) {
ent - > count = 1 ;
}
ent - > use = Use_Target_Score ;
}
//==========================================================
/*QUAKED target_print (1 0 0) (-8 -8 -8) (8 8 8) redteam blueteam private
" message " text to print
" wait " don ' t fire off again if triggered within this many milliseconds ago
If " private " , only the activator gets the message . If no checks , all clients get the message .
*/
void Use_Target_Print ( gentity_t * ent , gentity_t * other , gentity_t * activator )
{
if ( ! ent | | ! ent - > inuse )
{
2013-04-04 23:21:13 +00:00
Com_Printf ( " ERROR: Bad ent in Use_Target_Print " ) ;
return ;
2013-04-04 22:35:38 +00:00
}
if ( ent - > wait )
{
if ( ent - > genericValue14 > = level . time )
{
return ;
}
ent - > genericValue14 = level . time + ent - > wait ;
}
# ifndef FINAL_BUILD
2013-04-04 23:21:13 +00:00
if ( ! ent | | ! ent - > inuse )
{
Com_Error ( ERR_DROP , " Bad ent in Use_Target_Print " ) ;
}
else if ( ! activator | | ! activator - > inuse )
{
Com_Error ( ERR_DROP , " Bad activator in Use_Target_Print " ) ;
}
2013-04-04 22:35:38 +00:00
if ( ent - > genericValue15 > level . time )
{
Com_Printf ( " TARGET PRINT ERRORS: \n " ) ;
if ( activator & & activator - > classname & & activator - > classname [ 0 ] )
{
Com_Printf ( " activator classname: %s \n " , activator - > classname ) ;
}
if ( activator & & activator - > target & & activator - > target [ 0 ] )
{
Com_Printf ( " activator target: %s \n " , activator - > target ) ;
}
if ( activator & & activator - > targetname & & activator - > targetname [ 0 ] )
{
Com_Printf ( " activator targetname: %s \n " , activator - > targetname ) ;
}
if ( ent - > targetname & & ent - > targetname [ 0 ] )
{
Com_Printf ( " print targetname: %s \n " , ent - > targetname ) ;
}
Com_Error ( ERR_DROP , " target_print used in quick succession, fix it! See the console for details. " ) ;
}
ent - > genericValue15 = level . time + 5000 ;
# endif
G_ActivateBehavior ( ent , BSET_USE ) ;
2013-04-04 23:21:13 +00:00
if ( ( ent - > spawnflags & 4 ) )
{ //private, to one client only
if ( ! activator | | ! activator - > inuse )
2013-04-04 22:35:38 +00:00
{
2013-04-04 23:21:13 +00:00
Com_Printf ( " ERROR: Bad activator in Use_Target_Print " ) ;
2013-04-04 22:35:38 +00:00
}
2013-04-04 23:21:13 +00:00
if ( activator & & activator - > client )
{ //make sure there's a valid client ent to send it to
if ( ent - > message [ 0 ] = = ' @ ' & & ent - > message [ 1 ] ! = ' @ ' )
{
trap_SendServerCommand ( activator - g_entities , va ( " cps \" %s \" " , ent - > message ) ) ;
}
else
{
trap_SendServerCommand ( activator - g_entities , va ( " cp \" %s \" " , ent - > message ) ) ;
}
2013-04-04 22:35:38 +00:00
}
2013-04-04 23:21:13 +00:00
//NOTE: change in functionality - if there *is* no valid client ent, it won't send it to anyone at all
2013-04-04 22:35:38 +00:00
return ;
}
if ( ent - > spawnflags & 3 ) {
if ( ent - > spawnflags & 1 ) {
if ( ent - > message [ 0 ] = = ' @ ' & & ent - > message [ 1 ] ! = ' @ ' )
{
G_TeamCommand ( TEAM_RED , va ( " cps \" %s \" " , ent - > message ) ) ;
}
else
{
G_TeamCommand ( TEAM_RED , va ( " cp \" %s \" " , ent - > message ) ) ;
}
}
if ( ent - > spawnflags & 2 ) {
if ( ent - > message [ 0 ] = = ' @ ' & & ent - > message [ 1 ] ! = ' @ ' )
{
G_TeamCommand ( TEAM_BLUE , va ( " cps \" %s \" " , ent - > message ) ) ;
}
else
{
G_TeamCommand ( TEAM_BLUE , va ( " cp \" %s \" " , ent - > message ) ) ;
}
}
return ;
}
if ( ent - > message [ 0 ] = = ' @ ' & & ent - > message [ 1 ] ! = ' @ ' )
{
trap_SendServerCommand ( - 1 , va ( " cps \" %s \" " , ent - > message ) ) ;
}
else
{
trap_SendServerCommand ( - 1 , va ( " cp \" %s \" " , ent - > message ) ) ;
}
}
void SP_target_print ( gentity_t * ent ) {
ent - > use = Use_Target_Print ;
}
//==========================================================
/*QUAKED target_speaker (1 0 0) (-8 -8 -8) (8 8 8) looped-on looped-off global activator
" noise " wav file to play
A global sound will play full volume throughout the level .
Activator sounds will play on the player that activated the target .
Global and activator sounds can ' t be combined with looping .
Normal sounds play each time the target is used .
Looped sounds will be toggled by use functions .
Multiple identical looping sounds will just increase volume without any speed cost .
" wait " : Seconds between auto triggerings , 0 = don ' t auto trigger
" random " wait variance , default is 0
*/
void Use_Target_Speaker ( gentity_t * ent , gentity_t * other , gentity_t * activator ) {
G_ActivateBehavior ( ent , BSET_USE ) ;
if ( ent - > spawnflags & 3 ) { // looping sound toggles
if ( ent - > s . loopSound )
{
ent - > s . loopSound = 0 ; // turn it off
ent - > s . loopIsSoundset = qfalse ;
ent - > s . trickedentindex = 1 ;
}
else
{
ent - > s . loopSound = ent - > noise_index ; // start it
ent - > s . loopIsSoundset = qfalse ;
ent - > s . trickedentindex = 0 ;
}
} else { // normal sound
if ( ent - > spawnflags & 8 ) {
G_AddEvent ( activator , EV_GENERAL_SOUND , ent - > noise_index ) ;
} else if ( ent - > spawnflags & 4 ) {
G_AddEvent ( ent , EV_GLOBAL_SOUND , ent - > noise_index ) ;
} else {
G_AddEvent ( ent , EV_GENERAL_SOUND , ent - > noise_index ) ;
}
}
}
void SP_target_speaker ( gentity_t * ent ) {
char buffer [ MAX_QPATH ] ;
char * s ;
G_SpawnFloat ( " wait " , " 0 " , & ent - > wait ) ;
G_SpawnFloat ( " random " , " 0 " , & ent - > random ) ;
if ( G_SpawnString ( " soundSet " , " " , & s ) )
{ // this is a sound set
ent - > s . soundSetIndex = G_SoundSetIndex ( s ) ;
ent - > s . eFlags = EF_PERMANENT ;
VectorCopy ( ent - > s . origin , ent - > s . pos . trBase ) ;
trap_LinkEntity ( ent ) ;
return ;
}
if ( ! G_SpawnString ( " noise " , " NOSOUND " , & s ) ) {
G_Error ( " target_speaker without a noise key at %s " , vtos ( ent - > s . origin ) ) ;
}
// force all client reletive sounds to be "activator" speakers that
// play on the entity that activates it
if ( s [ 0 ] = = ' * ' ) {
ent - > spawnflags | = 8 ;
}
Q_strncpyz ( buffer , s , sizeof ( buffer ) ) ;
ent - > noise_index = G_SoundIndex ( buffer ) ;
// a repeating speaker can be done completely client side
ent - > s . eType = ET_SPEAKER ;
ent - > s . eventParm = ent - > noise_index ;
ent - > s . frame = ent - > wait * 10 ;
ent - > s . clientNum = ent - > random * 10 ;
// check for prestarted looping sound
if ( ent - > spawnflags & 1 ) {
ent - > s . loopSound = ent - > noise_index ;
ent - > s . loopIsSoundset = qfalse ;
}
ent - > use = Use_Target_Speaker ;
if ( ent - > spawnflags & 4 ) {
ent - > r . svFlags | = SVF_BROADCAST ;
}
VectorCopy ( ent - > s . origin , ent - > s . pos . trBase ) ;
// must link the entity so we get areas and clusters so
// the server can determine who to send updates to
trap_LinkEntity ( ent ) ;
}
//==========================================================
/*QUAKED target_laser (0 .5 .8) (-8 -8 -8) (8 8 8) START_ON
When triggered , fires a laser . You can either set a target or a direction .
*/
void target_laser_think ( gentity_t * self ) {
vec3_t end ;
trace_t tr ;
vec3_t point ;
// if pointed at another entity, set movedir to point at it
if ( self - > enemy ) {
VectorMA ( self - > enemy - > s . origin , 0.5 , self - > enemy - > r . mins , point ) ;
VectorMA ( point , 0.5 , self - > enemy - > r . maxs , point ) ;
VectorSubtract ( point , self - > s . origin , self - > movedir ) ;
VectorNormalize ( self - > movedir ) ;
}
// fire forward and see what we hit
VectorMA ( self - > s . origin , 2048 , self - > movedir , end ) ;
trap_Trace ( & tr , self - > s . origin , NULL , NULL , end , self - > s . number , CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_CORPSE ) ;
if ( tr . entityNum ) {
// hurt it if we can
G_Damage ( & g_entities [ tr . entityNum ] , self , self - > activator , self - > movedir ,
tr . endpos , self - > damage , DAMAGE_NO_KNOCKBACK , MOD_TARGET_LASER ) ;
}
VectorCopy ( tr . endpos , self - > s . origin2 ) ;
trap_LinkEntity ( self ) ;
self - > nextthink = level . time + FRAMETIME ;
}
void target_laser_on ( gentity_t * self )
{
if ( ! self - > activator )
self - > activator = self ;
target_laser_think ( self ) ;
}
void target_laser_off ( gentity_t * self )
{
trap_UnlinkEntity ( self ) ;
self - > nextthink = 0 ;
}
void target_laser_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
self - > activator = activator ;
if ( self - > nextthink > 0 )
target_laser_off ( self ) ;
else
target_laser_on ( self ) ;
}
void target_laser_start ( gentity_t * self )
{
gentity_t * ent ;
self - > s . eType = ET_BEAM ;
if ( self - > target ) {
ent = G_Find ( NULL , FOFS ( targetname ) , self - > target ) ;
if ( ! ent ) {
G_Printf ( " %s at %s: %s is a bad target \n " , self - > classname , vtos ( self - > s . origin ) , self - > target ) ;
}
self - > enemy = ent ;
} else {
G_SetMovedir ( self - > s . angles , self - > movedir ) ;
}
self - > use = target_laser_use ;
self - > think = target_laser_think ;
if ( ! self - > damage ) {
self - > damage = 1 ;
}
if ( self - > spawnflags & 1 )
target_laser_on ( self ) ;
else
target_laser_off ( self ) ;
}
void SP_target_laser ( gentity_t * self )
{
// let everything else get spawned before we start firing
self - > think = target_laser_start ;
self - > nextthink = level . time + FRAMETIME ;
}
//==========================================================
void target_teleporter_use ( gentity_t * self , gentity_t * other , gentity_t * activator ) {
gentity_t * dest ;
if ( ! activator - > client )
return ;
G_ActivateBehavior ( self , BSET_USE ) ;
dest = G_PickTarget ( self - > target ) ;
if ( ! dest ) {
G_Printf ( " Couldn't find teleporter destination \n " ) ;
return ;
}
TeleportPlayer ( activator , dest - > s . origin , dest - > s . angles ) ;
}
/*QUAKED target_teleporter (1 0 0) (-8 -8 -8) (8 8 8)
The activator will be teleported away .
*/
void SP_target_teleporter ( gentity_t * self ) {
if ( ! self - > targetname )
G_Printf ( " untargeted %s at %s \n " , self - > classname , vtos ( self - > s . origin ) ) ;
self - > use = target_teleporter_use ;
}
//==========================================================
/*QUAKED target_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM x x x x INACTIVE
This doesn ' t perform any actions except fire its targets .
The activator can be forced to be from a certain team .
if RANDOM is checked , only one of the targets will be fired , not all of them
INACTIVE Can ' t be used until activated
wait - set to - 1 to use it only once
*/
void target_relay_use ( gentity_t * self , gentity_t * other , gentity_t * activator ) {
qboolean ranscript = qfalse ;
if ( ( self - > spawnflags & 1 ) & & activator - > client
& & activator - > client - > sess . sessionTeam ! = TEAM_RED ) {
return ;
}
if ( ( self - > spawnflags & 2 ) & & activator - > client
& & activator - > client - > sess . sessionTeam ! = TEAM_BLUE ) {
return ;
}
if ( self - > flags & FL_INACTIVE )
{ //set by target_deactivate
return ;
}
ranscript = G_ActivateBehavior ( self , BSET_USE ) ;
if ( self - > wait = = - 1 )
{ //never use again
if ( ranscript )
{ //crap, can't remove!
self - > use = NULL ;
}
else
{ //remove
self - > think = G_FreeEntity ;
self - > nextthink = level . time + FRAMETIME ;
}
}
if ( self - > spawnflags & 4 ) {
gentity_t * ent ;
ent = G_PickTarget ( self - > target ) ;
if ( ent & & ent - > use ) {
GlobalUse ( ent , self , activator ) ;
}
return ;
}
G_UseTargets ( self , activator ) ;
}
void SP_target_relay ( gentity_t * self ) {
self - > use = target_relay_use ;
if ( self - > spawnflags & 128 )
{
self - > flags | = FL_INACTIVE ;
}
}
//==========================================================
/*QUAKED target_kill (.5 .5 .5) (-8 -8 -8) (8 8 8)
Kills the activator .
*/
void target_kill_use ( gentity_t * self , gentity_t * other , gentity_t * activator ) {
G_ActivateBehavior ( self , BSET_USE ) ;
G_Damage ( activator , NULL , NULL , NULL , NULL , 100000 , DAMAGE_NO_PROTECTION , MOD_TELEFRAG ) ;
}
void SP_target_kill ( gentity_t * self ) {
self - > use = target_kill_use ;
}
/*QUAKED target_position (0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for in - game calculation , like jumppad targets .
*/
void SP_target_position ( gentity_t * self ) {
G_SetOrigin ( self , self - > s . origin ) ;
/*
G_SetAngles ( self , self - > s . angles ) ;
self - > s . eType = ET_INVISIBLE ;
*/
}
static void target_location_linkup ( gentity_t * ent )
{
int i ;
int n ;
if ( level . locationLinked )
return ;
level . locationLinked = qtrue ;
level . locationHead = NULL ;
trap_SetConfigstring ( CS_LOCATIONS , " unknown " ) ;
for ( i = 0 , ent = g_entities , n = 1 ;
i < level . num_entities ;
i + + , ent + + ) {
if ( ent - > classname & & ! Q_stricmp ( ent - > classname , " target_location " ) ) {
// lets overload some variables!
ent - > health = n ; // use for location marking
trap_SetConfigstring ( CS_LOCATIONS + n , ent - > message ) ;
n + + ;
ent - > nextTrain = level . locationHead ;
level . locationHead = ent ;
}
}
// All linked together now
}
/*QUAKED target_location (0 0.5 0) (-8 -8 -8) (8 8 8)
Set " message " to the name of this location .
Set " count " to 0 - 7 for color .
0 : white 1 : red 2 : green 3 : yellow 4 : blue 5 : cyan 6 : magenta 7 : white
Closest target_location in sight used for the location , if none
in site , closest in distance
*/
void SP_target_location ( gentity_t * self ) {
self - > think = target_location_linkup ;
self - > nextthink = level . time + 200 ; // Let them all spawn first
G_SetOrigin ( self , self - > s . origin ) ;
}
/*QUAKED target_counter (1.0 0 0) (-4 -4 -4) (4 4 4) x x x x x x x INACTIVE
Acts as an intermediary for an action that takes multiple inputs .
INACTIVE cannot be used until used by a target_activate
target2 - what the counter should fire each time it ' s incremented and does NOT reach it ' s count
After the counter has been triggered " count " times ( default 2 ) , it will fire all of it ' s targets and remove itself .
bounceCount - number of times the counter should reset to it ' s full count when it ' s done
*/
extern void G_DebugPrint ( int level , const char * format , . . . ) ;
void target_counter_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
if ( self - > count = = 0 )
{
return ;
}
//gi.Printf("target_counter %s used by %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
self - > count - - ;
if ( activator )
{
G_DebugPrint ( WL_VERBOSE , " target_counter %s used by %s (%d/%d) \n " , self - > targetname , activator - > targetname , ( self - > genericValue1 - self - > count ) , self - > genericValue1 ) ;
}
if ( self - > count )
{
if ( self - > target2 )
{
//gi.Printf("target_counter %s firing target2 from %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
G_UseTargets2 ( self , activator , self - > target2 ) ;
}
return ;
}
G_ActivateBehavior ( self , BSET_USE ) ;
if ( self - > spawnflags & 128 )
{
self - > flags | = FL_INACTIVE ;
}
self - > activator = activator ;
G_UseTargets ( self , activator ) ;
if ( self - > count = = 0 )
{
if ( self - > bounceCount = = 0 )
{
return ;
}
self - > count = self - > genericValue1 ;
if ( self - > bounceCount > 0 )
{ //-1 means bounce back forever
self - > bounceCount - - ;
}
}
}
void SP_target_counter ( gentity_t * self )
{
self - > wait = - 1 ;
if ( ! self - > count )
{
self - > count = 2 ;
}
//if ( self->bounceCount > 0 )//let's always set this anyway
{ //we will reset when we use up our count, remember our initial count
self - > genericValue1 = self - > count ;
}
self - > use = target_counter_use ;
}
/*QUAKED target_random (.5 .5 .5) (-4 -4 -4) (4 4 4) USEONCE
Randomly fires off only one of it ' s targets each time used
USEONCE set to never fire again
*/
void target_random_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
int t_count = 0 , pick ;
gentity_t * t = NULL ;
//gi.Printf("target_random %s used by %s (entnum %d)\n", self->targetname, activator->targetname, activator->s.number );
G_ActivateBehavior ( self , BSET_USE ) ;
if ( self - > spawnflags & 1 )
{
self - > use = 0 ;
}
while ( ( t = G_Find ( t , FOFS ( targetname ) , self - > target ) ) ! = NULL )
{
if ( t ! = self )
{
t_count + + ;
}
}
if ( ! t_count )
{
return ;
}
if ( t_count = = 1 )
{
G_UseTargets ( self , activator ) ;
return ;
}
//FIXME: need a seed
pick = Q_irand ( 1 , t_count ) ;
t_count = 0 ;
while ( ( t = G_Find ( t , FOFS ( targetname ) , self - > target ) ) ! = NULL )
{
if ( t ! = self )
{
t_count + + ;
}
else
{
continue ;
}
if ( t = = self )
{
// gi.Printf ("WARNING: Entity used itself.\n");
}
else if ( t_count = = pick )
{
if ( t - > use ! = NULL ) // check can be omitted
{
GlobalUse ( t , self , activator ) ;
return ;
}
}
if ( ! self - > inuse )
{
Com_Printf ( " entity was removed while using targets \n " ) ;
return ;
}
}
}
void SP_target_random ( gentity_t * self )
{
self - > use = target_random_use ;
}
int numNewICARUSEnts = 0 ;
void scriptrunner_run ( gentity_t * self )
{
/*
if ( self - > behaviorSet [ BSET_USE ] )
{
char newname [ MAX_FILENAME_LENGTH ] ;
sprintf ( ( char * ) & newname , " %s/%s " , Q3_SCRIPT_DIR , self - > behaviorSet [ BSET_USE ] ) ;
ICARUS_RunScript ( self , newname ) ;
}
*/
if ( self - > count ! = - 1 )
{
if ( self - > count < = 0 )
{
self - > use = 0 ;
self - > behaviorSet [ BSET_USE ] = NULL ;
return ;
}
else
{
- - self - > count ;
}
}
if ( self - > behaviorSet [ BSET_USE ] )
{
if ( self - > spawnflags & 1 )
{
if ( ! self - > activator )
{
if ( g_developer . integer )
{
Com_Printf ( " target_scriptrunner tried to run on invalid entity! \n " ) ;
}
return ;
}
//if ( !self->activator->sequencer || !self->activator->taskManager )
if ( ! trap_ICARUS_IsInitialized ( self - > s . number ) )
{ //Need to be initialized through ICARUS
if ( ! self - > activator - > script_targetname | | ! self - > activator - > script_targetname [ 0 ] )
{
//We don't have a script_targetname, so create a new one
self - > activator - > script_targetname = va ( " newICARUSEnt%d " , numNewICARUSEnts + + ) ;
}
if ( trap_ICARUS_ValidEnt ( self - > activator ) )
{
trap_ICARUS_InitEnt ( self - > activator ) ;
}
else
{
if ( g_developer . integer )
{
Com_Printf ( " target_scriptrunner tried to run on invalid ICARUS activator! \n " ) ;
}
return ;
}
}
if ( g_developer . integer )
{
Com_Printf ( " target_scriptrunner running %s on activator %s \n " , self - > behaviorSet [ BSET_USE ] , self - > activator - > targetname ) ;
}
trap_ICARUS_RunScript ( self - > activator , va ( " %s/%s " , Q3_SCRIPT_DIR , self - > behaviorSet [ BSET_USE ] ) ) ;
}
else
{
if ( g_developer . integer & & self - > activator )
{
Com_Printf ( " target_scriptrunner %s used by %s \n " , self - > targetname , self - > activator - > targetname ) ;
}
G_ActivateBehavior ( self , BSET_USE ) ;
}
}
if ( self - > wait )
{
self - > nextthink = level . time + self - > wait ;
}
}
void target_scriptrunner_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
if ( self - > nextthink > level . time )
{
return ;
}
self - > activator = activator ;
self - > enemy = other ;
if ( self - > delay )
{ //delay before firing scriptrunner
self - > think = scriptrunner_run ;
self - > nextthink = level . time + self - > delay ;
}
else
{
scriptrunner_run ( self ) ;
}
}
/*QUAKED target_scriptrunner (1 0 0) (-4 -4 -4) (4 4 4) runonactivator x x x x x x INACTIVE
- - - SPAWNFLAGS - - -
runonactivator - Will run the script on the entity that used this or tripped the trigger that used this
INACTIVE - start off
- - - - - KEYS - - - - - -
Usescript - Script to run when used
count - how many times to run , - 1 = infinite . Default is once
wait - can ' t be used again in this amount of seconds ( Default is 1 second if it ' s multiple - use )
delay - how long to wait after use to run script
*/
void SP_target_scriptrunner ( gentity_t * self )
{
float v ;
if ( self - > spawnflags & 128 )
{
self - > flags | = FL_INACTIVE ;
}
if ( ! self - > count )
{
self - > count = 1 ; //default 1 use only
}
/*
else if ( ! self - > wait )
{
self - > wait = 1 ; //default wait of 1 sec
}
*/
// FIXME: this is a hack... because delay is read in as an int, so I'm bypassing that because it's too late in the project to change it and I want to be able to set less than a second delays
// no one should be setting a radius on a scriptrunner, if they are this would be bad, take this out for the next project
v = 0.0f ;
G_SpawnFloat ( " delay " , " 0 " , & v ) ;
self - > delay = v * 1000 ; //sec to ms
self - > wait * = 1000 ; //sec to ms
G_SetOrigin ( self , self - > s . origin ) ;
self - > use = target_scriptrunner_use ;
}
void G_SetActiveState ( char * targetstring , qboolean actState )
{
gentity_t * target = NULL ;
while ( NULL ! = ( target = G_Find ( target , FOFS ( targetname ) , targetstring ) ) )
{
target - > flags = actState ? ( target - > flags & ~ FL_INACTIVE ) : ( target - > flags | FL_INACTIVE ) ;
}
}
# define ACT_ACTIVE qtrue
# define ACT_INACTIVE qfalse
void target_activate_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
G_ActivateBehavior ( self , BSET_USE ) ;
G_SetActiveState ( self - > target , ACT_ACTIVE ) ;
}
void target_deactivate_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
G_ActivateBehavior ( self , BSET_USE ) ;
G_SetActiveState ( self - > target , ACT_INACTIVE ) ;
}
//FIXME: make these apply to doors, etc too?
/*QUAKED target_activate (1 0 0) (-4 -4 -4) (4 4 4)
Will set the target ( s ) to be usable / triggerable
*/
void SP_target_activate ( gentity_t * self )
{
G_SetOrigin ( self , self - > s . origin ) ;
self - > use = target_activate_use ;
}
/*QUAKED target_deactivate (1 0 0) (-4 -4 -4) (4 4 4)
Will set the target ( s ) to be non - usable / triggerable
*/
void SP_target_deactivate ( gentity_t * self )
{
G_SetOrigin ( self , self - > s . origin ) ;
self - > use = target_deactivate_use ;
}
void target_level_change_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
G_ActivateBehavior ( self , BSET_USE ) ;
trap_SendConsoleCommand ( EXEC_NOW , va ( " map %s " , self - > message ) ) ;
}
/*QUAKED target_level_change (1 0 0) (-4 -4 -4) (4 4 4)
" mapname " - Name of map to change to
*/
void SP_target_level_change ( gentity_t * self )
{
char * s ;
G_SpawnString ( " mapname " , " " , & s ) ;
self - > message = G_NewString ( s ) ;
if ( ! self - > message | | ! self - > message [ 0 ] )
{
G_Error ( " target_level_change with no mapname! \n " ) ;
return ;
}
G_SetOrigin ( self , self - > s . origin ) ;
self - > use = target_level_change_use ;
}
void target_play_music_use ( gentity_t * self , gentity_t * other , gentity_t * activator )
{
G_ActivateBehavior ( self , BSET_USE ) ;
trap_SetConfigstring ( CS_MUSIC , self - > message ) ;
}
/*QUAKED target_play_music (1 0 0) (-4 -4 -4) (4 4 4)
target_play_music
Plays the requested music files when this target is used .
" targetname "
" music " music WAV or MP3 file ( music / introfile . mp3 [ optional ] music / loopfile . mp3 )
If an intro file and loop file are specified , the intro plays first , then the looping
portion will start and loop indefinetly . If no introfile is entered , only the loopfile
will play .
*/
void SP_target_play_music ( gentity_t * self )
{
char * s ;
G_SetOrigin ( self , self - > s . origin ) ;
if ( ! G_SpawnString ( " music " , " " , & s ) )
{
G_Error ( " target_play_music without a music key at %s " , vtos ( self - > s . origin ) ) ;
}
self - > message = G_NewString ( s ) ;
self - > use = target_play_music_use ;
}