⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trigger.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 5 页
字号:

if "killtarget" is set, any objects that have a matching "target" will be
removed when the trigger is fired.

if "angle" is set, the trigger will only fire when someone is facing the 
direction of the angle.  Use "360" for an angle of 0.

"key" The item needed to activate this. (default nothing)

If NOT_PLAYERS is set, the trigger does not respond to players
If MONSTERS is set, the trigger will respond to monsters
If PROJECTILES is set, the trigger will respond to projectiles (rockets, grenades, etc.)

set "message" to text string

/*****************************************************************************/

CLASS_DECLARATION( Trigger, TriggerOnce, "trigger_once" );

ResponseDef TriggerOnce::Responses[] =
	{
		{ NULL, NULL }
	};

TriggerOnce::TriggerOnce()
	{
   //
   // gross HACK for oilrig.bsp
   //
   if ( message == "Foreman jumps over the edge of the rig" )
      {
      PostEvent( EV_Remove, 0 );
      }

	//
	// no matter what, we only trigger once
	//
	count = 1;
	respondto = spawnflags ^ TRIGGER_PLAYERS;

   // 
   // if it's not supposed to be touchable, clear the trigger
   //
   if ( spawnflags & 1 )
	   setSolidType( SOLID_NOT );
	}

/*****************************************************************************/
/*SINED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) x x NOT_PLAYERS MONSTERS PROJECTILES

This fixed size trigger cannot be touched, it can only be fired by other events.
It can contain killtargets, targets, delays, and messages.

If NOT_PLAYERS is set, the trigger does not respond to events triggered by players
If MONSTERS is set, the trigger will respond to events triggered by monsters
If PROJECTILES is set, the trigger will respond to events triggered by projectiles (rockets, grenades, etc.)

/*****************************************************************************/

CLASS_DECLARATION( Trigger, TriggerRelay, "trigger_relay" );

ResponseDef TriggerRelay::Responses[] =
	{
		{ &EV_Touch, NULL },
		{ NULL, NULL }
	};

TriggerRelay::TriggerRelay()
	{
	setSolidType( SOLID_NOT );
	}

/*****************************************************************************/
/*SINED trigger_damagethreshold (0 .5 .8) ? x INVISIBLE NOT_PLAYERS MONSTERS ACCUMULATIVE

Triggers only when a threshold of damage is exceeded.
When used in conjunction with func_breakawaywall, allows
walls that may be destroyed with a rocket blast.  Will also trigger
any targeted func_areaportals when not invisible.

INVISIBLE tells the trigger to not be visible.

"health" specifies how much damage must occur before trigger fires.
Default is 60.

"cnt" specifies how many times the trigger can fire before it will remove itself.
-1 sepecies infinite firing.  Default is 1.

"key" The item needed to activate this. (default nothing)

If NOT_PLAYERS is set, the trigger does not respond to damage caused by players
If MONSTERS is set, the trigger will respond to damage caused by monsters

/*****************************************************************************/
#define DAMAGETHRESHOLD_ACCUMULATIVE   ( 1 << 4 )

CLASS_DECLARATION( Trigger, DamageThreshold, "trigger_damagethreshold" );

// Only used internally
static Event EV_DamageThreshold_Setup( "setup" );

ResponseDef DamageThreshold::Responses[] =
	{
	   { &EV_Damage,						( Response )DamageThreshold::DamageEvent },
	   { &EV_DamageThreshold_Setup,	( Response )DamageThreshold::Setup },
		{ &EV_Touch,						NULL },
		{ NULL, NULL }
	};

void DamageThreshold::DamageEvent
	(
	Event *ev
	)

	{
	Event			*event;
	Entity		*inflictor;
	Entity		*attacker;
	int			damage;

	if ( takedamage == DAMAGE_NO )
		{
		return;
		}

	damage		= ev->GetInteger( 1 );
	inflictor	= ev->GetEntity( 2 );
	attacker		= ev->GetEntity( 3 );

   if ( spawnflags & DAMAGETHRESHOLD_ACCUMULATIVE )
      {
      health -= damage;
   	damage_taken += damage;
      if ( health > 0 )
         return;
      }
   else
      {
	   if ( damage < health )
		   {
		   return;
		   }
   	damage_taken = damage;
      }

	event = new Event( EV_Activate );
	event->AddEntity( attacker );
	ProcessEvent( event );
	}

void DamageThreshold::Setup
	(
	Event *ev
	)

	{
	SetAreaPortals( Target(), false );
	}

DamageThreshold::DamageThreshold()
	{
	//
	// Default behavior is one use
	//
	count = G_GetIntArg( "cnt", 1 );

	damage_taken = 0;

	setSolidType( SOLID_BSP );
	setMoveType( MOVETYPE_PUSH );

	if ( !( spawnflags & INVISIBLE ) )
		{
		showModel();
		PostEvent( EV_DamageThreshold_Setup, 0 );
		}

	health = G_GetFloatArg( "health", 60 );
	max_health = health;
	takedamage = DAMAGE_YES;

	respondto = ( spawnflags ^ TRIGGER_PLAYERS ) & ~TRIGGER_PROJECTILES;
	}

/*****************************************************************************/
/*SINED trigger_secret (.5 .5 .5) ? notouch x NOT_PLAYERS MONSTERS PROJECTILES
Secret counter trigger.  Automatically sets and increments script variables \
level.total_secrets and level.found_secrets.

set "message" to text string

"key" The item needed to activate this. (default nothing)

"thread" name of thread to trigger.  This can be in a different script file as well \
by using the '::' notation.  (defaults to "global/universal_script.scr::secret")

If NOT_PLAYERS is set, the trigger does not respond to players
If MONSTERS is set, the trigger will respond to monsters
If PROJECTILES is set, the trigger will respond to projectiles (rockets, grenades, etc.)

/*****************************************************************************/

CLASS_DECLARATION( TriggerOnce, TriggerSecret, "trigger_secret" );

ResponseDef TriggerSecret::Responses[] =
	{
		{ &EV_Trigger_Effect,		( Response )TriggerSecret::FoundSecret },
		{ NULL, NULL }
	};

TriggerSecret::TriggerSecret()
	{
   if ( !LoadingSavegame )
      {
	   level.total_secrets++;
      levelVars.SetVariable( "total_secrets", level.total_secrets );
      }
	respondto = spawnflags ^ TRIGGER_PLAYERS;

   // set the thread to trigger when secrets are found
   thread = G_GetStringArg( "thread", "global/universal_script.scr::secret" );
	}

void TriggerSecret::FoundSecret
	(
	Event *ev
	)

	{
	//
	// anything that causes the trigger to fire increments the number
   // of secrets found.  This way, if the level designer triggers the
   // secret from the script, the player still gets credit for finding
   // it.  This is to prevent a secret from becoming undiscoverable.
	//
	level.found_secrets++;
   levelVars.SetVariable( "found_secrets", level.found_secrets );
   }

/*****************************************************************************/
/*SINED trigger_push (.5 .5 .5) ? x x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES

Pushes entities as if they were caught in a heavy wind.

"speed" indicates the rate that entities are pushed (default 1000).

"angle" indicates the direction the wind is blowing (-1 is up, -2 is down)

"key" The item needed to activate this. (default nothing)

"target" if target is set, then a velocity will be calculated based on speed

If NOT_PLAYERS is set, the trigger does not push players
If NOT_MONSTERS is set, the trigger will not push monsters
If NOT_PROJECTILES is set, the trigger will not push projectiles (rockets, grenades, etc.)

/*****************************************************************************/

CLASS_DECLARATION( Trigger, TriggerPush, "trigger_push" );

ResponseDef TriggerPush::Responses[] =
	{
	   { &EV_Trigger_Effect,			( Response )TriggerPush::Push },
		{ NULL, NULL }
	};

void TriggerPush::Push
	(
	Event *ev
	)

	{
	Entity *other;

	other = ev->GetEntity( 1 );
	if ( other )
		{
      const char * targ;
	   Entity *ent;
	   int num;

      targ = Target ();
      if ( targ[ 0 ] )
         {
		   num = G_FindTarget( 0, Target() );
		   ent = G_GetEntity( num );
		   if ( num && ent )
            {
            other->velocity = G_CalculateImpulse
               (
               other->worldorigin,
               ent->worldorigin,
               speed,
               other->gravity
               );
            }
         }
      else
		   other->velocity = pushvelocity;
		}
	}

TriggerPush::TriggerPush()
	{
   speed = G_GetFloatArg( "speed", 1000 );
	pushvelocity = G_GetMovedir() * speed;
	respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES );
	}

/*****************************************************************************/
/*SINED trigger_pushany (.5 .5 .5) ? x x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES

Pushes entities as if they were caught in a heavy wind.

"speed" indicates the rate that entities are pushed (default 1000).
"angles" indicates the direction of the push
"key" The item needed to activate this. (default nothing)
"target" if target is set, then a velocity will be calculated based on speed

If NOT_PLAYERS is set, the trigger does not push players
If NOT_MONSTERS is set, the trigger will not push monsters
If NOT_PROJECTILES is set, the trigger will not push projectiles (rockets, grenades, etc.)

/*****************************************************************************/

CLASS_DECLARATION( Trigger, TriggerPushAny, "trigger_pushany" );

ResponseDef TriggerPushAny::Responses[] =
	{
	   { &EV_Trigger_Effect,			( Response )TriggerPushAny::Push },
		{ NULL, NULL }
	};

void TriggerPushAny::Push
	(
	Event *ev
	)

	{
	Entity *other;

	other = ev->GetEntity( 1 );
	if ( other )
		{
      const char * targ;
	   Entity *ent;
	   int num;

      targ = Target ();
      if ( targ[ 0 ] )
         {
		   num = G_FindTarget( 0, Target() );
		   ent = G_GetEntity( num );
		   if ( num && ent )
            {
            other->velocity = G_CalculateImpulse
               (
               other->worldorigin,
               ent->worldorigin,
               speed,
               other->gravity
               );
            }
         }
      else
		   other->velocity = pushvelocity;
		}
	}

TriggerPushAny::TriggerPushAny()
	{
   float mat[3][3];

   setAngles( G_GetVectorArg( "angles", Vector( 0, 0, 0 ) ) );
   AnglesToMat( angles.vec3(), mat );
   speed = G_GetFloatArg( "speed", 1000 );
	pushvelocity = Vector( mat[0][0],mat[0][1], mat[0][2] ) * speed;
	respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES );
	}

/*****************************************************************************/
/*SINED play_sound_triggered (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) AMBIENT-ON RELIABLE NOT_PLAYERS MONSTERS PROJECTILES AMBIENT-OFF x TOGGLE

DO NOT USE, USE TRIGGER_SPEAKER INSTEAD

play a sound when it is used

AMBIENT-ON specifies an ambient sound that starts on
RELIABLE should only be set for crucial voice-overs or sounds
AMBIENT-OFF specifies an ambient sound that starts off

if (AMBIENT-?) is not set, then the sound is sent over explicitly this creates more net traffic

"volume" how loud 0-4 (1 default full volume, ambients do not respond to volume)
"noise" sound to play
"channel" channel on which to play sound (0-7) (2 (voice) is default)
"attenuation" attenuation factor (0 becomes 1 for non-ambients, 2 for ambients)
   -1 - none, send to whole level
    0 - default (normal or ambient)
    1 - normal fighting sounds
    2 - idle monster sounds
    3 - ambient sounds
"key"          The item needed to activate this. (default nothing)

Normal sounds play each time the target is used.

Ambient Looped sounds have an attenuation of 2 by default, volume 1, and the use function toggles it on/off.
Multiple identical ambient looping sounds will just increase volume without any speed cost.
The attenuation factor can be over-ridden by specifying an attenuation factor.

If NOT_PLAYERS is set, the trigger does not respond to players
If MONSTERS is set, the trigger will respond to monsters
If PROJECTILES is set, the trigger will respond to projectiles (rockets, grenades, etc.)

/*****************************************************************************/

CLASS_DECLARATION( Trigger, TriggerPlaySound, "play_sound_triggered" );

Event EV_TriggerPlaySound_SetVolume( "volume" );
Event EV_TriggerPlaySound_SetAttenuation( "attenuation" );
Event EV_TriggerPlaySound_SetChannel( "channel" );

ResponseDef TriggerPlaySound::Responses[] =
	{
	   { &EV_Trigger_Effect,						( Response )TriggerPlaySound::ToggleSound },
	   { &EV_TriggerPlaySound_SetVolume,		( Response )TriggerPlaySound::SetVolume },
	   { &EV_TriggerPlaySound_SetAttenuation,	( Response )TriggerPlaySound::SetAttenuation },
	   { &EV_TriggerPlaySound_SetChannel,		( Response )TriggerPlaySound::SetChannel },
		{ &EV_Touch,                           NULL },
		{ NULL, NULL }
	};

void TriggerPlaySound::ToggleSound
	(
	Event *ev
	)

	{
	if ( !state )
		{
		// noise should already be initialized
		assert( Noise().length() );
      if ( ambient || spawnflags & 128 )
 		   state = 1;

      if (ambient)
         {
         int attn;

         attn = attenuation;
         if (attn > 3) attn = 3;
         if (attn < 0) attn = 0;
         edict->s.sound = ( gi.soundindex( Noise().c_str() ) ) + (attn<<14);
         }
      else
         {
		   sound( Noise().c_str(), volume, channel, attenuation, pitch, timeofs, fadetime );
         }
		}
	else
		{
		state = 0;
      if (ambient)
         edict->s.sound = 0;
      else
		   RandomGlobalSound( "null_sound", volume, channel | CHAN_NO_PHS_ADD, -1 );
		}
	}

void TriggerPlaySound::SetVolume
	(
	Event *ev
	)

	{
	//FIXME
	// update sound volume on client

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -