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

📄 hl1_npc_hgrunt.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		break;
	case 2:
		enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "hgrunt/gr_die3.wav", 1, ATTN_IDLE );	
		break;
	}
}

//=========================================================
// SetActivity 
//=========================================================
Activity CNPC_HGrunt::NPC_TranslateActivity( Activity eNewActivity )
{
	switch ( eNewActivity)
	{
	case ACT_RANGE_ATTACK1:
		// grunt is either shooting standing or shooting crouched
		if (FBitSet( m_iWeapons, HGRUNT_9MMAR))
		{
			if ( m_fStanding )
			{
				// get aimable sequence
				return (Activity)ACT_GRUNT_MP5_STANDING;
			}
			else
			{
				// get crouching shoot
				return (Activity)ACT_GRUNT_MP5_CROUCHING;
			}
		}
		else
		{
			if ( m_fStanding )
			{
				// get aimable sequence
				return (Activity)ACT_GRUNT_SHOTGUN_STANDING;
			}
			else
			{
				// get crouching shoot
				return (Activity)ACT_GRUNT_SHOTGUN_CROUCHING;
			}
		}
		break;
	case ACT_RANGE_ATTACK2:
		// grunt is going to a secondary long range attack. This may be a thrown 
		// grenade or fired grenade, we must determine which and pick proper sequence
 		if ( m_iWeapons & HGRUNT_HANDGRENADE )
		{
			// get toss anim
			return (Activity)ACT_GRUNT_TOSS_GRENADE;
		}
		else
		{
			// get launch anim
			return (Activity)ACT_GRUNT_LAUNCH_GRENADE;
		}
		break;
	case ACT_RUN:
		if ( m_iHealth <= HGRUNT_LIMP_HEALTH )
		{
			// limp!
			return ACT_RUN_HURT;
		}
		else
		{
			return eNewActivity;
		}
		break;
	case ACT_WALK:
		if ( m_iHealth <= HGRUNT_LIMP_HEALTH )
		{
			// limp!
			return ACT_WALK_HURT;
		}
		else
		{
			return eNewActivity;
		}
		break;
	case ACT_IDLE:
		if ( m_NPCState == NPC_STATE_COMBAT )
		{
			eNewActivity = ACT_IDLE_ANGRY;
		}
		
		break;
	}

	return BaseClass::NPC_TranslateActivity( eNewActivity );
}

void CNPC_HGrunt::ClearAttackConditions( void )
{
	bool fCanRangeAttack2 = HasCondition( COND_CAN_RANGE_ATTACK2 );

	// Call the base class.
	BaseClass::ClearAttackConditions();

	if( fCanRangeAttack2 )
	{
		// We don't allow the base class to clear this condition because we
		// don't sense for it every frame.
		SetCondition( COND_CAN_RANGE_ATTACK2 );
	}
}

int CNPC_HGrunt::SelectSchedule( void )
{
		// clear old sentence
	m_iSentence = HGRUNT_SENT_NONE;

	// flying? If PRONE, barnacle has me. IF not, it's assumed I am rapelling. 
	if ( GetMoveType() == MOVETYPE_FLY && m_NPCState != NPC_STATE_PRONE )
	{
		if (GetFlags() & FL_ONGROUND)
		{
			// just landed
			SetMoveType( MOVETYPE_STEP );
			return SCHED_GRUNT_REPEL_LAND;
		}
		else
		{
			// repel down a rope, 
			if ( m_NPCState == NPC_STATE_COMBAT )
				return SCHED_GRUNT_REPEL_ATTACK;
			else
				return SCHED_GRUNT_REPEL;
		}
	}

	// grunts place HIGH priority on running away from danger sounds.
	if ( HasCondition ( COND_HEAR_DANGER ) )
	{
		// dangerous sound nearby!
				
		//!!!KELLY - currently, this is the grunt's signal that a grenade has landed nearby,
		// and the grunt should find cover from the blast
		// good place for "SHIT!" or some other colorful verbal indicator of dismay.
		// It's not safe to play a verbal order here "Scatter", etc cause 
		// this may only affect a single individual in a squad. 
				
		if (FOkToSpeak())
		{
			SENTENCEG_PlayRndSz( edict(), "HG_GREN", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
			JustSpoke();
		}

		return SCHED_TAKE_COVER_FROM_BEST_SOUND;
	}

	switch	( m_NPCState )
	{

	case NPC_STATE_PRONE:
	{
		if (m_bInBarnacleMouth)
		{
			return SCHED_GRUNT_BARNACLE_CHOMP;
		}
		else
		{
			return SCHED_GRUNT_BARNACLE_HIT;
		}
	}

	case NPC_STATE_COMBAT:
		{
// dead enemy
			if ( HasCondition( COND_ENEMY_DEAD ) )
			{
				// call base class, all code to handle dead enemies is centralized there.
				return BaseClass::SelectSchedule();
			}

// new enemy
			if ( HasCondition( COND_NEW_ENEMY) )
			{
				if ( m_pSquad )
				{
					if ( !m_pSquad->IsLeader( this ) )
					{
						return SCHED_TAKE_COVER_FROM_ENEMY;
					}
					else 
					{
						//!!!KELLY - the leader of a squad of grunts has just seen the player or a 
						// monster and has made it the squad's enemy. You
						// can check pev->flags for FL_CLIENT to determine whether this is the player
						// or a monster. He's going to immediately start
						// firing, though. If you'd like, we can make an alternate "first sight" 
						// schedule where the leader plays a handsign anim
						// that gives us enough time to hear a short sentence or spoken command
						// before he starts pluggin away.
						if (FOkToSpeak())// && RANDOM_LONG(0,1))
						{
							if ((GetEnemy() != NULL) && GetEnemy()->IsPlayer())
								// player
								SENTENCEG_PlayRndSz( edict(), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
							else if ((GetEnemy() != NULL) &&
									(GetEnemy()->Classify() != CLASS_PLAYER_ALLY) && 
									(GetEnemy()->Classify() != CLASS_HUMAN_PASSIVE) && 
									(GetEnemy()->Classify() != CLASS_MACHINE) )
								// monster
								SENTENCEG_PlayRndSz( edict(), "HG_MONST", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);

							JustSpoke();
						}
						
						if ( HasCondition ( COND_CAN_RANGE_ATTACK1 ) )
						{
							return SCHED_GRUNT_SUPPRESS;
						}
						else
						{
							return SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE;
						}
					}
				}
			}
// no ammo
			else if ( HasCondition ( COND_NO_PRIMARY_AMMO ) )
			{
				//!!!KELLY - this individual just realized he's out of bullet ammo. 
				// He's going to try to find cover to run to and reload, but rarely, if 
				// none is available, he'll drop and reload in the open here. 
				return SCHED_GRUNT_HIDE_RELOAD;
			}
			
// damaged just a little
			else if ( HasCondition( COND_LIGHT_DAMAGE ) )
			{
				// if hurt:
				// 90% chance of taking cover
				// 10% chance of flinch.
				int iPercent = random->RandomInt(0,99);

				if ( iPercent <= 90 && GetEnemy() != NULL )
				{
					// only try to take cover if we actually have an enemy!

					//!!!KELLY - this grunt was hit and is going to run to cover.
					if (FOkToSpeak()) // && RANDOM_LONG(0,1))
					{
						//SENTENCEG_PlayRndSz( ENT(pev), "HG_COVER", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
						m_iSentence = HGRUNT_SENT_COVER;
						//JustSpoke();
					}
					return SCHED_TAKE_COVER_FROM_ENEMY;
				}
				else
				{
					return SCHED_SMALL_FLINCH;
				}
			}
// can kick
			else if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
			{
				return SCHED_MELEE_ATTACK1;
			}
// can grenade launch

			else if ( FBitSet( m_iWeapons, HGRUNT_GRENADELAUNCHER) && HasCondition ( COND_CAN_RANGE_ATTACK2 ) && OccupyStrategySlotRange( SQUAD_SLOT_GRENADE1, SQUAD_SLOT_GRENADE2 ) )
			{
				// shoot a grenade if you can
				return SCHED_RANGE_ATTACK2;
			}
// can shoot
			else if ( HasCondition ( COND_CAN_RANGE_ATTACK1 ) )
			{
				if ( m_pSquad )
				{
					if ( m_pSquad->GetLeader() != NULL )
					{
					
						CAI_BaseNPC *pSquadLeader = m_pSquad->GetLeader()->MyNPCPointer();
						
						// if the enemy has eluded the squad and a squad member has just located the enemy
						// and the enemy does not see the squad member, issue a call to the squad to waste a 
						// little time and give the player a chance to turn.
						if ( pSquadLeader && pSquadLeader->EnemyHasEludedMe() && !HasCondition ( COND_ENEMY_FACING_ME ) )
						{
							return SCHED_GRUNT_FOUND_ENEMY;
						}
					}
				}

				if ( OccupyStrategySlotRange ( SQUAD_SLOT_ENGAGE1, SQUAD_SLOT_ENGAGE2 ) )
				{
					// try to take an available ENGAGE slot
					return SCHED_RANGE_ATTACK1;
				}
				else if ( HasCondition ( COND_CAN_RANGE_ATTACK2 ) && OccupyStrategySlotRange( SQUAD_SLOT_GRENADE1, SQUAD_SLOT_GRENADE2 ) )
				{
					// throw a grenade if can and no engage slots are available
					return SCHED_RANGE_ATTACK2;
				}
				else
				{
					// hide!
					return SCHED_TAKE_COVER_FROM_ENEMY;
				}
			}
// can't see enemy
			else if ( HasCondition( COND_ENEMY_OCCLUDED ) )
			{
				if ( HasCondition( COND_CAN_RANGE_ATTACK2 ) && OccupyStrategySlotRange( SQUAD_SLOT_GRENADE1, SQUAD_SLOT_GRENADE2 ) )
				{
					//!!!KELLY - this grunt is about to throw or fire a grenade at the player. Great place for "fire in the hole"  "frag out" etc
					if (FOkToSpeak())
					{
						SENTENCEG_PlayRndSz( edict(), "HG_THROW", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
						JustSpoke();
					}
					return SCHED_RANGE_ATTACK2;
				}
				else if ( OccupyStrategySlotRange ( SQUAD_SLOT_ENGAGE1, SQUAD_SLOT_ENGAGE2 ) )
				{
					//!!!KELLY - grunt cannot see the enemy and has just decided to 
					// charge the enemy's position. 
					if (FOkToSpeak())// && RANDOM_LONG(0,1))
					{
						//SENTENCEG_PlayRndSz( ENT(pev), "HG_CHARGE", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
						m_iSentence = HGRUNT_SENT_CHARGE;
						//JustSpoke();
					}

					return SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE;
				}
				else
				{
					//!!!KELLY - grunt is going to stay put for a couple seconds to see if
					// the enemy wanders back out into the open, or approaches the
					// grunt's covered position. Good place for a taunt, I guess?
					if (FOkToSpeak() && random->RandomInt(0,1))
					{
						SENTENCEG_PlayRndSz( edict(), "HG_TAUNT", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
						JustSpoke();
					}
					return SCHED_STANDOFF;
				}
			}
			
			if ( HasCondition( COND_SEE_ENEMY ) && !HasCondition ( COND_CAN_RANGE_ATTACK1 ) )
			{
				return SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE;
			}
		}
		case NPC_STATE_ALERT:
			if ( HasCondition( COND_ENEMY_DEAD ) && SelectWeightedSequence( ACT_VICTORY_DANCE ) != ACTIVITY_NOT_AVAILABLE )
			{
				// Scan around for new enemies
				return SCHED_VICTORY_DANCE;
			}
			break;
	}

	return BaseClass::SelectSchedule();
}

int CNPC_HGrunt::TranslateSchedule( int scheduleType )
{

	if ( scheduleType == SCHED_CHASE_ENEMY_FAILED )
	{
		 return SCHED_ESTABLISH_LINE_OF_FIRE;
	}
	switch	( scheduleType )
	{
	case SCHED_TAKE_COVER_FROM_ENEMY:
		{
			if ( m_pSquad )
			{
				if ( g_iSkillLevel == SKILL_HARD && HasCondition( COND_CAN_RANGE_ATTACK2 ) && OccupyStrategySlotRange( SQUAD_SLOT_GRENADE1, SQUAD_SLOT_GRENADE2 ) )
				{
					if (FOkToSpeak())
					{
						SENTENCEG_PlayRndSz( edict(), "HG_THROW", HGRUNT_SENTENCE_VOLUME, GRUNT_SNDLVL, 0, m_voicePitch);
						JustSpoke();
					}
					return SCHED_GRUNT_TOSS_GRENADE_COVER;
				}
				else
				{
			  	    return SCHED_GRUNT_TAKE_COVER;
				}
			}
			else
			{
				if ( random->RandomInt(0,1) )
				{
					return SCHED_GRUNT_TAKE_COVER;
				}
				else
				{
					return SCHED_GRUNT_GRENADE_COVER;
				}
			}
		}
	case SCHED_GRUNT_TAKE_COVER_FAILED:
		{
			if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) )
			{
				return SCHED_RANGE_ATTACK1;
			}

			return SCHED_FAIL;
		}
		break;
	
	case SCHED_RANGE_ATTACK1:
		{
			// randomly stand or crouch
			if ( random->RandomInt( 0,9 ) == 0)
			{
				m_fStanding = random->RandomInt( 0, 1 ) != 0;
			}
		 
			if ( m_fStanding )
				return SCHED_GRUNT_RANGE_ATTACK1B;
			else
				return SCHED_GRUNT_RANGE_ATTACK1A;
		}

	case SCHED_RANGE_ATTACK2:
		{
			return SCHED_GRUNT_RANGE_ATTACK2;
		}
	case SCHED_VICTORY_DANCE:
		{
			if ( m_pSquad )
			{
				if ( !m_pSquad->IsLeader( this ) )
				{
					return SCHED_GRUNT_FAIL;
				}
			}

			return SCHED_GRUNT_VICTORY_DANCE;
		}
	case SCHED_GRUNT_SUPPRESS:
		{
			if ( GetEnemy()->IsPlayer() && m_fFirstEncounter )
			{
				m_fFirstEncounter = FALSE;// after first encounter, leader won't issue handsigns anymore when he has a new enemy
				return SCHED_GRUNT_SIGNAL_SUPPRESS;
			}
			else
			{
				return SCHED_GRUNT_SUPPRESS;
			}
		}
	case SCHED_FAIL:
		{
			if ( GetEnemy() != NULL )
			{
				// grunt has an enemy, so pick a different default fail schedule most likely to help recover.
				return SCHED_GRUNT_COMBAT_FAIL;
			}

			return SCHED_GRUNT_FAIL;
		}
	case SCHED_GRUNT_REPEL:
		{
			Vector vecVel = GetAbsVelocity();
			if ( vecVel.z > -128 )
			{
				vecVel.z -= 32;

⌨️ 快捷键说明

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