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

📄 npc_sscanner.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	engine->PrecacheModel("sprites/physbeam.vmt");	
	engine->PrecacheModel("sprites/glow01.vmt");

	engine->PrecacheModel("sprites/physring1.vmt");

	BaseClass::Precache();
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CNPC_SScanner::Gib(void)
{
	// Sparks
	for (int i = 0; i < 4; i++)
	{
		Vector sparkPos = GetAbsOrigin();
		sparkPos.x += random->RandomFloat(-12,12);
		sparkPos.y += random->RandomFloat(-12,12);
		sparkPos.z += random->RandomFloat(-12,12);
		g_pEffects->Sparks(sparkPos);
	}
	// Smoke
	UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10);

	// Light
	CBroadcastRecipientFilter filter;
	te->DynamicLight( filter, 0.0,
			&GetAbsOrigin(), 255, 180, 100, 0, 100, 0.1, 0 );

	// Throw scanner gibs
	CGib::SpawnSpecificGibs( this, SSCANNER_GIB_COUNT, 800, 1000, "models/gibs/mortarsynth_gibs.mdl");

	ExplosionCreate(GetAbsOrigin(), GetAbsAngles(), NULL, random->RandomInt(30, 40), 0, true);

	UTIL_Remove(this);
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pTask - 
//-----------------------------------------------------------------------------
void CNPC_SScanner::RunTask( const Task_t *pTask )
{
	switch ( pTask->iTask )
	{
		// If my enemy has moved significantly, update my path
		case TASK_WAIT_FOR_MOVEMENT:
		{
			CBaseEntity *pEnemy = GetEnemy();
			if (pEnemy && IsCurSchedule(SCHED_SSCANNER_CHASE_ENEMY) && GetNavigator()->IsGoalActive())
			{
				Vector flEnemyLKP = GetEnemyLKP();
				if ((GetNavigator()->GetGoalPos() - pEnemy->EyePosition()).Length() > 40 )
				{
					GetNavigator()->UpdateGoalPos(pEnemy->EyePosition());
				}
				// If final position is enemy, exit my schedule (will go to attack hover)
				if (GetNavigator()->IsGoalActive() && 
					GetNavigator()->GetCurWaypointPos() == pEnemy->EyePosition())
				{
					TaskComplete();
					GetNavigator()->ClearGoal();		// Stop moving
					break;
				}
			}
			if (m_nState == SSCANNER_OPEN)
			{
				GetNavigator()->SetMovementActivity(ACT_IDLE_ANGRY);
			}
			else
			{
				GetNavigator()->SetMovementActivity(ACT_IDLE);
			}

			BaseClass::RunTask(pTask);
			break;
		}

		default:
		{
			BaseClass::RunTask(pTask);
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_SScanner::Spawn(void)
{
	Precache();

	SetModel( "models/shield_scanner.mdl");

	SetHullType(HULL_SMALL_CENTERED); 
	SetHullSizeNormal();

	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_NOT_STANDABLE );

	// Make bounce so I bounce off the surfaces I hit, but turn gravity off
	SetMoveType( MOVETYPE_STEP );
	SetGravity(0.001);

	m_iHealth			= sk_sscanner_health.GetFloat();
	SetViewOffset( Vector(0, 0, 10) );		// Position of the eyes relative to NPC's origin.
	m_flFieldOfView		= VIEW_FIELD_FULL;
	m_NPCState			= NPC_STATE_NONE;
	SetNavType( NAV_FLY );
	m_bloodColor		= DONT_BLEED;
	SetCurrentVelocity( Vector(0, 0, 0) );
	m_vCurrentBanking	= Vector(0, 0, 0);

	AddFlag( FL_FLY );

	CapabilitiesAdd( bits_CAP_MOVE_FLY );
	CapabilitiesAdd( bits_CAP_SQUAD);

	m_nState					= SSCANNER_CLOSED;
	m_bShieldsDisabled			= false;

	m_vLastPatrolDir			= vec3_origin;
	m_fNextFlySoundTime			= 0;

	m_fNextShieldCheckTime		= 0;

	SetNoiseMod( 2, 2, 2 );

	m_fHeadYaw			= 0;

	NPCInit();

	// Let this guy look far
	m_flDistTooFar	= 99999999.0;
	SetDistLook( 4000.0 );
	m_flSpeed = SSCANNER_MAX_SPEED;
}


void CNPC_SScanner::OnScheduleChange()
{
	m_flSpeed = SSCANNER_MAX_SPEED;

	BaseClass::OnScheduleChange();
}


//-----------------------------------------------------------------------------
// Purpose: Gets the appropriate next schedule based on current condition
//			bits.
//-----------------------------------------------------------------------------
int CNPC_SScanner::SelectSchedule(void)
{
	switch ( m_NPCState )
	{
		// -------------------------------------------------
		//  In idle attemp to pair up with a squad 
		//  member that could use shielding
		// -------------------------------------------------
		case NPC_STATE_IDLE:
		{
			// --------------------------------------------------
			//  If I'm blocked find a path to my goal entity
			// --------------------------------------------------
			if (HasCondition( COND_SSCANNER_FLY_BLOCKED ) && (GetTarget() != NULL))
			{  
				return SCHED_SSCANNER_CHASE_TARGET;
			}

			return SCHED_SSCANNER_HOVER;
			break;
		}
		case NPC_STATE_DEAD:
		case NPC_STATE_SCRIPT:
		{
			return BaseClass::SelectSchedule();
			break;
		}
		default:
		{

			// --------------------------------------------------
			//  If I'm blocked find a path to my goal entity
			// --------------------------------------------------
			if (HasCondition( COND_SSCANNER_FLY_BLOCKED ))
			{  
				if ((GetTarget() != NULL) && !HasCondition( COND_SSCANNER_PISSED_OFF))
				{
					return SCHED_SSCANNER_CHASE_TARGET;
				}
			}
			// --------------------------------------------------
			//  If I have a live enemy
			// --------------------------------------------------
			if (GetEnemy() != NULL && GetEnemy()->IsAlive())
			{
				// --------------------------------------------------
				//  If I'm open 
				// --------------------------------------------------
				if (m_nState == SSCANNER_OPEN)
				{	
					if (GetTarget()	== NULL				)
					{
						return SCHED_SSCANNER_CLOSE;
					}
					else if (HasCondition( COND_SSCANNER_PISSED_OFF))
					{
						return SCHED_SSCANNER_CLOSE;
					}
					else
					{
						return SCHED_SSCANNER_HOVER;
					}
				}
				else if (m_nState == SSCANNER_CLOSED)
				{
					if (GetTarget()	!= NULL				)
					{
						float fDist = (GetAbsOrigin() - GetTarget()->GetAbsOrigin()).Length();
						if (fDist <= SSCANNER_MAX_SHEILD_DIST)
						{
							return SCHED_SSCANNER_OPEN;
						}
						else
						{
							return SCHED_SSCANNER_HOVER;
						}
					}	
					else if (HasCondition( COND_SSCANNER_PISSED_OFF))
					{
						return SCHED_TAKE_COVER_FROM_ENEMY;
					}
					else
					{
						return SCHED_SSCANNER_HOVER;
					}
				}
				else
				{
					return SCHED_SSCANNER_HOVER;
				}
			}
			// --------------------------------------------------
			//  I have no enemy so patrol
			// --------------------------------------------------
			else if (GetEnemy() == NULL)
			{
				return SCHED_SSCANNER_PATROL;
			}
			// --------------------------------------------------
			//  I have no enemy so patrol
			// --------------------------------------------------
			else
			{
				return SCHED_SSCANNER_HOVER;
			}
			break;
		}
	}
}


//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pTask - 
//-----------------------------------------------------------------------------
void CNPC_SScanner::StartTask( const Task_t *pTask )
{
	switch (pTask->iTask)
	{	
		case TASK_SSCANNER_OPEN:  
		{
			m_nState = SSCANNER_OPEN;
			TaskComplete();
			break;
		}
		case TASK_SSCANNER_CLOSE:  
		{
			m_nState = SSCANNER_CLOSED;
			TaskComplete();
			break;
		}
		// Override so can find hint nodes that are much further away
		case TASK_FIND_HINTNODE:
		{
			if (!m_pHintNode)
			{
				m_pHintNode = CAI_Hint::FindHint(this, HINT_NONE, pTask->flTaskData, 5000 );
			}
			if ( m_pHintNode )
			{
				TaskComplete();
			}
			else
			{
				// No hint node run from enemy
				SetSchedule( SCHED_RUN_FROM_ENEMY );
			}
			break;
		}
		default:
		{
			BaseClass::StartTask(pTask);
		}
	}
}


//------------------------------------------------------------------------------
// Purpose : 
// Input   :
// Output  :
//------------------------------------------------------------------------------
bool CNPC_SScanner::IsValidShieldTarget(CBaseEntity *pEntity)
{
	// Reject if already shielded by another squad member
	AISquadIter_t iter;
	for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) )
	{
		CNPC_SScanner *pScanner = dynamic_cast<CNPC_SScanner*>(pSquadMember);
		if (pScanner										&&
			pScanner			   != this					&&
			pScanner->Classify() == CLASS_SCANNER	)
		{
			if (pScanner->GetTarget() == pEntity)
			{
				// Reject unless I'm significantly closer
				float fNPCDist	= (pScanner->GetLocalOrigin() - pEntity->GetLocalOrigin()).Length();
				float fMyDist	= (GetLocalOrigin() - pEntity->GetLocalOrigin()).Length();
				if ((fNPCDist - fMyDist) > 150 )
				{
					// Steal from other scanner
					pScanner->StopShield();
					pScanner->SetTarget( NULL );
					return true;
				}
				return false;
			}
		}
	}
	return true;
}


//------------------------------------------------------------------------------
//
// Schedules
//
//------------------------------------------------------------------------------

//=========================================================
// > SCHED_SSCANNER_HOVER
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_HOVER,

	"	Tasks"
	"		TASK_RESET_ACTIVITY		0"
	"		TASK_PLAY_SEQUENCE		ACTIVITY:ACT_IDLE"
	"	"
	"	Interrupts"
	"		COND_NEW_ENEMY"
	"		COND_SSCANNER_FLY_BLOCKED"
	"		COND_LIGHT_DAMAGE"
);

//=========================================================
// > SCHED_SSCANNER_OPEN
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_OPEN,

	"	Tasks"
	"		TASK_PLAY_SEQUENCE		ACTIVITY:ACT_SSCANNER_OPEN"
	"		TASK_SSCANNER_OPEN		0"
	"	"
	"	Interrupts"
);

//=========================================================
// > SCHED_SSCANNER_CLOSE
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_CLOSE,

	"	Tasks"
	"		TASK_SSCANNER_CLOSE		0"
	"		TASK_PLAY_SEQUENCE		ACTIVITY:ACT_SSCANNER_CLOSE"
	"	"
	"	Interrupts"
);

//=========================================================
// > SCHED_SSCANNER_PATROL
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_PATROL,

	"	Tasks"
	"		TASK_SET_TOLERANCE_DISTANCE		48"
	"		TASK_SET_ROUTE_SEARCH_TIME		5"	// Spend 5 seconds trying to build a path if stuck
	"		TASK_GET_PATH_TO_RANDOM_NODE	2000"
	"		TASK_RUN_PATH					0"
	"		TASK_WAIT_FOR_MOVEMENT			0		"
	"	"
	"	Interrupts"
	"		COND_GIVE_WAY"
	"		COND_NEW_ENEMY"
	"		COND_SEE_ENEMY"
	"		COND_SEE_FEAR"
	"		COND_HEAR_COMBAT"
	"		COND_HEAR_DANGER"
	"		COND_HEAR_PLAYER"
	"		COND_LIGHT_DAMAGE"
	"		COND_HEAVY_DAMAGE"
	"		COND_PROVOKED"
);

//=========================================================
// > SCHED_SSCANNER_CHASE_ENEMY
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_CHASE_ENEMY,

	"	Tasks"
	"		 TASK_SET_FAIL_SCHEDULE				SCHEDULE:SCHED_SSCANNER_PATROL"
	"		 TASK_SET_TOLERANCE_DISTANCE		120"
	"		 TASK_GET_PATH_TO_ENEMY				0"
	"		 TASK_RUN_PATH						0"
	"		 TASK_WAIT_FOR_MOVEMENT				0"
	"	"
	"	Interrupts"
	"		COND_ENEMY_DEAD"
	"		COND_SSCANNER_FLY_CLEAR"
);

//=========================================================
// > SCHED_SSCANNER_CHASE_TARGET
//=========================================================
AI_DEFINE_SCHEDULE
(
	SCHED_SSCANNER_CHASE_TARGET,

	"	Tasks"
	"		 TASK_SET_FAIL_SCHEDULE				SCHEDULE:SCHED_SSCANNER_HOVER"
	"		 TASK_SET_TOLERANCE_DISTANCE		120"
	"		 TASK_GET_PATH_TO_TARGET			0"
	"		 TASK_RUN_PATH						0"
	"		 TASK_WAIT_FOR_MOVEMENT				0"
	"	"
	"	"
	"	Interrupts"
	"		COND_SSCANNER_FLY_CLEAR"
	"		COND_SSCANNER_PISSED_OFF"
);

⌨️ 快捷键说明

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