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

📄 misc.cpp

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

	other = ev->GetEntity( 1 );

   if ( !other || ( other == world ) )
      return;

	num = G_FindTarget( 0, Target() );
	if ( !num )
		{
		warning( "Teleport", "Couldn't find destination\n" );
		return;
		}

	dest = G_GetEntity( num );
	assert( dest );

   other->RandomGlobalSound( "snd_teleport" );

	// unlink to make sure it can't possibly interfere with KillBox
	other->unlink();

	if ( other->isSubclassOf( Sentient ) )
		{
		PathManager.Teleport( other, other->worldorigin, dest->worldorigin );
		other->worldorigin = dest->worldorigin + Vector( 0, 0, 1 );
		other->velocity = vec_zero;
		}
	else
		{
		mid = ( absmax - absmin ) * 0.5;
		other->worldorigin = dest->worldorigin + Vector( 0, 0, 1 );
      other->origin += mid;
		}

	// draw the teleport splash at the destination
	//other->edict->s.event = EV_PLAYER_TELEPORT;

   // set angles
	other->setAngles( dest->angles );

	// set their gravity axis
	other->SetGravityAxis( gravaxis );

   if ( other->client )
		{
      Event * ev;
		client = other->client;

      if ( !gravaxis )
         {
		   // clear the velocity and hold them in place briefly
		   client->ps.pmove.pm_time = 100;
         client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;

         ev = new Event( EV_Player_SaveFov );
         other->ProcessEvent( ev );

         ev = new Event( EV_Player_Fov );
         ev->AddFloat( 180 );
         other->ProcessEvent( ev );
         }

      /*
      if ( gravaxis )
         {
         ev = new Event( EV_Player_RestoreFov );
         other->PostEvent( ev, 0.1f );
         }
      */

		for( i = 0; i < 3; i++ )
			{
			client->ps.pmove.delta_angles[ i ] = ANGLE2SHORT( dest->angles[ i ] - client->resp.cmd_angles[ i ] );
			}

		VectorCopy( angles.vec3(), client->ps.viewangles );
		}

	if ( dest->isSubclassOf( TeleporterDestination ) && !gravaxis )
		{
		float len;

		len = other->velocity.length();
      //
      // give them a bit of a push
      //
      if ( len < 400 )
         len = 400;
		other->velocity = ( ( TeleporterDestination * )dest )->movedir * len;
		}

	// kill anything at the destination
	KillBox( other );

	other->setOrigin( other->worldorigin );
	other->worldorigin.copyTo( other->edict->s.old_origin );
	}

Teleporter::Teleporter()
	{
	if ( !Target() )
		{
		gi.dprintf( "teleporter without a target.\n" );
		ProcessEvent( EV_Remove );
		return;
		}

	if ( spawnflags & 1 )
		{
		showModel();
		}

	respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES );
	}

/*****************************************************************************/
/*SINED misc_teleporter_dest (1 0 0) (-32 -32 0) (32 32 8)

Point teleporters at these.

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

CLASS_DECLARATION( Entity, TeleporterDestination, "misc_teleporter_dest" );

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

TeleporterDestination::TeleporterDestination()
	{
	movedir = G_GetMovedir();
	setAngles( movedir.toAngles() );
	}

/*****************************************************************************/
/*SINED waypoint (0 0.5 0) (-8 -8 -8) (8 8 8)

Used as a positioning device for objects

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

CLASS_DECLARATION( Entity, Waypoint, "waypoint" );

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

/*****************************************************************************/
/*SINED func_shatter (0 .5 .8) ? x x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES HURT_SHATTER THRESHOLD

For shattering objects.  Triggers only when a threshold of damage is exceeded.
Will also trigger any targeted func_areaportals when not invisible.

"health" specifies how much damage must occur before trigger fires.  Default is 20.
"percentage" specifies how much of the thing to shatter. Default is 50
"minsize" specifies minsize for tesselation, default based off size
"maxsize" specifies maxsize for tesselation, default based off size
"thickness" specifies thickness for tesselation, default same as minsize
"key"     The item needed to activate this. (default nothing)
"noise" sound to play when shattered, defaults to nothing

HURT_SHATTER - when the thing gets hurt, spawn pieces of itself
THRESHOLD - damage threshold behavior

If NOT_PLAYERS is set, the trigger does not respond to damage caused by players
If NOT_MONSTERS is set, the trigger does not respond to damage caused by monsters
If NOT_PROJECTILES is set, the trigger does not respond to damage caused by projectiles

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

CLASS_DECLARATION( Trigger, Shatter, "func_shatter" );

ResponseDef Shatter::Responses[] =
	{
	   { &EV_Trigger_Effect,			( Response )Shatter ::DoShatter },
	   { &EV_Damage,						( Response )Shatter ::DamageEvent },
		{ NULL, NULL }
	};

void Shatter::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 ( threshold && damage < health )
		{
		return;
		}
   else if ( !threshold )
      {
      health -= damage;
      if (health > 0 )
         {
      	damage_taken += damage;
         return;
         }
      }

	damage_taken += damage;

   if ( attacker )
      {
   	event = new Event( EV_Activate );
	   event->AddEntity( attacker );
	   ProcessEvent( event );
      }
   else
      {
      warning("Damage", "Attacker is null\n" );
      }
	}

void Shatter::DoShatter
	(
	Event *ev
	)

	{
	Entity	*other;
	Event		*event;
   Vector   dir;

	if ( takedamage == DAMAGE_NO )
		{
		return;
		}

   if ( noise.length() > 1 )
      {
      sound( noise.c_str(), 1, CHAN_VOICE + CHAN_NO_PHS_ADD );
      }

	other = ev->GetEntity( 1 );

	takedamage = DAMAGE_NO;

   dir = worldorigin - other->worldorigin;

   TesselateModel
      (
      this,
      tess_min_size,
      tess_max_size,
      dir,
      damage_taken,
      tess_percentage,
      tess_thickness,
      vec3_origin
      );

	SetAreaPortals( Target(), true );

	event = new Event( EV_Trigger_ActivateTargets );
	event->AddEntity( other );
	ProcessEvent( event );

	ProcessEvent( EV_BreakingSound );

	PostEvent( EV_Remove, 0 );
	}

Shatter::Shatter()
	{
	//
	// Can only be used once
	//
	count = -1;
   threshold = false;

	// Since we're a subclass of DamageThreshold, override the invisible behaviour
	showModel();
	PostEvent( Event( "setup" ), 0 );

   tess_percentage = G_GetFloatArg( "percentage", tess_percentage*100 ) / 100.0f;
   tess_min_size = G_GetIntArg( "minsize", tess_min_size );
   tess_max_size = G_GetIntArg( "maxsize", tess_max_size );
   tess_thickness = G_GetIntArg( "thickness", tess_thickness );

	health = G_GetFloatArg( "health", 20 );
	max_health = health;

	noise = str( G_GetSpawnArg( "noise", "" ) );

   if ( spawnflags & (1<<5) )
      flags |= FL_TESSELATE;

   if ( spawnflags & (1<<6) )
      threshold = true;

   tess_thickness = 10;

	respondto = spawnflags ^ ( TRIGGER_PLAYERS | TRIGGER_MONSTERS | TRIGGER_PROJECTILES );
	}

/*****************************************************************************/
/*SINED func_glass (0 .5 .8) ? x x NOT_PLAYERS NOT_MONSTERS NOT_PROJECTILES HURT_SHATTER THRESHOLD

For glass objects.  Shatters when the accumulated damage is exceeded, or when activated

"health" specifies how much damage must occur before the glass shatters.  Default is 60.
"percentage" specifies how much of the thing to shatter. Default is 50
"minsize" specifies minsize for tesselation, default based off size
"maxsize" specifies maxsize for tesselation, default based off size
"thickness" specifies thickness for tesselation, default same as minsize
"key"     The item needed to activate this. (default nothing)
"noise" sound to play when shattered, defaults to glass breaking

If NOT_PLAYERS is set, the trigger does not respond to events caused by players
If NOT_MONSTERS is set, the trigger does not respond to events caused by monsters
If NOT_PROJECTILES is set, the trigger does not respond to events caused by projectiles

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

CLASS_DECLARATION( Shatter, Glass, "func_glass" );

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

Glass::Glass()
	{
   if ( !noise.length() )
      {
      const char * realname;

      if (max_health <= 60)
         {
         realname = gi.GlobalAlias_FindRandom( "impact_smlglass" );
         if ( realname )
            noise = str( realname );
         }
      else
         {
         realname = gi.GlobalAlias_FindRandom( "impact_lrgglass" );
         if ( realname )
            noise = str( realname );
         }
      }
   gi.soundindex( noise.c_str() );
	}

//
// MadeBreakingSound
//
// Entity-less notifier for AI
//
void MadeBreakingSound
	(
   Vector pos,
   Entity * activator
	)

	{
	Entity	*ent;
	Event		*ev;

   //
   // make sure activator is valid
   //

   if ( !activator )
      activator = world;

	ent = NULL;
	while( ent = findradius( ent, pos.vec3(), SOUND_BREAKING_RADIUS ) )
		{
		if ( !ent->deadflag && ent->isSubclassOf( Sentient ) && ( ent != activator ) &&
			gi.inPHS( pos.vec3(), ent->centroid.vec3() ) 
			)
			{
			ev = new Event( EV_HeardBreaking );
			ev->AddEntity( activator );
			ev->AddVector( pos );
			ent->PostEvent( ev, 0 );
			}
		}
   }

CLASS_DECLARATION( Entity, BloodSplat, NULL );

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

int BloodSplat::numBloodSplats = 0;
Queue BloodSplat::queueBloodSplats;

BloodSplat::BloodSplat
   (
   Vector pos,
   Vector ang,
   float scale
   )

	{
   BloodSplat *fadesplat;

   if ( numBloodSplats > sv_maxbloodsplats->value )
      {
      // Fade one out of the list.
      fadesplat = ( BloodSplat * )queueBloodSplats.Dequeue();
      fadesplat->ProcessEvent( EV_FadeOut );
      numBloodSplats--;

      // Don't spawn one until we others have faded
      PostEvent( EV_Remove, 0 );
      return;
      }

	setMoveType( MOVETYPE_NONE );
	setSolidType( SOLID_NOT );
   setModel( "sprites/bloodsplat.spr" );
	edict->s.frame = G_Random( 4 );
	setSize( "0 0 0", "0 0 0" );

   queueBloodSplats.Enqueue( this );
   numBloodSplats++;

   edict->s.scale = scale * edict->s.scale;
	setAngles( ang );
   setOrigin( pos );
	}

BloodSplat::~BloodSplat()
   {
   if ( queueBloodSplats.Inqueue( this ) )
      {
      queueBloodSplats.Remove( this );
      numBloodSplats--;
      }
   }

/*****************************************************************************/
/*SINED func_clipbox (0 .5 .8) (-16 -16 -16) (16 16 16)

Invisible bounding box used like a clip brush.  This is mainly used for blocking
off areas or improving clipping without having to recompile the map.  Because of
this, it will most likely only be spawned via script.
age is exceeded, or when activated

"mins" min point of the clip.
"maxs" max point of the clip.
"type" -
0 Monster and Player clip
1 Monster clip
2 Player clip

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

CLASS_DECLARATION( Entity, ClipBox, "func_clipbox" );

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

ClipBox::ClipBox()
	{
   int type;

	setMoveType( MOVETYPE_NONE );
	setSolidType( SOLID_BBOX );
	hideModel();

   type = G_GetIntArg( "type" );

   edict->clipmask = MASK_SOLID;
   switch( type )
      {
      case 1 :
         edict->svflags |= SVF_MONSTERCLIP;
         break;

      case 2 :
         edict->svflags |= SVF_PLAYERCLIP;
         break;

      default :
         edict->svflags |= SVF_PLAYERCLIP|SVF_MONSTERCLIP;
         break;
      }

   mins = G_GetVectorArg( "mins" );
   maxs = G_GetVectorArg( "maxs" );

   origin = ( mins + maxs ) * 0.5;

   setSize( mins - origin, maxs - origin );
	setOrigin( origin );
   }

⌨️ 快捷键说明

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