bool CCollisionProperty::ShouldTouchTrigger( int triggerSolidFlags ) const { // debris only touches certain triggers if ( GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) { if ( triggerSolidFlags & FSOLID_TRIGGER_TOUCH_DEBRIS ) return true; return false; } // triggers don't touch other triggers (might be solid to other ents as well as trigger) if ( IsSolidFlagSet( FSOLID_TRIGGER ) ) return false; return true; }
void C_PhysPropClientside::Break() { m_takedamage = DAMAGE_NO; IPhysicsObject *pPhysics = VPhysicsGetObject(); Vector velocity; AngularImpulse angVelocity; Vector origin; QAngle angles; AddSolidFlags( FSOLID_NOT_SOLID ); if ( pPhysics ) { pPhysics->GetVelocity( &velocity, &angVelocity ); pPhysics->GetPosition( &origin, &angles ); pPhysics->RecheckCollisionFilter(); } else { velocity = GetAbsVelocity(); QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); origin = GetAbsOrigin(); angles = GetAbsAngles(); } breakablepropparams_t params( origin, angles, velocity, angVelocity ); params.impactEnergyScale = m_impactEnergyScale; params.defCollisionGroup = GetCollisionGroup(); if ( params.defCollisionGroup == COLLISION_GROUP_NONE ) { // don't automatically make anything COLLISION_GROUP_NONE or it will // collide with debris being ejected by breaking params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; } // no damage/damage force? set a burst of 100 for some movement params.defBurstScale = 100; // spwan break chunks PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, false ); Release(); // destroy object }
// Always explode immediately upon hitting anything void CGERocket::ExplodeTouch( CBaseEntity *pOther ) { if ( !pOther->IsSolid() ) return; // This also handles teammate collisions. if ( !g_pGameRules->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + (m_vForward * 32), MASK_SOLID, this, GetCollisionGroup(), &tr ); if( tr.surface.flags & SURF_SKY ) { // Game Over, we hit the sky box, remove the rocket from the world (no explosion) StopSound("Weapon_RocketLauncher.Ignite"); UTIL_Remove(this); return; } // If we are a bot, see if we hit our own NPC CGEBotPlayer *pBot = ToGEBotPlayer( GetThrower() ); if ( pBot && pBot->GetNPC() == pOther ) return; if (pOther != GetThrower()) { // Check if they're a player, if they are deal out instant death. if (!m_bHitPlayer && (pOther->IsPlayer() || pOther->IsNPC())) { Vector playercenter = pOther->GetAbsOrigin() + Vector(0, 0, 38); Vector impactforce = playercenter - GetAbsOrigin(); VectorNormalize(impactforce); impactforce *= 1000; CTakeDamageInfo rocketinfo(this, GetThrower(), impactforce, GetAbsOrigin(), 398.0f, DMG_BLAST); pOther->TakeDamage(rocketinfo); m_bHitPlayer = true; // Only deal one direct hit per projectile. } Explode(); } }
void CASW_Rocket::MissileTouch( CBaseEntity *pOther ) { Assert( pOther ); // Don't touch triggers (but DO hit weapons) if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) && pOther->GetCollisionGroup() != COLLISION_GROUP_WEAPON ) return; if (pOther == GetOwnerEntity()) return; // make sure we don't die on things we shouldn't if ( !ASWGameRules() || !ASWGameRules()->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; if (asw_rocket_debug.GetBool()) Msg("Rocket exploding on %d:%s\n", pOther->entindex(), pOther->GetClassname()); //Msg("owner is %d:%s\n", GetOwnerEntity() ? GetOwnerEntity()->entindex() : -1, //GetOwnerEntity() ? GetOwnerEntity()->GetClassname() : "unknown"); Explode(); }
bool CASW_Parasite::HasHeadroom() { trace_t tr; UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 1 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); #if 0 if( tr.fraction == 1.0f ) { Msg("Headroom\n"); } else { Msg("NO Headroom\n"); } #endif return (tr.fraction == 1.0); }
int CASW_Parasite::RangeAttack1Conditions( float flDot, float flDist ) { if ( gpGlobals->curtime < m_flNextAttack ) return 0; if ( ( GetFlags() & FL_ONGROUND ) == false ) return 0; // This code stops lots of headcrabs swarming you and blocking you // whilst jumping up and down in your face over and over. It forces // them to back up a bit. If this causes problems, consider using it // for the fast headcrabs only, rather than just removing it.(sjb) if ( flDist < ASW_PARASITE_MIN_JUMP_DIST ) return COND_TOO_CLOSE_TO_ATTACK; if ( flDist > ASW_PARASITE_MAX_JUMP_DIST ) return COND_TOO_FAR_TO_ATTACK; // Make sure the way is clear! CBaseEntity *pEnemy = GetEnemy(); if( pEnemy ) { bool bEnemyIsBullseye = ( dynamic_cast<CNPC_Bullseye *>(pEnemy) != NULL ); trace_t tr; AI_TraceLine( EyePosition(), pEnemy->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt != GetEnemy() ) { if ( !bEnemyIsBullseye || tr.m_pEnt != NULL ) return COND_NONE; } if( GetEnemy()->EyePosition().z - 36.0f > GetAbsOrigin().z ) { // Only run this test if trying to jump at a player who is higher up than me, else this // code will always prevent a headcrab from jumping down at an enemy, and sometimes prevent it // jumping just slightly up at an enemy. Vector vStartHullTrace = GetAbsOrigin(); vStartHullTrace.z += 1.0; Vector vEndHullTrace = GetEnemy()->EyePosition() - GetAbsOrigin(); vEndHullTrace.NormalizeInPlace(); vEndHullTrace *= 8.0; vEndHullTrace += GetAbsOrigin(); AI_TraceHull( vStartHullTrace, vEndHullTrace,GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); if ( tr.m_pEnt != NULL && tr.m_pEnt != GetEnemy() ) { return COND_TOO_CLOSE_TO_ATTACK; } } } return COND_CAN_RANGE_ATTACK1; }
void CASW_Shotgun_Pellet_Predicted::PelletTouch( CBaseEntity *pOther ) { if (!pOther) return; if (pOther == m_pLastHit) // don't damage the same alien twice return; if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; // make sure we don't die on things we shouldn't if (!ASWGameRules() || !ASWGameRules()->ShouldCollide(GetCollisionGroup(), pOther->GetCollisionGroup())) return; if ( pOther->m_takedamage != DAMAGE_NO ) { trace_t tr, tr2; tr = BaseClass::GetTouchTrace(); Vector vecNormalizedVel = GetAbsVelocity(); VectorNormalize( vecNormalizedVel ); #ifdef GAME_DLL ClearMultiDamage(); if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() && pOther->IsNPC() ) { CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_flDamage, DMG_NEVERGIB ); dmgInfo.AdjustPlayerDamageInflictedForSkillLevel(); CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); dmgInfo.SetDamagePosition( tr.endpos ); pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); } else { CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_flDamage, DMG_BULLET | DMG_NEVERGIB ); CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); dmgInfo.SetDamagePosition( tr.endpos ); pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); } ApplyMultiDamage(); #endif //Adrian: keep going through the glass. if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS ) return; // pellets should carry on through spawnable enemies? //IASW_Spawnable_NPC* pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pOther); //if (pSpawnable && asw_shotgun_pellets_pass.GetBool()) //{ //m_pLastHit = pOther; //return; //} SetAbsVelocity( Vector( 0, 0, 0 ) ); // play body "thwack" sound EmitSound( "Weapon_Crossbow.BoltHitBody" ); Vector vForward; AngleVectors( GetAbsAngles(), &vForward ); VectorNormalize ( vForward ); UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_OPAQUE, pOther, COLLISION_GROUP_NONE, &tr2 ); #ifdef GAME_DLL if ( tr2.fraction != 1.0f ) { // NDebugOverlay::Box( tr2.endpos, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 255, 0, 0, 10 ); // NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 0, 255, 0, 10 ); if ( tr2.m_pEnt == NULL || ( tr2.m_pEnt && tr2.m_pEnt->GetMoveType() == MOVETYPE_NONE ) ) { CEffectData data; data.m_vOrigin = tr2.endpos; data.m_vNormal = vForward; data.m_nEntIndex = tr2.fraction != 1.0f; //DispatchEffect( "BoltImpact", data ); } } #endif SetTouch( NULL ); SetThink( NULL ); //KillEffects(); //UTIL_Remove( this ); //Release(); SetThink( &CASW_Shotgun_Pellet_Predicted::SUB_Remove ); SetNextThink( gpGlobals->curtime ); } else { trace_t tr; tr = BaseClass::GetTouchTrace(); // See if we struck the world if ( pOther->GetMoveType() == MOVETYPE_NONE && !( tr.surface.flags & SURF_SKY ) ) { //EmitSound( "Weapon_Crossbow.BoltHitWorld" ); // if what we hit is static architecture, can stay around for a while. Vector vecDir = GetAbsVelocity(); VectorNormalize( vecDir ); SetMoveType( MOVETYPE_NONE ); Vector vForward; AngleVectors( GetAbsAngles(), &vForward ); VectorNormalize ( vForward ); #ifdef GAME_DLL CEffectData data; data.m_vOrigin = tr.endpos; data.m_vNormal = vForward; data.m_nEntIndex = 0; #endif //DispatchEffect( "BoltImpact", data ); UTIL_ImpactTrace( &tr, DMG_BULLET ); AddEffects( EF_NODRAW ); SetTouch( NULL ); //KillEffects(); SetThink( &CASW_Shotgun_Pellet_Predicted::SUB_Remove ); SetNextThink( gpGlobals->curtime + 2.0f ); // Shoot some sparks #ifdef GAME_DLL if ( UTIL_PointContents( GetAbsOrigin(), CONTENTS_WATER ) != CONTENTS_WATER) { g_pEffects->Sparks( GetAbsOrigin() ); } #endif } else { // Put a mark unless we've hit the sky if ( ( tr.surface.flags & SURF_SKY ) == false ) { UTIL_ImpactTrace( &tr, DMG_BULLET ); } //KillEffects(); //UTIL_Remove( this ); //Release(); SetThink( &CASW_Shotgun_Pellet_Predicted::SUB_Remove ); SetNextThink( gpGlobals->curtime ); } } }
void CGETKnife::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) { // Call the baseclass first so we don't interfere with the normal running of things BaseClass::VPhysicsCollision( index, pEvent ); // Grab what we hit CBaseEntity *pOther = pEvent->pEntities[!index]; if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( !PassServerEntityFilter( this, pOther) ) return; if ( !g_pGameRules->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; trace_t tr; CollisionEventToTrace( index, pEvent, tr ); Vector vecAiming = pEvent->preVelocity[index]; VectorNormalize( vecAiming ); if ( pOther->m_takedamage != DAMAGE_NO && (pOther->IsPlayer() || pOther->IsNPC()) ) { ClearMultiDamage(); CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), GetDamage(), DMG_SLASH | DMG_NEVERGIB ); CalculateMeleeDamageForce( &dmgInfo, vecAiming, tr.endpos, TKNIFE_FORCE_SCALE ); dmgInfo.SetDamagePosition( tr.endpos ); if ( this->GetOwnerEntity() && this->GetOwnerEntity()->IsPlayer() ) { CBasePlayer *pPlayer = ToBasePlayer( this->GetOwnerEntity() ); dmgInfo.SetWeapon( pPlayer->Weapon_OwnsThisType( "weapon_throwing_knife" ) ); } pOther->DispatchTraceAttack( dmgInfo, vecAiming, &tr ); ApplyMultiDamage(); PhysCallbackSetVelocity( pEvent->pObjects[index], vec3_origin ); SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); } else { if ( pOther->IsWorld() ) { // We hit the world, we have to check if this is sky trace_t tr2; Vector origin; pEvent->pInternalData->GetContactPoint( origin ); UTIL_TraceLine( origin, origin + (vecAiming * 4), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr2 ); if ( tr2.surface.flags & SURF_SKY ) { // We hit sky, remove us NOW SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); return; } } m_bInAir = false; CollisionProp()->UseTriggerBounds( true, 24 ); g_PostSimulationQueue.QueueCall( this, &CBaseEntity::SetOwnerEntity, (CBaseEntity*)NULL ); // const CBaseEntity *host = te->GetSuppressHost(); // te->SetSuppressHost( NULL ); // StopParticleEffects( this ); // te->SetSuppressHost( (CBaseEntity*)host ); SetTouch( &CGETKnife::PickupTouch ); SetThink( &CGETKnife::RemoveThink ); g_PostSimulationQueue.QueueCall(this, &CBaseEntity::SetCollisionGroup, COLLISION_GROUP_DROPPEDWEAPON); SetNextThink( gpGlobals->curtime + 10.0f ); } }
void CGETKnife::DamageTouch( CBaseEntity *pOther ) { if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( !PassServerEntityFilter( this, pOther) ) return; if ( !g_pGameRules->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; if (!pOther->IsPlayer() && !pOther->IsNPC()) return; Vector vecAiming; VPhysicsGetObject()->GetVelocity( &vecAiming, NULL ); VectorNormalize( vecAiming ); trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + (vecAiming * 24), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); // We didn't hit the player again with our damage cast. Do a cast to the player's center to get a proper hit. if (tr.m_pEnt != pOther) { Vector TargetVec = pOther->GetAbsOrigin(); TargetVec.z = min(GetAbsOrigin().z, pOther->EyePosition().z); //Make sure we don't cast over their head. UTIL_TraceLine(GetAbsOrigin(), pOther->GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); } // TEMPORARY DEBUGGING PURPOSES // DebugDrawLine( tr.startpos, tr.endpos, 0, 255, 0, true, 5.0f ); // debugoverlay->AddSweptBoxOverlay( tr.startpos, tr.endpos, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), GetAbsAngles(), 0, 0, 255, 100, 5.0f ); // END TEMPORARY // If our target can take damage and the trace actually hit our target if ( pOther->m_takedamage != DAMAGE_NO && tr.fraction < 1.0f && tr.m_pEnt == pOther ) { ClearMultiDamage(); CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), GetDamage(), DMG_SLASH | DMG_NEVERGIB ); CalculateMeleeDamageForce( &dmgInfo, vecAiming, tr.endpos, TKNIFE_FORCE_SCALE ); dmgInfo.SetDamagePosition( tr.endpos ); if ( this->GetOwnerEntity() && this->GetOwnerEntity()->IsPlayer() ) { CBasePlayer *pPlayer = ToBasePlayer( this->GetOwnerEntity() ); dmgInfo.SetWeapon( pPlayer->Weapon_OwnsThisType( "weapon_knife_throwing" ) ); } pOther->DispatchTraceAttack( dmgInfo, vecAiming, &tr ); ApplyMultiDamage(); SetAbsVelocity( vec3_origin ); SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); } }
bool CNPC_Controller::OverrideMove( float flInterval ) { if (m_flGroundSpeed == 0) { m_flGroundSpeed = 100; } // ---------------------------------------------- // Select move target // ---------------------------------------------- CBaseEntity *pMoveTarget = NULL; if (GetTarget() != NULL ) { pMoveTarget = GetTarget(); } else if (GetEnemy() != NULL ) { pMoveTarget = GetEnemy(); } // ---------------------------------------------- // Select move target position // ---------------------------------------------- Vector vMoveTargetPos(0,0,0); if (GetTarget()) { vMoveTargetPos = GetTarget()->GetAbsOrigin(); } else if (GetEnemy() != NULL) { vMoveTargetPos = GetEnemy()->GetAbsOrigin(); } // ----------------------------------------- // See if we can fly there directly // ----------------------------------------- if (pMoveTarget /*|| HaveInspectTarget()*/) { trace_t tr; if (pMoveTarget) { UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, pMoveTarget, GetCollisionGroup(), &tr); } else { UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, &tr); } /* float fTargetDist = (1-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length(); if (fTargetDist > 50) { //SetCondition( COND_SCANNER_FLY_BLOCKED ); } else { //SetCondition( COND_SCANNER_FLY_CLEAR ); } */ } // ----------------------------------------------------------------- // If I have a route, keep it updated and move toward target // ------------------------------------------------------------------ if (GetNavigator()->IsGoalActive()) { if ( OverridePathMove( flInterval ) ) return true; } else { //do nothing Stop(); TaskComplete(); } return true; }
void CNPC_Dog::SetPlayerAvoidState( void ) { bool bIntersectingBoneFollowers = false; bool bIntersectingNPCBox = false; Vector vNothing; GetSequenceLinearMotion( GetSequence(), &vNothing ); bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); //If we are coming out of a script, check if we are stuck inside the player. if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) { trace_t trace; Vector vMins, vMaxs; Vector vWorldMins, vWorldMaxs; Vector vPlayerMins, vPlayerMaxs; physfollower_t *pBone; int i; #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); #else CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pLocalPlayer ) { vWorldMins = WorldAlignMins(); vWorldMaxs = WorldAlignMaxs(); vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(); vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs(); // check if the player intersects the bounds of any of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) { bIntersectingBoneFollowers = true; break; } } } bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs ); if ( ai_debug_avoidancebounds.GetBool() ) { int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0; NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 ); // draw the bounds of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0; NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); } } } } } m_bPlayerAvoidState = ShouldPlayerAvoid(); m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers; if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) { if ( bIntersectingNPCBox == true ) { SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); } else { SetCollisionGroup( COLLISION_GROUP_NPC ); } if ( bIntersectingBoneFollowers == true ) { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR ); } else { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC ); } } }
//----------------------------------------------------------------------------- // Purpose: Should objects repel players on the same team //----------------------------------------------------------------------------- bool CBaseObject::ShouldPlayersAvoid( void ) { return ( GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT ); }
void CRagdollProp::VPhysicsUpdate( IPhysicsObject *pPhysics ) { if ( m_lastUpdateTickCount == (unsigned int)gpGlobals->tickcount ) return; m_lastUpdateTickCount = gpGlobals->tickcount; //NetworkStateChanged(); matrix3x4_t boneToWorld[MAXSTUDIOBONES]; QAngle angles; Vector surroundingMins, surroundingMaxs; if ( m_ragdoll.pGroup->IsInErrorState() ) { RagdollSolveSeparation( m_ragdoll, this ); } int i; for ( i = 0; i < m_ragdoll.listCount; i++ ) { CBoneAccessor boneaccessor( boneToWorld ); RagdollGetBoneMatrix( m_ragdoll, boneaccessor, i ); Vector vNewPos; MatrixAngles( boneToWorld[m_ragdoll.boneIndex[i]], angles, vNewPos ); m_ragPos.Set( i, vNewPos ); m_ragAngles.Set( i, angles ); } // BUGBUG: Use the ragdollmins/maxs to do this instead of the collides m_allAsleep = RagdollIsAsleep( m_ragdoll ); // Don't scream after you've come to rest if ( m_allAsleep ) { m_strSourceClassName = NULL_STRING; } // Interactive debris converts back to debris when it comes to rest if ( m_allAsleep && GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetCollisionGroup( COLLISION_GROUP_DEBRIS ); RecheckCollisionFilter(); SetContextThink( NULL, gpGlobals->curtime, s_pDebrisContext ); } Vector vecFullMins, vecFullMaxs; vecFullMins = m_ragPos[0]; vecFullMaxs = m_ragPos[0]; for ( i = 0; i < m_ragdoll.listCount; i++ ) { Vector mins, maxs; matrix3x4_t update; m_ragdoll.list[i].pObject->GetPositionMatrix( &update ); TransformAABB( update, m_ragdollMins[i], m_ragdollMaxs[i], mins, maxs ); for ( int j = 0; j < 3; j++ ) { if ( mins[j] < vecFullMins[j] ) { vecFullMins[j] = mins[j]; } if ( maxs[j] > vecFullMaxs[j] ) { vecFullMaxs[j] = maxs[j]; } } } SetAbsOrigin( m_ragPos[0] ); SetAbsAngles( vec3_angle ); const Vector &vecOrigin = CollisionProp()->GetCollisionOrigin(); CollisionProp()->AddSolidFlags( FSOLID_FORCE_WORLD_ALIGNED ); CollisionProp()->SetSurroundingBoundsType( USE_COLLISION_BOUNDS_NEVER_VPHYSICS ); SetCollisionBounds( vecFullMins - vecOrigin, vecFullMaxs - vecOrigin ); CollisionProp()->MarkSurroundingBoundsDirty(); PhysicsTouchTriggers(); }