void CNPC_Dog::PrescheduleThink( void ) { BaseClass::PrescheduleThink(); if ( m_hPhysicsEnt ) { IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( pPhysObj && pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { m_hPhysicsEnt->SetOwnerEntity( NULL ); } } if ( m_flTimeToCatch < gpGlobals->curtime ) m_flTimeToCatch = 0.0f; if ( GetIdealActivity() == ACT_IDLE ) { if ( m_hPhysicsEnt && m_bHasObject == true ) { SetIdealActivity( (Activity)ACT_DOG_WAITING ); } } }
void CNPC_Portal_FloorTurret::InactiveThink( void ) { LaserOff(); RopesOff(); // Update our PVS state CheckPVSCondition(); SetNextThink( gpGlobals->curtime + 1.0f ); // Wake up if we're not on our side if ( !OnSide() && VPhysicsGetObject()->GetContactPoint( NULL, NULL ) && m_bEnabled ) { // Never return to life! SetCollisionGroup( COLLISION_GROUP_NONE ); //ReturnToLife(); } else { IPhysicsObject *pTurretPhys = VPhysicsGetObject(); if ( !(pTurretPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) && pTurretPhys->IsAsleep() ) SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ); else SetCollisionGroup( COLLISION_GROUP_NONE ); } }
bool CPhysicsNPCSolver::CheckTouching() { CAI_BaseNPC *pNPC = m_hNPC.Get(); if ( !pNPC ) return false; CBaseEntity *pPhysicsEnt = m_hEntity.Get(); if ( !pPhysicsEnt ) return false; IPhysicsObject *pPhysics = pPhysicsEnt->VPhysicsGetObject(); IPhysicsObject *pNPCPhysics = pNPC->VPhysicsGetObject(); if ( !pNPCPhysics || !pPhysics ) return false; IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); bool found = false; bool penetrate = false; while ( pSnapshot->IsValid() ) { IPhysicsObject *pOther = pSnapshot->GetObject(1); if ( pOther == pNPCPhysics ) { found = true; if ( IsContactOnNPCHead(pSnapshot, pPhysics, pNPC ) ) { penetrate = true; pSnapshot->MarkContactForDelete(); } break; } pSnapshot->NextFrictionData(); } pSnapshot->DeleteAllMarkedContacts( true ); pPhysics->DestroyFrictionSnapshot( pSnapshot ); // if the object is penetrating something, check to see if it's intersecting this NPC // if so, go ahead and switch over to penetration solver mode if ( !penetrate && (pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING) ) { penetrate = IsIntersecting(); } if ( penetrate ) { pPhysicsEnt->ClearNavIgnore(); BecomePenetrationSolver(); } return found; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CNPC_Stalker::IsValidEnemy( CBaseEntity *pEnemy ) { Class_T enemyClass = pEnemy->Classify(); if( enemyClass == CLASS_PLAYER || enemyClass == CLASS_PLAYER_ALLY || enemyClass == CLASS_PLAYER_ALLY_VITAL ) { // Don't get angry at these folks unless provoked. if( m_iPlayerAggression < STALKER_PLAYER_AGGRESSION ) { return false; } } if( enemyClass == CLASS_BULLSEYE && pEnemy->GetParent() ) { // This bullseye is in heirarchy with something. If that // something is held by the physcannon, this bullseye is // NOT a valid enemy. IPhysicsObject *pPhys = pEnemy->GetParent()->VPhysicsGetObject(); if( pPhys && (pPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) { return false; } } if( GetEnemy() && HasCondition(COND_SEE_ENEMY) ) { // Short attention span. If I have an enemy, stick with it. if( GetEnemy() != pEnemy ) { return false; } } if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) && !HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) { return false; } if( !FVisible(pEnemy) ) { // Don't take an enemy you can't see. Since stalkers move way too slowly to // establish line of fire, usually an enemy acquired by means other than // the Stalker's own eyesight will always get away while the stalker plods // slowly to their last known position. So don't take enemies you can't see. return false; } return BaseClass::IsValidEnemy(pEnemy); }
// player pickup utility routine void Pickup_ForcePlayerToDropThisObject( CBaseEntity *pTarget ) { if ( pTarget == NULL ) return; IPhysicsObject *pPhysics = pTarget->VPhysicsGetObject(); if ( pPhysics == NULL ) return; if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); pPlayer->ForceDropOfCarriedPhysObjects( pTarget ); } }
//----------------------------------------------------------------------------- // Purpose: The turret has been tipped over and will thrash for awhile //----------------------------------------------------------------------------- void CNPC_Portal_FloorTurret::HeldThink( void ) { PreThink( (turretState_e)PORTAL_TURRET_PICKUP ); SetNextThink( gpGlobals->curtime + 0.05f ); SetEnemy( NULL ); StudioFrameAdvance(); IPhysicsObject *pTurretPhys = VPhysicsGetObject(); // If we're not held anymore, stop thrashing if ( !(pTurretPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) { m_fNextTalk = gpGlobals->curtime + 1.25f; if ( m_lifeState == LIFE_ALIVE ) SetThink( &CNPC_FloorTurret::ActiveThink ); else SetThink( &CNPC_FloorTurret::InactiveThink ); } LaserOn(); RopesOn(); //See if we should continue to thrash if ( !IsDissolving() ) { if ( m_flShotTime < gpGlobals->curtime ) { SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); DryFire(); m_flShotTime = gpGlobals->curtime + RandomFloat( 0.25f, 0.75f ); m_vecGoalAngles.x = GetAbsAngles().x + RandomFloat( -15, 15 ); m_vecGoalAngles.y = GetAbsAngles().y + RandomFloat( -40, 40 ); } UpdateFacing(); } }
float CalculateObjectStress( IPhysicsObject *pObject, CBaseEntity *pInputOwnerEntity, vphysics_objectstress_t *pOutput ) { CUtlVector< CBaseEntity * > pObjectList; CUtlVector< Vector > objectForce; bool hasLargeObject = false; // add a slot for static objects pObjectList.AddToTail( NULL ); objectForce.AddToTail( vec3_origin ); // add a slot for friendly objects pObjectList.AddToTail( NULL ); objectForce.AddToTail( vec3_origin ); CBaseCombatCharacter *pBCC = pInputOwnerEntity->MyCombatCharacterPointer(); IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); float objMass = pObject->GetMass(); while ( pSnapshot->IsValid() ) { float force = pSnapshot->GetNormalForce(); if ( force > 0.0f ) { IPhysicsObject *pOther = pSnapshot->GetObject(1); CBaseEntity *pOtherEntity = static_cast<CBaseEntity *>(pOther->GetGameData()); if ( !pOtherEntity ) { // object was just deleted, but we still have a contact point this frame... // just assume it came from the world. pOtherEntity = GetWorldEntity(); } CBaseEntity *pOtherOwner = pOtherEntity; if ( pOtherEntity->GetOwnerEntity() ) { pOtherOwner = pOtherEntity->GetOwnerEntity(); } int outIndex = 0; if ( !pOther->IsMoveable() ) { outIndex = 0; } // NavIgnored objects are often being pushed by a friendly else if ( pBCC && (pBCC->IRelationType( pOtherOwner ) == D_LI || pOtherEntity->IsNavIgnored()) ) { outIndex = 1; } // player held objects do no stress else if ( pOther->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { outIndex = 1; } else { if ( pOther->GetMass() >= VPHYSICS_LARGE_OBJECT_MASS ) { if ( pInputOwnerEntity->GetGroundEntity() != pOtherEntity) { hasLargeObject = true; } } // moveable, non-friendly // aggregate contacts over each object to avoid greater stress in multiple contact cases // NOTE: Contacts should be in order, so this shouldn't ever search, but just in case outIndex = pObjectList.Count(); for ( int i = pObjectList.Count()-1; i >= 2; --i ) { if ( pObjectList[i] == pOtherOwner ) { outIndex = i; break; } } if ( outIndex == pObjectList.Count() ) { pObjectList.AddToTail( pOtherOwner ); objectForce.AddToTail( vec3_origin ); } } if ( outIndex != 0 && pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && !IsPhysicallyControlled(pOtherEntity, pOther) ) { // UNDONE: Test this! This is to remove any shadow/shadow stress. The game should handle this with blocked/damage force = 0.0f; } Vector normal; pSnapshot->GetSurfaceNormal( normal ); objectForce[outIndex] += normal * force; } pSnapshot->NextFrictionData(); } pObject->DestroyFrictionSnapshot( pSnapshot ); pSnapshot = NULL; // clear out all friendly force objectForce[1].Init(); float sum = 0; Vector negativeForce = vec3_origin; Vector positiveForce = vec3_origin; Assert( pObjectList.Count() == objectForce.Count() ); for ( int objectIndex = pObjectList.Count()-1; objectIndex >= 0; --objectIndex ) { sum += objectForce[objectIndex].Length(); for ( int i = 0; i < 3; i++ ) { if ( objectForce[objectIndex][i] < 0 ) { negativeForce[i] -= objectForce[objectIndex][i]; } else { positiveForce[i] += objectForce[objectIndex][i]; } } } // "external" stress is two way (something pushes on the object and something else pushes back) // so the set of minimum values per component are the projections of the two-way force // "internal" stress is one way (the object is pushing against something OR something pushing back) // the momentum must have come from inside the object (gravity, controller, etc) Vector internalForce = vec3_origin; Vector externalForce = vec3_origin; for ( int i = 0; i < 3; i++ ) { if ( negativeForce[i] < positiveForce[i] ) { internalForce[i] = positiveForce[i] - negativeForce[i]; externalForce[i] = negativeForce[i]; } else { internalForce[i] = negativeForce[i] - positiveForce[i]; externalForce[i] = positiveForce[i]; } } // sum is kg in / s Vector gravVector; physenv->GetGravity( &gravVector ); float gravity = gravVector.Length(); if ( pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && pObject->IsMoveable() ) { Vector lastVel; lastVel.Init(); if ( pObject->GetShadowController() ) { pObject->GetShadowController()->GetLastImpulse( &lastVel ); } else { if ( ( pObject->GetCallbackFlags() & CALLBACK_IS_PLAYER_CONTROLLER ) ) { CBasePlayer *pPlayer = ToBasePlayer( pInputOwnerEntity ); IPhysicsPlayerController *pController = pPlayer ? pPlayer->GetPhysicsController() : NULL; if ( pController ) { pController->GetLastImpulse( &lastVel ); } } } // Work in progress... // Peek into the controller for this object. Look at the input velocity and make sure it's all // accounted for in the computed stress. If not, redistribute external to internal as it's // probably being reflected in a way we can't measure here. float inputLen = lastVel.Length() * (1.0f / physenv->GetSimulationTimestep()) * objMass; if ( inputLen > 0.0f ) { float internalLen = internalForce.Length(); if ( internalLen < inputLen ) { float ratio = internalLen / inputLen; Vector delta = internalForce * (1.0f - ratio); internalForce += delta; float deltaLen = delta.Length(); sum -= deltaLen; float extLen = VectorNormalize(externalForce) - deltaLen; if ( extLen < 0 ) { extLen = 0; } externalForce *= extLen; } } } float invGravity = gravity; if ( invGravity <= 0 ) { invGravity = 1.0f; } else { invGravity = 1.0f / invGravity; } sum *= invGravity; internalForce *= invGravity; externalForce *= invGravity; if ( !pObject->IsMoveable() ) { // the above algorithm will see almost all force as internal if the object is not moveable // (it doesn't push on anything else, so nothing is reciprocated) // exceptions for friction of a single other object with multiple contact points on this object // But the game wants to see it all as external because obviously the object can't move, so it can't have // internal stress externalForce = internalForce; internalForce.Init(); if ( !pObject->IsStatic() ) { sum += objMass; } } else { // assume object is at rest if ( sum > objMass ) { sum = objMass + (sum-objMass) * 0.5; } } if ( pOutput ) { pOutput->exertedStress = internalForce.Length(); pOutput->receivedStress = externalForce.Length(); pOutput->hasNonStaticStress = pObjectList.Count() > 2 ? true : false; pOutput->hasLargeObjectContact = hasLargeObject; } // sum is now kg return sum; }
void CNPC_Dog::PullObject( bool bMantain ) { if ( m_hPhysicsEnt == NULL ) { TaskFail( "Ack! No Phys Object!"); return; } IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( pPhysObj == NULL ) { TaskFail( "Pulling object with no Phys Object?!" ); return; } if( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { m_bHasObject = false; ClearBeams(); TaskFail("Player Grabbed Ball"); return; } CreateBeams(); Vector vGunPos; GetAttachment( m_iPhysGunAttachment, vGunPos ); float flDistance = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ).Length(); if ( bMantain == false ) { if ( flDistance <= DOG_CATCH_DISTANCE ) { m_hPhysicsEnt->SetOwnerEntity( this ); GetNavigator()->StopMoving(); //Fire Output! m_OnPickup.FireOutput( this, this ); m_bHasObject = true; ClearBeams(); TaskComplete(); return; } } Vector vDir = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ); Vector vCurrentVel; float flCurrentVel; AngularImpulse vCurrentAI; pPhysObj->GetVelocity( &vCurrentVel, &vCurrentAI ); flCurrentVel = vCurrentVel.Length(); VectorNormalize( vCurrentVel ); VectorNormalize( vDir ); float flVelMod = DOG_PULL_VELOCITY_MOD; if ( bMantain == true ) flVelMod *= 2; vCurrentVel = vCurrentVel * flCurrentVel * flVelMod; vCurrentAI = vCurrentAI * DOG_PULL_ANGULARIMP_MOD; pPhysObj->SetVelocity( &vCurrentVel, &vCurrentAI ); vDir = vDir * flDistance * (DOG_PULL_TO_GUN_VEL_MOD * 2); Vector vAngle( 0, 0, 0 ); pPhysObj->AddVelocity( &vDir, &vAngle ); }
//--------------------------------------------------------- //--------------------------------------------------------- void CNPC_Dog::RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_DOG_PICKUP_ITEM: { PullObject( false ); } break; case TASK_DOG_GET_PATH_TO_PHYSOBJ: { //Check this cause our object might have been deleted. if ( m_hPhysicsEnt == NULL ) FindPhysicsObject( NULL ); //And if we still can't find anything, then just go away. if ( m_hPhysicsEnt == NULL ) { TaskFail( "Can't find an object I like!" ); return; } IPhysicsObject *pPhysicsObject = m_hPhysicsEnt->VPhysicsGetObject(); Vector vecGoalPos; Vector vecDir; vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); VectorNormalize(vecDir); vecDir.z = 0; if ( m_hPhysicsEnt->GetOwnerEntity() == NULL ) m_hPhysicsEnt->SetOwnerEntity( this ); if ( pPhysicsObject ) pPhysicsObject->RecheckCollisionFilter(); vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); bool bBuiltRoute = false; //If I'm near my goal, then just walk to it. Activity aActivity = ACT_RUN; if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) aActivity = ACT_WALK; bBuiltRoute = GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); if ( bBuiltRoute == true ) TaskComplete(); else { m_flTimeToCatch = gpGlobals->curtime + 0.1; m_flNextRouteTime = gpGlobals->curtime + 0.3; m_flNextSwat = gpGlobals->curtime + 0.1; if ( m_hUnreachableObjects.Find( m_hPhysicsEnt ) == -1 ) m_hUnreachableObjects.AddToTail( m_hPhysicsEnt ); m_hPhysicsEnt = NULL; GetNavigator()->ClearGoal(); } } break; case TASK_WAIT: { if ( IsWaitFinished() ) { TaskComplete(); } if ( m_hPhysicsEnt ) { if ( m_bHasObject == false ) { GetMotor()->SetIdealYawToTarget( m_hPhysicsEnt->GetAbsOrigin() ); GetMotor()->UpdateYaw(); } } break; } case TASK_DOG_LAUNCH_ITEM: if( IsActivityFinished() ) { if ( m_hPhysicsEnt ) { m_hPhysicsEnt->SetOwnerEntity( NULL ); } TaskComplete(); } break; case TASK_DOG_WAIT_FOR_TARGET_TO_FACE: { if ( CanTargetSeeMe() ) TaskComplete(); } break; case TASK_WAIT_FOR_MOVEMENT: { if ( GetState() == NPC_STATE_SCRIPT || IsInAScript() ) { BaseClass::RunTask( pTask ); return; } if ( m_hPhysicsEnt != NULL ) { IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( !pPhysObj ) { Warning( "npc_dog TASK_WAIT_FOR_MOVEMENT with NULL m_hPhysicsEnt->VPhysicsGetObject\n" ); } if ( pPhysObj && pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) TaskFail( "Player picked it up!" ); //If the object is moving then my old goal might not be valid //cancel the schedule and make it restart again in a bit. if ( pPhysObj && pPhysObj->IsAsleep() == false && GetNavigator()->IsGoalActive() == false ) { Vector vecGoalPos; Vector vecDir; vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); VectorNormalize(vecDir); vecDir.z = 0; vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); GetNavigator()->ClearGoal(); float flDistance = (vecGoalPos - GetLocalOrigin()).Length(); //If I'm near my goal, then just walk to it. Activity aActivity = ACT_RUN; if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) aActivity = ACT_WALK; GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); if ( flDistance <= DOG_PHYSOBJ_MOVE_TO_DIST ) { TaskComplete(); GetNavigator()->StopMoving(); } } } BaseClass::RunTask( pTask ); } break; case TASK_DOG_WAIT_FOR_OBJECT: { if ( m_hPhysicsEnt != NULL ) { if ( FVisible( m_hPhysicsEnt ) == false ) { m_flTimeToCatch = 0.0f; ClearBeams(); TaskFail( "Lost sight of the object!" ); m_hPhysicsEnt->SetOwnerEntity( NULL ); return; } m_hPhysicsEnt->SetOwnerEntity( this ); Vector vForward; AngleVectors( GetAbsAngles(), &vForward ); Vector vGunPos; GetAttachment( m_iPhysGunAttachment, vGunPos ); Vector vToObject = m_hPhysicsEnt->WorldSpaceCenter() - vGunPos; float flDistance = vToObject.Length(); VectorNormalize( vToObject ); SetAim( m_hPhysicsEnt->WorldSpaceCenter() - GetAbsOrigin() ); #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(this); #else CBasePlayer *pPlayer = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI float flDistanceToPlayer = flDistance; if ( pPlayer ) { flDistanceToPlayer = (pPlayer->GetAbsOrigin() - m_hPhysicsEnt->WorldSpaceCenter()).Length(); } IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( !pPhysObj ) { Warning( "npc_dog: TASK_DOG_WAIT_FOR_OBJECT with m_hPhysicsEnt->VPhysicsGetObject == NULL\n" ); } if ( pPhysObj && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) && flDistanceToPlayer > ( flDistance * 2 ) ) { if ( m_flTimeToPull <= gpGlobals->curtime ) { Vector vCurrentVel; float flCurrentVel; AngularImpulse vCurrentAI; pPhysObj->GetVelocity( &vCurrentVel, &vCurrentAI ); flCurrentVel = vCurrentVel.Length(); VectorNormalize( vCurrentVel ); if ( pPhysObj && flDistance <= DOG_PULL_DISTANCE ) { Vector vDir = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ); VectorNormalize( vDir ); vCurrentVel = vCurrentVel * ( flCurrentVel * DOG_PULL_VELOCITY_MOD ); vCurrentAI = vCurrentAI * DOG_PULL_ANGULARIMP_MOD; pPhysObj->SetVelocity( &vCurrentVel, &vCurrentAI ); vDir = vDir * flDistance * DOG_PULL_TO_GUN_VEL_MOD; Vector vAngle( 0, 0, 0 ); pPhysObj->AddVelocity( &vDir, &vAngle ); CreateBeams(); } float flDot = DotProduct( vCurrentVel, vForward ); if ( flDistance >= DOG_PULL_DISTANCE && flDistance <= ( DOG_PULL_DISTANCE * 2 ) && flDot > -0.3 ) { if ( pPhysObj->IsAsleep() == false && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) { Vector vecGoalPos; Vector vecDir; vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); VectorNormalize(vecDir); vecDir.z = 0; vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); GetNavigator()->ClearGoal(); //If I'm near my goal, then just walk to it. Activity aActivity = ACT_RUN; if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) aActivity = ACT_WALK; GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); } } } } float flDirDot = DotProduct( vToObject, vForward ); if ( flDirDot < 0.2 ) { GetMotor()->SetIdealYawToTarget( m_hPhysicsEnt->GetAbsOrigin() ); GetMotor()->UpdateYaw(); } if ( m_flTimeToCatch < gpGlobals->curtime && m_bDoWaitforObjectBehavior == false ) { m_hPhysicsEnt->SetOwnerEntity( NULL ); m_flTimeToCatch = 0.0f; ClearBeams(); TaskFail( "Done waiting!" ); } else if ( pPhysObj && ( flDistance <= DOG_CATCH_DISTANCE && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) ) { AngularImpulse vZero( 0, 0, 0 ); pPhysObj->SetVelocity( &vec3_origin, &vZero ); GetNavigator()->StopMoving(); //Fire Output! m_OnCatch.FireOutput( this, this ); m_bHasObject = true; ClearBeams(); TaskComplete(); } } else { GetNavigator()->StopMoving(); ClearBeams(); TaskFail("No Physics Object!"); } } break; case TASK_DOG_CATCH_OBJECT: if( IsActivityFinished() ) { m_flTimeToCatch = 0.0f; TaskComplete(); } break; default: BaseClass::RunTask( pTask ); break; } }
bool CNPC_Dog::FindPhysicsObject( const char *pPickupName, CBaseEntity *pIgnore ) { CBaseEntity *pEnt = NULL; CBaseEntity *pNearest = NULL; float flDist; IPhysicsObject *pPhysObj = NULL; float flNearestDist = 99999; if ( pPickupName != NULL && strlen( pPickupName ) > 0 ) { pEnt = gEntList.FindEntityByName( NULL, pPickupName ); if ( m_hUnreachableObjects.Find( pEnt ) == -1 ) { m_bHasObject = false; m_hPhysicsEnt = pEnt; return true; } } while ( ( pEnt = gEntList.FindEntityByClassname( pEnt, "prop_physics" ) ) != NULL ) { //We don't want this one. if ( pEnt == pIgnore ) continue; if ( m_hUnreachableObjects.Find( pEnt ) != -1 ) continue; pPhysObj = pEnt->VPhysicsGetObject(); if( pPhysObj == NULL ) continue; if ( pPhysObj->GetMass() > DOG_MAX_THROW_MASS ) continue; Vector center = pEnt->WorldSpaceCenter(); flDist = UTIL_DistApprox2D( GetAbsOrigin(), center ); vcollide_t *pCollide = modelinfo->GetVCollide( pEnt->GetModelIndex() ); if ( pCollide == NULL ) continue; if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) continue; if ( pPhysObj->IsMoveable() == false ) continue; if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_DEBRIS || pEnt->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) continue; if ( center.z > EyePosition().z ) continue; if ( flDist >= flNearestDist ) continue; if ( FVisible( pEnt ) == false ) continue; pNearest = pEnt; flNearestDist = flDist; } m_bHasObject = false; m_hPhysicsEnt = pNearest; if ( dog_debug.GetBool() == true ) { if ( pNearest ) NDebugOverlay::Box( pNearest->WorldSpaceCenter(), pNearest->CollisionProp()->OBBMins(), pNearest->CollisionProp()->OBBMaxs(), 255, 0, 255, true, 3 ); } if( m_hPhysicsEnt == NULL ) { return false; } else { return true; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAntlionGrub::GrubTouch( CBaseEntity *pOther ) { // We can be squished by the player, Vort, or flying heavy things. IPhysicsObject *pPhysOther = pOther->VPhysicsGetObject(); // bool bThrown = ( pTarget->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_WAS_THROWN ) != 0; if ( pOther->IsPlayer() || FClassnameIs(pOther,"npc_vortigaunt") || ( pPhysOther && (pPhysOther->GetGameFlags() & FVPHYSICS_WAS_THROWN )) ) { m_OnAgitated.FireOutput( pOther, pOther ); Squash( pOther, true, true ); } }
void CNPC_Portal_FloorTurret::StartTouch( CBaseEntity *pOther ) { BaseClass::StartTouch( pOther ); IPhysicsObject *pOtherPhys = pOther->VPhysicsGetObject(); if ( !pOtherPhys ) return; if ( !m_pMotionController ) return; if ( m_pMotionController->Enabled() ) { m_pMotionController->Suspend( 2.0f ); IPhysicsObject *pTurretPhys = VPhysicsGetObject(); if ( !pOther->IsPlayer() && pOther->GetMoveType() == MOVETYPE_VPHYSICS && !(pTurretPhys && ((pTurretPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) != 0)) ) { // Get a lateral impulse Vector vVelocityImpulse = GetAbsOrigin() - pOther->GetAbsOrigin(); vVelocityImpulse.z = 0.0f; if ( vVelocityImpulse.IsZero() ) { vVelocityImpulse.x = 1.0f; vVelocityImpulse.y = 1.0f; } VectorNormalize( vVelocityImpulse ); // If impulse is too much along the forward or back axis, skew it Vector vTurretForward, vTurretRight; GetVectors( &vTurretForward, &vTurretRight, NULL ); float fForwardDotImpulse = vTurretForward.Dot( vVelocityImpulse ); if ( fForwardDotImpulse > 0.7f || fForwardDotImpulse < -0.7f ) { vVelocityImpulse += vTurretRight; VectorNormalize( vVelocityImpulse ); } Vector vAngleImpulse( ( vTurretRight.Dot( vVelocityImpulse ) < 0.0f ) ? ( -1.6f ) : ( 1.6f ), RandomFloat( -0.5f, 0.5f ), RandomFloat( -0.5f, 0.5f ) ); vVelocityImpulse *= TURRET_FLOOR_PHYSICAL_FORCE_MULTIPLIER; vAngleImpulse *= TURRET_FLOOR_PHYSICAL_FORCE_MULTIPLIER; pTurretPhys->AddVelocity( &vVelocityImpulse, &vAngleImpulse ); // Check if another turret is hitting us CNPC_Portal_FloorTurret *pPortalFloor = dynamic_cast<CNPC_Portal_FloorTurret*>( pOther ); if ( pPortalFloor && pPortalFloor->m_lifeState == LIFE_ALIVE ) { Vector vTurretVelocity, vOtherVelocity; pTurretPhys->GetVelocity( &vTurretVelocity, NULL ); pOtherPhys->GetVelocity( &vOtherVelocity, NULL ); // If it's moving faster if ( vOtherVelocity.LengthSqr() > vTurretVelocity.LengthSqr() ) { // Make the turret falling onto this one talk pPortalFloor->EmitSound( GetTurretTalkName( PORTAL_TURRET_COLLIDE ) ); pPortalFloor->m_fNextTalk = gpGlobals->curtime + 1.2f; pPortalFloor->m_bDelayTippedTalk = true; // Delay out potential tipped talking so we can here the other turret talk m_fNextTalk = gpGlobals->curtime + 0.6f; m_bDelayTippedTalk = true; } } if ( pPortalFloor && m_bEnabled && m_bLaserOn && !m_bOutOfAmmo ) { // Award friendly fire achievement if we're a live turret being knocked over by another turret. IGameEvent *event = gameeventmanager->CreateEvent( "turret_hit_turret" ); if ( event ) { gameeventmanager->FireEvent( event ); } } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFGameMovement::CheckWaterJump( void ) { Vector flatforward; Vector flatvelocity; float curspeed; // Jump button down? bool bJump = ( ( mv->m_nButtons & IN_JUMP ) != 0 ); Vector forward, right; AngleVectors( mv->m_vecViewAngles, &forward, &right, NULL ); // Determine movement angles // Already water jumping. if (player->m_flWaterJumpTime) return; // Don't hop out if we just jumped in if (mv->m_vecVelocity[2] < -180) return; // only hop out if we are moving up // See if we are backing up flatvelocity[0] = mv->m_vecVelocity[0]; flatvelocity[1] = mv->m_vecVelocity[1]; flatvelocity[2] = 0; // Must be moving curspeed = VectorNormalize( flatvelocity ); #if 1 // Copy movement amounts float fmove = mv->m_flForwardMove; float smove = mv->m_flSideMove; for ( int iAxis = 0; iAxis < 2; ++iAxis ) { flatforward[iAxis] = forward[iAxis] * fmove + right[iAxis] * smove; } #else // see if near an edge flatforward[0] = forward[0]; flatforward[1] = forward[1]; #endif flatforward[2] = 0; VectorNormalize( flatforward ); // Are we backing into water from steps or something? If so, don't pop forward if ( curspeed != 0.0 && ( DotProduct( flatvelocity, flatforward ) < 0.0 ) && !bJump ) return; Vector vecStart; // Start line trace at waist height (using the center of the player for this here) vecStart= mv->GetAbsOrigin() + (GetPlayerMins() + GetPlayerMaxs() ) * 0.5; Vector vecEnd; VectorMA( vecStart, TF_WATERJUMP_FORWARD/*tf_waterjump_forward.GetFloat()*/, flatforward, vecEnd ); trace_t tr; TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( tr.fraction < 1.0 ) // solid at waist { IPhysicsObject *pPhysObj = tr.m_pEnt->VPhysicsGetObject(); if ( pPhysObj ) { if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) return; } vecStart.z = mv->GetAbsOrigin().z + player->GetViewOffset().z + WATERJUMP_HEIGHT; VectorMA( vecStart, TF_WATERJUMP_FORWARD/*tf_waterjump_forward.GetFloat()*/, flatforward, vecEnd ); VectorMA( vec3_origin, -50.0f, tr.plane.normal, player->m_vecWaterJumpVel ); TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( tr.fraction == 1.0 ) // open at eye level { // Now trace down to see if we would actually land on a standable surface. VectorCopy( vecEnd, vecStart ); vecEnd.z -= 1024.0f; TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); if ( ( tr.fraction < 1.0f ) && ( tr.plane.normal.z >= 0.7 ) ) { mv->m_vecVelocity[2] = TF_WATERJUMP_UP/*tf_waterjump_up.GetFloat()*/; // Push up mv->m_nOldButtons |= IN_JUMP; // Don't jump again until released player->AddFlag( FL_WATERJUMP ); player->m_flWaterJumpTime = 2000.0f; // Do this for 2 seconds } } } }