📄 hl1_npc_gargantua.cpp
字号:
else
m_pFlame[i] = CBeam::BeamCreate( GARG_BEAM_SPRITE2, 14.0 );
if ( m_pFlame[i] )
{
int attach = i%2;
// attachment is 0 based in GetAttachment
GetAttachment( attach+1, posGun, angleGun );
Vector vecEnd = ( vForward * GARG_FLAME_LENGTH) + posGun;
//UTIL_TraceLine( posGun, vecEnd, dont_ignore_monsters, edict(), &trace );
UTIL_TraceLine ( posGun, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);
// NDebugOverlay::Line( posGun, vecEnd, 255, 255, 255, false, 10.0f );
m_pFlame[i]->PointEntInit( trace.endpos, this );
if ( i < 2 )
m_pFlame[i]->SetColor( 255, 130, 90 );
else
m_pFlame[i]->SetColor( 0, 120, 255 );
m_pFlame[i]->SetBrightness( 190 );
m_pFlame[i]->SetBeamFlags( FBEAM_SHADEIN );
m_pFlame[i]->SetScrollRate( 20 );
// attachment is 1 based in SetEndAttachment
m_pFlame[i]->SetEndAttachment( attach + 2 );
CSoundEnt::InsertSound( SOUND_COMBAT, posGun, 384, 0.3 );
}
}
CPASAttenuationFilter filter4( this );
enginesound->EmitSound( filter4, entindex(), CHAN_BODY, pBeamAttackSounds[ 1 ], 1, ATTN_NORM, 0, PITCH_NORM );
enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, pBeamAttackSounds[ 2 ], 1, ATTN_NORM, 0, PITCH_NORM );
}
void CNPC_Gargantua::FlameControls( float angleX, float angleY )
{
if ( angleY < -180 )
angleY += 360;
else if ( angleY > 180 )
angleY -= 360;
if ( angleY < -45 )
angleY = -45;
else if ( angleY > 45 )
angleY = 45;
m_flameX = UTIL_ApproachAngle( angleX, m_flameX, 4 );
m_flameY = UTIL_ApproachAngle( angleY, m_flameY, 8 );
SetBoneController( 0, m_flameY );
SetBoneController( 1, m_flameX );
}
void CNPC_Gargantua::FlameUpdate( void )
{
int i;
static float offset[2] = { 60, -60 };
trace_t trace;
Vector vecStart;
QAngle angleGun;
BOOL streaks = FALSE;
Vector vForward;
for ( i = 0; i < 2; i++ )
{
if ( m_pFlame[i] )
{
QAngle vecAim = GetAbsAngles();
vecAim.x += -m_flameX;
vecAim.y += m_flameY;
AngleVectors( vecAim, &vForward );
GetAttachment( i + 2, vecStart, angleGun );
Vector vecEnd = vecStart + ( vForward * GARG_FLAME_LENGTH); // - offset[i] * gpGlobals->v_right;
UTIL_TraceLine ( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);
m_pFlame[i]->SetStartPos( trace.endpos );
m_pFlame[i+2]->SetStartPos( (vecStart * 0.6) + (trace.endpos * 0.4) );
if ( trace.fraction != 1.0 && gpGlobals->curtime > m_streakTime )
{
g_pEffects->Sparks( trace.endpos, 1, 1, &trace.plane.normal );
streaks = TRUE;
UTIL_DecalTrace( &trace, "SmallScorch" );
}
// RadiusDamage( trace.vecEndPos, pev, pev, gSkillData.gargantuaDmgFire, CLASS_ALIEN_MONSTER, DMG_BURN );
FlameDamage( vecStart, trace.endpos, this, this, sk_gargantua_dmg_fire.GetFloat(), CLASS_ALIEN_MONSTER, DMG_BURN );
CBroadcastRecipientFilter filter;
GetAttachment(i + 2, vecStart, angleGun);
te->DynamicLight( filter, 0.0, &vecStart, 255, 0, 0, 0, 48, 0.2, 150 );
}
}
if ( streaks )
m_streakTime = gpGlobals->curtime;
}
void CNPC_Gargantua::FlameDamage( Vector vecStart, Vector vecEnd, CBaseEntity *pevInflictor, CBaseEntity *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType )
{
CBaseEntity *pEntity = NULL;
trace_t tr;
float flAdjustedDamage;
Vector vecSpot;
Vector vecMid = (vecStart + vecEnd) * 0.5;
// float searchRadius = (vecStart - vecMid).Length();
float searchRadius = GARG_FLAME_LENGTH;
float maxDamageRadius = searchRadius / 2.0;
Vector vecAim = (vecEnd - vecStart);
VectorNormalize( vecAim );
// iterate on all entities in the vicinity.
while ((pEntity = gEntList.FindEntityInSphere( pEntity, GetAbsOrigin(), searchRadius )) != NULL)
{
if ( pEntity->m_takedamage != DAMAGE_NO )
{
// UNDONE: this should check a damage mask, not an ignore
if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
{// houndeyes don't hurt other houndeyes with their attack
continue;
}
vecSpot = pEntity->BodyTarget( vecMid );
float dist = DotProduct( vecAim, vecSpot - vecMid );
if (dist > searchRadius)
dist = searchRadius;
else if (dist < -searchRadius)
dist = searchRadius;
Vector vecSrc = vecMid + dist * vecAim;
UTIL_TraceLine ( vecStart, vecSpot, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
// NDebugOverlay::Line( vecStart, vecSpot, 0, 255, 0, false, 10.0f );
if ( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
{// the explosion can 'see' this entity, so hurt them!
// decrease damage for an ent that's farther from the flame.
dist = ( vecSrc - tr.endpos ).Length();
if (dist > maxDamageRadius)
{
flAdjustedDamage = flDamage - (dist - maxDamageRadius) * 0.4;
if (flAdjustedDamage <= 0)
continue;
}
else
{
flAdjustedDamage = flDamage;
}
// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
if (tr.fraction != 1.0)
{
ClearMultiDamage( );
Vector vDir = (tr.endpos - vecSrc);
VectorNormalize( vDir );
CTakeDamageInfo info( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
CalculateMeleeDamageForce( &info, vDir, tr.endpos );
pEntity->DispatchTraceAttack( info, vDir, &tr );
ApplyMultiDamage();
}
else
{
pEntity->TakeDamage( CTakeDamageInfo( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType ) );
}
}
}
}
}
void CNPC_Gargantua::FlameDestroy( void )
{
int i;
CPASAttenuationFilter filter4( this );
enginesound->EmitSound( filter4, entindex(), CHAN_WEAPON, pBeamAttackSounds[ 0 ], 1, ATTN_NORM, 0, PITCH_NORM );
for ( i = 0; i < 4; i++ )
{
if ( m_pFlame[i] )
{
UTIL_Remove( m_pFlame[i] );
m_pFlame[i] = NULL;
}
}
}
void CNPC_Gargantua::EyeOn( int level )
{
m_eyeBrightness = level;
}
void CNPC_Gargantua::EyeOff( void )
{
m_eyeBrightness = 0;
}
void CNPC_Gargantua::EyeUpdate( void )
{
if ( m_pEyeGlow )
{
m_pEyeGlow->SetBrightness( UTIL_Approach( m_eyeBrightness, m_pEyeGlow->GetBrightness(), 26 ), 0.5f );
if ( m_pEyeGlow->GetBrightness() == 0 )
{
m_pEyeGlow->m_fEffects |= EF_NODRAW;
}
else
{
m_pEyeGlow->m_fEffects &= ~EF_NODRAW;
}
}
}
void CNPC_Gargantua::StompAttack( void )
{
trace_t trace;
Vector vecForward;
AngleVectors(GetAbsAngles(), &vecForward );
Vector vecStart = GetAbsOrigin() + Vector(0,0,60) + 35 * vecForward;
CBaseEntity* pPlayer = GetEnemy();
if ( !pPlayer )
return;
Vector vecAim = pPlayer->GetAbsOrigin() - GetAbsOrigin();
VectorNormalize( vecAim );
Vector vecEnd = (vecAim * 1024) + vecStart;
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
// NDebugOverlay::Line( vecStart, vecEnd, 255, 0, 0, false, 10.0f );
CStomp::StompCreate( vecStart, trace.endpos, 0, this );
UTIL_ScreenShake( GetAbsOrigin(), 12.0, 100.0, 2.0, 1000, SHAKE_START );
CPASAttenuationFilter filter( this );
enginesound->EmitSound( filter, entindex(), CHAN_VOICE, pStompSounds[ RandomInt(0,ARRAYSIZE(pStompSounds)-1) ], 1.0, ATTN_GARG, 0, PITCH_NORM + RandomInt(-10,10) );
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,20), MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
if ( trace.fraction < 1.0 )
{
UTIL_DecalTrace( &trace, "SmallScorch" );
}
}
void CNPC_Gargantua::DeathEffect( void )
{
int i;
Vector vForward;
AngleVectors( GetAbsAngles(), &vForward );
Vector deathPos = GetAbsOrigin() + vForward * 100;
Vector position = GetAbsOrigin();
position.z += 32;
CPASFilter filter( GetAbsOrigin() );
for ( i = 0; i < 7; i++)
{
te->Explosion( filter, i * 0.2, &GetAbsOrigin(), g_sModelIndexFireball, 10, 15, TE_EXPLFLAG_NONE, 100, 0 );
position.z += 15;
}
UTIL_Smoke(GetAbsOrigin(),random->RandomInt(10, 15), 10);
UTIL_ScreenShake( GetAbsOrigin(), 25.0, 100.0, 5.0, 1000, SHAKE_START );
}
void CNPC_Gargantua::Event_Killed( const CTakeDamageInfo &info )
{
EyeOff();
UTIL_Remove( m_pEyeGlow );
m_pEyeGlow = NULL;
BaseClass::Event_Killed( info );
}
void CNPC_Gargantua::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
{
CTakeDamageInfo subInfo = info;
if ( !IsAlive() )
{
BaseClass::TraceAttack( subInfo, vecDir, ptr );
return;
}
// UNDONE: Hit group specific damage?
if ( subInfo.GetDamageType() & ( GARG_DAMAGE | DMG_BLAST ) )
{
if ( m_painSoundTime < gpGlobals->curtime )
{
CPASAttenuationFilter filter( this );
EmitSound( filter, entindex(), CHAN_VOICE, pPainSounds[ random->RandomInt(0,ARRAYSIZE(pPainSounds)-1) ], 1, ATTN_GARG );
m_painSoundTime = gpGlobals->curtime + random->RandomFloat( 2.5, 4 );
}
}
int bitsDamageType = subInfo.GetDamageType();
bitsDamageType &= GARG_DAMAGE;
subInfo.SetDamageType( bitsDamageType );
if ( subInfo.GetDamageType() == 0 )
{
if ( m_flDmgTime != gpGlobals->curtime || (random->RandomInt( 0, 100 ) < 20) )
{
g_pEffects->Ricochet(ptr->endpos, -vecDir );
m_flDmgTime = gpGlobals->curtime;
}
subInfo.SetDamage( 0 );
}
BaseClass::TraceAttack( subInfo, vecDir, ptr );
}
int CNPC_Gargantua::OnTakeDamage_Alive( const CTakeDamageInfo &info )
{
CTakeDamageInfo subInfo = info;
float flDamage = subInfo.GetDamage();
if ( IsAlive() )
{
if ( !(subInfo.GetDamageType() & GARG_DAMAGE) )
{
flDamage *= 0.01;
subInfo.SetDamage( flDamage );
}
if ( subInfo.GetDamageType() & DMG_BLAST )
{
SetCondition( COND_LIGHT_DAMAGE );
}
}
return BaseClass::OnTakeDamage_Alive( subInfo );
}
AI_BEGIN_CUSTOM_NPC( monster_gargantua, CNPC_Gargantua )
DECLARE_TASK ( TASK_SOUND_ATTACK )
DECLARE_TASK ( TASK_FLAME_SWEEP )
//=========================================================
// > SCHED_GARG_FLAME
//=========================================================
DEFINE_SCHEDULE
(
SCHED_GARG_FLAME,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_FACE_ENEMY 0"
" TASK_SOUND_ATTACK 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_MELEE_ATTACK2"
" TASK_FLAME_SWEEP 4.5"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
)
//=========================================================
// > SCHED_GARG_SWIPE
//=========================================================
DEFINE_SCHEDULE
(
SCHED_GARG_SWIPE,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_FACE_ENEMY 0"
" TASK_MELEE_ATTACK1 0"
" "
" Interrupts"
" COND_CAN_MELEE_ATTACK2"
)
AI_END_CUSTOM_NPC()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -