// // This search function will sit with the turret deployed and look for a new target. // After a set amount of time, the barrel will spin down. After m_flMaxWait, the turret will // retact. // void CBaseTurret::SearchThink(void) { // ensure rethink SetTurretAnim(TURRET_ANIM_SPIN); StudioFrameAdvance( ); pev->nextthink = gpGlobals->time + 0.1; if (m_flSpinUpTime == 0 && m_flMaxSpin) m_flSpinUpTime = gpGlobals->time + m_flMaxSpin; Ping( ); // If we have a target and we're still healthy if (m_hEnemy != NULL) { if (!m_hEnemy->IsAlive() ) m_hEnemy = NULL;// Dead enemy forces a search for new one } // Acquire Target if (m_hEnemy == NULL) { Look(TURRET_RANGE); m_hEnemy = BestVisibleEnemy(); } // If we've found a target, spin up the barrel and start to attack if (m_hEnemy != NULL) { m_flLastSight = 0; m_flSpinUpTime = 0; SetThink(&CBaseTurret::ActiveThink); } else { // Are we out of time, do we need to retract? if (gpGlobals->time > m_flLastSight) { //Before we retrace, make sure that we are spun down. m_flLastSight = 0; m_flSpinUpTime = 0; SetThink(&CBaseTurret::Retire); } // should we stop the spin? else if ((m_flSpinUpTime) && (gpGlobals->time > m_flSpinUpTime)) { SpinDownCall(); } // generic hunt for new victims m_vecGoalAngles.y = (m_vecGoalAngles.y + 0.1 * m_fTurnRate); if (m_vecGoalAngles.y >= 360) m_vecGoalAngles.y -= 360; MoveTurret(); } }
//----------------------------------------------------------------------------- // Make sure our target is still valid, and if so, fire at it //----------------------------------------------------------------------------- void CObjectSentrygun::Attack() { StudioFrameAdvance( ); if ( !FindTarget() ) { m_iState.Set( SENTRY_STATE_SEARCHING ); m_hEnemy = NULL; return; } // Track enemy Vector vecMid = EyePosition(); Vector vecMidEnemy = m_hEnemy->WorldSpaceCenter(); Vector vecDirToEnemy = vecMidEnemy - vecMid; QAngle angToTarget; VectorAngles( vecDirToEnemy, angToTarget ); angToTarget.y = UTIL_AngleMod( angToTarget.y ); if (angToTarget.x < -180) angToTarget.x += 360; if (angToTarget.x > 180) angToTarget.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-50...50] if (angToTarget.x > 50) angToTarget.x = 50; else if (angToTarget.x < -50) angToTarget.x = -50; m_vecGoalAngles.y = angToTarget.y; m_vecGoalAngles.x = angToTarget.x; MoveTurret(); // Fire on the target if it's within 10 units of being aimed right at it if ( m_flNextAttack <= gpGlobals->curtime && (m_vecGoalAngles - m_vecCurAngles).Length() <= 10 ) { Fire(); if ( m_iUpgradeLevel == 1 ) { // Level 1 sentries fire slower m_flNextAttack = gpGlobals->curtime + 0.2; } else { m_flNextAttack = gpGlobals->curtime + 0.1; } } else { // SetSentryAnim( TFTURRET_ANIM_SPIN ); } }
//========================================================= // Retire - stop being active //========================================================= void CNPC_BaseTurret::Retire(void) { // make the turret level m_vecGoalAngles.x = 0; m_vecGoalAngles.y = m_flStartYaw; SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); EyeOff( ); if (!MoveTurret()) { if (m_iSpin) { SpinDownCall(); } else if (GetSequence() != TURRET_ANIM_RETIRE) { SetTurretAnim(TURRET_ANIM_RETIRE); CPASAttenuationFilter filter( this ); EmitSound( filter, entindex(), "Turret.Undeploy" ); m_OnDeactivate.FireOutput(this, this); } //else if (IsSequenceFinished()) else if( GetSequence() == TURRET_ANIM_RETIRE && GetCycle() <= 0.0 ) { m_iOn = 0; m_flLastSight = 0; //SetTurretAnim(TURRET_ANIM_NONE); Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iRetractHeight; curmins.z = -m_iRetractHeight; SetCollisionBounds( curmins, curmaxs ); if (m_iAutoStart) { SetThink(&CNPC_BaseTurret::AutoSearchThink); SetNextThink( gpGlobals->curtime + 0.1 ); } else { SetThink( &CBaseEntity::SUB_DoNothing ); } } } else { SetTurretAnim(TURRET_ANIM_SPIN); } }
//========================================================= // TurretDeath - I die as I have lived, beyond my means //========================================================= void CNPC_BaseTurret::TurretDeath(void) { StudioFrameAdvance( ); SetNextThink( gpGlobals->curtime + 0.1 ); if (m_lifeState != LIFE_DEAD) { m_lifeState = LIFE_DEAD; CPASAttenuationFilter filter( this ); EmitSound( filter, entindex(), "Turret.Die" ); StopSound( entindex(), "Turret.Spinup" ); if (m_iOrientation == TURRET_ORIENTATION_FLOOR) m_vecGoalAngles.x = -14; else m_vecGoalAngles.x = 90;//-90; SetTurretAnim(TURRET_ANIM_DIE); EyeOn( ); } EyeOff( ); if (m_flDamageTime + random->RandomFloat( 0, 2 ) > gpGlobals->curtime) { // lots of smoke Vector pos; CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos ); pos.z = CollisionProp()->GetCollisionOrigin().z; CBroadcastRecipientFilter filter; te->Smoke( filter, 0.0, &pos, g_sModelIndexSmoke, 2.5, 10 ); } if (m_flDamageTime + random->RandomFloat( 0, 5 ) > gpGlobals->curtime) { Vector vecSrc; CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecSrc ); g_pEffects->Sparks( vecSrc ); } if (IsSequenceFinished() && !MoveTurret() && m_flDamageTime + 5 < gpGlobals->curtime) { m_flPlaybackRate = 0; SetThink( NULL ); } }
void CBaseTurret::Retire(void) { // make the turret level m_vecGoalAngles = GetAngles( ); SetNextThink( gpGlobals->curtime + 0.1f ); StudioFrameAdvance( ); EyeOff( ); if ( m_Activity != ACT_TURRET_CLOSE ) { SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); if (!MoveTurret()) { SetActivity( (Activity)ACT_TURRET_CLOSE ); EmitSound( "NPC_Turret.Retire" ); m_OnRetire.FireOutput(NULL, this); } } else if (m_fSequenceFinished) { m_iOn = 0; m_flLastSight = 0; SetActivity( (Activity)ACT_TURRET_CLOSED_IDLE ); Vector curmins, curmaxs; curmins = WorldAlignMins(); curmaxs = WorldAlignMaxs(); curmaxs.z = m_iRetractHeight; curmins.z = -m_iRetractHeight; SetCollisionBounds( curmins, curmaxs ); Relink(); if (m_iAutoStart) { SetThink(AutoSearchThink); SetNextThink( gpGlobals->curtime + .1 ); } else { SetThink(SUB_DoNothing); } } }
// // This search function will sit with the turret deployed and look for a new target. // After a set amount of time, the barrel will spin down. After m_flMaxWait, the turret will // retact. // void CBaseTurret::SearchThink(void) { // ensure rethink SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); StudioFrameAdvance( ); SetNextThink( gpGlobals->curtime + 0.1f ); Ping( ); // If we have a target and we're still healthy if (GetEnemy() != NULL) { if (!GetEnemy()->IsAlive() ) SetEnemy( NULL );// Dead enemy forces a search for new one } // Acquire Target if (GetEnemy() == NULL) { GetSenses()->Look(TURRET_RANGE); SetEnemy( BestEnemy() ); } // If we've found a target, spin up the barrel and start to attack if (GetEnemy() != NULL) { m_flLastSight = 0; SetThink(ActiveThink); } else { // Are we out of time, do we need to retract? if (gpGlobals->curtime > m_flLastSight) { //Before we retrace, make sure that we are spun down. m_flLastSight = 0; SetThink(Retire); } // generic hunt for new victims m_vecGoalAngles.y = (m_vecGoalAngles.y + 0.1 * m_iBaseTurnRate); if (m_vecGoalAngles.y >= 360) m_vecGoalAngles.y -= 360; MoveTurret(); } }
void CBaseTurret::Retire(void) { // make the turret level m_vecGoalAngles.x = 0; m_vecGoalAngles.y = m_flStartYaw; pev->nextthink = gpGlobals->time + 0.1; StudioFrameAdvance( ); EyeOff( ); if (!MoveTurret()) { if (m_iSpin) { SpinDownCall(); } else if (pev->sequence != TURRET_ANIM_RETIRE) { SetTurretAnim(TURRET_ANIM_RETIRE); EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "turret/tu_deploy.wav", TURRET_MACHINE_VOLUME, ATTN_NORM, 0, 120); SUB_UseTargets( this, USE_OFF, 0 ); } else if (m_fSequenceFinished) { m_iOn = 0; m_flLastSight = 0; SetTurretAnim(TURRET_ANIM_NONE); pev->maxs.z = m_iRetractHeight; pev->mins.z = -m_iRetractHeight; UTIL_SetSize(pev, pev->mins, pev->maxs); if (m_iAutoStart) { SetThink(&CBaseTurret::AutoSearchThink); pev->nextthink = gpGlobals->time + .1; } else SetThink(&CBaseTurret::SUB_DoNothing); } } else { SetTurretAnim(TURRET_ANIM_SPIN); } }
void CBaseTurret :: TurretDeath( void ) { StudioFrameAdvance( ); SetNextThink( gpGlobals->curtime + 0.1f ); if (m_lifeState != LIFE_DEAD) { m_lifeState = LIFE_DEAD; EmitSound( "NPC_Turret.Die" ); SetActivity( (Activity)ACT_TURRET_CLOSE ); EyeOn( ); } EyeOff( ); if (m_flDamageTime + random->RandomFloat( 0, 2 ) > gpGlobals->curtime) { // lots of smoke Vector pos; CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos ); pos.z = CollisionProp()->GetCollisionOrigin().z; CBroadcastRecipientFilter filter; te->Smoke( filter, 0.0, &pos, g_sModelIndexSmoke, 2.5, 10 ); } if (m_flDamageTime + random->RandomFloat( 0, 5 ) > gpGlobals->curtime) { Vector vecSrc; CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecSrc ); g_pEffects->Sparks( vecSrc ); } if (m_fSequenceFinished && !MoveTurret( ) && m_flDamageTime + 5 < gpGlobals->curtime) { m_flPlaybackRate = 0; SetThink( NULL ); } }
void CBaseTurret :: TurretDeath( void ) { BOOL iActive = FALSE; StudioFrameAdvance( ); pev->nextthink = gpGlobals->time + 0.1; if (pev->deadflag != DEAD_DEAD) { pev->deadflag = DEAD_DEAD; float flRndSound = RANDOM_FLOAT ( 0 , 1 ); if ( flRndSound <= 0.33 ) EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die.wav", 1.0, ATTN_NORM); else if ( flRndSound <= 0.66 ) EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die2.wav", 1.0, ATTN_NORM); else EMIT_SOUND(ENT(pev), CHAN_BODY, "turret/tu_die3.wav", 1.0, ATTN_NORM); EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "turret/tu_active2.wav", 0, 0, SND_STOP, 100); if (m_iOrientation == 0) m_vecGoalAngles.x = -15; else m_vecGoalAngles.x = -90; SetTurretAnim(TURRET_ANIM_DIE); EyeOn( ); } EyeOff( ); if (pev->dmgtime + RANDOM_FLOAT( 0, 2 ) > gpGlobals->time) { // lots of smoke MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_SMOKE ); WRITE_COORD( RANDOM_FLOAT( pev->absmin.x, pev->absmax.x ) ); WRITE_COORD( RANDOM_FLOAT( pev->absmin.y, pev->absmax.y ) ); WRITE_COORD( pev->origin.z - m_iOrientation * 64 ); WRITE_SHORT( g_sModelIndexSmoke ); WRITE_BYTE( 25 ); // scale * 10 WRITE_BYTE( 10 - m_iOrientation * 5); // framerate MESSAGE_END(); } if (pev->dmgtime + RANDOM_FLOAT( 0, 5 ) > gpGlobals->time) { Vector vecSrc = Vector( RANDOM_FLOAT( pev->absmin.x, pev->absmax.x ), RANDOM_FLOAT( pev->absmin.y, pev->absmax.y ), 0 ); if (m_iOrientation == 0) vecSrc = vecSrc + Vector( 0, 0, RANDOM_FLOAT( pev->origin.z, pev->absmax.z ) ); else vecSrc = vecSrc + Vector( 0, 0, RANDOM_FLOAT( pev->absmin.z, pev->origin.z ) ); UTIL_Sparks( vecSrc ); } if (m_fSequenceFinished && !MoveTurret( ) && pev->dmgtime + 5 < gpGlobals->time) { pev->framerate = 0; SetThink( NULL ); } }
void CBaseTurret::ActiveThink(void) { int fAttack = 0; Vector vecDirToEnemy; pev->nextthink = gpGlobals->time + 0.1; StudioFrameAdvance( ); if ((!m_iOn) || (m_hEnemy == NULL)) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } // if it's dead, look for something new if ( !m_hEnemy->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->time + 0.5; // continue-shooting timeout } else { if (gpGlobals->time > m_flLastSight) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } } } Vector vecMid = pev->origin + pev->view_ofs; Vector vecMidEnemy = m_hEnemy->BodyTarget( vecMid ); // Look for our current enemy int fEnemyVisible = FBoxVisible(pev, m_hEnemy->pev, vecMidEnemy ); vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy float flDistToEnemy = vecDirToEnemy.Length(); Vector vec = UTIL_VecToAngles(vecMidEnemy - vecMid); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { if (!m_flLastSight) m_flLastSight = gpGlobals->time + 0.5; else { // Should we look for a new target? if (gpGlobals->time > m_flLastSight) { m_hEnemy = NULL; m_flLastSight = gpGlobals->time + m_flMaxWait; SetThink(&CBaseTurret::SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } UTIL_MakeAimVectors(m_vecCurAngles); /* ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", m_vecCurAngles.x, m_vecCurAngles.y, gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); */ Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight; vecLOS = vecLOS.Normalize(); // Is the Gun looking at the target if (DotProduct(vecLOS, gpGlobals->v_forward) <= 0.866) // 30 degree slop fAttack = FALSE; else fAttack = TRUE; // fire the gun if (m_iSpin && ((fAttack) || (m_fBeserk))) { Vector vecSrc, vecAng; GetAttachment( 0, vecSrc, vecAng ); SetTurretAnim(TURRET_ANIM_FIRE); Shoot(vecSrc, gpGlobals->v_forward ); } else { SetTurretAnim(TURRET_ANIM_SPIN); } //move the gun if (m_fBeserk) { if (RANDOM_LONG(0,9) == 0) { m_vecGoalAngles.y = RANDOM_FLOAT(0,360); m_vecGoalAngles.x = RANDOM_FLOAT(0,90) - 90 * m_iOrientation; TakeDamage(pev,pev,1, DMG_GENERIC); // don't beserk forever return; } } else if (fEnemyVisible) { if (vec.y > 360) vec.y -= 360; if (vec.y < 0) vec.y += 360; //ALERT(at_console, "[%.2f]", vec.x); if (vec.x < -180) vec.x += 360; if (vec.x > 180) vec.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-90...15] if (m_iOrientation == 0) { if (vec.x > 90) vec.x = 90; else if (vec.x < m_iMinPitch) vec.x = m_iMinPitch; } else { if (vec.x < -90) vec.x = -90; else if (vec.x > -m_iMinPitch) vec.x = -m_iMinPitch; } // ALERT(at_console, "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vec.y; m_vecGoalAngles.x = vec.x; } SpinUpCall(); MoveTurret(); }
//----------------------------------------------------------------------------- // Rotate and scan for targets //----------------------------------------------------------------------------- void CObjectSentrygun::SentryRotate( void ) { // if we're playing a fire gesture, stop it if ( IsPlayingGesture( ACT_RANGE_ATTACK1 ) ) { RemoveGesture( ACT_RANGE_ATTACK1 ); } if ( IsPlayingGesture( ACT_RANGE_ATTACK1_LOW ) ) { RemoveGesture( ACT_RANGE_ATTACK1_LOW ); } // animate StudioFrameAdvance(); // Look for a target if ( FindTarget() ) return; // Rotate if ( !MoveTurret() ) { // Change direction if ( IsDisabled() ) { EmitSound( "Building_Sentrygun.Disabled" ); m_vecGoalAngles.x = 30; } else { switch( m_iUpgradeLevel ) { case 1: default: EmitSound( "Building_Sentrygun.Idle" ); break; case 2: EmitSound( "Building_Sentrygun.Idle2" ); break; case 3: EmitSound( "Building_Sentrygun.Idle3" ); break; } // Switch rotation direction if ( m_bTurningRight ) { m_bTurningRight = false; m_vecGoalAngles.y = m_iLeftBound; } else { m_bTurningRight = true; m_vecGoalAngles.y = m_iRightBound; } // Randomly look up and down a bit if (random->RandomFloat(0, 1) < 0.3) { m_vecGoalAngles.x = (int)random->RandomFloat(-10,10); } } } }
//========================================================= // ActiveThink - //========================================================= void CNPC_BaseTurret::ActiveThink(void) { int fAttack = 0; SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance( ); if ( (!m_iOn) || (GetEnemy() == NULL) ) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } // if it's dead, look for something new if ( !GetEnemy()->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout } else { if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } } Vector vecMid = GetAbsOrigin() + GetViewOffset(); Vector vecMidEnemy = GetEnemy()->BodyTarget( vecMid, false ); // Look for our current enemy int fEnemyVisible = FBoxVisible(this, GetEnemy(), vecMidEnemy ); //We want to look at the enemy's eyes so we don't jitter Vector vecDirToEnemyEyes = vecMidEnemy - vecMid; float flDistToEnemy = vecDirToEnemyEyes.Length(); VectorNormalize( vecDirToEnemyEyes ); QAngle vecAnglesToEnemy; VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { if (!m_flLastSight) m_flLastSight = gpGlobals->curtime + 0.5; else { // Should we look for a new target? if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(&CNPC_BaseTurret::SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } //ALERT( at_console, "%.0f %.0f : %.2f %.2f %.2f\n", // m_vecCurAngles.x, m_vecCurAngles.y, // gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_forward.z ); Vector vecLOS = vecDirToEnemyEyes; //vecMid - m_vecLastSight; VectorNormalize( vecLOS ); Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( 1, vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); // Is the Gun looking at the target if (DotProduct(vecLOS, vecMuzzleDir) <= 0.866) // 30 degree slop fAttack = FALSE; else fAttack = TRUE; //forward // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecMuzzleDir * 200 ), 255,0,0, false, 0.1); //LOS // NDebugOverlay::Line(vecMuzzle, vecMid + ( vecLOS * 200 ), 0,0,255, false, 0.1); // fire the gun if (m_iSpin && ((fAttack) || (m_fBeserk))) { Vector vecOrigin; QAngle vecAngles; GetAttachment( 1, vecOrigin, vecAngles ); Shoot(vecOrigin, vecMuzzleDir ); SetTurretAnim(TURRET_ANIM_FIRE); } else { SetTurretAnim(TURRET_ANIM_SPIN); } //move the gun if (m_fBeserk) { if (random->RandomInt(0,9) == 0) { m_vecGoalAngles.y = random->RandomFloat(0,360); m_vecGoalAngles.x = random->RandomFloat(0,90) - 90 * m_iOrientation; CTakeDamageInfo info; info.SetAttacker(this); info.SetInflictor(this); info.SetDamage( 1 ); info.SetDamageType( DMG_GENERIC ); TakeDamage( info ); // don't beserk forever return; } } else if (fEnemyVisible) { if (vecAnglesToEnemy.y > 360) vecAnglesToEnemy.y -= 360; if (vecAnglesToEnemy.y < 0) vecAnglesToEnemy.y += 360; //ALERT(at_console, "[%.2f]", vec.x); if (vecAnglesToEnemy.x < -180) vecAnglesToEnemy.x += 360; if (vecAnglesToEnemy.x > 180) vecAnglesToEnemy.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-90...14] if (m_iOrientation == TURRET_ORIENTATION_FLOOR) { if (vecAnglesToEnemy.x > 90) vecAnglesToEnemy.x = 90; else if (vecAnglesToEnemy.x < m_iMinPitch) vecAnglesToEnemy.x = m_iMinPitch; } else { if (vecAnglesToEnemy.x < -90) vecAnglesToEnemy.x = -90; else if (vecAnglesToEnemy.x > -m_iMinPitch) vecAnglesToEnemy.x = -m_iMinPitch; } //DevMsg( 1, "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vecAnglesToEnemy.y; m_vecGoalAngles.x = vecAnglesToEnemy.x; } SpinUpCall(); MoveTurret(); }
void CBaseTurret::ActiveThink(void) { int fAttack = 0; Vector vecDirToEnemy; SetNextThink( gpGlobals->curtime + 0.1f ); StudioFrameAdvance( ); if ((!m_iOn) || (GetEnemy() == NULL)) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(SearchThink); return; } // if it's dead, look for something new if ( !GetEnemy()->IsAlive() ) { if (!m_flLastSight) { m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout } else { if (gpGlobals->curtime > m_flLastSight) { SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(SearchThink); return; } } } Vector vecMid = EyePosition( ); Vector vecMidEnemy = GetEnemy()->BodyTarget(vecMid); // g_pEffects->Sparks( vecMid ); // g_pEffects->Sparks( vecMidEnemy ); // Look for our current enemy //int fEnemyVisible = FBoxVisible( this, GetEnemy(), vecMidEnemy ); int fEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() ); vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy // NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.1 ); float flDistToEnemy = vecDirToEnemy.Length(); QAngle vecAnglesToEnemy; VectorNormalize( vecDirToEnemy ); VectorAngles( vecDirToEnemy, vecAnglesToEnemy ); // Current enmey is not visible. if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) { // DevMsg( "lost you\n" ); if (!m_flLastSight) { m_flLastSight = gpGlobals->curtime + 0.5; } else { // Should we look for a new target? if (gpGlobals->curtime > m_flLastSight) { ClearEnemyMemory(); SetEnemy( NULL ); m_flLastSight = gpGlobals->curtime + m_flMaxWait; SetThink(SearchThink); return; } } fEnemyVisible = 0; } else { m_vecLastSight = vecMidEnemy; } Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight; VectorNormalize( vecLOS ); Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); // Is the Gun looking at the target if (DotProduct(vecLOS, vecMuzzleDir) <= 0.9848) // 10 degree slop { fAttack = FALSE; } else { fAttack = TRUE; } // fire the gun if (fAttack || m_fBeserk) { m_Activity = ACT_RESET; SetActivity( (Activity)ACT_TURRET_FIRE ); Shoot(vecMuzzle, vecMuzzleDir ); } else { SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); } //move the gun if (m_fBeserk) { // DevMsg( "berserk" ); if (random->RandomInt(0,9) == 0) { m_vecGoalAngles.y = random->RandomFloat(-180,180); m_vecGoalAngles.x = random->RandomFloat(-90,90); OnTakeDamage( CTakeDamageInfo( this, this, 1, DMG_GENERIC ) ); // don't beserk forever return; } } else if (fEnemyVisible) { // DevMsg( "->[%.2f]\n", vec.x); m_vecGoalAngles.y = vecAnglesToEnemy.y; m_vecGoalAngles.x = vecAnglesToEnemy.x; } MoveTurret(); }
void C_ObjectSentrygun::ClientThink( void ) { // Turtling sentryguns don't think if ( IsTurtled() ) return; if ( IsPlacing() || IsBuilding() ) return; if ( m_hEnemy != NULL ) { // Figure out where we're firing at Vector vecMid = EyePosition(); Vector vecFireTarget = m_hEnemy->WorldSpaceCenter(); // + vecMid; // BodyTarget( vecMid ); Vector vecDirToEnemy = vecFireTarget - vecMid; QAngle angToTarget; VectorAngles(vecDirToEnemy, angToTarget); angToTarget.y = UTIL_AngleMod( angToTarget.y ); if (angToTarget.x < -180) angToTarget.x += 360; if (angToTarget.x > 180) angToTarget.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-50...50] if (angToTarget.x > 50) angToTarget.x = 50; else if (angToTarget.x < -50) angToTarget.x = -50; m_vecGoalAngles.y = angToTarget.y; m_vecGoalAngles.x = angToTarget.x; MoveTurret(); return; } // Rotate if ( !MoveTurret() ) { // Play a sound occasionally if ( random->RandomFloat(0, 1) < 0.02 ) { EmitSound( "ObjectSentrygun.Idle" ); } // Switch rotation direction if (m_bTurningRight) { m_bTurningRight = false; m_vecGoalAngles.y = m_iLeftBound; } else { m_bTurningRight = true; m_vecGoalAngles.y = m_iRightBound; } // Randomly look up and down a bit if ( random->RandomFloat(0, 1) < 0.3 ) { m_vecGoalAngles.x = (int)random->RandomFloat(-10,10); } } }