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

📄 behavior.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				mode = 1;
				}
			else
				{
				// skip the ready fire animation
				animdone = true;
				}

		case 1 :
			// readying gun
			if ( !animdone )
				{
				aim.SetTarget( self.currentEnemy );
				aim.Evaluate( self );
				break;
				}
			// start Aiming
			animdone = false;
         if ( aimanim.length() )
            {
			   self.SetAnim( aimanim.c_str() );
            }
         // 
         // save off time, in case we aim for too long
         //
         aim_time = level.time + 1;
			mode = 2;

		case 2 :
			// Aiming
         if ( !self.currentEnemy )
            {
            return false;
            }
         //
         // see if we aimed for too long
         //
         if ( aim_time < level.time )
            {
            return false;
            }

			aim.SetTarget( self.currentEnemy );
			aim.Evaluate( self );

			// don't go into our firing animation until our weapon is ready, and we are on target
			if ( self.WeaponReady() && self.currentEnemy && self.CanShoot( self.currentEnemy, true ) )
				{
				animdone = false;
				self.Chatter( "snd_inmysights", 5 );
				self.SetAnim( fireanim.c_str(), EV_Actor_NotifyBehavior );
            enemy_health = self.currentEnemy->health;
				mode = 3;
				}
			else if ( !self.currentEnemy || self.currentEnemy->deadflag ||
				( self.currentEnemy->health <= 0 ) || !self.CanShoot( self.currentEnemy, false ) )
				{
				// either our enemy is dead, or we can't shoot the enemy from here
				if ( self.CurrentWeapon() )
					{
					self.CurrentWeapon()->ForceReload();
					}
				return false;
				}
			break;

		case 3 :
			// Fire
			aim.SetTarget( self.currentEnemy );
			aim.Evaluate( self );
			if ( animdone )
				{
            if ( !self.currentEnemy || ( self.currentEnemy->health < enemy_health ) )
					self.Chatter( "snd_attacktaunt", 4 );
            else
					self.Chatter( "snd_missed", 7 );

				animdone = false;
				numshots++;

				if ( ( numshots >= maxshots ) || !self.currentEnemy || self.currentEnemy->deadflag ||
					( self.currentEnemy->health <= 0 ) || !self.CanShoot( self.currentEnemy, false ) )
					{
					// either we're out of shots, our enemy is dead, or we can't shoot the enemy from here
					if ( self.CurrentWeapon() )
						{
						self.CurrentWeapon()->ForceReload();
						}
					return false;
					}
				else if ( !self.WeaponReady() || !self.CanShoot( self.currentEnemy, false ) )
					{
					// weapon not ready or not aimed at enemy, so just keep trying to get enemy in our sights
               if ( aimanim.length() )
                  {
		   			self.SetAnim( aimanim.c_str() );
                  }
               // 
               // save off time, in case we aim for too long
               //
               aim_time = level.time + 1;
					mode = 2;
					}
				else
					{
					// keep firing
					self.SetAnim( fireanim.c_str(), EV_Actor_NotifyBehavior );
               enemy_health = self.currentEnemy->health;
					}
				}
			break;
		}

	return true;
	}

void AimAndShoot::End
	(
	Actor &self
	)

	{
	aim.End( self );
	self.SetAnim( "idle" );
	}

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

  AimAndMelee Class Definition

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

CLASS_DECLARATION( Behavior, AimAndMelee, NULL );

ResponseDef AimAndMelee::Responses[] =
	{
		{ &EV_Behavior_Args,			( Response )AimAndMelee::SetArgs },
		{ &EV_Behavior_AnimDone,	( Response )AimAndMelee::AnimDone },
		{ NULL, NULL }
	};

AimAndMelee::AimAndMelee()
	{
	}

void AimAndMelee::ShowInfo
	(
	Actor &self
	)

	{
   Behavior::ShowInfo( self );

   gi.printf( "\naim:\n" );
   aim.ShowInfo( self );

   gi.printf( "\nmode: %d\n", mode );
   gi.printf( "maxshots: %d\n", maxshots );
   gi.printf( "numshots: %d\n", numshots );
   gi.printf( "animdone: %d\n", animdone );
	}

void AimAndMelee::Begin
	(
	Actor &self
	)

	{
	mode = 0;
   numshots = 0;
	maxshots = 2 + G_Random( 4 );
	animdone = false;
	}

void AimAndMelee::SetArgs
	(
	Event *ev
	)

	{
   int num;

	num = ev->GetInteger( 2 );
	maxshots = (num>>1) + G_Random( num );
	}

void AimAndMelee::AnimDone
	(
	Event *ev
	)

	{
	animdone = true;
	}

qboolean	AimAndMelee::Evaluate
	(
	Actor &self
	)

	{
   float r;
   Vector delta;

	switch( mode )
		{
		case 0 :
         if ( !self.has_melee || !self.currentEnemy )
            {
            return false;
            }

         delta = self.centroid - self.currentEnemy->centroid;
	      r = delta.length();
         if ( r > self.melee_range )
            {
            return false;
            }

			aim.SetTarget( self.currentEnemy );
         if ( aim.Evaluate( self ) )
            {
            break;
            }
         numshots++;
         animdone = false;
			// melee
			self.SetAnim( "melee", EV_Actor_NotifyBehavior );
			self.Chatter( "snd_attacktaunt", 4 );

         mode = 1;

		case 1 :
			// finish up the attack
			if ( animdone )
				{
            if ( numshots < maxshots )
               {
               mode = 0;
               }
            else
               {
				   return false;
               }
				}
			break;
		}

	return true;
	}

void AimAndMelee::End
	(
	Actor &self
	)

	{
	aim.End( self );
	self.SetAnim( "idle" );
	}

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

  Melee Class Definition

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

CLASS_DECLARATION( Behavior, Melee, NULL );

ResponseDef Melee::Responses[] =
	{
		{ &EV_Behavior_Args,			( Response )Melee::SetArgs },
		{ &EV_Behavior_AnimDone,	( Response )Melee::AnimDone },
		{ NULL, NULL }
	};

Melee::Melee()
	{
	}

void Melee::ShowInfo
	(
	Actor &self
	)

	{
   Behavior::ShowInfo( self );

   gi.printf( "\nmode: %d\n", mode );
   gi.printf( "animdone: %d\n", animdone );
	}

void Melee::Begin
	(
	Actor &self
	)

	{
	mode = 0;
	animdone = false;
	}

void Melee::SetArgs
	(
	Event *ev
	)

	{
	}

void Melee::AnimDone
	(
	Event *ev
	)

	{
	animdone = true;
	}

qboolean	Melee::Evaluate
	(
	Actor &self
	)

	{
   float r;
   Vector delta;
   Vector ang;

	switch( mode )
		{
		case 0 :
         if ( !self.has_melee || !self.currentEnemy )
            {
            return false;
            }

         delta = self.currentEnemy->worldorigin - self.worldorigin;
	      r = delta.length();
         if ( r > self.melee_range )
            {
            return false;
            }
         animdone = false;
			// melee
         ang = delta.toAngles();
         ang[ PITCH ] = -ang[ PITCH ];
         self.setAngles( ang );
			self.SetAnim( "melee", EV_Actor_NotifyBehavior );
			self.Chatter( "snd_attacktaunt", 4 );

         mode = 1;

		case 1 :
			// finsh up the attack
			if ( animdone )
				{
				return false;
				}
			break;
		}

	return true;
	}

void Melee::End
	(
	Actor &self
	)

	{
	self.SetAnim( "idle" );
	}

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

  Repel Class Definition

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

CLASS_DECLARATION( Behavior, Repel, NULL );

ResponseDef Repel::Responses[] =
	{
		{ &EV_Behavior_Args,			( Response )Repel::SetArgs },
		{ NULL, NULL }
	};

void Repel::SetArgs
	(
	Event *ev
	)

	{
	anim = ev->GetString( 2 );
	movegoal = AI_FindNode( ev->GetString( 3 ) );
	if ( movegoal )
		{
		goal = movegoal->worldorigin;
		}
	speed = ev->GetFloat( 4 );
	}

void Repel::ShowInfo
	(
	Actor &self
	)
		
	{
   Behavior::ShowInfo( self );

   gi.printf( "\nanim: %s\n", anim.c_str() );

   gi.printf( "dist: %f\n", dist );
   gi.printf( "len: %f\n", len );
   gi.printf( "speed: %f\n", speed );
   gi.printf( "goal: ( %f, %f, %f )\n", goal.x, goal.y, goal.z );
   gi.printf( "start: ( %f, %f, %f )\n", start.x, start.y, start.z );
   gi.printf( "dir: ( %f, %f, %f )\n", dir.x, dir.y, dir.z );
	}

void Repel::Begin
	(
	Actor &self
	)

	{
	start.x = goal.x;
	start.y = goal.y;
	start.z = self.worldorigin.z;
	dir = goal - start;
	len = dir.length();
	dir *= 1 / len;

	if ( speed <= 0 )
		{
		speed = 32;
		}

	if ( anim.length() )
		{
		self.SetAnim( anim );
		}
	dist = -1;
	}

qboolean	Repel::Evaluate
	(
	Actor &self
	)

	{
	Vector pos;
	qboolean done;
	float sp;
	trace_t trace;

	done = false;

	// this is silly, but it works
	if ( dist < 0 )
		{
		sp = 0;
		}
	else if ( dist < 32 )
		{
		sp = dist * speed / 32;
		}
	else if ( ( len - dist ) < 32 )
		{
		sp = ( len - dist ) * speed / 32;
		}
	else
		{
		sp = speed;
		}

	pos = start + dir * ( dist + sp );
	dist = ( pos - start ) * dir;
	if ( dist >= (len-1) )
		{
		pos = goal;
		done = true;
		}
	else if ( dist < 1 )
		{
		dist = 1;
		}

	trace = G_Trace( self.worldorigin, self.mins, self.maxs, pos, &self, self.edict->clipmask, "Repel" );
	self.setOrigin( trace.endpos );

	return !done;
	}

void Repel::End
	(
	Actor &self
	)

	{
	self.SetAnim( "idle" );
	}

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

  Pickup Behavior Class Definition

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

CLASS_DECLARATION( Behavior, PickupAndThrow, NULL );

Event EV_PickupAndThrow_Pickup( "pickup" );
Event EV_PickupAndThrow_Throw( "throw" );

ResponseDef PickupAndThrow::Responses[] =
	{
		{ &EV_Behavior_Args,			( Response )PickupAndThrow::SetArgs },
		{ &EV_Behavior_AnimDone,	( Response )PickupAndThrow::AnimDone },
		{ &EV_PickupAndThrow_Pickup,( Response )PickupAndThrow::Pickup },
		{ &EV_PickupAndThrow_Throw,( Response )PickupAndThrow::Throw },
		{ NULL, NULL }
	};

PickupAndThrow::PickupAndThrow()
	{
	}

void PickupAndThrow::ShowInfo
	(
	Actor &self
	)

	{
   Behavior::ShowInfo( self );

   gi.printf( "\naim:\n" );
   aim.ShowInfo( self );

   gi.printf( "\nmode: %d\n", mode );
   gi.printf( "animdone: %d\n", animdone );

   if ( pickup_target )
      {
      gi.printf( "\npickup_target: #%d '%s'\n", pickup_target->entnum, pickup_target->targetname.c_str() );
      }
   else
      {
      gi.printf( "\npickup_target: NULL\n" );
      }
	}

void PickupAndThrow::Begin
	(
	Actor &self
	)

	{
	mode = 0;
	animdone = false;
	}

void PickupAndThrow::SetArgs
	(
	Event *ev
	)

	{
   pickup_target = ev->GetEntity( 2 );
	}

void PickupAndThrow::AnimDone
	(
	Event *ev
	)

	{
	animdone = true;
	}

void PickupAndThrow::Pickup
	(
	Event *ev
	)

	{
   Entity * ent;
   Event * e;

   ent = ev->GetEntity( 1 );
   if ( pickup_target )
      {
      e = new Event( EV_ThrowObject_Pickup );
      e->AddEntity( ent );
      e->AddString( ev->GetString( 2 ) );
      pickup_target->ProcessEvent( e );
      }
	}

void PickupAndThrow::Throw
	(
	Event *ev
	)

	{
   Actor * act;
   Event * e;

   act = (Actor *)ev->GetEntity( 1 );
   if ( pickup_target )
      {
      if ( !act->currentEnemy )
         return;
      e = new Event( EV_ThrowObject_Throw );
      e->AddEntity( act );
      e->AddFloat( 500 );
      e->AddEntity( act->currentEnemy );
      e->AddFloat( 1 );
      pickup_target->ProcessEvent( e );
      }
	}

qboolean	PickupAndThrow::Evaluate
	(
	Actor &self
	)

	{
   Event * ev;

   if ( !self.currentEnemy || !pickup_target )
      return false;

	switch( mode )
		{
		case 0 :
			if ( self.HasAnim( "pickup" ) )
				{
				animdone = false;
				self.SetAnim( "pickup", EV_Actor_NotifyBehavior );
				mode = 1;
				}
			else
				{
				// skip the pickup animation
         	ev = new Event( EV_PickupAndThrow_Pickup );
            ev->AddEntity( &self );
            ev->AddString( "gun" );
            ProcessEvent( ev );
				animdone = true;
				}

		case 1 :
         if ( !animdone )
            break;
			aim.Begin( self );
         mode = 2;
			if ( self.HasAnim( "throw_aim" ) )
				{
				self.SetAnim( "throw_aim", EV_Actor_NotifyBehavior );
				}
         else
            {
				self.SetAnim( "idle" );
            }

		case 2 :
         // aim towards our target
			aim.SetTarget( self.currentEnemy );
         if ( aim.Evaluate( self ) )
            {
            break;
            }
         mode = 3;

		case 3 :
			// Throwing
         mode = 4;
			if ( self.HasAnim( "throw" ) )
				{
				animdone = false;
				self.SetAnim( "throw", EV_Actor_NotifyBehavior );
				mode = 4;
				}
			else
				{
				// skip the pickup animation
         	ev = new Event( EV_PickupAndThrow_Throw );
            ev->AddEntity( &self );
            ProcessEvent( ev );
				animdone = true;
				}
			break;

		case 4 :

⌨️ 快捷键说明

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