//----------------------------------------------------------------------------- // Purpose: Returns whether or not the template entities can fit if spawned. // Input : pBlocker - Returns blocker unless NULL. //----------------------------------------------------------------------------- bool CEnvEntityMaker::HasRoomToSpawn() { // Do we have a blocker from last time? if ( m_hCurrentBlocker ) { // If it hasn't moved, abort immediately if ( m_vecBlockerOrigin == m_hCurrentBlocker->GetAbsOrigin() ) { return false; } } // Check to see if there's enough room to spawn trace_t tr; UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin(), m_vecEntityMins, m_vecEntityMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt || tr.startsolid ) { // Store off our blocker to check later m_hCurrentBlocker = tr.m_pEnt; if ( m_hCurrentBlocker ) { m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); } return false; } return true; }
//----------------------------------------------------------------------------- // Purpose: Check to see if we should spawn another instance //----------------------------------------------------------------------------- void CEnvEntityMaker::CheckSpawnThink( void ) { SetNextThink( gpGlobals->curtime + 0.5f ); // Do we have an instance? if ( m_hCurrentInstance ) { // If Wait-For-Destruction is set, abort immediately if ( m_spawnflags & SF_ENTMAKER_WAITFORDESTRUCTION ) return; } // Do we have a blocker? if ( m_hCurrentBlocker ) { // If it hasn't moved, abort immediately if ( m_vecBlockerOrigin == m_hCurrentBlocker->GetAbsOrigin() ) return; } // Check to see if there's enough room to spawn trace_t tr; UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin(), m_vecEntityMins, m_vecEntityMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt || tr.startsolid ) { // Store off our blocker to check later m_hCurrentBlocker = tr.m_pEnt; if ( m_hCurrentBlocker ) { m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); } return; } // We're clear, now check to see if the player's looking if ( !(m_spawnflags & SF_ENTMAKER_IGNOREFACING) ) { for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex(i); if ( pPlayer ) { // Only spawn if the player's looking away from me Vector vLookDir = pPlayer->EyeDirection3D(); Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition(); VectorNormalize(vTargetDir); float fDotPr = DotProduct(vLookDir,vTargetDir); if ( fDotPr > 0 ) return; } } } // Clear, no player watching, so spawn! SpawnEntity(); }
void CNPC_GMan::RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_WAIT: // look at who I'm talking to if (m_flTalkTime > gpGlobals->curtime && m_hTalkTarget != NULL) { AddLookTarget( m_hTalkTarget->GetAbsOrigin(), 1.0, 2.0 ); } // look at player, but only if playing a "safe" idle animation else if (m_hPlayer != NULL && (GetSequence() == 0 || IsInC5A1()) ) { AddLookTarget( m_hPlayer->EyePosition(), 1.0, 3.0 ); } else { // Just center the head forward. Vector forward; GetVectors( &forward, NULL, NULL ); AddLookTarget( GetAbsOrigin() + forward * 12.0f, 1.0, 1.0 ); SetBoneController( 0, 0 ); } BaseClass::RunTask( pTask ); break; } SetBoneController( 0, 0 ); BaseClass::RunTask( pTask ); }
//------------------------------------------------------------------------------ // Purpose: //------------------------------------------------------------------------------ void CPointCommentaryNode::FinishCommentary( bool bBlendOut ) { CBasePlayer *pPlayer = GetCommentaryPlayer(); if ( !pPlayer ) return; // Fire off our postcommands if ( m_iszPostCommands != NULL_STRING ) { g_CommentarySystem.SetCommentaryConvarsChanging( true ); engine->ClientCommand( pPlayer->edict(), STRING(m_iszPostCommands) ); engine->ClientCommand( pPlayer->edict(), "commentary_cvarsnotchanging\n" ); } // Stop the commentary m_flFinishedTime = gpGlobals->curtime; if ( bBlendOut && m_hViewPositionMover ) { m_bActive = false; m_flPlaybackRate = 1.0; m_vecFinishOrigin = m_hViewPositionMover->GetAbsOrigin(); m_vecFinishAngles = m_hViewPositionMover->GetAbsAngles(); m_bPreventChangesWhileMoving = true; // We've moved away from the player's position. Move back to it before ending SetContextThink( &CPointCommentaryNode::UpdateViewPostThink, gpGlobals->curtime, s_pCommentaryUpdateViewThink ); return; } CleanupPostCommentary(); }
void CNPC_Zombine::ReleaseGrenade( Vector vPhysgunPos ) { if ( HasGrenade() == false ) return; Vector vDir = vPhysgunPos - m_hGrenade->GetAbsOrigin(); VectorNormalize( vDir ); Activity aActivity; Vector vForward, vRight; GetVectors( &vForward, &vRight, NULL ); float flDotForward = DotProduct( vForward, vDir ); float flDotRight = DotProduct( vRight, vDir ); bool bNegativeForward = false; bool bNegativeRight = false; if ( flDotForward < 0.0f ) { bNegativeForward = true; flDotForward = flDotForward * -1; } if ( flDotRight < 0.0f ) { bNegativeRight = true; flDotRight = flDotRight * -1; } if ( flDotRight > flDotForward ) { if ( bNegativeRight == true ) aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_WEST; else aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_EAST; } else { if ( bNegativeForward == true ) aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_BACK; else aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_FRONT; } AddGesture( aActivity ); DropGrenade( vec3_origin ); if ( IsSprinting() ) { StopSprint(); } else { Sprint(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_ScriptIntro::ClientThink( void ) { Assert( m_IntroData.m_Passes.Count() <= 2 ); if ( m_hCameraEntity ) { m_IntroData.m_vecCameraView = m_hCameraEntity->GetAbsOrigin(); m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->GetAbsAngles(); } CalculateFOV(); CalculateAlpha(); // Calculate the blend levels of each pass float flPerc = 1.0; if ( (m_flNextBlendTime - m_flBlendStartTime) != 0 ) { flPerc = clamp( (gpGlobals->curtime - m_flBlendStartTime) / (m_flNextBlendTime - m_flBlendStartTime), 0, 1 ); } // Detect when we're finished blending if ( flPerc >= 1.0 ) { if ( m_IntroData.m_Passes.Count() == 2 ) { // We're done blending m_IntroData.m_Passes[0].m_BlendMode = m_IntroData.m_Passes[1].m_BlendMode; m_IntroData.m_Passes[0].m_Alpha = 1.0; m_IntroData.m_Passes.Remove(1); //Msg("FINISHED BLEND.\n"); } return; } /* if ( m_flNextBlendTime >= gpGlobals->curtime ) { Msg("INTRO BLENDING: Blending from mode %d to %d.\n", m_IntroData.m_Passes[0].m_BlendMode, m_IntroData.m_Passes[1].m_BlendMode ); Msg(" curtime %.2f StartedAt %.2f FinishAt: %.2f\n", gpGlobals->curtime, m_flBlendStartTime, m_flNextBlendTime ); Msg(" Perc: %.2f\n", flPerc ); } */ if ( m_IntroData.m_Passes.Count() == 2 ) { m_IntroData.m_Passes[0].m_Alpha = 1.0 - flPerc; m_IntroData.m_Passes[1].m_Alpha = flPerc; } else { m_IntroData.m_Passes[0].m_Alpha = 1.0 - flPerc; } }
void CNPC_GMan :: RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_WAIT: // look at who I'm talking to if (m_flTalkTime > gpGlobals->curtime && m_hTalkTarget != NULL) { float yaw = VecToYaw(m_hTalkTarget->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; // turn towards vector SetBoneController( 0, yaw ); } // look at player, but only if playing a "safe" idle animation else if (m_hPlayer != NULL && GetSequence() == 0) { float yaw = VecToYaw(m_hPlayer->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; // turn towards vector SetBoneController( 0, yaw ); } else { SetBoneController( 0, 0 ); } BaseClass::RunTask( pTask ); break; } SetBoneController( 0, 0 ); BaseClass::RunTask( pTask ); }
//----------------------------------------------------------------------------- // Purpose: Called every frame //----------------------------------------------------------------------------- void CPointProximitySensor::Think( void ) { if ( m_hTargetEntity != NULL ) { Vector vecTestDir = ( m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin() ); float flDist = VectorNormalize( vecTestDir ); // If we're only interested in the distance along a vector, modify the length the accomodate that if ( HasSpawnFlags( SF_PROXIMITY_TEST_AGAINST_AXIS ) ) { Vector vecDir; GetVectors( &vecDir, NULL, NULL ); float flDot = DotProduct( vecTestDir, vecDir ); flDist *= fabs( flDot ); } m_Distance.Set( flDist, this, this ); SetNextThink( gpGlobals->curtime ); } }
//----------------------------------------------------------------------------- // Rules about which entities need to transmit along with me //----------------------------------------------------------------------------- void CAmbientGeneric::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) { // Ambient generics never transmit; this is just a way for us to ensure // the sound source gets transmitted; that's why we don't call pInfo->m_pTransmitEdict->Set if ( !m_hSoundSource || m_hSoundSource == this || !m_fActive ) return; // Don't bother sending the position of the source if we have to play everywhere if ( FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE ) ) return; Assert( pInfo->m_pClientEnt ); CBaseEntity *pClient = (CBaseEntity*)(pInfo->m_pClientEnt->GetUnknown()); if ( !pClient ) return; // Send the sound source if he's close enough if ( ( m_flMaxRadius < 0 ) || ( pClient->GetAbsOrigin().DistToSqr( m_hSoundSource->GetAbsOrigin() ) <= m_flMaxRadius * m_flMaxRadius ) ) { m_hSoundSource->SetTransmit( pInfo, false ); } }
//----------------------------------------------------------------------------- // Purpose: Spawn an instance of the entity //----------------------------------------------------------------------------- void CEnvEntityMaker::SpawnEntity( void ) { // Find our point_template CPointTemplate *pTemplate = dynamic_cast<CPointTemplate *>(gEntList.FindEntityByName( NULL, STRING(m_iszTemplate), NULL )); if ( !pTemplate ) { Warning( "env_entity_maker %s failed to spawn template %s.\n", GetEntityName(), STRING(m_iszTemplate) ); return; } // Spawn our template CUtlVector<CBaseEntity*> hNewEntities; if ( !pTemplate->CreateInstance( GetAbsOrigin(), GetAbsAngles(), &hNewEntities ) ) return; m_hCurrentInstance = hNewEntities[0]; // Assume it'll block us m_hCurrentBlocker = m_hCurrentInstance; m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); // Store off the mins & maxs the first time we spawn if ( m_vecEntityMins == vec3_origin ) { m_vecEntityMins = m_hCurrentInstance->WorldAlignMins(); m_vecEntityMaxs = m_hCurrentInstance->WorldAlignMaxs(); } // Fire our output m_pOutputOnSpawned.FireOutput( this, this ); // Start thinking if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN ) { SetThink( &CEnvEntityMaker::CheckSpawnThink ); SetNextThink( gpGlobals->curtime + 0.5f ); } }
void CPointEntityFinder::FindByDistance( void ) { m_hEntity = NULL; CBaseFilter *pFilter = m_hFilter.Get(); // go through each entity and determine whether it's closer or farther from the current entity. Pick according to Method selected. float flBestDist = 0; CBaseEntity *pEntity = gEntList.FirstEnt(); while ( pEntity ) { if ( FStrEq( STRING( pEntity->m_iClassname ), "worldspawn" ) || FStrEq( STRING( pEntity->m_iClassname ), "soundent" ) || FStrEq( STRING( pEntity->m_iClassname ), "player_manager" ) || FStrEq( STRING( pEntity->m_iClassname ), "bodyque" ) || FStrEq( STRING( pEntity->m_iClassname ), "ai_network" ) || pEntity == this || ( pFilter && !( pFilter->PassesFilter( this, pEntity ) ) ) ) { pEntity = gEntList.NextEnt( pEntity ); continue; } // if we have a reference entity, use that, otherwise, check against 'this' Vector vecStart; if ( m_hReference ) { vecStart = m_hReference->GetAbsOrigin(); } else { vecStart = GetAbsOrigin(); } // init m_hEntity with a valid entity. if (m_hEntity == NULL ) { m_hEntity = pEntity; flBestDist = ( pEntity->GetAbsOrigin() - vecStart ).LengthSqr(); } float flNewDist = ( pEntity->GetAbsOrigin() - vecStart ).LengthSqr(); switch ( m_FindMethod ) { case ( ENT_FIND_METHOD_NEAREST ): if ( flNewDist < flBestDist ) { m_hEntity = pEntity; flBestDist = flNewDist; } break; case ( ENT_FIND_METHOD_FARTHEST ): if ( flNewDist > flBestDist ) { m_hEntity = pEntity; flBestDist = flNewDist; } break; default: Assert( false ); break; } pEntity = gEntList.NextEnt( pEntity ); } }
//----------------------------------------------------------------------------- // Purpose: This takes the current place the NPC's trying to get to, figures out // what keys to press to get the vehicle to go there, and then sends // them to the vehicle. //----------------------------------------------------------------------------- void CNPC_CraneDriver::DriveVehicle( void ) { // No targets? if ( !GetEnemy() && m_vecDesiredPosition == vec3_origin ) return; Vector vecTarget = m_vecDesiredPosition; // Track our targets if ( m_hPickupTarget ) { vecTarget = m_hPickupTarget->GetAbsOrigin(); } else if ( !m_bForcedPickup && !m_bForcedDropoff && GetEnemy() ) { vecTarget = GetEnemy()->GetAbsOrigin(); } // Move the crane over the target // Use the crane type as a targeting point Vector vecCraneTip = m_hCrane->GetCraneTipPosition(); Vector2D vecCraneTip2D( vecCraneTip.x, vecCraneTip.y ); Vector2D vecTarget2D( vecTarget.x, vecTarget.y ); Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); if ( g_debug_vehicledriver.GetInt() ) { NDebugOverlay::Box( vecTarget, -Vector(50,50,50), Vector(50,50,50), 0,255,0, true, 0.1 ); NDebugOverlay::Box( vecCraneTip, -Vector(2,2,5000), Vector(2,2,5), 0,255,0, true, 0.1 ); NDebugOverlay::Box( vecTarget, -Vector(2,2,5), Vector(2,2,5000), 0,255,0, true, 0.1 ); } // Store off the distance to our target m_flDistanceToTarget = (vecTarget2D - vecCraneTip2D).Length(); // First determine whether we need to extend / retract the arm float flDistToTarget = (vecOrigin2D - vecTarget2D).LengthSqr(); float flDistToCurrent = (vecOrigin2D - vecCraneTip2D).LengthSqr(); float flDelta = fabs(flDistToTarget - flDistToCurrent); // Slow down as we get closer, but do it based upon our current extension rate float flMinDelta = 50 + (50 * fabs(m_hCrane->GetExtensionRate() / CRANE_EXTENSION_RATE_MAX)); flMinDelta *= flMinDelta; if ( flDelta > flMinDelta ) { if ( flDistToCurrent > flDistToTarget ) { // Retract m_pVehicleInterface->NPC_ThrottleReverse(); } else if ( flDistToCurrent < flDistToTarget ) { // Extend m_pVehicleInterface->NPC_ThrottleForward(); } } else { m_pVehicleInterface->NPC_ThrottleCenter(); } // Then figure out if we need to rotate. Do it all in 2D space. Vector vecRight, vecForward; m_hCrane->GetVectors( &vecForward, &vecRight, NULL ); vecRight.z = 0; vecForward.z = 0; VectorNormalize( vecRight ); VectorNormalize( vecForward ); Vector vecToTarget = ( vecTarget - m_hCrane->GetAbsOrigin() ); vecToTarget.z = 0; VectorNormalize( vecToTarget ); float flDotRight = DotProduct( vecRight, vecToTarget ); float flDotForward = DotProduct( vecForward, vecToTarget ); // Start slowing if we're going to hit the point soon float flTurnInDeg = RAD2DEG( acos(flDotForward) ); float flSpeed = m_hCrane->GetMaxTurnRate() * (flTurnInDeg / 15.0); flSpeed = min( m_hCrane->GetMaxTurnRate(), flSpeed ); if ( fabs(flSpeed) < 0.05 ) { // We're approaching the target, so stop turning m_pVehicleInterface->NPC_TurnCenter(); } else { if ( flDotRight < 0 ) { // Turn right m_pVehicleInterface->NPC_TurnRight( flSpeed ); } else if ( flDotRight > 0 ) { // Turn left m_pVehicleInterface->NPC_TurnLeft( flSpeed ); } } }
//----------------------------------------------------------------------------- // Purpose: Spawn an instance of the entity //----------------------------------------------------------------------------- void CEnvEntityMaker::SpawnEntity( Vector vecAlternateOrigin, QAngle vecAlternateAngles ) { CPointTemplate *pTemplate = FindTemplate(); if (!pTemplate) return; // Spawn our template Vector vecSpawnOrigin = GetAbsOrigin(); QAngle vecSpawnAngles = GetAbsAngles(); if( vecAlternateOrigin != vec3_invalid ) { // We have a valid alternate origin and angles. Use those instead // of spawning the items at my own origin and angles. vecSpawnOrigin = vecAlternateOrigin; vecSpawnAngles = vecAlternateAngles; } CUtlVector<CBaseEntity*> hNewEntities; if ( !pTemplate->CreateInstance( vecSpawnOrigin, vecSpawnAngles, &hNewEntities, this ) ) return; //Adrian: oops we couldn't spawn the entity (or entities) for some reason! if ( hNewEntities.Count() == 0 ) return; m_hCurrentInstance = hNewEntities[0]; // Assume it'll block us m_hCurrentBlocker = m_hCurrentInstance; m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); // Store off the mins & maxs the first time we spawn if ( m_vecEntityMins == vec3_origin ) { m_hCurrentInstance->CollisionProp()->WorldSpaceAABB( &m_vecEntityMins, &m_vecEntityMaxs ); m_vecEntityMins -= m_hCurrentInstance->GetAbsOrigin(); m_vecEntityMaxs -= m_hCurrentInstance->GetAbsOrigin(); } // Fire our output m_pOutputOnSpawned.FireOutput( this, this ); // Start thinking if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN ) { SetThink( &CEnvEntityMaker::CheckSpawnThink ); SetNextThink( gpGlobals->curtime + 0.5f ); } // If we have a specified post spawn speed, apply it to all spawned entities if ( m_flPostSpawnSpeed ) { for ( int i = 0; i < hNewEntities.Count(); i++ ) { CBaseEntity *pEntity = hNewEntities[i]; if ( pEntity->GetMoveType() == MOVETYPE_NONE ) continue; // Calculate a velocity for this entity Vector vForward,vRight,vUp; QAngle angSpawnDir( m_angPostSpawnDirection ); if ( m_bPostSpawnUseAngles ) { if ( GetParent() ) { angSpawnDir += GetParent()->GetAbsAngles(); } else { angSpawnDir += GetAbsAngles(); } } AngleVectors( angSpawnDir, &vForward, &vRight, &vUp ); Vector vecShootDir = vForward; vecShootDir += vRight * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; vecShootDir += vForward * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; vecShootDir += vUp * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; VectorNormalize( vecShootDir ); vecShootDir *= m_flPostSpawnSpeed; // Apply it to the entity IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity(&vecShootDir, NULL); } else { pEntity->SetAbsVelocity( vecShootDir ); } } } pTemplate->CreationComplete( hNewEntities ); }
//--------------------------------------------------------- //--------------------------------------------------------- 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; } }
void CWeaponGravityGun::SoundUpdate( void ) { int newState; if ( m_hObject ) newState = SS_LOCKEDON; else newState = SS_SCANNING; if ( newState != m_soundState ) { SoundStop(); m_soundState = newState; SoundStart(); } switch( m_soundState ) { case SS_SCANNING: break; case SS_LOCKEDON: { CPASAttenuationFilter filter( GetOwner() ); filter.MakeReliable(); float height = m_hObject->GetAbsOrigin().z - m_originalObjectPosition.z; // go from pitch 90 to 150 over a height of 500 int pitch = 90 + (int)UTIL_LineFraction( height, 0, 500, 60 ); CSoundParameters params; if ( GetParametersForSound( "Weapon_Physgun.LockedOn", params, NULL ) ) { EmitSound_t ep( params ); ep.m_nFlags = SND_CHANGE_VOL | SND_CHANGE_PITCH; ep.m_nPitch = pitch; EmitSound( filter, GetOwner()->entindex(), ep ); } // attenutate the movement sounds over 200 units of movement float distance = UTIL_LineFraction( m_movementLength, 0, 200, 1.0 ); // blend the "mass" sounds between 50 and 500 kg IPhysicsObject *pPhys = m_hObject->VPhysicsGetObject(); float fade = UTIL_LineFraction( pPhys->GetMass(), 50, 500, 1.0 ); if ( GetParametersForSound( "Weapon_Physgun.LightObject", params, NULL ) ) { EmitSound_t ep( params ); ep.m_nFlags = SND_CHANGE_VOL; ep.m_flVolume = fade * distance; EmitSound( filter, GetOwner()->entindex(), ep ); } if ( GetParametersForSound( "Weapon_Physgun.HeavyObject", params, NULL ) ) { EmitSound_t ep( params ); ep.m_nFlags = SND_CHANGE_VOL; ep.m_flVolume = (1.0 - fade) * distance; EmitSound( filter, GetOwner()->entindex(), ep ); } } break; } }
void CNPC_Dog::ThrowObject( const char *pAttachmentName ) { if ( m_hPhysicsEnt ) { m_bHasObject = false; IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); if ( pPhysObj ) { Vector vGunPos; QAngle angGunAngles; AngularImpulse angVelocity = RandomAngularImpulse( -250 , -250 ) / pPhysObj->GetMass(); InvalidateBoneCache(); int iAttachment = LookupAttachment( pAttachmentName ); if ( iAttachment == 0 ) iAttachment = m_iPhysGunAttachment; GetAttachment( iAttachment, vGunPos, angGunAngles ); pPhysObj->Wake(); if ( pPhysObj->GetShadowController() ) { m_hPhysicsEnt->SetParent( NULL ); m_hPhysicsEnt->SetMoveType( (MoveType_t)m_iContainerMoveType ); m_hPhysicsEnt->SetOwnerEntity( this ); pPhysObj->RemoveShadowController(); pPhysObj->SetPosition( m_hPhysicsEnt->GetLocalOrigin(), m_hPhysicsEnt->GetLocalAngles(), true ); pPhysObj->RecheckCollisionFilter(); pPhysObj->RecheckContactPoints(); } if ( m_hThrowTarget == NULL ) #ifdef SecobMod__Enable_Fixed_Multiplayer_AI m_hThrowTarget = UTIL_GetNearestVisiblePlayer(this); #else m_hThrowTarget = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI Vector vThrowDirection; if ( m_hThrowTarget ) { Vector vThrowOrigin = m_hThrowTarget->GetAbsOrigin(); if ( m_hThrowTarget->IsPlayer() ) vThrowOrigin = vThrowOrigin + Vector( random->RandomFloat( -128, 128 ), random->RandomFloat( -128, 128 ), 0 ); Vector vecToss = VecCheckToss( this, vGunPos, vThrowOrigin, m_flThrowArcModifier, 1.0f, true ); if( vecToss == vec3_origin ) { // Fix up an impossible throw so dog will at least toss the box in the target's general direction instead of dropping it. // Also toss it up in the air so it will fall down and break. (Just throw the box up at a 45 degree angle) Vector forward, up; GetVectors( &forward, NULL, &up ); vecToss = forward + up; VectorNormalize( vecToss ); vecToss *= pPhysObj->GetMass() * 30.0f; } vThrowDirection = vecToss + ( m_hThrowTarget->GetSmoothedVelocity() / 2 ); Vector vLinearDrag; Vector unitVel = vThrowDirection; VectorNormalize( unitVel ); float flTest = 1000 / vThrowDirection.Length(); float flDrag = pPhysObj->CalculateLinearDrag( vThrowDirection ); vThrowDirection = vThrowDirection + ( unitVel * ( flDrag * flDrag ) ) / flTest; pPhysObj->SetVelocity( &vThrowDirection, &angVelocity ); m_flTimeToCatch = gpGlobals->curtime + dog_max_wait_time.GetFloat(); //Don't start pulling until the object is away from me. //We base the time on the throw velocity. m_flTimeToPull = gpGlobals->curtime + ( 1000 / vThrowDirection.Length() ); } //Fire Output! m_OnThrow.FireOutput( this, this ); ClearBeams(); if ( m_bBeamEffects == true ) { EmitSound( "Weapon_PhysCannon.Launch" ); CBeam *pBeam = CBeam::BeamCreate( "sprites/orangelight1.vmt", 1.8 ); if ( pBeam != NULL ) { pBeam->PointEntInit( m_hPhysicsEnt->WorldSpaceCenter(), this ); pBeam->SetEndAttachment( m_iPhysGunAttachment ); pBeam->SetWidth( 6.4 ); pBeam->SetEndWidth( 12.8 ); pBeam->SetBrightness( 255 ); pBeam->SetColor( 255, 255, 255 ); pBeam->LiveForTime( 0.2f ); pBeam->RelinkBeam(); pBeam->SetNoise( 2 ); } Vector shotDir = ( m_hPhysicsEnt->WorldSpaceCenter() - vGunPos ); VectorNormalize( shotDir ); CPVSFilter filter( m_hPhysicsEnt->WorldSpaceCenter() ); te->GaussExplosion( filter, 0.0f, m_hPhysicsEnt->WorldSpaceCenter() - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); } } } }
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate ) { if ( m_bState == false ) { if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { ShutDownLightHandle(); } return; } Vector vForward, vRight, vUp, vPos = GetAbsOrigin(); FlashlightState_t state; if ( m_hTargetEntity != NULL ) { if ( m_bCameraSpace ) { const QAngle &angles = GetLocalAngles(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if( pPlayer ) { const QAngle playerAngles = pPlayer->GetAbsAngles(); Vector vPlayerForward, vPlayerRight, vPlayerUp; AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp ); matrix3x4_t mRotMatrix; AngleMatrix( angles, mRotMatrix ); VectorITransform( vPlayerForward, mRotMatrix, vForward ); VectorITransform( vPlayerRight, mRotMatrix, vRight ); VectorITransform( vPlayerUp, mRotMatrix, vUp ); float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length(); vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist; VectorNormalize( vForward ); VectorNormalize( vRight ); VectorNormalize( vUp ); } } else { // VXP: Fixing targeting Vector vecToTarget; QAngle vecAngles; if ( m_hTargetEntity == NULL ) { vecAngles = GetAbsAngles(); } else { vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin(); VectorAngles( vecToTarget, vecAngles ); } AngleVectors( vecAngles, &vForward, &vRight, &vUp ); } } else { AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp ); } state.m_fHorizontalFOVDegrees = m_flLightFOV; state.m_fVerticalFOVDegrees = m_flLightFOV; state.m_vecLightOrigin = vPos; BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation ); state.m_fQuadraticAtten = 0.0; state.m_fLinearAtten = 100; state.m_fConstantAtten = 0.0f; state.m_Color[0] = m_LinearFloatLightColor.x; state.m_Color[1] = m_LinearFloatLightColor.y; state.m_Color[2] = m_LinearFloatLightColor.z; state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_NearZ = m_flNearZ; state.m_FarZ = m_flFarZ; state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); state.m_bEnableShadows = m_bEnableShadows; state.m_pSpotlightTexture = materials->FindTexture( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, false ); state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame; state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE ) { m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } else { if ( m_hTargetEntity != NULL || bForceUpdate == true ) { g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state ); } } if( m_bLightOnlyTarget ) { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity ); } else { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL ); } g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld ); //if ( bForceUpdate == false ) //{ g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true ); //} }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPointCommentaryNode::UpdateViewThink( void ) { if ( !m_bActive ) return; CBasePlayer *pPlayer = GetCommentaryPlayer(); if ( !pPlayer ) return; // Swing the view towards the target if ( m_hViewTarget ) { QAngle angGoal; QAngle angCurrent; if ( m_hViewPositionMover ) { angCurrent = m_hViewPositionMover->GetAbsAngles(); VectorAngles( m_hViewTarget->WorldSpaceCenter() - m_hViewPositionMover->GetAbsOrigin(), angGoal ); } else { angCurrent = pPlayer->EyeAngles(); VectorAngles( m_hViewTarget->WorldSpaceCenter() - pPlayer->EyePosition(), angGoal ); } // Accelerate towards the target goal angles float dx = AngleDiff( angGoal.x, angCurrent.x ); float dy = AngleDiff( angGoal.y, angCurrent.y ); float mod = 1.0 - ExponentialDecay( 0.5, 0.3, gpGlobals->frametime ); float dxmod = dx * mod; float dymod = dy * mod; angCurrent.x = AngleNormalize( angCurrent.x + dxmod ); angCurrent.y = AngleNormalize( angCurrent.y + dymod ); if ( m_hViewPositionMover ) { m_hViewPositionMover->SetAbsAngles( angCurrent ); } else { pPlayer->SnapEyeAngles( angCurrent ); } SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink ); } if ( m_hViewPosition.Get() ) { if ( pPlayer->GetActiveWeapon() ) { pPlayer->GetActiveWeapon()->Holster(); } if ( !m_hViewPositionMover ) { // Make an invisible info target entity for us to attach the view to, // and move it to the desired view position. m_hViewPositionMover = CreateEntityByName( "env_laserdot" ); m_hViewPositionMover->SetAbsAngles( pPlayer->EyeAngles() ); pPlayer->SetViewEntity( m_hViewPositionMover ); } // Blend to the target position over time. float flCurTime = (gpGlobals->curtime - m_flStartTime); float flBlendPerc = clamp( flCurTime / 2.0, 0, 1 ); // Figure out the current view position Vector vecCurEye; VectorLerp( pPlayer->EyePosition(), m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye ); m_hViewPositionMover->SetAbsOrigin( vecCurEye ); SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pTask - //----------------------------------------------------------------------------- void CNPC_CraneDriver::StartTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_WAIT_FOR_MOVEMENT: break; case TASK_CRANE_GET_POSITION_OVER_ENEMY: { if ( !GetEnemy() ) { TaskFail(FAIL_NO_ROUTE); return; } SetDesiredPosition( GetEnemy()->GetAbsOrigin() ); TaskComplete(); } break; case TASK_CRANE_GET_POSITION_OVER_OBJECT: { if ( !m_hPickupTarget ) { TaskFail("No object to pickup!"); return; } SetDesiredPosition( m_hPickupTarget->GetAbsOrigin() ); TaskComplete(); } break; case TASK_CRANE_GET_POSITION_OVER_LASTPOSITION: { SetDesiredPosition( m_vecLastPosition ); TaskComplete(); } break; case TASK_CRANE_TURN_MAGNET_OFF: { // If we picked up something, and we were being forced to pick something up, fire our output if ( m_hCrane->GetTotalMassOnCrane() > 0 && m_bForcedDropoff ) { // Are we supposed to pause first? if ( m_flReleasePause ) { m_flReleaseAt = gpGlobals->curtime + m_flReleasePause; m_OnPausingBeforeDrop.FireOutput( this, this ); return; } m_OnDroppedObject.FireOutput( this, this ); } m_hCrane->TurnMagnetOff(); TaskComplete(); } break; case TASK_END_FORCED_DROP: { m_bForcedDropoff = false; TaskComplete(); } break; case TASK_CRANE_FIND_OBJECT_TO_PICKUP: { Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); // Find a large physics object within our reach to pickup float flLargestMass = 0; CBaseEntity *pLargestEntity = NULL; CBaseEntity *pList[1024]; Vector delta( m_flDistTooFar, m_flDistTooFar, m_flDistTooFar*2 ); int count = UTIL_EntitiesInBox( pList, 1024, m_hCrane->GetAbsOrigin() - delta, m_hCrane->GetAbsOrigin() + delta, 0 ); for ( int i = 0; i < count; i++ ) { if ( !pList[i] ) continue; // Ignore the crane & the magnet if ( pList[i] == m_hCrane || pList[i] == m_hCrane->GetMagnet() ) continue; if ( m_PreviouslyPickedUpObjects.Find( pList[i] ) != m_PreviouslyPickedUpObjects.InvalidIndex() ) continue; // Get the VPhysics object IPhysicsObject *pPhysics = pList[i]->VPhysicsGetObject(); if ( pPhysics && pList[i]->GetMoveType() == MOVETYPE_VPHYSICS ) { float flMass = pPhysics->GetMass(); if ( flMass > flLargestMass && (flMass < MAXIMUM_CRANE_PICKUP_MASS) && (flMass > MINIMUM_CRANE_PICKUP_MASS) ) { // Biggest one we've found so far // Now make sure it's within our reach // Do our distance check in 2D Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); Vector2D vecEnemy2D( pList[i]->GetAbsOrigin().x, pList[i]->GetAbsOrigin().y ); float flDist = (vecOrigin2D - vecEnemy2D).Length(); // Maximum & Minimum size of the crane's reach if ( flDist > MAX_CRANE_FLAT_REACH ) continue; if ( flDist < MIN_CRANE_FLAT_REACH ) continue; flLargestMass = flMass; pLargestEntity = pList[i]; } } } // If we didn't find anything new, clear our list of targets if ( !pLargestEntity ) { m_PreviouslyPickedUpObjects.Purge(); } if ( !pLargestEntity ) { TaskFail("Couldn't find anything to pick up!"); return; } m_hPickupTarget = pLargestEntity; TaskComplete(); } break; case TASK_CRANE_DROP_MAGNET: { // Drop the magnet, but only end the task once the magnet's back up m_pVehicleInterface->NPC_SecondaryFire(); // Don't check to see if drop's finished until this time is up. // This is necessary because the crane won't start dropping this // frame, and our cranedriver will think it's finished immediately. m_flDropWait = gpGlobals->curtime + 0.5; } break; default: BaseClass::StartTask( pTask ); break; } }
//------------------------------------------------------------------------------ // Purpose : //------------------------------------------------------------------------------ void CLookDoor::MoveThink(void) { // -------------------------------- // Make sure we have a looker // -------------------------------- if (m_hLooker == NULL) { m_hLooker = (CBaseEntity*)gEntList.FindEntityByName( NULL, m_target, NULL ); if (m_hLooker == NULL) { return; } } //-------------------------------------- // Calculate an orgin for the door //-------------------------------------- Vector vOrigin = 0.5*(GetAbsMaxs() + GetAbsMins()) - GetAbsOrigin(); // If FROM_OPEN flag is set, door proximity is measured // from the open and not the closed position if (FBitSet (m_spawnflags, SF_LDOOR_FROM_OPEN)) { vOrigin += m_vecPosition2; } // ------------------------------------------------------ // First add movement based on proximity // ------------------------------------------------------ float flProxMove = 0; if (m_flProximityDistance > 0) { float flDist = (m_hLooker->GetAbsOrigin() - vOrigin).Length()-m_flProximityOffset; if (flDist < 0) flDist = 0; if (flDist < m_flProximityDistance) { if (FBitSet (m_spawnflags, SF_LDOOR_THRESHOLD)) { flProxMove = 1.0; } else { flProxMove = 1-flDist/m_flProximityDistance; } } } // ------------------------------------------------------ // Then add movement based on view angle // ------------------------------------------------------ float flViewMove = 0; if (m_flFieldOfView > 0) { // ---------------------------------------- // Check that toucher is facing the target // ---------------------------------------- Assert( dynamic_cast< CBaseCombatCharacter* >( m_hLooker.Get() ) ); CBaseCombatCharacter* pBCC = (CBaseCombatCharacter*)m_hLooker.Get(); Vector vTouchDir = pBCC->EyeDirection3D( ); Vector vTargetDir = vOrigin - pBCC->EyePosition(); VectorNormalize(vTargetDir); float flDotPr = DotProduct(vTouchDir,vTargetDir); if (flDotPr < m_flFieldOfView) { flViewMove = 0.0; } else { flViewMove = (flDotPr-m_flFieldOfView)/(1.0 - m_flFieldOfView); } } //--------------------------------------- // Summate the two moves //--------------------------------------- float flMove = flProxMove + flViewMove; if (flMove > 1.0) { flMove = 1.0; } // If behavior is inverted do the reverse if (FBitSet (m_spawnflags, SF_LDOOR_INVERT)) { flMove = 1-flMove; } // Move the door SetPosition( flMove ); }