?? trigger.cpp
字號:
/*****************************************************************************/
CLASS_DECLARATION( Entity, Trigger, "trigger_multiple" );
ResponseDef Trigger::Responses[] =
{
{ &EV_Trigger_SetWait, ( Response )Trigger::EventSetWait },
{ &EV_Trigger_SetDelay, ( Response )Trigger::EventSetDelay },
{ &EV_Trigger_SetCount, ( Response )Trigger::EventSetCount },
{ &EV_Trigger_SetMessage, ( Response )Trigger::EventSetMessage },
{ &EV_Trigger_SetNoise, ( Response )Trigger::EventSetNoise },
{ &EV_Touch, ( Response )Trigger::TriggerStuff },
{ &EV_Killed, ( Response )Trigger::TriggerStuff },
{ &EV_Activate, ( Response )Trigger::TriggerStuff },
{ &EV_Trigger_ActivateTargets, ( Response )Trigger::ActivateTargets },
{ &EV_Trigger_SetKey, ( Response )Trigger::EventSetKey },
{ &EV_Trigger_StartThread, ( Response )Trigger::StartThread },
{ NULL, NULL }
};
Trigger::Trigger()
{
triggerActivated = false;
activator = NULL;
trigger_time = (float)0;
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_TRIGGER );
delay = G_GetFloatArg( "delay" );
wait = G_GetFloatArg( "wait", 0.2 );
health = G_GetFloatArg( "health", 0 );
max_health = health;
if ( health )
{
takedamage = DAMAGE_YES;
setSolidType( SOLID_BBOX );
}
trigger_time = (float)0;
count = G_GetFloatArg( "cnt", -1 );
SetNoise( G_GetSpawnArg( "noise", "environment/switch/switch2.wav" ) );
SetMessage( G_GetSpawnArg( "message" ) );
SetKillTarget( G_GetSpawnArg( "killtarget" ) );
hideModel();
respondto = spawnflags ^ TRIGGER_PLAYERS;
key = G_GetStringArg( "key" );
thread = G_GetStringArg( "thread" );
//
// gross HACK for non-standard secret triggers
//
if ( message == "secret" )
{
TriggerSecret *trig;
// don't ever trigger
trigger_time = -1;
// clear out the message
G_SetSpawnArg( "message", "" );
// spawn the replacement trigger
trig = new TriggerSecret;
// delete ourself on the way out.
PostEvent( EV_Remove, 0 );
}
}
Trigger::~Trigger()
{
}
void Trigger::StartThread
(
Event *ev
)
{
if ( thread.length() )
{
if ( !ExecuteThread( thread ) )
{
warning( "StartThread", "Null game script" );
}
}
}
void Trigger::TriggerStuff
(
Event *ev
)
{
Entity *other;
Event *event;
qboolean respond;
// Don't bother with testing anything if we can't trigger yet
if ( ( level.time < trigger_time ) || ( trigger_time == -1 ) )
{
return;
}
health = max_health;
if ( health && ( ( int )*ev != ( int )EV_Killed ) && ( ( int )*ev != ( int )EV_Activate ) )
{
// if health is set, we only respond to killed and activate messages
return;
}
other = ev->GetEntity( 1 );
assert( other != this );
respond = ( ( ( respondto & TRIGGER_PLAYERS ) && other->isClient() ) ||
( ( respondto & TRIGGER_MONSTERS ) && other->isSubclassOf( Actor ) ) ||
( ( respondto & TRIGGER_PROJECTILES ) && other->isSubclassOf( Projectile ) ) );
// Always respond to activate messages from the world since they're probably from
// the "trigger" command
if ( !respond && !( ( other == world ) && ( ( int )*ev == ( int )EV_Activate ) ) )
{
return;
}
if ( key.length() )
{
if ( !other->isSubclassOf( Sentient ) || !( ( (Sentient *)other )->HasItem( key.c_str() ) ) )
{
Item *item;
ClassDef *cls;
str dialog;
cls = getClass( key.c_str() );
if ( !cls )
{
gi.dprintf( "No item named '%s'\n", key.c_str() );
return;
}
item = ( Item * )cls->newInstance();
item->CancelEventsOfType( EV_Item_DropToFloor );
item->CancelEventsOfType( EV_Remove );
item->ProcessPendingEvents();
dialog = item->GetDialogNeeded();
if ( dialog.length() > 1 )
{
if ( !ExecuteThread( dialog ) )
{
warning( "TriggerStuff", "Null game script" );
}
}
else
{
gi.centerprintf ( other->edict, "jcx yv 20 string \"You need this item:\" jcx yv -20 icon %d", item->GetIconIndex() );
}
delete item;
return;
}
}
trigger_time = level.time + wait;
event = new Event( EV_Trigger_Effect );
event->AddEntity( other );
PostEvent( event, delay );
event = new Event( EV_Trigger_ActivateTargets );
event->AddEntity( other );
PostEvent( event, delay );
if ( thread.length() )
{
// don't trigger the thread if we were triggered by the world touching us
if ( ( other != world ) || ( ev->GetSource() != EV_FROM_CODE ) )
{
event = new Event( EV_Trigger_StartThread );
PostEvent( event, delay );
}
}
if ( count > -1 )
{
count--;
if ( count < 1 )
{
//
// Don't allow it to trigger anymore
//
trigger_time = -1;
//
// Make sure we wait until we're done triggering things before removing
//
PostEvent( EV_Remove, delay + 0.1 );
}
}
}
//
//==============================
// ActivateTargets
//
// "other" should be set to the entity that initiated the firing.
//
// Centerprints any message to the activator.
//
// Removes all entities with a targetname that match killtarget,
// so some events can remove other triggers.
//
// Search in targetname of all entities that match target
// and send EVENT_ACTIVATE to there event handler
//==============================
//
void Trigger::ActivateTargets
(
Event *ev
)
{
Entity *other;
Entity *ent;
Event *event;
const char *name;
int num;
other = ev->GetEntity( 1 );
if ( !other )
other = world;
if ( triggerActivated )
{
//
// Entity triggered itself. Prevent an infinite loop
//
ev->Error( "Entity targeting itself--Targetname '%s'", TargetName() );
return;
}
triggerActivated = true;
activator = other;
//
// print the message
//
if ( message.length() && other && other->isClient() )
{
gi.centerprintf( other->edict, "jcx jcy string \"%s\"", message.c_str() );
if ( Noise().length() )
{
other->sound( noise, 1, CHAN_VOICE, ATTN_NORM );
}
}
//
// kill the killtargets
//
name = KillTarget();
if ( name && strcmp( name, "" ) )
{
num = 0;
do
{
num = G_FindTarget( num, name );
if ( !num )
{
break;
}
ent = G_GetEntity( num );
ent->PostEvent( EV_Remove, 0 );
}
while ( 1 );
}
//
// fire targets
//
name = Target();
if ( name && strcmp( name, "" ) )
{
num = 0;
do
{
num = G_FindTarget( num, name );
if ( !num )
{
break;
}
ent = G_GetEntity( num );
event = new Event( EV_Activate );
event->AddEntity( other );
ent->ProcessEvent( event );
}
while ( 1 );
}
triggerActivated = false;
}
void Trigger::EventSetWait
(
Event *ev
)
{
wait = ev->GetFloat( 1 );
}
void Trigger::EventSetDelay
(
Event *ev
)
{
delay = ev->GetFloat( 1 );
}
void Trigger::EventSetKey
(
Event *ev
)
{
key = ev->GetString( 1 );
}
void Trigger::EventSetCount
(
Event *ev
)
{
count = ev->GetInteger( 1 );
}
void Trigger::EventSetMessage
(
Event *ev
)
{
SetMessage( ev->GetString( 1 ) );
}
void Trigger::SetMessage
(
const char *text
)
{
if ( text )
message = str( text );
}
str &Trigger::Message
(
void
)
{
return message;
}
void Trigger::EventSetNoise
(
Event *ev
)
{
SetNoise( ev->GetString( 1 ) );
}
void Trigger::SetNoise
(
const char *text
)
{
if ( text )
{
noise = str( text );
//
// cache in the sound
//
gi.soundindex( text );
}
}
str &Trigger::Noise
(
void
)
{
return noise;
}
CLASS_DECLARATION( Trigger, TouchField, NULL );
ResponseDef TouchField::Responses[] =
{
{ &EV_Trigger_Effect, ( Response )TouchField::SendEvent },
{ NULL, NULL }
};
void TouchField::Setup
(
Entity *ownerentity,
Event touchevent,
Vector min,
Vector max,
int respondto
)
{
assert( ownerentity );
if ( !ownerentity )
{
error( "Setup", "Null owner" );
}
owner = ownerentity;
ontouch = touchevent;
setSize( min, max );
setSolidType( SOLID_TRIGGER );
this->respondto = respondto;
}
void TouchField::SendEvent
(
Event *ev
)
{
Event *event;
// Check if our owner is still around
if ( owner )
{
event = new Event( ontouch );
event->AddEntity( ev->GetEntity( 1 ) );
owner->PostEvent( event, delay );
}
else
{
// Our owner is gone! The bastard didn't delete us!
// Guess we're no longer needed, so remove ourself.
PostEvent( EV_Remove, 0 );
}
}
/*****************************************************************************/
/*SINED trigger_once (.5 .5 .5) ? notouch x NOT_PLAYERS MONSTERS PROJECTILES
Variable sized trigger. Triggers once, then removes itself.
You must set the key "target" to the name of another object in the
level that has a matching
If "health" is set, the trigger must be killed to activate it.
If "delay" is set, the trigger waits some time after activating before firing.
"targetname". If "health" is set, the trigger must be killed to activate.
"thread" name of thread to trigger. This can be in a different script file as well\
by using the '::' notation.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -