//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CNPC_Bullsquid::HandleAnimEvent( animevent_t *pEvent ) { switch( pEvent->event ) { case BSQUID_AE_SPIT: { Vector vSpitPos; GetAttachment("mouth", vSpitPos); vSpitPos.z += 40.0f; Vector vTarget; // If our enemy is looking at us and far enough away, lead him if (HasCondition(COND_ENEMY_FACING_ME) && UTIL_DistApprox(GetAbsOrigin(), GetEnemy()->GetAbsOrigin()) > (40 * 12)) { UTIL_PredictedPosition(GetEnemy(), 0.5f, &vTarget); vTarget.z = GetEnemy()->GetAbsOrigin().z; } else { // Otherwise he can't see us and he won't be able to dodge vTarget = GetEnemy()->BodyTarget(vSpitPos, true); } vTarget[2] += random->RandomFloat(0.0f, 32.0f); // Try and spit at our target Vector vecToss; if (GetSpitVector(vSpitPos, vTarget, &vecToss) == false) { DevMsg("GetSpitVector( vSpitPos, vTarget, &vecToss ) == false\n"); // Now try where they were if (GetSpitVector(vSpitPos, m_vSavePosition, &vecToss) == false) { DevMsg("GetSpitVector( vSpitPos, m_vSavePosition, &vecToss ) == false\n"); // Failing that, just shoot with the old velocity we calculated initially! vecToss = m_vecSaveSpitVelocity; } } // Find what our vertical theta is to estimate the time we'll impact the ground Vector vecToTarget = (vTarget - vSpitPos); VectorNormalize(vecToTarget); float flVelocity = VectorNormalize(vecToss); float flCosTheta = DotProduct(vecToTarget, vecToss); float flTime = (vSpitPos - vTarget).Length2D() / (flVelocity * flCosTheta); // Emit a sound where this is going to hit so that targets get a chance to act correctly CSoundEnt::InsertSound(SOUND_DANGER, vTarget, (15 * 12), flTime, this); // Don't fire again until this volley would have hit the ground (with some lag behind it) SetNextAttack(gpGlobals->curtime + flTime + random->RandomFloat(0.5f, 2.0f)); for (int i = 0; i < 6; i++) { CGrenadeSpit *pGrenade = (CGrenadeSpit*)CreateEntityByName("grenade_spit"); pGrenade->SetAbsOrigin(vSpitPos); pGrenade->SetAbsAngles(vec3_angle); DispatchSpawn(pGrenade); pGrenade->SetThrower(this); pGrenade->SetOwnerEntity(this); if (i == 0) { pGrenade->SetSpitSize(SPIT_LARGE); pGrenade->SetAbsVelocity(vecToss * flVelocity); } else { pGrenade->SetAbsVelocity((vecToss + RandomVector(-0.035f, 0.035f)) * flVelocity); pGrenade->SetSpitSize(random->RandomInt(SPIT_SMALL, SPIT_MEDIUM)); } // Tumble through the air pGrenade->SetLocalAngularVelocity(QAngle(random->RandomFloat(-250, -500), random->RandomFloat(-250, -500), random->RandomFloat(-250, -500))); } for (int i = 0; i < 8; i++) { DispatchParticleEffect("blood_impact_yellow_01", vSpitPos + RandomVector(-12.0f, 12.0f), RandomAngle(0, 360)); } EmitSound("NPC_Antlion.PoisonShoot"); } break; case BSQUID_AE_BITE: { // SOUND HERE! CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_bite.GetFloat(), DMG_SLASH ); if ( pHurt ) { Vector forward, up; AngleVectors( GetAbsAngles(), &forward, NULL, &up ); pHurt->ApplyAbsVelocityImpulse( 100 * (up-forward) ); pHurt->SetGroundEntity( NULL ); } } break; case BSQUID_AE_WHIP_SND: { EmitSound( "NPC_Bullsquid.TailWhip" ); break; } /* case BSQUID_AE_TAILWHIP: { CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_whip.GetFloat(), DMG_SLASH | DMG_ALWAYSGIB ); if ( pHurt ) { Vector right, up; AngleVectors( GetAbsAngles(), NULL, &right, &up ); if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) pHurt->ViewPunch( QAngle( 20, 0, -20 ) ); pHurt->ApplyAbsVelocityImpulse( 100 * (up+2*right) ); } } break; */ case BSQUID_AE_BLINK: { // close eye. m_nSkin = 1; } break; case BSQUID_AE_HOP: { float flGravity = GetCurrentGravity(); // throw the squid up into the air on this frame. if ( GetFlags() & FL_ONGROUND ) { SetGroundEntity( NULL ); } // jump 40 inches into the air Vector vecVel = GetAbsVelocity(); vecVel.z += sqrt( flGravity * 2.0 * 40 ); SetAbsVelocity( vecVel ); } break; case BSQUID_AE_THROW: { // squid throws its prey IF the prey is a client. CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), 0, 0 ); if ( pHurt ) { pHurt->ViewPunch( QAngle(20,0,-20) ); // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. UTIL_ScreenShake( pHurt->GetAbsOrigin(), 25.0, 1.5, 0.7, 2, SHAKE_START ); // If the player, throw him around if ( pHurt->IsPlayer()) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pHurt->ApplyAbsVelocityImpulse( forward * 300 + up * 300 ); } // If not the player see if has bullsquid throw interatcion else { CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pHurt ); if (pVictim) { if ( pVictim->DispatchInteraction( g_interactionBullsquidThrow, NULL, this ) ) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pVictim->ApplyAbsVelocityImpulse( forward * 300 + up * 250 ); } } } } } break; default: BaseClass::HandleAnimEvent( pEvent ); } }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CNPC_Bullsquid::HandleAnimEvent( animevent_t *pEvent ) { switch( pEvent->event ) { case BSQUID_AE_SPIT: { if ( GetEnemy() ) { Vector vSpitPos; QAngle vSpitAngle; GetAttachment( "Mouth", vSpitPos, vSpitAngle); Vector vTarget = GetEnemy()->GetAbsOrigin(); Vector vToss; CBaseEntity* pBlocker; float flGravity = sv_gravity.GetFloat() * SPIT_GRAVITY; ThrowLimit(vSpitPos, vTarget, flGravity, 3, Vector(0,0,0), Vector(0,0,0), GetEnemy(), &vToss, &pBlocker); CGrenadeSpit *pGrenade = (CGrenadeSpit*)CreateNoSpawn( "grenade_spit", vSpitPos, vec3_angle, this ); //pGrenade->KeyValue( "velocity", vToss ); pGrenade->Spawn( ); pGrenade->SetOwner( this ); pGrenade->SetOwnerEntity( this ); pGrenade->SetSpitSize( 2 ); pGrenade->SetAbsVelocity( vToss ); // Tumble through the air pGrenade->SetLocalAngularVelocity( QAngle( random->RandomFloat ( -100, -500 ), random->RandomFloat ( -100, -500 ), random->RandomFloat ( -100, -500 ) ) ); AttackSound(); CPVSFilter filter( vSpitPos ); te->SpriteSpray( filter, 0.0, &vSpitPos, &vToss, m_nSquidSpitSprite, 5, 10, 15 ); } } break; case BSQUID_AE_BITE: { // SOUND HERE! CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_bite.GetFloat(), DMG_SLASH ); if ( pHurt ) { Vector forward, up; AngleVectors( GetAbsAngles(), &forward, NULL, &up ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - (forward * 100) ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (up * 100) ); pHurt->RemoveFlag( FL_ONGROUND ); } } break; case BSQUID_AE_WHIP_SND: { EmitSound( "NPC_Bullsquid.TailWhip" ); break; } /* case BSQUID_AE_TAILWHIP: { CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_whip.GetFloat(), DMG_SLASH | DMG_ALWAYSGIB ); if ( pHurt ) { Vector right, up; AngleVectors( GetAbsAngles(), NULL, &right, &up ); if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) pHurt->ViewPunch( QAngle( 20, 0, -20 ) ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (right * 200) ); pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() + (up * 100) ); } } break; */ case BSQUID_AE_BLINK: { // close eye. m_nSkin = 1; } break; case BSQUID_AE_HOP: { float flGravity = sv_gravity.GetFloat(); // throw the squid up into the air on this frame. if ( GetFlags() & FL_ONGROUND ) { RemoveFlag( FL_ONGROUND ); } // jump into air for 0.8 (24/30) seconds Vector vecVel = GetAbsVelocity(); vecVel.z += ( 0.625 * flGravity ) * 0.5; SetAbsVelocity( vecVel ); } break; case BSQUID_AE_THROW: { // squid throws its prey IF the prey is a client. CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), 0, 0 ); if ( pHurt ) { pHurt->ViewPunch( QAngle(20,0,-20) ); // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. UTIL_ScreenShake( pHurt->GetAbsOrigin(), 25.0, 1.5, 0.7, 2, SHAKE_START ); // If the player, throw him around if ( pHurt->IsPlayer()) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pHurt->ApplyAbsVelocityImpulse( forward * 300 + up * 300 ); } // If not the player see if has bullsquid throw interatcion else { CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pHurt ); if (pVictim) { if ( pVictim->HandleInteraction( g_interactionBullsquidThrow, NULL, this ) ) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pVictim->ApplyAbsVelocityImpulse( forward * 300 + up * 250 ); } } } } } break; default: BaseClass::HandleAnimEvent( pEvent ); } }