//----------------------------------------------------------------------------- // Purpose: // Input : *pHandleEntity - // contentsMask - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CASW_Trace_Filter_Door_Crush::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) return false; if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) return false; // Don't test if the game code tells us we should ignore this collision... CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); if ( pEntity ) { //Msg("%f CASW_Trace_Filter_Door_Crush::ShouldHitEntity %s\n", gpGlobals->curtime, pEntity->GetClassname()); if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) return false; if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) return false; if ( pEntity->Classify() == CLASS_ASW_DOOR ) return false; if ( pEntity->m_takedamage == DAMAGE_NO ) return false; // Translate the vehicle into its driver for damage if ( pEntity->GetServerVehicle() != NULL ) { CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); if ( pDriver != NULL ) { pEntity = pDriver; } } Vector attackDir = pEntity->WorldSpaceCenter() - m_dmgInfo->GetAttacker()->WorldSpaceCenter(); VectorNormalize( attackDir ); pEntity->TakeDamage( *m_dmgInfo ); //CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), m_flForceScale ); return true; } return false; }
IPhysicsVehicleController *GetLuaVehicle(ILuaInterface *gLua) { gLua->CheckType(1, GLua::TYPE_ENTITY); CBaseHandle *handle = (CBaseHandle*)gLua->GetUserData(1); CBaseEntity *entity = GetBaseEntity(handle->GetEntryIndex()); if(!entity) { gLua->Error("[gm_pimpmyride] NO ENTITY!"); return NULL; } IServerVehicle *vehicle = entity->GetServerVehicle(); if(!vehicle) { gLua->Error("[gm_pimpmyride] NO VEHICLE!"); return NULL; } IPhysicsVehicleController *controller = vehicle->GetVehicleController(); if(!controller) { gLua->Error("[gm_pimpmyride] NO PHYSICS CONTROLLER!"); return NULL; } return controller; }
//----------------------------------------------------------------------------- // Purpose: Check the weapon LOS for an owner at an arbitrary position // If bSetConditions is true, LOS related conditions will also be set //----------------------------------------------------------------------------- bool CBaseCombatWeapon::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) { // -------------------- // Check for occlusion // -------------------- CAI_BaseNPC* npcOwner = m_hOwner.Get()->MyNPCPointer(); // Find its relative shoot position Vector vecRelativeShootPosition; VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition ); Vector barrelPos = ownerPos + vecRelativeShootPosition; // Use the custom LOS trace filter CWeaponLOSFilter traceFilter( m_hOwner.Get(), npcOwner->GetEnemy(), COLLISION_GROUP_BREAKABLE_GLASS ); trace_t tr; UTIL_TraceLine( barrelPos, targetPos, MASK_SHOT, &traceFilter, &tr ); // See if we completed the trace without interruption if ( tr.fraction == 1.0 ) { if ( ai_debug_shoot_positions.GetBool() ) { NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 ); } return true; } CBaseEntity *pHitEnt = tr.m_pEnt; CBasePlayer *pEnemyPlayer = ToBasePlayer( npcOwner->GetEnemy() ); // is player in a vehicle? if so, verify vehicle is target and return if so (so npc shoots at vehicle) if ( pEnemyPlayer && pEnemyPlayer->IsInAVehicle() ) { // Ok, player in vehicle, check if vehicle is target we're looking at, fire if it is // Also, check to see if the owner of the entity is the vehicle, in which case it's valid too. // This catches vehicles that use bone followers. CBaseEntity *pVehicle = pEnemyPlayer->GetVehicle()->GetVehicleEnt(); if ( pHitEnt == pVehicle || pHitEnt->GetOwnerEntity() == pVehicle ) return true; } // Hitting our enemy is a success case if ( pHitEnt == npcOwner->GetEnemy() ) { if ( ai_debug_shoot_positions.GetBool() ) { NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 ); } return true; } // If a vehicle is blocking the view, grab its driver and use that as the combat character CBaseCombatCharacter *pBCC; IServerVehicle *pVehicle = pHitEnt->GetServerVehicle(); if ( pVehicle ) { pBCC = pVehicle->GetPassenger( ); } else { pBCC = ToBaseCombatCharacter( pHitEnt ); } if ( pBCC ) { if ( npcOwner->IRelationType( pBCC ) == D_HT ) return true; if ( bSetConditions ) { npcOwner->SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); } } else if ( bSetConditions ) { npcOwner->SetCondition( COND_WEAPON_SIGHT_OCCLUDED ); npcOwner->SetEnemyOccluder( pHitEnt ); if( ai_debug_shoot_positions.GetBool() ) { NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 1.0 ); } } return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBaseHelicopter::DoRotorPhysicsPush( const Vector &vecRotorOrigin, float flAltitude ) { CBaseEntity *pEntity = NULL; trace_t tr; // First, trace down and find out where the was is hitting the ground UTIL_TraceLine( vecRotorOrigin, vecRotorOrigin+Vector(0,0,-flAltitude), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER), NULL, COLLISION_GROUP_NONE, &tr ); // Always raise the physics origin a bit Vector vecPhysicsOrigin = tr.endpos + Vector(0,0,64); // Debug if ( g_debug_basehelicopter.GetInt() == BASECHOPPER_DEBUG_WASH ) { NDebugOverlay::Cross3D( vecPhysicsOrigin, -Vector(16,16,16), Vector(16,16,16), 0, 255, 255, true, 0.1f ); } // Push entities that we've pushed before, and are still within range // Walk backwards because they may be removed if they're now out of range int iCount = m_hEntitiesPushedByWash.Count(); bool bWasPushingObjects = (iCount > 0); for ( int i = (iCount-1); i >= 0; i-- ) { if ( !DoWashPush( &(m_hEntitiesPushedByWash[i]), vecPhysicsOrigin ) ) { // Out of range now, so remove m_hEntitiesPushedByWash.Remove(i); } } if ( m_flRotorWashEntitySearchTime > gpGlobals->curtime ) return; // Any spare slots? iCount = m_hEntitiesPushedByWash.Count(); if ( iCount >= BASECHOPPER_WASH_MAX_OBJECTS ) return; // Find the lightest physics entity below us and add it to our list to push around CBaseEntity *pLightestEntity = NULL; float flLightestMass = 9999; while ((pEntity = gEntList.FindEntityInSphere(pEntity, vecPhysicsOrigin, BASECHOPPER_WASH_RADIUS )) != NULL) { IRotorWashShooter *pShooter = GetRotorWashShooter( pEntity ); if ( pEntity->IsEFlagSet( EFL_NO_ROTORWASH_PUSH )) continue; if ( pShooter || pEntity->GetMoveType() == MOVETYPE_VPHYSICS || (pEntity->VPhysicsGetObject() && !pEntity->IsPlayer()) ) { // Make sure it's not already in our wash bool bAlreadyPushing = false; for ( int i = 0; i < iCount; i++ ) { if ( m_hEntitiesPushedByWash[i].hEntity == pEntity ) { bAlreadyPushing = true; break; } } if ( bAlreadyPushing ) continue; float flMass = FLT_MAX; if ( pShooter ) { flMass = 1.0f; } else { // Don't try to push anything too big IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); if ( pPhysObject ) { flMass = pPhysObject->GetMass(); if ( flMass > BASECHOPPER_WASH_MAX_MASS ) continue; } } // Ignore anything bigger than the one we've already found if ( flMass > flLightestMass ) continue; Vector vecSpot = pEntity->BodyTarget( vecPhysicsOrigin ); // Don't push things too far below our starting point (helps reduce through-roof cases w/o doing a trace) if ( fabs( vecSpot.z - vecPhysicsOrigin.z ) > 96 ) continue; Vector vecToSpot = ( vecSpot - vecPhysicsOrigin ); vecToSpot.z = 0; float flDist = VectorNormalize( vecToSpot ); if ( flDist > BASECHOPPER_WASH_RADIUS ) continue; // Try to cast to the helicopter; if we can't, then we can't be hit. if ( pEntity->GetServerVehicle() ) { UTIL_TraceLine( vecSpot, vecPhysicsOrigin, MASK_SOLID_BRUSHONLY, pEntity, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0f ) continue; } flLightestMass = flMass; pLightestEntity = pEntity; washentity_t Wash; Wash.hEntity = pLightestEntity; Wash.flWashStartTime = gpGlobals->curtime; m_hEntitiesPushedByWash.AddToTail( Wash ); // Can we fit more after adding this one? No? Then we are done. iCount = m_hEntitiesPushedByWash.Count(); if ( iCount >= BASECHOPPER_WASH_MAX_OBJECTS ) break; } } // Handle sound. // If we just started pushing objects, ramp the blast sound up. if ( !bWasPushingObjects && m_hEntitiesPushedByWash.Count() ) { if ( m_pRotorBlast ) { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundChangeVolume( m_pRotorBlast, 1.0, 1.0 ); } } else if ( bWasPushingObjects && m_hEntitiesPushedByWash.Count() == 0 ) { if ( m_pRotorBlast ) { // We just stopped pushing objects, so fade the blast sound out. CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundChangeVolume( m_pRotorBlast, 0, 1.0 ); } } }