//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void CBaseHelicopter::Flight( void ) { if( GetFlags() & FL_ONGROUND ) { //This would be really bad. SetGroundEntity( NULL ); } // Generic speed up if (m_flGoalSpeed < GetMaxSpeed()) { m_flGoalSpeed += GetAcceleration(); } //NDebugOverlay::Line(GetAbsOrigin(), m_vecDesiredPosition, 0,0,255, true, 0.1); // tilt model 5 degrees (why?! sjb) QAngle vecAdj = QAngle( 5.0, 0, 0 ); // estimate where I'll be facing in one seconds Vector forward, right, up; AngleVectors( GetLocalAngles() + GetLocalAngularVelocity() * 2 + vecAdj, &forward, &right, &up ); // Vector vecEst1 = GetLocalOrigin() + GetAbsVelocity() + up * m_flForce - Vector( 0, 0, 384 ); // float flSide = DotProduct( m_vecDesiredPosition - vecEst1, right ); QAngle angVel = GetLocalAngularVelocity(); float flSide = DotProduct( m_vecDesiredFaceDir, right ); if (flSide < 0) { if (angVel.y < 60) { angVel.y += 8; } } else { if (angVel.y > -60) { angVel.y -= 8; } } angVel.y *= ( 0.98 ); // why?! (sjb) // estimate where I'll be in two seconds AngleVectors( GetLocalAngles() + angVel * 1 + vecAdj, NULL, NULL, &up ); Vector vecEst = GetAbsOrigin() + GetAbsVelocity() * 2.0 + up * m_flForce * 20 - Vector( 0, 0, 384 * 2 ); // add immediate force AngleVectors( GetLocalAngles() + vecAdj, &forward, &right, &up ); Vector vecImpulse( 0, 0, 0 ); vecImpulse.x += up.x * m_flForce; vecImpulse.y += up.y * m_flForce; vecImpulse.z += up.z * m_flForce; // add gravity vecImpulse.z -= 38.4; // 32ft/sec ApplyAbsVelocityImpulse( vecImpulse ); float flSpeed = GetAbsVelocity().Length(); float flDir = DotProduct( Vector( forward.x, forward.y, 0 ), Vector( GetAbsVelocity().x, GetAbsVelocity().y, 0 ) ); if (flDir < 0) { flSpeed = -flSpeed; } float flDist = DotProduct( GetDesiredPosition() - vecEst, forward ); // float flSlip = DotProduct( GetAbsVelocity(), right ); float flSlip = -DotProduct( GetDesiredPosition() - vecEst, right ); // fly sideways if (flSlip > 0) { if (GetLocalAngles().z > -30 && angVel.z > -15) angVel.z -= 4; else angVel.z += 2; } else { if (GetLocalAngles().z < 30 && angVel.z < 15) angVel.z += 4; else angVel.z -= 2; } // These functions contain code Ken wrote that used to be right here as part of the flight model, // but we want different helicopter vehicles to have different drag characteristics, so I made // them virtual functions (sjb) ApplySidewaysDrag( right ); ApplyGeneralDrag(); // apply power to stay correct height // FIXME: these need to be per class variables #define MAX_FORCE 80 #define FORCE_POSDELTA 12 #define FORCE_NEGDELTA 8 if (m_flForce < MAX_FORCE && vecEst.z < GetDesiredPosition().z) { m_flForce += FORCE_POSDELTA; } else if (m_flForce > 30) { if (vecEst.z > GetDesiredPosition().z) m_flForce -= FORCE_NEGDELTA; } // pitch forward or back to get to target //----------------------------------------- // Pitch is reversed since Half-Life! (sjb) //----------------------------------------- if (flDist > 0 && flSpeed < m_flGoalSpeed /* && flSpeed < flDist */ && GetLocalAngles().x + angVel.x < 40) { // ALERT( at_console, "F " ); // lean forward angVel.x += 12.0; } else if (flDist < 0 && flSpeed > -50 && GetLocalAngles().x + angVel.x > -20) { // ALERT( at_console, "B " ); // lean backward angVel.x -= 12.0; } else if (GetLocalAngles().x + angVel.x < 0) { // ALERT( at_console, "f " ); angVel.x += 4.0; } else if (GetLocalAngles().x + angVel.x > 0) { // ALERT( at_console, "b " ); angVel.x -= 4.0; } SetLocalAngularVelocity( angVel ); // ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", GetAbsOrigin().x, GetAbsVelocity().x, flDist, flSpeed, GetLocalAngles().x, m_vecAngVelocity.x, m_flForce ); // ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", GetAbsOrigin().z, GetAbsVelocity().z, vecEst.z, m_vecDesiredPosition.z, m_flForce ); }
//------------------------------------------------------------------------------ // Purpose : Move toward targetmap // Input : // Output : //------------------------------------------------------------------------------ void CGrenadeHomer::AimThink( void ) { // Blow up the missile if we have an explicit detonate time that // has been reached if (m_flDetonateTime != 0 && gpGlobals->curtime > m_flDetonateTime) { Detonate(); return; } PlayFlySound(); Vector vTargetPos = vec3_origin; Vector vTargetDir; float flCurHomingStrength = 0; // ------------------------------------------------ // If I'm homing // ------------------------------------------------ if (m_hTarget != NULL) { vTargetPos = m_hTarget->EyePosition(); vTargetDir = vTargetPos - GetAbsOrigin(); VectorNormalize(vTargetDir); // -------------------------------------------------- // If my target is far away do some primitive // obstacle avoidance // -------------------------------------------------- if ((vTargetPos - GetAbsOrigin()).Length() > 200) { Vector vTravelDir = GetAbsVelocity(); VectorNormalize(vTravelDir); vTravelDir *= 50; trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vTravelDir, MASK_SHOT, m_hTarget, COLLISION_GROUP_NONE, &tr ); if (tr.fraction != 1.0) { // Head off in normal float dotPr = DotProduct(vTravelDir,tr.plane.normal); Vector vBounce = -dotPr * tr.plane.normal; vBounce.z = 0; VectorNormalize(vBounce); vTargetDir += vBounce; VectorNormalize(vTargetDir); // DEBUG TOOL //NDebugOverlay::Line(GetOrigin(), GetOrigin()+vTravelDir, 255,0,0, true, 20); //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(12*tr.plane.normal), 0,0,255, true, 20); //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(vTargetDir), 0,255,0, true, 20); } } float flTargetSpeed = GetAbsVelocity().Length(); float flHomingRampUpStartTime = m_flHomingLaunchTime + m_flHomingDelay; float flHomingSustainStartTime = flHomingRampUpStartTime + m_flHomingRampUp; float flHomingRampDownStartTime = flHomingSustainStartTime + m_flHomingDuration; float flHomingEndHomingTime = flHomingRampDownStartTime + m_flHomingRampDown; // --------- // Delay // --------- if (gpGlobals->curtime < flHomingRampUpStartTime) { flCurHomingStrength = 0; flTargetSpeed = 0; } // ---------- // Ramp Up // ---------- else if (gpGlobals->curtime < flHomingSustainStartTime) { float flAge = gpGlobals->curtime - flHomingRampUpStartTime; flCurHomingStrength = m_flHomingStrength * (flAge/m_flHomingRampUp); flTargetSpeed = flCurHomingStrength * m_flHomingSpeed; } // ---------- // Sustain // ---------- else if (gpGlobals->curtime < flHomingRampDownStartTime) { flCurHomingStrength = m_flHomingStrength; flTargetSpeed = m_flHomingSpeed; } // ----------- // Ramp Down // ----------- else if (gpGlobals->curtime < flHomingEndHomingTime) { float flAge = gpGlobals->curtime - flHomingRampDownStartTime; flCurHomingStrength = m_flHomingStrength * (1-(flAge/m_flHomingRampDown)); flTargetSpeed = m_flHomingSpeed; } // --------------- // Set Homing // --------------- if (flCurHomingStrength > 0) { // ------------- // Smoke trail. // ------------- if (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON_HOMING) { UpdateRocketTrail(flCurHomingStrength); } // Extract speed and direction Vector vCurDir = GetAbsVelocity(); float flCurSpeed = VectorNormalize(vCurDir); flTargetSpeed = MAX(flTargetSpeed, flCurSpeed); // Add in homing direction Vector vecNewVelocity = GetAbsVelocity(); float flTimeToUse = gpGlobals->frametime; while (flTimeToUse > 0) { vecNewVelocity = (flCurHomingStrength * vTargetDir) + ((1 - flCurHomingStrength) * vCurDir); flTimeToUse = -0.1; } VectorNormalize(vecNewVelocity); vecNewVelocity *= flTargetSpeed; SetAbsVelocity( vecNewVelocity ); } } // ---------------------------------------------------------------------------------------- // Add time-coherent noise to the current velocity // ---------------------------------------------------------------------------------------- Vector vecImpulse( 0, 0, 0 ); if (m_flSpinMagnitude > 0) { vecImpulse.x += m_flSpinMagnitude*sin(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); vecImpulse.y += m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); vecImpulse.z -= m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); } // Add in gravity vecImpulse.z -= GetGravity() * GetCurrentGravity() * gpGlobals->frametime; ApplyAbsVelocityImpulse( vecImpulse ); QAngle angles; VectorAngles( GetAbsVelocity(), angles ); SetLocalAngles( angles ); #if 0 // BUBBLE if( gpGlobals->curtime > m_flNextWarnTime ) { // Make a bubble of warning sound in front of me. const float WARN_INTERVAL = 0.25f; float flSpeed = GetAbsVelocity().Length(); Vector vecWarnLocation; // warn a little bit ahead of us, please. vecWarnLocation = GetAbsOrigin() + GetAbsVelocity() * 0.75; // Make a bubble of warning ahead of the missile. CSoundEnt::InsertSound ( SOUND_DANGER, vecWarnLocation, flSpeed * WARN_INTERVAL, 0.5 ); #if 0 Vector vecRight, vecForward; AngleVectors( GetAbsAngles(), &vecForward, &vecRight, NULL ); NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); #endif m_flNextWarnTime = gpGlobals->curtime + WARN_INTERVAL; } #endif // BUBBLE SetNextThink( gpGlobals->curtime + 0.1f ); }