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

📄 hl1_npc_bigmomma.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			Vector center = GetAbsOrigin() + vecFwd * 128;
			Vector mins = center - Vector( 64, 64, 0 );
			Vector maxs = center + Vector( 64, 64, 64 );

			CBaseEntity *pList[8];
			int count = UTIL_EntitiesInBox( pList, 8, mins, maxs, FL_NPC | FL_CLIENT );
			CBaseEntity *pHurt = NULL;

			for ( int i = 0; i < count && !pHurt; i++ )
			{
				if ( pList[i] != this )
				{
					if ( pList[i]->GetOwnerEntity() != this )
					{
						pHurt = pList[i];
					}
				}
			}
					
			if ( pHurt )
			{
				CTakeDamageInfo info( this, this, 15, DMG_CLUB | DMG_SLASH );
				CalculateMeleeDamageForce( &info, (pHurt->GetAbsOrigin() - GetAbsOrigin()), pHurt->GetAbsOrigin() );
				pHurt->TakeDamage( info );
				QAngle newAngles = angles;
				newAngles.x = 15;
				if ( pHurt->IsPlayer() )
				{
					((CBasePlayer *)pHurt)->SetPunchAngle( newAngles );
				}
				switch( pEvent->event )
				{
					case BIG_AE_MELEE_ATTACKBR:
//						pHurt->pev->velocity = pHurt->pev->velocity + (vecFwd * 150) + Vector(0,0,250) - (vecRight * 200);
						pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (vecFwd * 150) + Vector(0,0,250) - (vecRight * 200) );
					break;

					case BIG_AE_MELEE_ATTACKBL:
						pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (vecFwd * 150) + Vector(0,0,250) + (vecRight * 200) );
					break;

					case BIG_AE_MELEE_ATTACK1:
						pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (vecFwd * 220) + Vector(0,0,200) );
					break;
				}

				pHurt->RemoveFlag( FL_ONGROUND );
				enginesound->EmitSound( filter, entindex(), CHAN_BODY, pAttackHitSounds[ random->RandomInt(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RandomInt(-5,5) );
			}
		}
		break;
		
		case BIG_AE_SCREAM:
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pAlertSounds[ random->RandomInt(0,ARRAYSIZE(pAlertSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;
		
		case BIG_AE_PAIN_SOUND:
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pPainSounds[ random->RandomInt(0,ARRAYSIZE(pPainSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;
		
		case BIG_AE_ATTACK_SOUND:
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pAttackSounds[ random->RandomInt(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;

		case BIG_AE_BIRTH_SOUND:
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pBirthSounds[ random->RandomInt(0,ARRAYSIZE(pBirthSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;

		case BIG_AE_SACK:
			if ( RandomInt(0,100) < 30 )
			{
				enginesound->EmitSound( filter, entindex(), CHAN_BODY, pSackSounds[ random->RandomInt(0,ARRAYSIZE(pSackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			}
			break;

		case BIG_AE_DEATHSOUND:
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pDeathSounds[ random->RandomInt(0,ARRAYSIZE(pDeathSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;

		case BIG_AE_STEP1:		// Footstep left
		case BIG_AE_STEP3:		// Footstep back left
			enginesound->EmitSound( filter, entindex(), CHAN_ITEM, pFootSounds[ random->RandomInt(0,ARRAYSIZE(pFootSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;

		case BIG_AE_STEP4:		// Footstep back right
		case BIG_AE_STEP2:		// Footstep right
			enginesound->EmitSound( filter, entindex(), CHAN_BODY, pFootSounds[ random->RandomInt(0,ARRAYSIZE(pFootSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
			break;

		case BIG_AE_MORTAR_ATTACK1:
			LaunchMortar();
			break;

		case BIG_AE_LAY_CRAB:
			LayHeadcrab();
			break;

		case BIG_AE_JUMP_FORWARD:
			RemoveFlag( FL_ONGROUND );
			SetAbsOrigin(GetAbsOrigin() + Vector ( 0 , 0 , 1) );// take him off ground so engine doesn't instantly reset onground 
			SetAbsVelocity(vecFwd * 200 + vecUp * 500 );
			break;

		case BIG_AE_EARLY_TARGET:
			{
				CInfoBM *pTarget = (CInfoBM*) GetTarget();

				if ( pTarget )
				{
					pTarget->m_OnAnimationEvent.FireOutput( this, this );
				}
				
				Remember( bits_MEMORY_FIRED_NODE );
			}
			break;

		default:
			BaseClass::HandleAnimEvent( pEvent );
			break;
	}
}


void CNPC_BigMomma::LayHeadcrab( void )
{
	CBaseEntity *pChild = CBaseEntity::Create( BIG_CHILDCLASS, GetAbsOrigin(), GetAbsAngles(), this );

	pChild->AddSpawnFlags( SF_NPC_FALL_TO_GROUND );

	pChild->SetOwnerEntity( this );

	// Is this the second crab in a pair?
	if ( HasMemory( bits_MEMORY_CHILDPAIR ) )
	{
		m_crabTime = gpGlobals->curtime + RandomFloat( 5, 10 );
		Forget( bits_MEMORY_CHILDPAIR );
	}
	else
	{
		m_crabTime = gpGlobals->curtime + RandomFloat( 0.5, 2.5 );
		Remember( bits_MEMORY_CHILDPAIR );
	}

	trace_t tr;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,100), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
	UTIL_DecalTrace( &tr, "Splash" );

	CPASAttenuationFilter filter( this );
	enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pBirthSounds[ random->RandomInt(0,ARRAYSIZE(pBirthSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + random->RandomInt(-5,5) );
	m_crabCount++;
}

void CNPC_BigMomma::DeathNotice( CBaseEntity *pevChild )
{
	if ( m_crabCount > 0 )		// Some babies may cross a transition, but we reset the count then
	{
		m_crabCount--;
	}
	if ( IsAlive() )
	{
		// Make the "my baby's dead" noise!
		CPASAttenuationFilter filter( this );
		EmitSound( filter, entindex(), CHAN_WEAPON, RANDOM_SOUND_ARRAY( pChildDieSounds ), 1.0f, ATTN_NORM, 0, PITCH_NORM );

		enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pBirthSounds[ random->RandomInt(0,ARRAYSIZE(pBirthSounds)-1) ], 1.0, ATTN_NORM, 0, 100 );
	}
}


void CNPC_BigMomma::LaunchMortar( void )
{
	m_mortarTime = gpGlobals->curtime + RandomFloat( 2, 15 );
	
	Vector startPos = GetAbsOrigin();
	startPos.z += 180;

	CPASAttenuationFilter filter( this );
	enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, pSackSounds[ random->RandomInt(0,ARRAYSIZE(pSackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + random->RandomInt(-5,5) );
	CBMortar *pBomb = CBMortar::Shoot( this, startPos, m_vTossDir );
	pBomb->SetGravity( 1.0 );
	MortarSpray( startPos, Vector(0,0,10), gSpitSprite, 24 );
}

int CNPC_BigMomma::MeleeAttack1Conditions( float flDot, float flDist )
{
	if (flDot >= 0.7)
	{
		if ( flDist > BIG_ATTACKDIST )
			 return COND_TOO_FAR_TO_ATTACK;
		else
			 return COND_CAN_MELEE_ATTACK1;
	}
	else
	{
		return COND_NOT_FACING_ATTACK;
	}

	return COND_NONE;
}


// Lay a crab
int CNPC_BigMomma::MeleeAttack2Conditions( float flDot, float flDist )
{
	return CanLayCrab();
}


Vector VecCheckSplatToss( CBaseEntity *pEnt, const Vector &vecSpot1, Vector vecSpot2, float maxHeight )
{
	trace_t			tr;
	Vector			vecMidPoint;// halfway point between Spot1 and Spot2
	Vector			vecApex;// highest point 
	Vector			vecScale;
	Vector			vecGrenadeVel;
	Vector			vecTemp;
	float			flGravity = sv_gravity.GetFloat();

	// calculate the midpoint and apex of the 'triangle'
	vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
	UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,maxHeight), MASK_SOLID_BRUSHONLY, pEnt, COLLISION_GROUP_NONE, &tr );
	vecApex = tr.endpos;
	
	UTIL_TraceLine(vecSpot1, vecApex, MASK_SOLID, pEnt, COLLISION_GROUP_NONE, &tr );
	if (tr.fraction != 1.0)
	{
		// fail!
		return vec3_origin;
	}

	// Don't worry about actually hitting the target, this won't hurt us!

	// How high should the grenade travel (subtract 15 so the grenade doesn't hit the ceiling)?
	float height = (vecApex.z - vecSpot1.z) - 15;

	//HACK HACK
	if ( height < 0 )
		 height *= -1;

	// How fast does the grenade need to travel to reach that height given gravity?
	float speed = sqrt( 2 * flGravity * height );

	// How much time does it take to get there?
	float time = speed / flGravity;
	vecGrenadeVel = (vecSpot2 - vecSpot1);
	vecGrenadeVel.z = 0;
	
	// Travel half the distance to the target in that time (apex is at the midpoint)
	vecGrenadeVel = vecGrenadeVel * ( 0.5 / time );
	// Speed to offset gravity at the desired height
	vecGrenadeVel.z = speed;

	return vecGrenadeVel;
}

// Mortar launch
int CNPC_BigMomma::RangeAttack1Conditions( float flDot, float flDist )
{
	if ( flDist > BIG_MORTARDIST )
		 return COND_TOO_FAR_TO_ATTACK;

	if ( flDist <= BIG_MORTARDIST && m_mortarTime < gpGlobals->curtime )
	{
		CBaseEntity *pEnemy = GetEnemy();

		if ( pEnemy )
		{
			Vector startPos = GetAbsOrigin();
			startPos.z += 180;

			m_vTossDir = VecCheckSplatToss( this, startPos, pEnemy->BodyTarget( GetAbsOrigin() ), random->RandomFloat( 150, 500 ) );

			if ( m_vTossDir != vec3_origin )
				return COND_CAN_RANGE_ATTACK1;
		}
	}
	
	return COND_NONE;
}

// ---------------------------------
//
// Mortar
//
// ---------------------------------
void MortarSpray( const Vector &position, const Vector &direction, int spriteModel, int count )
{
	CPVSFilter filter( position );
	
	te->SpriteSpray( filter, 0.0, &position, &direction, spriteModel, 200, 80, count );
}


// UNDONE: right now this is pretty much a copy of the squid spit with minor changes to the way it does damage
void CBMortar:: Spawn( void )
{
	SetMoveType( MOVETYPE_FLYGRAVITY );
	SetClassname( "bmortar" );
	
	SetSolid( SOLID_BBOX );

	pSprite = CSprite::SpriteCreate( "sprites/mommaspit.vmt", GetAbsOrigin(), true ); 

	if ( pSprite )
	{
		pSprite->SetAttachment( this, 0 );
		pSprite->m_flSpriteFramerate = 5;

		pSprite->m_nRenderMode = kRenderTransAlpha;
		pSprite->SetBrightness( 255 );

		m_iFrame = 0;

		pSprite->SetScale( 2.5f );
	}

	UTIL_SetSize( this, Vector( 0, 0, 0), Vector(0, 0, 0) );

	m_maxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1;
	m_flDmgTime = gpGlobals->curtime + 0.4;
}

void CBMortar::Animate( void )
{
	SetNextThink( gpGlobals->curtime + 0.1 );

	Vector vVelocity = GetAbsVelocity();

	VectorNormalize( vVelocity );

	if ( gpGlobals->curtime > m_flDmgTime )
	{
		m_flDmgTime = gpGlobals->curtime + 0.2;
		MortarSpray( GetAbsOrigin() + Vector( 0, 0, 15 ), -vVelocity, gSpitSprite, 3 );
	}
	if ( m_iFrame++ )
	{
		if ( m_iFrame > m_maxFrame )
		{
			m_iFrame = 0;
		}
	}
}

CBMortar *CBMortar::Shoot( CBaseEntity *pOwner, Vector vecStart, Vector vecVelocity )
{
	CBMortar *pSpit = CREATE_ENTITY( CBMortar, "bmortar" ); 
	pSpit->Spawn();
	
	UTIL_SetOrigin( pSpit, vecStart );
	pSpit->SetAbsVelocity( vecVelocity );
	pSpit->SetOwnerEntity( pOwner );
	pSpit->SetThink ( &CBMortar::Animate );
	pSpit->SetNextThink( gpGlobals->curtime + 0.1 );

	return pSpit;
}


void CBMortar::Touch( CBaseEntity *pOther )
{
	trace_t tr;
	int		iPitch;

	// splat sound
	iPitch = random->RandomFloat( 90, 110 );

	EmitSound( "NPC_BigMomma.SpitTouch1" );

	switch ( random->RandomInt( 0, 1 ) )
	{
	case 0:
		EmitSound( "NPC_BigMomma.SpitHit1" );
		break;
	case 1:
		EmitSound( "NPC_BigMomma.SpitHit2" );
		break;
	}

	if ( pOther->IsBSPModel() )
	{
		// make a splat on the wall
		UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 10, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
		UTIL_DecalTrace( &tr, "Splash" );
	}
	else
	{
		tr.endpos = GetAbsOrigin();

		Vector vVelocity = GetAbsVelocity();
		VectorNormalize( vVelocity );

		tr.plane.normal = -1 * vVelocity;
	}
	// make some flecks
	MortarSpray( tr.endpos + Vector( 0, 0, 15 ), tr.plane.normal, gSpitSprite, 24 );

	CBaseEntity *pOwner = GetOwnerEntity();

	RadiusDamage( CTakeDamageInfo( this, pOwner, sk_bigmomma_dmg_blast.GetFloat(), DMG_ACID ), GetAbsOrigin(), sk_bigmomma_radius_blast.GetFloat(), CLASS_NONE );
		
	UTIL_Remove( pSprite );
	UTIL_Remove( this );
}


AI_BEGIN_CUSTOM_NPC( monster_bigmomma, CNPC_BigMomma )

	DECLARE_TASK( TASK_MOVE_TO_NODE_RANGE )
	DECLARE_TASK( TASK_FIND_NODE )
	DECLARE_TASK( TASK_PLAY_NODE_PRESEQUENCE )
	DECLARE_TASK( TASK_PLAY_NODE_SEQUENCE )
	DECLARE_TASK( TASK_PROCESS_NODE )
	DECLARE_TASK( TASK_WAIT_NODE )
	DECLARE_TASK( TASK_NODE_DELAY )
	DECLARE_TASK( TASK_NODE_YAW )
	DECLARE_TASK( TASK_CHECK_NODE_PROXIMITY )

	
	//=========================================================
	// > SCHED_BIG_NODE
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_NODE_FAIL,

		"	Tasks"
		"		TASK_NODE_DELAY						3"
		"		TASK_SET_ACTIVITY					ACTIVITY:ACT_IDLE"
		"	"
		"	Interrupts"
	)

	//=========================================================
	// > SCHED_BIG_NODE
	//=========================================================
	DEFINE_SCHEDULE
	(
		SCHED_BIG_NODE,

		"	Tasks"
		"		TASK_SET_FAIL_SCHEDULE				SCHEDULE:SCHED_NODE_FAIL"
		"		TASK_STOP_MOVING					0"
		"		TASK_FIND_NODE						0"
		"		TASK_PLAY_NODE_PRESEQUENCE			0"
		"		TASK_MOVE_TO_NODE_RANGE				0"
		"		TASK_CHECK_NODE_PROXIMITY			0"
		"		TASK_STOP_MOVING					0"
		"		TASK_NODE_YAW						0"
		"		TASK_FACE_IDEAL						0"
		"		TASK_WAIT_NODE						0"
		"		TASK_PLAY_NODE_SEQUENCE				0"
		"		TASK_PROCESS_NODE					0"
			
		"	"
		"	Interrupts"
	)

AI_END_CUSTOM_NPC()

	

⌨️ 快捷键说明

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