void QUA_helicopter::Event_Killed( const CTakeDamageInfo &info ) { //m_lifeState=LIFE_DYING; // Calculate death force m_vecTotalBulletForce = CalcDamageForceVector( info ); CBasePlayer *pPlayer = m_hPlayer; if ( pPlayer ) { pPlayer->LeaveVehicle(); // Force exit vehicle CBaseEntity *pAPC=this->GetBaseEntity(); CTakeDamageInfo playerinfo; if (info.GetAttacker()==pAPC && info.GetInflictor()==pAPC) { playerinfo.SetAttacker(pPlayer); playerinfo.SetInflictor(pPlayer); playerinfo.SetDamage(10000); playerinfo.SetDamageType(DMG_BLAST); } else { playerinfo.SetAttacker(info.GetAttacker()); playerinfo.SetInflictor(info.GetInflictor()); playerinfo.SetDamage(10000); playerinfo.SetDamageType(DMG_BLAST); } playerinfo.SetDamagePosition( pPlayer->WorldSpaceCenter() ); playerinfo.SetDamageForce( Vector(0,0,-1) ); pPlayer->TakeDamage( playerinfo ); m_hPlayer = NULL; } m_OnDeath.FireOutput( info.GetAttacker(), this ); //StopSmoking(); Vector vecAbsMins, vecAbsMaxs; CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); Vector vecNormalizedMins, vecNormalizedMaxs; CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins ); CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs ); Vector vecAbsPoint; CPASFilter filter( GetAbsOrigin() ); for (int i = 0; i < 5; i++) { CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint ); te->Explosion( filter, random->RandomFloat( 0.0, 1.0 ), &vecAbsPoint, g_sModelIndexFireball, random->RandomInt( 4, 10 ), random->RandomInt( 8, 15 ), ( i < 2 ) ? TE_EXPLFLAG_NODLIGHTS : TE_EXPLFLAG_NOPARTICLES | TE_EXPLFLAG_NOFIREBALLSMOKE | TE_EXPLFLAG_NODLIGHTS, 100, 0 ); } // Aqui destruiremos todo StopLoopingSounds(); BecomeRagdoll( info, m_vecTotalBulletForce ); UTIL_ScreenShake( vecAbsPoint, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); CreateCorpse(); //BecomeRagdoll( info, m_vecTotalBulletForce ); //BecomeRagdollOnClient(m_vecTotalBulletForce); //Dissolve(NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseProjectile::ProjectileTouch( CBaseEntity *pOther ) { // Verify a correct "other." Assert( pOther ); if ( !pOther->IsSolid() || pOther->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) return; // Handle hitting skybox (disappear). const trace_t *pTrace = &CBaseEntity::GetTouchTrace(); trace_t *pNewTrace = const_cast<trace_t*>( pTrace ); if( pTrace->surface.flags & SURF_SKY ) { UTIL_Remove( this ); return; } CTakeDamageInfo info; info.SetAttacker( GetOwnerEntity() ); info.SetInflictor( this ); info.SetDamage( GetDamage() ); info.SetDamageType( GetDamageType() ); CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin(), GetDamageScale() ); Vector dir; AngleVectors( GetAbsAngles(), &dir ); pOther->DispatchTraceAttack( info, dir, pNewTrace ); ApplyMultiDamage(); UTIL_Remove( this ); }
int CNPC_Portal_GroundTurret::OnTakeDamage_Alive( const CTakeDamageInfo &info ) { // Taking damage from myself, make sure it's fatal. CTakeDamageInfo infoCopy = info; if ( infoCopy.GetDamageType() == DMG_CRUSH ) { infoCopy.SetDamage( GetHealth() ); infoCopy.SetDamageType( DMG_REMOVENORAGDOLL | DMG_GENERIC ); } return BaseClass::BaseClass::OnTakeDamage_Alive( infoCopy ); }
void CNPC_Zombine::Event_Killed( const CTakeDamageInfo &info ) { CTakeDamageInfo dInfo = info; if (!(g_Language.GetInt() == LANGUAGE_GERMAN || UTIL_IsLowViolence()) && info.GetDamageType() & (DMG_ALWAYSGIB | DMG_BLAST | DMG_CRUSH) && !(info.GetDamageType() & (DMG_DISSOLVE)) && !m_fIsTorso) { dInfo.SetDamageType(info.GetDamageType() | DMG_REMOVENORAGDOLL); } BaseClass::Event_Killed( dInfo ); if ( HasGrenade() ) { DropGrenade( vec3_origin ); } }
void asw_ragdoll_marine_f() { CASW_Player *pPlayer = ToASW_Player(UTIL_GetCommandClient()); static CRagdollProp * s_pRagdoll = NULL; if (pPlayer && pPlayer->GetMarine()) { CASW_Marine* pMarine = pPlayer->GetMarine(); pMarine->SetKnockedOut(!pMarine->m_bKnockedOut); return; if (pMarine->IsEffectActive(EF_NODRAW) && s_pRagdoll) { //Calcs the diff between ragdoll worldspace center and victim worldspace center, moves the victim by this diff. //Sets the victim's angles to 0, ragdoll yaw, 0 QAngle newAngles( 0, s_pRagdoll->GetAbsAngles()[YAW], 0 ); Vector centerDelta = s_pRagdoll->WorldSpaceCenter() - pMarine->WorldSpaceCenter(); centerDelta.z = 0; // don't put us in the floor Vector newOrigin = pMarine->GetAbsOrigin() + centerDelta; pMarine->SetAbsOrigin( newOrigin ); pMarine->SetAbsAngles( newAngles ); //DetachAttachedRagdoll( s_pRagdoll ); // unnecessary since we remove it next? UTIL_Remove( s_pRagdoll ); pMarine->RemoveEffects( EF_NODRAW ); pMarine->RemoveSolidFlags( FSOLID_NOT_SOLID ); } else { pMarine->InvalidateBoneCache(); pMarine->AddSolidFlags( FSOLID_NOT_SOLID ); CTakeDamageInfo info; info.SetDamageType( DMG_GENERIC ); info.SetDamageForce( vec3_origin ); info.SetDamagePosition( pMarine->WorldSpaceCenter() ); s_pRagdoll = (CRagdollProp*) CreateServerRagdoll( pMarine, 0, info, COLLISION_GROUP_NONE ); if ( s_pRagdoll ) { s_pRagdoll->DisableAutoFade(); s_pRagdoll->SetThink( NULL ); s_pRagdoll->SetUnragdoll( pMarine ); } pMarine->AddEffects( EF_NODRAW ); //pMarine->SetupBones( m_pRagdollBones, BONE_USED_BY_ANYTHING ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pOther - //----------------------------------------------------------------------------- void CDODBaseRocket::RocketTouch( CBaseEntity *pOther ) { Assert( pOther ); if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( pOther->GetCollisionGroup() == COLLISION_GROUP_WEAPON ) return; // if we hit the skybox, just disappear const trace_t &tr = CBaseEntity::GetTouchTrace(); const trace_t *p = &tr; trace_t *newTrace = const_cast<trace_t*>(p); if( tr.surface.flags & SURF_SKY ) { UTIL_Remove( this ); return; } if( !pOther->IsPlayer() ) { CTakeDamageInfo info; info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamage( 50 ); info.SetDamageForce( vec3_origin ); // don't worry about this not having a damage force. // It will explode on touch and impart its own forces info.SetDamageType( DMG_CLUB ); Vector dir; AngleVectors( GetAbsAngles(), &dir ); pOther->DispatchTraceAttack( info, dir, newTrace ); ApplyMultiDamage(); } if( pOther->IsAlive() ) { Explode(); } // else we will continue our movement }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CASW_PropJeep::OnTakeDamage( const CTakeDamageInfo &inputInfo ) { //Do scaled up physics damage to the car CTakeDamageInfo info = inputInfo; info.ScaleDamage( 25 ); // HACKHACK: Scale up grenades until we get a better explosion/pressure damage system if ( inputInfo.GetDamageType() & DMG_BLAST ) { info.SetDamageForce( inputInfo.GetDamageForce() * 10 ); } VPhysicsTakeDamage( info ); // reset the damage info.SetDamage( inputInfo.GetDamage() ); // small amounts of shock damage disrupt the car, but aren't transferred to the player if ( info.GetDamageType() == DMG_SHOCK ) { if ( info.GetDamage() <= 10 ) { // take 10% damage and make the engine stall info.ScaleDamage( 0.1 ); m_throttleDisableTime = gpGlobals->curtime + 2; } } //Check to do damage to driver if ( GetDriver() ) { //Take no damage from physics damages if ( info.GetDamageType() & DMG_CRUSH ) return 0; // Take the damage (strip out the DMG_BLAST) info.SetDamageType( info.GetDamageType() & (~DMG_BLAST) ); GetDriver()->TakeDamage( info ); } return 0; }
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(), "Garg.Pain" ); 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 ); }
//----------------------------------------------------------------------------- // Purpose: Slowly destroy the object I'm attached to //----------------------------------------------------------------------------- void CObjectSapper::SapperThink( void ) { if ( !GetTeam() ) return; CBaseObject *pObject = GetParentObject(); if ( !pObject ) { DestroyObject(); return; } SetNextThink( gpGlobals->curtime + 0.1, SAPPER_THINK_CONTEXT ); // Don't bring objects back from the dead if ( !pObject->IsAlive() || pObject->IsDying() ) return; // how much damage to give this think? float flTimeSinceLastThink = gpGlobals->curtime - m_flLastThinkTime; float flDamageToGive = ( flTimeSinceLastThink ) * obj_sapper_amount.GetFloat(); // add to accumulator m_flSapperDamageAccumulator += flDamageToGive; int iDamage = (int)m_flSapperDamageAccumulator; m_flSapperDamageAccumulator -= iDamage; CTakeDamageInfo info; info.SetDamage( iDamage ); info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamageType( DMG_CRUSH ); pObject->TakeDamage( info ); m_flLastThinkTime = gpGlobals->curtime; }
void CSnark::Event_Killed( const CTakeDamageInfo &inputInfo ) { // pev->model = iStringNull;// make invisible SetThink( &CSnark::SUB_Remove ); SetNextThink( gpGlobals->curtime + 0.1f ); SetTouch( NULL ); // since squeak grenades never leave a body behind, clear out their takedamage now. // Squeaks do a bit of radius damage when they pop, and that radius damage will // continue to call this function unless we acknowledge the Squeak's death now. (sjb) m_takedamage = DAMAGE_NO; // play squeek blast CPASAttenuationFilter filter( this, 0.5 ); enginesound->EmitSound( filter, entindex(), CHAN_ITEM, "squeek/sqk_blast1.wav", 1, 0.5, 0, PITCH_NORM ); CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SNARK_EXPLOSION_VOLUME, 3.0 ); UTIL_BloodDrips( WorldSpaceCenter(), Vector( 0, 0, 0 ), BLOOD_COLOR_YELLOW, 80 ); if ( m_hOwner != NULL ) { RadiusDamage( CTakeDamageInfo( this, m_hOwner, GetDamage(), DMG_BLAST ), GetAbsOrigin(), GetDamage() * 2.5, CLASS_NONE ); } else { RadiusDamage( CTakeDamageInfo( this, this, GetDamage(), DMG_BLAST ), GetAbsOrigin(), GetDamage() * 2.5, CLASS_NONE ); } // reset owner so death message happens if ( m_hOwner != NULL ) SetOwnerEntity( m_hOwner ); CTakeDamageInfo info = inputInfo; info.SetDamageType( DMG_GIB_CORPSE ); BaseClass::Event_Killed( info ); }
//--------------------------------------------------------- //--------------------------------------------------------- int CNPC_GroundTurret::OnTakeDamage_Alive( const CTakeDamageInfo &info ) { if( !info.GetInflictor() ) { return 0; } // Only take damage from self (kill input from my bullseye) or missiles. if( info.GetInflictor() != this && info.GetInflictor()->Classify() != CLASS_MISSILE ) { return 0; } CTakeDamageInfo infoCopy = info; if( info.GetInflictor() == this ) { // Taking damage from myself, make sure it's fatal. infoCopy.SetDamage( GetHealth() ); infoCopy.SetDamageType( DMG_REMOVENORAGDOLL | DMG_GENERIC ); } return BaseClass::OnTakeDamage_Alive( infoCopy ); }
//========================================================= // Pensamiento: Nectar //========================================================= void CFR_Player::NectarThink() { // Menos nectar para tu cuerpo. if ( random->RandomInt(0, 5) <= 2 && m_iNectar > 0 ) --m_iNectar; DevMsg("m_iEmptyNectarSeconds: %i \r\n", m_iEmptyNectarSeconds); // ¡Te has quedado sin nectar! if ( m_iNectar <= 0 ) { // Todavia te quedan unos segundos para recuperar el nectar perdido. if ( m_iEmptyNectarSeconds > 0 ) --m_iEmptyNectarSeconds; // Sin nectar y sin segundos. Le quitamos salud cada 5 segs. else if ( GetLastDamageTime() < (gpGlobals->curtime - 5) ) { CTakeDamageInfo damage; damage.SetAttacker(this); damage.SetInflictor(this); damage.SetDamageType(DMG_GENERIC); damage.SetDamage(random->RandomInt(10, 30)); // Entre 10 a 30 de daño. TakeDamage(damage); } } // Tienes nectar, restaurar los segundos para recuperarlo. else if ( m_iEmptyNectarSeconds != fr_emptynectar_seconds.GetInt() ) m_iEmptyNectarSeconds = fr_emptynectar_seconds.GetInt(); m_HL2Local.m_iNectar = GetNectar(); SetNextThink(gpGlobals->curtime + 1, "NectarContext"); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPropAPC2::Event_Killed( const CTakeDamageInfo &info ) { CBasePlayer *pPlayer = m_hPlayer; if ( pPlayer ) { pPlayer->LeaveVehicle(); // Force exit vehicle CBaseEntity *pAPC=this->GetBaseEntity(); CTakeDamageInfo playerinfo; if (info.GetAttacker()==pAPC && info.GetInflictor()==pAPC) { playerinfo.SetAttacker(pPlayer); playerinfo.SetInflictor(pPlayer); playerinfo.SetDamage(10000); playerinfo.SetDamageType(DMG_BLAST); } else { playerinfo.SetAttacker(info.GetAttacker()); playerinfo.SetInflictor(info.GetInflictor()); playerinfo.SetDamage(10000); playerinfo.SetDamageType(DMG_BLAST); } playerinfo.SetDamagePosition( pPlayer->WorldSpaceCenter() ); playerinfo.SetDamageForce( Vector(0,0,-1) ); pPlayer->TakeDamage( playerinfo ); m_hPlayer = NULL; } m_OnDeath.FireOutput( info.GetAttacker(), this ); Vector vecAbsMins, vecAbsMaxs; CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); Vector vecNormalizedMins, vecNormalizedMaxs; CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins ); CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs ); Vector vecAbsPoint; CPASFilter filter( GetAbsOrigin() ); for (int i = 0; i < 3; i++) { CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint ); te->Explosion( filter, random->RandomFloat( 0.0, 1.0 ), &vecAbsPoint, g_sModelIndexFireball, random->RandomInt( 4, 10 ), random->RandomInt( 8, 15 ), ( i < 2 ) ? TE_EXPLFLAG_NODLIGHTS : TE_EXPLFLAG_NOPARTICLES | TE_EXPLFLAG_NOFIREBALLSMOKE | TE_EXPLFLAG_NODLIGHTS, 100, 0 ); } // TODO: make the gibs spawn in sync with the delayed explosions //int nGibs = random->RandomInt( 1, 4 ); //for ( i = 0; i < nGibs; i++) //{ // // Throw a flaming, smoking chunk. // CGib *pChunk = CREATE_ENTITY( CGib, "gib" ); // pChunk->Spawn( "models/gibs/hgibs.mdl" ); // pChunk->SetBloodColor( DONT_BLEED ); // QAngle vecSpawnAngles; // vecSpawnAngles.Random( -90, 90 ); // pChunk->SetAbsOrigin( vecAbsPoint ); // pChunk->SetAbsAngles( vecSpawnAngles ); // int nGib = random->RandomInt( 0, APC_MAX_CHUNKS - 1 ); // pChunk->Spawn( s_pChunkModelName[nGib] ); // pChunk->SetOwnerEntity( this ); // pChunk->m_lifeTime = random->RandomFloat( 6.0f, 8.0f ); // pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); // IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); // // // Set the velocity // if ( pPhysicsObject ) // { // pPhysicsObject->EnableMotion( true ); // Vector vecVelocity; // QAngle angles; // angles.x = random->RandomFloat( -20, 20 ); // angles.y = random->RandomFloat( 0, 360 ); // angles.z = 0.0f; // AngleVectors( angles, &vecVelocity ); // // vecVelocity *= random->RandomFloat( 300, 900 ); // vecVelocity += GetAbsVelocity(); // AngularImpulse angImpulse; // angImpulse = RandomAngularImpulse( -180, 180 ); // pChunk->SetAbsVelocity( vecVelocity ); // pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse ); // } // CEntityFlame *pFlame = CEntityFlame::Create( pChunk, false ); // if ( pFlame != NULL ) // { // pFlame->SetLifetime( pChunk->m_lifeTime ); // } // pChunk->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); //} UTIL_ScreenShake( vecAbsPoint, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); //Ignite( 60, false ); //m_lifeState = LIFE_DYING; // Spawn a lesser amount if the player is close /*m_iRocketSalvoLeft = DEATH_VOLLEY_ROCKET_COUNT; m_flRocketTime = gpGlobals->curtime;*/ CreateCorpse(); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CNPC_Blob::RunAI() { BaseClass::RunAI(); if( !m_bInitialized ) { // m_bInitialized is set to false in the constructor. So this bit of // code runs one time, the first time I think. Msg("I need to initialize\n"); InitializeElements(); m_bInitialized = true; return; } int iIdealNumElements = blob_numelements.GetInt(); if( iIdealNumElements != m_iNumElements ) { int delta = iIdealNumElements - m_iNumElements; if( delta < 0 ) { delta = -delta; delta = MIN(delta, 5 ); RemoveExcessElements( delta ); if( m_iReconfigureElement > m_iNumElements ) { // Start this index over at zero, if it is past the new end of the utlvector. m_iReconfigureElement = 0; } } else { delta = MIN(delta, 5 ); AddNewElements( delta ); } RecomputeIdealElementDist(); } ComputeCentroid(); if( npc_blob_show_centroid.GetBool() ) { NDebugOverlay::Cross3D( m_vecCentroid + Vector( 0, 0, 12 ), 32, 0, 255, 0, false, 0.025f ); } if( npc_blob_use_threading.GetBool() ) { IterRangeParallel( this, &CNPC_Blob::DoBlobBatchedAI, 0, m_Elements.Count() ); } else { DoBlobBatchedAI( 0, m_Elements.Count() ); } if( GetEnemy() != NULL ) { float flEnemyDistSqr = m_vecCentroid.DistToSqr( GetEnemy()->GetAbsOrigin() ); if( flEnemyDistSqr <= Square( 32.0f ) ) { if( GetEnemy()->Classify() == CLASS_COMBINE ) { if( !m_bEatCombineHack ) { variant_t var; var.SetFloat( 0 ); g_EventQueue.AddEvent( GetEnemy(), "HitByBugBait", 0.0f, this, this ); g_EventQueue.AddEvent( GetEnemy(), "SetHealth", var, 3.0f, this, this ); m_bEatCombineHack = true; blob_radius.SetValue( 48.0f ); RecomputeIdealElementDist(); } } else { CTakeDamageInfo info; info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamage( 5 ); info.SetDamageType( DMG_SLASH ); info.SetDamageForce( Vector( 0, 0, 1 ) ); GetEnemy()->TakeDamage( info ); } } } SetNextThink( gpGlobals->curtime + npc_blob_think_interval.GetFloat() ); }
//----------------------------------------------------------------------------- // Purpose: The turret has been tipped over and will thrash for awhile //----------------------------------------------------------------------------- void CNPC_Portal_FloorTurret::TippedThink( void ) { PreThink( TURRET_TIPPED ); SetNextThink( gpGlobals->curtime + 0.05f ); SetEnemy( NULL ); StudioFrameAdvance(); // If we're not on side anymore, stop thrashing if ( !OnSide() && VPhysicsGetObject()->GetContactPoint( NULL, NULL ) ) { ReturnToLife(); return; } LaserOn(); RopesOn(); //See if we should continue to thrash if ( gpGlobals->curtime < m_flThrashTime && !IsDissolving() ) { if ( m_flShotTime < gpGlobals->curtime ) { if( m_bOutOfAmmo ) { SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); DryFire(); } else { Vector vecMuzzle, vecMuzzleDir; GetAttachment( m_iMuzzleAttachment, vecMuzzle, &vecMuzzleDir ); SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); SetActivity( (Activity)( ( m_bShootWithBottomBarrels ) ? ( ACT_FLOOR_TURRET_FIRE2 ) : ( ACT_FLOOR_TURRET_FIRE ) ) ); #if !DISABLE_SHOT Shoot( vecMuzzle, vecMuzzleDir ); #endif } m_flShotTime = gpGlobals->curtime + 0.05f; } m_vecGoalAngles.x = GetAbsAngles().x + random->RandomFloat( -60, 60 ); m_vecGoalAngles.y = GetAbsAngles().y + random->RandomFloat( -60, 60 ); UpdateFacing(); } else { //Face forward m_vecGoalAngles = GetAbsAngles(); //Set ourselves to close if ( GetActivity() != ACT_FLOOR_TURRET_CLOSE ) { SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); //If we're done moving to our desired facing, close up if ( UpdateFacing() == false ) { //Make any last death noises and anims EmitSound( "NPC_FloorTurret.Die" ); EmitSound( GetTurretTalkName( PORTAL_TURRET_DISABLED ) ); SpinDown(); SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSE ); EmitSound( "NPC_FloorTurret.Retract" ); CTakeDamageInfo info; info.SetDamage( 1 ); info.SetDamageType( DMG_CRUSH ); Event_Killed( info ); } } else if ( IsActivityFinished() ) { m_bActive = false; m_flLastSight = 0; SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSED_IDLE ); // Don't need to store last NPC anymore, because I've been knocked over if ( m_hLastNPCToKickMe ) { m_hLastNPCToKickMe = NULL; m_flKnockOverFailedTime = 0; } //Try to look straight if ( UpdateFacing() == false ) { m_OnTipped.FireOutput( this, this ); SetEyeState( TURRET_EYE_DEAD ); //SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ); // Start thinking slowly to see if we're ever set upright somehow SetThink( &CNPC_FloorTurret::InactiveThink ); SetNextThink( gpGlobals->curtime + 1.0f ); RopesOff(); } } } }
void CNPC_Portal_GroundTurret::Shoot() { FireBulletsInfo_t info; Vector vecSrc = EyePosition(); Vector vecDir; GetVectors( &vecDir, NULL, NULL ); for( int i = 0 ; i < 1 ; i++ ) { info.m_vecSrc = vecSrc; if( i > 0 || !GetEnemy()->IsPlayer() ) { // Subsequent shots or shots at non-players random GetVectors( &info.m_vecDirShooting, NULL, NULL ); info.m_vecSpread = m_vecSpread; } else { // First shot is at the enemy. info.m_vecDirShooting = GetActualShootTrajectory( vecSrc ); info.m_vecSpread = VECTOR_CONE_PRECALCULATED; } info.m_iTracerFreq = 1; info.m_iShots = 1; info.m_pAttacker = this; info.m_flDistance = MAX_COORD_RANGE; info.m_iAmmoType = m_iAmmoType; FireBullets( info ); trace_t tr; CTraceFilterSkipTwoEntities traceFilter( this, info.m_pAdditionalIgnoreEnt, COLLISION_GROUP_NONE ); Vector vecEnd = info.m_vecSrc + vecDir * info.m_flDistance; AI_TraceLine( info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr ); if ( tr.m_pEnt && !tr.m_pEnt->IsPlayer() && ( vecDir * info.m_flDistance * tr.fraction ).Length() < 16.0f ) { CTakeDamageInfo damageInfo; damageInfo.SetAttacker( this ); damageInfo.SetDamageType( DMG_BULLET ); damageInfo.SetDamage( 20.0f ); TakeDamage( damageInfo ); EmitSound( "NPC_FloorTurret.DryFire" ); } } // Do the AR2 muzzle flash CEffectData data; data.m_nEntIndex = entindex(); data.m_nAttachmentIndex = LookupAttachment( "eyes" ); data.m_flScale = 1.0f; data.m_fFlags = MUZZLEFLASH_COMBINE; DispatchEffect( "MuzzleFlash", data ); EmitSound( "NPC_FloorTurret.ShotSounds" ); m_flTimeNextShoot = gpGlobals->curtime + 0.09; }
//========================================================= // ActiveThink - //========================================================= void CNPC_BaseTurret::ActiveThink(void) { int fAttack = 0; SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); if ( (!m_iOn) || (GetEnemy() == NULL) ) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } // if it's dead, look for something new if ( !GetEnemy()->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout } else { if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } } Vector vecMid = GetAbsOrigin() + GetViewOffset(); Vector vecMidEnemy = GetEnemy()->BodyTarget( vecMid, false ); // Look for our current enemy int fEnemyVisible = FBoxVisible(this, GetEnemy(), vecMidEnemy ); //We want to look at the enemy's eyes so we don't jitter Vector vecDirToEnemyEyes = vecMidEnemy - vecMid; float flDistToEnemy = vecDirToEnemyEyes.Length(); VectorNormalize( vecDirToEnemyEyes ); QAngle vecAnglesToEnemy; VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { if (!m_flLastSight) m_flLastSight = gpGlobals->curtime + 0.5; else { // Should we look for a new target? if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } //ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", // m_vecCurAngles.x, m_vecCurAngles.y, // gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); Vector vecLOS = vecDirToEnemyEyes; //vecMid - m_vecLastSight; VectorNormalize( vecLOS ); Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( 1, vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); // Is the Gun looking at the target if (DotProduct(vecLOS, vecMuzzleDir) <= 0.866) // 30 degree slop fAttack = FALSE; else fAttack = TRUE; //forward // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecMuzzleDir * 200 ), 255,0,0, false, 0.1); //LOS // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecLOS * 200 ), 0,0,255, false, 0.1); // fire the gun if (m_iSpin && ((fAttack) || (m_fBeserk))) { Vector vecOrigin; QAngle vecAngles; GetAttachment( 1, vecOrigin, vecAngles ); Shoot(vecOrigin, vecMuzzleDir ); SetTurretAnim(TURRET_ANIM_FIRE); } else { SetTurretAnim(TURRET_ANIM_SPIN); } //move the gun if (m_fBeserk) { if (random->RandomInt(0,9) == 0) { m_vecGoalAngles.y = random->RandomFloat(0,360); m_vecGoalAngles.x = random->RandomFloat(0,90) - 90 * m_iOrientation; CTakeDamageInfo info; info.SetAttacker(this); info.SetInflictor(this); info.SetDamage( 1 ); info.SetDamageType( DMG_GENERIC ); TakeDamage( info ); // don't beserk forever return; } } else if (fEnemyVisible) { if (vecAnglesToEnemy.y > 360) vecAnglesToEnemy.y -= 360; if (vecAnglesToEnemy.y < 0) vecAnglesToEnemy.y += 360; //ALERT(at_console, "[%.2f]", vec.x); if (vecAnglesToEnemy.x < -180) vecAnglesToEnemy.x += 360; if (vecAnglesToEnemy.x > 180) vecAnglesToEnemy.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-90...14] if (m_iOrientation == TURRET_ORIENTATION_FLOOR) { if (vecAnglesToEnemy.x > 90) vecAnglesToEnemy.x = 90; else if (vecAnglesToEnemy.x < m_iMinPitch) vecAnglesToEnemy.x = m_iMinPitch; } else { if (vecAnglesToEnemy.x < -90) vecAnglesToEnemy.x = -90; else if (vecAnglesToEnemy.x > -m_iMinPitch) vecAnglesToEnemy.x = -m_iMinPitch; } //DevMsg( 1, "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vecAnglesToEnemy.y; m_vecGoalAngles.x = vecAnglesToEnemy.x; } SpinUpCall(); MoveTurret(); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CRagdollProp::HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ) { IPhysicsObject *pObj = VPhysicsGetObject(); if ( !pObj) return; if( HasPhysgunInteraction( "onfirstimpact", "break" ) ) { // Looks like it's best to break by having the object damage itself. CTakeDamageInfo info; info.SetDamage( m_iHealth ); info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamageType( DMG_GENERIC ); Vector vecPosition; Vector vecVelocity; VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); VPhysicsGetObject()->GetPosition( &vecPosition, NULL ); info.SetDamageForce( vecVelocity ); info.SetDamagePosition( vecPosition ); TakeDamage( info ); return; } if( HasPhysgunInteraction( "onfirstimpact", "paintsplat" ) ) { IPhysicsObject *pObj = VPhysicsGetObject(); Vector vecPos; pObj->GetPosition( &vecPos, NULL ); trace_t tr; UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); switch( random->RandomInt( 1, 3 ) ) { case 1: UTIL_DecalTrace( &tr, "PaintSplatBlue" ); break; case 2: UTIL_DecalTrace( &tr, "PaintSplatGreen" ); break; case 3: UTIL_DecalTrace( &tr, "PaintSplatPink" ); break; } } bool bAlienBloodSplat = HasPhysgunInteraction( "onfirstimpact", "alienbloodsplat" ); if( bAlienBloodSplat || HasPhysgunInteraction( "onfirstimpact", "bloodsplat" ) ) { IPhysicsObject *pObj = VPhysicsGetObject(); Vector vecPos; pObj->GetPosition( &vecPos, NULL ); trace_t tr; UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); UTIL_BloodDecalTrace( &tr, bAlienBloodSplat ? BLOOD_COLOR_GREEN : BLOOD_COLOR_RED ); } }