void CTank :: UpdateCamAngle ( Vector vecNewPosition, float flTime ) { Vector vecNewAngle; GetAttachment( 2, vecCamTarget, Vector ( 0, 0, 0 ) ); vecNewAngle = UTIL_VecToAngles( vecCamTarget - vecNewPosition ); vecNewAngle.x = -vecNewAngle.x; float distX = UTIL_AngleDistance( m_pCam->pev->angles.x, vecNewAngle.x ); m_pCam->pev->avelocity.x = -distX / flTime; float distY = UTIL_AngleDistance( m_pCam->pev->angles.y, vecNewAngle.y ); m_pCam->pev->avelocity.y = -distY / flTime; }
/* <8efe4> ../cstrike/dlls/func_tank.cpp:488 */ void CFuncTank::TrackTarget(void) { TraceResult tr; edict_t *pPlayer = FIND_CLIENT_IN_PVS(edict()); BOOL updateTime = FALSE, lineOfSight; Vector angles, direction, targetPosition, barrelEnd; edict_t *pTarget = NULL; // Get a position to aim for if (m_pController != NULL) { // Tanks attempt to mirror the player's angles angles = m_pController->pev->v_angle; angles.x = 0 - angles.x; pev->nextthink = pev->ltime + 0.05; } else { if (IsActive()) pev->nextthink = pev->ltime + 0.1; else return; if (FNullEnt(pPlayer)) { if (IsActive()) { // Wait 2 secs pev->nextthink = pev->ltime + 2; } return; } pTarget = FindTarget(pPlayer); if (!pTarget) { return; } // Calculate angle needed to aim at target barrelEnd = BarrelPosition(); targetPosition = pTarget->v.origin + pTarget->v.view_ofs; float range = (targetPosition - barrelEnd).Length(); if (!InRange(range)) return; UTIL_TraceLine(barrelEnd, targetPosition, dont_ignore_monsters, edict(), &tr); lineOfSight = FALSE; // No line of sight, don't track if (tr.flFraction == 1.0f || tr.pHit == pTarget) { lineOfSight = TRUE; CBaseEntity *pInstance = CBaseEntity::Instance(pTarget); if (InRange(range) && pInstance && pInstance->IsAlive()) { updateTime = TRUE; m_sightOrigin = UpdateTargetPosition(pInstance); } } // Track sight origin // !!! I'm not sure what i changed direction = m_sightOrigin - pev->origin; //direction = m_sightOrigin - barrelEnd; angles = UTIL_VecToAngles(direction); // Calculate the additional rotation to point the end of the barrel at the target (not the gun's center) AdjustAnglesForBarrel(angles, direction.Length()); } angles.x = -angles.x; // Force the angles to be relative to the center position angles.y = m_yawCenter + UTIL_AngleDistance(angles.y, m_yawCenter); angles.x = m_pitchCenter + UTIL_AngleDistance(angles.x, m_pitchCenter); // Limit against range in y if (angles.y > m_yawCenter + m_yawRange) { angles.y = m_yawCenter + m_yawRange; // Don't update if you saw the player, but out of range updateTime = FALSE; } else if (angles.y < (m_yawCenter - m_yawRange)) { angles.y = (m_yawCenter - m_yawRange); // Don't update if you saw the player, but out of range updateTime = FALSE; } if (updateTime) { m_lastSightTime = gpGlobals->time; } // Move toward target at rate or less float_precision distY = UTIL_AngleDistance(angles.y, pev->angles.y); pev->avelocity.y = distY * 10; if (pev->avelocity.y > m_yawRate) { pev->avelocity.y = m_yawRate; } else if (pev->avelocity.y < -m_yawRate) { pev->avelocity.y = -m_yawRate; } // Limit against range in x if (angles.x > m_pitchCenter + m_pitchRange) { angles.x = m_pitchCenter + m_pitchRange; } else if (angles.x < m_pitchCenter - m_pitchRange) { angles.x = m_pitchCenter - m_pitchRange; } // Move toward target at rate or less float_precision distX = UTIL_AngleDistance(angles.x, pev->angles.x); pev->avelocity.x = distX * 10; if (pev->avelocity.x > m_pitchRate) { pev->avelocity.x = m_pitchRate; } else if (pev->avelocity.x < -m_pitchRate) { pev->avelocity.x = -m_pitchRate; } if (m_pController != NULL) { return; } if (CanFire() && ((fabs(distX) < m_pitchTolerance && fabs(distY) < m_yawTolerance) || (pev->spawnflags & SF_TANK_LINEOFSIGHT))) { BOOL fire = FALSE; Vector forward; UTIL_MakeVectorsPrivate(pev->angles, forward, NULL, NULL); if (pev->spawnflags & SF_TANK_LINEOFSIGHT) { float length = direction.Length(); UTIL_TraceLine(barrelEnd, barrelEnd + forward * length, dont_ignore_monsters, edict(), &tr); if (tr.pHit == pTarget) { fire = TRUE; } } else fire = TRUE; if (fire) { Fire(BarrelPosition(), forward, pev); } else m_fireLast = 0; } else m_fireLast = 0; }
void CFuncTank::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); // Get a position to aim for if (m_pController) { // Tanks attempt to mirror the player's angles angles = m_pController->EyeAngles(); SetNextThink( gpGlobals->curtime + 0.05 ); } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; if (m_spawnflags & SF_TANK_AIM_AT_POS) { worldTargetPosition = m_vTargetPosition; } else { CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { if ( m_targetEntityName != NULL_STRING ) // New HL2 behavior { m_hTarget = FindTarget( m_targetEntityName, NULL ); } else // HL1 style { m_hTarget = ToBasePlayer( GetContainingEntity( UTIL_FindClientInPVS( edict() ) ) ); } if ( m_hTarget != NULL ) { SetNextThink( gpGlobals->curtime ); // Think again immediately } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 secs } if ( m_fireLast !=0 ) { m_OnLoseTarget.FireOutput(this, this); m_fireLast = 0; } } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); } float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) { m_fireLast = 0; return; } UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if (m_spawnflags & SF_TANK_AIM_AT_POS) { updateTime = TRUE; m_sightOrigin = m_vTargetPosition; } else { lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); } // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Limit against range in y // MDB - don't check pitch! If two func_tanks are meant to align, // and one can pitch and the other cannot, this can lead to them getting // different values for angles.y. Nothing is lost by not updating yaw // because the target is not in pitch range. bool bOutsideYawRange = ( fabs( offsetY ) > m_yawRange + m_yawTolerance ); bool bOutsidePitchRange = ( fabs( offsetX ) > m_pitchRange + m_pitchTolerance ); Vector vecToTarget = m_sightOrigin - GetLocalOrigin(); // if target is outside yaw range if ( bOutsideYawRange ) { if ( angles.y > m_yawCenter + m_yawRange ) { angles.y = m_yawCenter + m_yawRange; } else if ( angles.y < (m_yawCenter - m_yawRange) ) { angles.y = (m_yawCenter - m_yawRange); } } if ( bOutsidePitchRange || bOutsideYawRange || ( vecToTarget.Length() < ( barrelEnd - GetAbsOrigin() ).Length() ) ) { // Don't update if you saw the player, but out of range updateTime = false; } if ( updateTime ) { m_lastSightTime = gpGlobals->curtime; m_persist2burst = 0; } // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Limit against range in x angles.x = clamp( angles.x, m_pitchCenter - m_pitchRange, m_pitchCenter + m_pitchRange ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); if ( m_pController ) return; if ( CanFire() && ( (fabs(distX) < m_pitchTolerance && fabs(distY) < m_yawTolerance) || (m_spawnflags & SF_TANK_LINEOFSIGHT) ) ) { bool fire = FALSE; Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); if ( m_spawnflags & SF_TANK_LINEOFSIGHT ) { float length = (m_maxRange > 0) ? m_maxRange : MAX_TRACE_LENGTH; UTIL_TraceLine( barrelEnd, barrelEnd + forward * length, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt == pTarget ) fire = TRUE; } else fire = TRUE; if ( fire ) { if (m_fireLast == 0) { m_OnAquireTarget.FireOutput(this, this); } FiringSequence( barrelEnd, forward, this ); } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } }
void CAPCController::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { m_hTarget = FindTarget( m_targetEntityName, NULL ); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 sec s } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) { m_bFireDelayed = false; return; } UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); AngleVectors(angles, &forward); if ( lineOfSight == TRUE ) { // FIXME: This will ultimately have to deal with NPCs being in the vehicle as well // See if the target is in a vehicle. If so, check its relationship CBasePlayer *pPlayer = ToBasePlayer( pTarget ); if ( pPlayer && pPlayer->IsInAVehicle() ) { IServerVehicle *pVehicle = pPlayer->GetVehicle(); if ( pVehicle->ClassifyPassenger( pPlayer, CLASS_PLAYER ) == CLASS_PLAYER) { if ( !m_bFireDelayed ) { m_bFireDelayed = true; m_flFiringDelay = gpGlobals->curtime + 1.5; // setup delay time before we start firing return; } if ( gpGlobals->curtime > m_flFiringDelay ) { m_OnFireAtTarget.Set(forward, this, this); // tell apc to fire rockets, and what direction } } } } else { m_bFireDelayed = false; // reset flag since we can no longer see target } }
void CFuncTank::TrackTarget(void) { TraceResult tr; edict_t *pPlayer = FIND_CLIENT_IN_PVS(edict()); BOOL updateTime = FALSE, lineOfSight; Vector angles, direction, targetPosition, barrelEnd; edict_t *pTarget = NULL; if (m_pController) { angles = m_pController->pev->v_angle; angles[0] = 0 - angles[0]; pev->nextthink = pev->ltime + 0.05; } else { if (IsActive()) pev->nextthink = pev->ltime + 0.1; else return; if (FNullEnt(pPlayer)) { if (IsActive()) pev->nextthink = pev->ltime + 2; return; } pTarget = FindTarget(pPlayer); if (!pTarget) return; barrelEnd = BarrelPosition(); targetPosition = pTarget->v.origin + pTarget->v.view_ofs; float range = (targetPosition - barrelEnd).Length(); if (!InRange(range)) return; UTIL_TraceLine(barrelEnd, targetPosition, dont_ignore_monsters, edict(), &tr); lineOfSight = FALSE; if (tr.flFraction == 1 || tr.pHit == pTarget) { lineOfSight = TRUE; CBaseEntity *pInstance = CBaseEntity::Instance(pTarget); if (InRange(range) && pInstance && pInstance->IsAlive()) { updateTime = TRUE; m_sightOrigin = UpdateTargetPosition(pInstance); } } direction = m_sightOrigin - pev->origin; angles = UTIL_VecToAngles(direction); AdjustAnglesForBarrel(angles, direction.Length()); } angles.x = -angles.x; angles.y = m_yawCenter + UTIL_AngleDistance(angles.y, m_yawCenter); angles.x = m_pitchCenter + UTIL_AngleDistance(angles.x, m_pitchCenter); if (angles.y > m_yawCenter + m_yawRange) { angles.y = m_yawCenter + m_yawRange; updateTime = FALSE; } else if (angles.y < (m_yawCenter - m_yawRange)) { angles.y = (m_yawCenter - m_yawRange); updateTime = FALSE; } if (updateTime) m_lastSightTime = gpGlobals->time; float distY = UTIL_AngleDistance(angles.y, pev->angles.y); pev->avelocity.y = distY * 10; if (pev->avelocity.y > m_yawRate) pev->avelocity.y = m_yawRate; else if (pev->avelocity.y < -m_yawRate) pev->avelocity.y = -m_yawRate; if (angles.x > m_pitchCenter + m_pitchRange) angles.x = m_pitchCenter + m_pitchRange; else if (angles.x < m_pitchCenter - m_pitchRange) angles.x = m_pitchCenter - m_pitchRange; float distX = UTIL_AngleDistance(angles.x, pev->angles.x); pev->avelocity.x = distX * 10; if (pev->avelocity.x > m_pitchRate) pev->avelocity.x = m_pitchRate; else if (pev->avelocity.x < -m_pitchRate) pev->avelocity.x = -m_pitchRate; if (m_pController) return; if (CanFire() && ((fabs(distX) < m_pitchTolerance && fabs(distY) < m_yawTolerance) || (pev->spawnflags & SF_TANK_LINEOFSIGHT))) { BOOL fire = FALSE; Vector forward; UTIL_MakeVectorsPrivate(pev->angles, forward, NULL, NULL); if (pev->spawnflags & SF_TANK_LINEOFSIGHT) { float length = direction.Length(); UTIL_TraceLine(barrelEnd, barrelEnd + forward * length, dont_ignore_monsters, edict(), &tr); if (tr.pHit == pTarget) fire = TRUE; } else fire = TRUE; if (fire) Fire(BarrelPosition(), forward, pev); else m_fireLast = 0; } else m_fireLast = 0; }
void CFuncVehicle::Next() { Vector vGravityVector, forward, right, up; float time = 0.1f; vGravityVector = g_vecZero; UTIL_MakeVectors(pev->angles); forward = (gpGlobals->v_forward * -1) * (m_length * 0.5); right = (gpGlobals->v_right * -1) * (m_width * 0.5); up = gpGlobals->v_up * 16; m_vFrontLeft = pev->origin + forward - right + up; m_vFrontRight = pev->origin + forward + right + up; m_vFront = pev->origin + forward + up; m_vBackLeft = pev->origin - forward - right + up; m_vBackRight = pev->origin - forward + right + up; m_vBack = pev->origin - forward + up; m_vSurfaceNormal = g_vecZero; CheckTurning(); if (m_flSteeringWheelDecay < gpGlobals->time) { m_flSteeringWheelDecay = gpGlobals->time + 0.1f; if (m_iTurnAngle < 0) m_iTurnAngle++; else if (m_iTurnAngle > 0) m_iTurnAngle--; } if (m_flAcceleratorDecay < gpGlobals->time) { m_flAcceleratorDecay = gpGlobals->time + 0.1f; if (pev->speed < 0) { pev->speed += 20; if (pev->speed > 0) pev->speed = 0; } else if (pev->speed > 0) { pev->speed -= 20; if (pev->speed < 0) pev->speed = 0; } } if (pev->speed == 0) { m_iTurnAngle = 0; pev->avelocity = g_vecZero; pev->velocity = g_vecZero; SetThink(&CFuncVehicle::Next); NextThink(pev->ltime + time, TRUE); return; } TerrainFollowing(); CollisionDetection(); Vector temp; if (m_vSurfaceNormal != g_vecZero) { Vector vTargetAngle, vAngle; float vx; real_t vy; m_vVehicleDirection = CrossProduct(m_vSurfaceNormal, gpGlobals->v_forward); m_vVehicleDirection = CrossProduct(m_vSurfaceNormal, m_vVehicleDirection); vTargetAngle = UTIL_VecToAngles(m_vVehicleDirection); vAngle = pev->angles; vTargetAngle.y += 180; if (m_iTurnAngle != 0) { vTargetAngle.y += m_iTurnAngle; } UTIL_FixupAngles(vTargetAngle); UTIL_FixupAngles(vAngle); vx = UTIL_AngleDistance(vTargetAngle.x, vAngle.x); vy = UTIL_AngleDistance(vTargetAngle.y, vAngle.y); if (vx > 10) vx = 10; else if (vx < -10) vx = -10; if (vy > 10) vy = 10; else if (vy < -10) vy = -10; pev->avelocity.y = int(vy * 10); pev->avelocity.x = int(vx * 10); m_flLaunchTime = -1; m_flLastNormalZ = m_vSurfaceNormal.z; } else { if (m_flLaunchTime != -1) { vGravityVector.x = 0; vGravityVector.y = 0; vGravityVector.z = (gpGlobals->time - m_flLaunchTime) * -35; if (vGravityVector.z < -400) { vGravityVector.z = -400; } } else { m_flLaunchTime = gpGlobals->time; vGravityVector = Vector(0, 0, 0); pev->velocity = pev->velocity * 1.5; } m_vVehicleDirection = gpGlobals->v_forward * -1; } UTIL_VecToAngles(m_vVehicleDirection); if (m_flUpdateSound < gpGlobals->time) { UpdateSound(); m_flUpdateSound = gpGlobals->time + 1.0f; } if (m_vSurfaceNormal != g_vecZero) { pev->velocity = m_vVehicleDirection.Normalize() * pev->speed; } else { pev->velocity = pev->velocity + vGravityVector; } SetThink(&CFuncVehicle::Next); NextThink(pev->ltime + time, TRUE); }