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

📄 actor.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      {
      enemydistance = MIN_AIM_DISTANCE;
      }

      // 0 is maximum accuracy
   invaim = 1.0f - aim;
   if ( invaim < 0 )
      invaim = 0;
	skl = min( skill->value, 3 );
   if ( skl < 1 )
      skl = 1;
	accuracy = 1 - ( min( skl, 3 ) * 0.18 );
   accuracy *= invaim;
	spread = ( 8 * MIN_AIM_DISTANCE * accuracy ) / enemydistance;
	ang.x += G_CRandom( spread );
	ang.y += G_CRandom( spread );

	ang.AngleVectors( forward, right, up );
	}

qboolean Actor::CanShootFrom
	(
	Vector pos,
	Entity *ent,
	qboolean usecurrentangles
	)

	{
   int      mask;
	Vector	delta;
	Vector	start;
	Vector	end;
	float		len;
	trace_t	trace;
	Vehicle	*v;
	Entity	*t;
   Vector   ang;

	if ( !currentWeapon || !WithinDistance( ent, vision_distance ) )
		{
      if (!currentWeapon && !has_melee )
		   return false;
		}

	if ( usecurrentangles )
		{
   	Vector	dir;

      start = pos + GunPosition() - worldorigin;
//      start = pos + centroid - worldorigin;
		end = ent->centroid;
		end.z += ( ent->absmax.z - ent->centroid.z ) * 0.75f;
		delta = end - start;
      ang = delta.toAngles();
      ang.x = -ang.x;
      ang.y = angles.y;
		len = delta.length();
   	ang.AngleVectors( &dir, NULL, NULL );
      dir *= len;
      end = start + dir;
		}
	else
		{
		start = pos + GunPosition() - worldorigin;
		end = ent->centroid;
		end.z += ( ent->absmax.z - ent->centroid.z ) * 0.75f;
      delta = end - start;
      len = delta.length();
		}

	// check if we're too far away, or too close
   if ( currentWeapon )
      {
	   if ( ( len > attack_range ) || ( len > currentWeapon->GetMaxRange() ) || ( len < currentWeapon->GetMinRange() ) )
		   {
		   return false;
		   }
      mask = MASK_SHOT;
      }
   else
      {
	   if ( ( len > attack_range ) || ( len > melee_range ) )
		   {
		   return false;
		   }
      mask = MASK_PROJECTILE;
      }

	// shoot past the guy we're shooting at
	end += delta * 4;

#if 0
   if ( usecurrentangles )
      {
      G_DebugLine( start, end, 1, 0, 0, 1 );
      }
   else
      {
	   G_DebugLine( start, end, 1, 1, 0, 1 );
      }
#endif

	// Check if he's visible
	trace = G_Trace( start, vec_zero, vec_zero, end, this, mask, "Actor::CanShootFrom" );
	if ( trace.startsolid )
		{
		return false;
		}

	// If we hit the guy we wanted, then shoot
	if ( trace.ent == ent->edict )
		{
		return true;
		}

	// if we hit a vehicle, check if the driver is someone we want to hit
	t = trace.ent->entity;
	if ( t && t->isSubclassOf( Vehicle ) )
		{
		v = ( Vehicle * )t;
		if ( ( v->Driver() == ent ) || IsEnemy( v->Driver() ) )
			{
			return true;
			}
		return false;
		}

	// If we hit someone else we don't like, then shoot
	if ( IsEnemy( t ) )
		{
		return true;
		}

	// if we hit something breakable, check if shooting it will
   // let us shoot someone.
	if ( t->isSubclassOf( Shatter ) || 
		t->isSubclassOf( Object ) ||
		t->isSubclassOf( DamageThreshold ) ||
		t->isSubclassOf( ScriptModel ) )
		{
      trace = G_Trace( Vector( trace.endpos ), vec_zero, vec_zero, end, t, mask, "Actor::CanShootFrom 2" );
	   if ( trace.startsolid )
		   {
		   return false;
		   }

	   // If we hit the guy we wanted, then shoot
	   if ( trace.ent == ent->edict )
		   {
		   return true;
		   }

	   // If we hit someone else we don't like, then shoot
	   if ( IsEnemy( trace.ent->entity ) )
		   {
		   return true;
		   }

      // Forget it then
      return false;
		}

	return false;
	}

qboolean Actor::CanShoot
	(
	Entity *ent,
	qboolean usecurrentangles
	)

	{
	return CanShootFrom( worldorigin, ent, usecurrentangles );
	}

float Actor::AttackRange
	(
   void
	)

	{
	if ( !currentWeapon && !has_melee )
		{
		return 0;
		}

   if ( currentWeapon )
      {
	   return ( currentWeapon->GetMaxRange() );
      }
   else
      {
      return ( melee_range );
      }
	}

float Actor::MinimumAttackRange
	(
   void
	)

	{
   float range;
   float maxrange;

	if ( !currentWeapon && !has_melee )
		{
		return 100;
		}

   range = melee_range * 0.75f;
   maxrange = melee_range;

   if ( currentWeapon )
      {
	   range = currentWeapon->GetMinRange();
      if ( !range && melee_range )
         range = melee_range * 0.75f;
	   maxrange = currentWeapon->GetMaxRange();
      }

   if ( range > maxrange )
      range = maxrange;

   return range;
	}

qboolean Actor::HasWeapon
	(
   void
	)
   {
   return ( currentWeapon != NULL );
   }

//***********************************************************************************************
//
// Actor type script commands
//
//***********************************************************************************************

void Actor::FriendEvent
	(
	Event *ev
	)

	{
	actortype = IS_FRIEND;
	}

void Actor::CivilianEvent
	(
	Event *ev
	)

	{
	actortype = IS_CIVILIAN;
	}

void Actor::EnemyEvent
	(
	Event *ev
	)

	{
	actortype = IS_ENEMY;
	}

void Actor::InanimateEvent
   (
   Event *ev
   )

   {
   actortype = IS_INANIMATE;
   //
   // clear the monster flag so triggers are not triggered
   //
	edict->svflags	&= ~SVF_MONSTER;
   //
   // don't make them move
   //
   setMoveType( MOVETYPE_NONE );
   // 
   // don't make it bleed
   //
   flags &= ~FL_BLOOD;
   // 
   // don't make it gib
   //
   flags &= ~FL_DIE_GIBS;
   }
   
void Actor::MonsterEvent
	(
	Event *ev
	)

	{
	actortype = IS_MONSTER;
	}

void Actor::AnimalEvent
	(
	Event *ev
	)

	{
	actortype = IS_ANIMAL;
	}

//***********************************************************************************************
//
// Enemy management
//
//***********************************************************************************************

qboolean Actor::HasEnemies
	(
	void
	)

	{
	return ( enemyList.NumObjects() > 0 );
	}

qboolean Actor::IsEnemy
	(
	Entity *ent
	)

	{
	return enemyList.ObjectInList( EntityPtr( ent ) ) && seenEnemy;
	}

void Actor::MakeEnemy
	(
	Entity *ent,
   qboolean force
	)

	{
   // don't get mad at things that can't be hurt or the world
	if ( 
         ent && 
         ( ent != world ) && 
         ( ent != this ) && 
         !( ent->flags & FL_NOTARGET ) &&
         ( ent->takedamage != DAMAGE_NO )
      )
		{
      if ( !enemyList.ObjectInList( EntityPtr( ent ) ) )
         {
		   enemyList.AddObject( EntityPtr( ent ) );
         }

		if ( !currentEnemy && !seenEnemy )
			{
			currentEnemy = ent;
			if ( DoAction( "sightenemy", force ) )
				{
				seenEnemy = true;
            Chatter( "snd_sightenemy", 5 );
				}
			else
				{
				currentEnemy = NULL;
				}
			}
		}
	}

void Actor::ClearEnemies
   (
   void
   )

   {
	currentEnemy = NULL;
   seenEnemy = false;
   enemyList.ClearObjectList();
   }


qboolean Actor::Likes
	(
	Entity *ent
	)

	{
	Actor *act;

	if ( ent->isClient() )
		{
		return ( actortype == IS_FRIEND );
		}
   else if ( actortype == IS_MONSTER )
      {
      // monsters don't like anyone, but they don't particular hate everyone
      return false;
      }
	else if ( ent->isSubclassOf( Actor ) )
		{
		act = ( Actor * )ent;
		return ( act->actortype == actortype );
		}

	return false;
	}

qboolean Actor::Hates
	(
	Entity *ent
	)

	{
	Actor *act;

   assert( ent );
   if ( !ent )
      {
      return false;
      }

	if ( ent->isClient() )
		{
      if ( ent->flags & FL_SP_MUTANT )
         {
         if ( actortype == IS_ENEMY )
            return false;
         else
            return true;
         }
      else
         {
		   return ( actortype != IS_CIVILIAN ) && ( actortype != IS_FRIEND );
         }
		}
	else if ( ent->isSubclassOf( Actor ) && ( actortype != IS_INANIMATE ) )
		{
		act = ( Actor * )ent;
//      if ( act->actortype == IS_INANIMATE )
//         {
//         // heh... Mutants hate inanimate objects. :)
//         return ( actortype == IS_MONSTER );
//         }
      if ( ( act->actortype <= IS_ENEMY ) && ( actortype <= IS_ENEMY ) )
			{
			return false;
			}
		if ( ( act->actortype == IS_FRIEND ) && ( actortype <= IS_ENEMY ) )
			{
			return true;
			}
		if ( ( act->actortype <= IS_ENEMY ) && ( actortype == IS_FRIEND ) )
			{
			return true;
			}
		}

	return false;
	}

//***********************************************************************************************
//
// Targeting functions
//
//***********************************************************************************************

qboolean Actor::GetVisibleTargets
	(
	void
	)

	{
	Sentient	*ent;
	Vector	delta;
	int		i;
	int		n;

	targetList.ClearObjectList();
	nearbyList.ClearObjectList();

	n = SentientList.NumObjects();
	for( i = 1; i <= n; i++ )
		{
		ent = SentientList.ObjectAt( i );

		//if ( ( ent == this ) || ent->deadflag || ( ent->flags & FL_NOTARGET ) || !Hates( ent ) )
		if ( ( ent == this ) || ( ent->flags & FL_NOTARGET ) || ent->hidden() )
			{
			continue;
			}

		if ( WithinDistance( ent, vision_distance ) && CanSeeFOV( ent ) )
			{
			targetList.AddObject( EntityPtr( ent ) );
			if ( WithinDistance( ent, 96 ) )
				{
				nearbyList.AddObject( EntityPtr( ent ) );
				}
			}
		}

	return ( targetList.NumObjects() > 0 );
	}

void Actor::TargetEnemies
	(
	Event *ev
	)

	{
	int i;
	int n;
	Entity *ent;
	Entity *newtarget;
	Actor *act;

   if ( actortype == IS_INANIMATE )
      {
      // inanimate objects don't need to worry about this kind of thing
      return;
      }

   if ( enemyList.NumObjects() >= 1 )
      {
      // don't target new enemies as much while we've already got an enemy
      PostEvent( EV_Actor_TargetEnemies, 5 );
      }
   else
      {
      PostEvent( EV_Actor_TargetEnemies, 1 );
      }

	if ( hidden() )
		{
		// don't target while hidden (for cinematic characters)
		//FIXME
		// probably should have a start/stop function
		return;
		}

	if ( GetVisibleTargets() )
		{
		n = targetList.NumObjects();
		for( i = 1; i <= n; i++ )
			{

⌨️ 快捷键说明

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