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

📄 npc_sscanner.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	{
		float	myDecay	 = 9.5;
		Decelerate( flInterval, myDecay );
		// -------------------------------------
		// If I have an enemy turn to face him
		// -------------------------------------
		if (GetEnemy())
		{
			TurnHeadToTarget(flInterval, GetEnemy()->GetLocalOrigin() );
		}
	}
	MoveExecute_Alive(flInterval);

	UpdateShields();
	return true;
}


//-----------------------------------------------------------------------------
// Purpose: Override base class activiites
// Input  :
// Output :
//-----------------------------------------------------------------------------
Activity CNPC_SScanner::NPC_TranslateActivity( Activity eNewActivity )
{
	if ( eNewActivity == ACT_IDLE)
	{
		if (m_nState == SSCANNER_OPEN)
		{
			return ACT_IDLE_ANGRY;
		}
		else
		{
			return ACT_IDLE;
		}
	}
	return eNewActivity;
}

//------------------------------------------------------------------------------
// Purpose : Choose which entity to shield
// Input   :
// Output  :
//------------------------------------------------------------------------------
CBaseEntity* CNPC_SScanner::PickShieldEntity(void)
{
	if (m_bShieldsDisabled)
	{
		return NULL;
	}

	//	Don't pick every frame as it gets expensive
	if (gpGlobals->curtime > m_fNextShieldCheckTime)
	{
		m_fNextShieldCheckTime = gpGlobals->curtime + 1.0;

		CBaseEntity* pBestEntity = NULL;
		float		 fBestDist	 = MAX_COORD_RANGE;
		bool		 bBestLOS	 = false;
		float		 fTestDist;
		bool		 bTestLOS	 = false;;

		AISquadIter_t iter;
		for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) )
		{
			CAI_BaseNPC* pTestNPC = pSquadMember;
			if (pTestNPC != NULL && 
				pTestNPC != this &&
				pTestNPC->Classify() != CLASS_SCANNER	)
			{
				bTestLOS  = pTestNPC->HasCondition( COND_HAVE_ENEMY_LOS);
				fTestDist = (GetLocalOrigin() - pTestNPC->GetLocalOrigin()).Length();

				// -----------------------------------------
				//  Test has LOS and best doesn't, pick test
				// -----------------------------------------
				if (bTestLOS && !bBestLOS)
				{
					// Skip if I can't see this entity
					if (IsValidShieldTarget(pTestNPC) )
					{
						fBestDist	= fTestDist;
						pBestEntity	= pTestNPC;
						bBestLOS	= bTestLOS;
					}
				}
				// -----------------------------------------
				//  Best has LOS and test doesn't, skip
				// -----------------------------------------
				else if (!bTestLOS && bBestLOS)
				{
					continue;
				}
				// -----------------------------------------------
				//  Otherwise pick by distance
				// -----------------------------------------------
				if (fTestDist <	fBestDist )					
				{
					// Skip if I can't see this entity
					if (IsValidShieldTarget(pTestNPC) )
					{
						fBestDist	= fTestDist;
						pBestEntity	= pTestNPC;
						bBestLOS	= bTestLOS;
					}
				}
			}
		}
		return pBestEntity;
	}
	else
	{
		return GetTarget();
	}
}

//------------------------------------------------------------------------------
// Purpose : Override to set pissed level of sscanner
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_SScanner::NPCThink(void)
{
	// --------------------------------------------------
	//  COND_SSCANNER_PISSED_OFF
	// --------------------------------------------------
	float fHurtAge		= gpGlobals->curtime - m_lastHurtTime;

	if (fHurtAge > 5.0)
	{
		ClearCondition(COND_SSCANNER_PISSED_OFF);
		m_bShieldsDisabled = false;
	}
	else
	{
		SetCondition(COND_SSCANNER_PISSED_OFF);
		m_bShieldsDisabled = true;
	}

	BaseClass::NPCThink();
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_SScanner::PowerShield(void)
{
	// -----------------------------
	//	Start the shield chase beam
	// -----------------------------
	if (!m_pShieldBeamL)
	{
		m_pShieldBeamL = CShieldBeam::ShieldBeamCreate( this, 2 );
		m_pShieldBeamR = CShieldBeam::ShieldBeamCreate( this, 3 );
	}

	if (!m_pShieldBeamL->IsShieldBeamOn())
	{
		m_pShieldBeamL->ShieldBeamStart(this, GetTarget(), GetCurrentVelocity(), 500 );
		m_pShieldBeamR->ShieldBeamStart(this, GetTarget(), GetCurrentVelocity(), 500 );
		m_pShieldBeamL->m_vTailOffset		= Vector(0,0,88);
		m_pShieldBeamR->m_vTailOffset		= Vector(0,0,88);
	}

	// -------------------------------------------------
	//	Start the shield when chaser reaches the shield
	// ------------------------------------------------- 
	if (m_pShieldBeamL->IsShieldBeamOn() && m_pShieldBeamL->ReachedTail())
	{

		if (!m_pShield)
		{
			m_pShield = (CScannerShield *)CreateEntityByName("scanner_shield" );
			m_pShield->Spawn();
		}
		m_pShield->SetTarget(GetTarget());
		m_pShieldBeamL->SetNoise(GetCurrentVelocity().Length());
		m_pShieldBeamR->SetNoise(GetCurrentVelocity().Length());
	}
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_SScanner::StopShield(void)
{
	// -----------------------------
	//	Stop shield chase beam
	// -----------------------------
	if (m_pShieldBeamL)
	{
		m_pShieldBeamL->ShieldBeamStop();
	}
	if (m_pShieldBeamR)
	{
		m_pShieldBeamR->ShieldBeamStop();
	}

	// -----------------------------
	//	Stop the shield
	// -----------------------------
	if (m_pShield)
	{
		m_pShield->SetTarget(NULL);
	}
}
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_SScanner::UpdateShields(void)
{
	// -------------------------------------------------------
	//  Turn of shield and don't reset m_hTarget if in script
	// -------------------------------------------------------
	if (m_IdealNPCState != NPC_STATE_SCRIPT ||
		m_NPCState != NPC_STATE_SCRIPT)
	{
		StopShield();
		return;
	}

	// -------------------------------------------------------------------------
	//  If I'm not in a squad there's no one to shield
	// -------------------------------------------------------------------------
	if (!m_pSquad)
	{
		return;
	}

	// -------------------------------------------------------------------------
	// If I'm dead, stop the shields
	// -------------------------------------------------------------------------
	if ( m_IdealNPCState == NPC_STATE_DEAD )
	{
		SetTarget( NULL );
		StopShield();
	}

	// -------------------------------------------------------------------------
	// Pick the best entity to shield
	// -------------------------------------------------------------------------
	CBaseEntity* pShielded = PickShieldEntity();

	// -------------------------------------------------------------------------
	// If there was no best entity stop the shields 
	// -------------------------------------------------------------------------
	if (pShielded == NULL)
	{
		SetTarget( NULL );
		StopShield();
		return;
	}

	// -------------------------------------------------------------------------
	// If I'm too far to shield set best entity as target but stop the shields
	// -------------------------------------------------------------------------
	float fDist = (GetLocalOrigin() - pShielded->GetLocalOrigin()).Length();
	if (fDist > SSCANNER_MAX_SHEILD_DIST)
	{
		SetTarget( pShielded );
		StopShield();
		return;
	}

	// -------------------------------------------------------------------------
	// If this is a new target, stop the shield
	// -------------------------------------------------------------------------
	if (m_pShieldBeamL				&&
		GetTarget() != pShielded	&&
		m_pShieldBeamL->IsShieldBeamOn()	)
	{
		StopShield();
	}

	// -------------------------------------------------------------------------
	// Reset my target entity and power the shield
	// -------------------------------------------------------------------------
	SetTarget( pShielded );

		// -------------------------------------------------------------------------
	// If I'm closed, stop the shields
	// -------------------------------------------------------------------------
	if ( m_nState == SSCANNER_CLOSED )
	{
		StopShield();
	}
	else
	{
		PowerShield();
	}
	
	/* DEBUG TOOL 
	if (GetTarget())
	{
		int blue = 0;
		int red  = 0;
		if (GetTarget())
		{
			red = 255;
		}
		else
		{
			blue = 255;
		}
		NDebugOverlay::Cross3D(GetTarget()->GetLocalOrigin()+Vector(0,0,60),Vector(-15,-15,-15),Vector(5,5,5),red,0,blue,true,0.1);
		NDebugOverlay::Cross3D(GetLocalOrigin()+Vector(0,0,60),Vector(-15,-15,-15),Vector(5,5,5),red,0,blue,true,0.1);
		NDebugOverlay::Line(GetLocalOrigin(), GetTarget()->GetLocalOrigin(), red,0,blue, true, 0.1);
	}
	else
	{
		NDebugOverlay::Cross3D(GetLocalOrigin()+Vector(0,0,60),Vector(-15,-15,-15),Vector(5,5,5),0,255,0,true,0.1);
	}
	*/
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_SScanner::MoveToTarget(float flInterval, const Vector &MoveTarget)
{
	const float	myAccel	 = 300.0;
	const float	myDecay	 = 9.0;
	
	TurnHeadToTarget( flInterval, MoveTarget );
	MoveToLocation( flInterval, MoveTarget, myAccel, (2 * myAccel), myDecay );
}



//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_SScanner::MoveToEntity(float flInterval, CBaseEntity* pMoveTarget, float fMinRange, float fMaxRange)
{
	// -----------------------------------------
	//  Make sure we have a move target
	// -----------------------------------------
	if (!pMoveTarget)
	{
		return;
	}

	// -----------------------------------------
	//  Keep within range of enemy
	// -----------------------------------------
	Vector vFlyDirection = vec3_origin;
	Vector	vEnemyDir  = pMoveTarget->EyePosition() - GetAbsOrigin();
	float	fEnemyDist = VectorNormalize(vEnemyDir);
	if (fEnemyDist < fMinRange)
	{
		vFlyDirection = -vEnemyDir;
	}
	else if (fEnemyDist > fMaxRange)
	{
		vFlyDirection = vEnemyDir;
	}
	// If I'm shielding someone see if I can go to cover
	else if (SetShieldCoverPosition())
	{
		vFlyDirection = m_vCoverPosition - GetAbsOrigin();
		VectorNormalize(vFlyDirection);
	}

	TurnHeadToTarget( flInterval, pMoveTarget->GetAbsOrigin() );

	// -------------------------------------
	// Set net velocity 
	// -------------------------------------
	float	myAccel	 = 500.0;
	float	myDecay	 = 0.35; // decay to 35% in 1 second
	MoveInDirection(flInterval, vFlyDirection, myAccel, (2 * myAccel), myDecay);
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_SScanner::PlayFlySound(void)
{
	if (gpGlobals->curtime > m_fNextFlySoundTime)
	{
		EmitSound( "NPC_SScanner.FlySound" );
		m_fNextFlySoundTime	= gpGlobals->curtime + 1.0;
	}
}

//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
float CNPC_SScanner::MinGroundDist(void)
{
	return SSCANNER_MIN_GROUND_DIST;
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
void CNPC_SScanner::MoveExecute_Alive(float flInterval)
{
	// ----------------------------------------------------------------------------------------
	// Add time-coherent noise to the current velocity so that it never looks bolted in place.
	// ----------------------------------------------------------------------------------------
	AddNoiseToVelocity( 2.0 );

	// -------------------------------------------
	//  Avoid obstacles
	// -------------------------------------------
	SetCurrentVelocity( GetCurrentVelocity() + VelocityToAvoidObstacles(flInterval) );

	// ---------------------
	//  Limit overall speed
	// ---------------------
	LimitSpeed( 200 );

	// If I'm right over the ground limit my banking so my blades
	// don't sink into the floor
	float floorZ = GetFloorZ(GetLocalOrigin());
	if (abs(GetLocalOrigin().z - floorZ) < 36)
	{
		QAngle angles = GetLocalAngles();
		if (angles.x < -20) angles.x = -20;
		if (angles.x >  20) angles.x =  20;
		if (angles.z < -20) angles.z = -20;
		if (angles.z >  20) angles.z =  20;
		SetLocalAngles( angles );
	}

	PlayFlySound();
	WalkMove( GetCurrentVelocity() * flInterval, MASK_NPCSOLID );
}


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_SScanner::Precache(void)
{
	//
	// Model.
	//
	engine->PrecacheModel("models/shield_scanner.mdl");
	engine->PrecacheModel("models/scanner_shield.mdl");
	engine->PrecacheModel("models/gibs/mortarsynth_gibs.mdl");
	
	enginesound->PrecacheSound( "npc/waste_scanner/grenade_fire.wav");
	enginesound->PrecacheSound( "npc/waste_scanner/hover.wav");

⌨️ 快捷键说明

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