void CNPC_Monk::RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_RELOAD: { Activity reloadGesture = TranslateActivity( ACT_GESTURE_RELOAD ); if ( GetIdealActivity() != ACT_RELOAD && reloadGesture != ACT_INVALID ) { if ( !IsPlayingGesture( reloadGesture ) ) { if ( GetShotRegulator() ) { GetShotRegulator()->Reset( false ); } TaskComplete(); } return; } BaseClass::RunTask( pTask ); } break; default: BaseClass::RunTask( pTask ); break; } }
void CNPC_Monk::StartTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_RELOAD: { if ( GetActiveWeapon() && GetActiveWeapon()->HasPrimaryAmmo() ) { // Don't reload if you have done so while moving (See BACK_AWAY_AND_RELOAD schedule). TaskComplete(); return; } if( m_iNumZombies >= 2 && random->RandomInt( 1, 3 ) == 1 ) { SpeakIfAllowed( TLK_ATTACKING ); } Activity reloadGesture = TranslateActivity( ACT_GESTURE_RELOAD ); if ( reloadGesture != ACT_INVALID && IsPlayingGesture( reloadGesture ) ) { ResetIdealActivity( ACT_IDLE ); return; } BaseClass::StartTask( pTask ); } break; default: BaseClass::StartTask( pTask ); break; } }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ int CBaseAnimatingOverlay::AddGesture( Activity activity, bool autokill /*= true*/ ) { if ( IsPlayingGesture( activity ) ) { return FindGestureLayer( activity ); } MDLCACHE_CRITICAL_SECTION(); int seq = SelectWeightedSequence( activity ); if ( seq <= 0 ) { const char *actname = CAI_BaseNPC::GetActivityName( activity ); DevMsg( "CBaseAnimatingOverlay::AddGesture: model %s missing activity %s\n", STRING(GetModelName()), actname ); return -1; } int i = AddGestureSequence( seq, autokill ); Assert( i != -1 ); if ( i != -1 ) { m_AnimOverlay[ i ].m_nActivity = activity; } return i; }
//----------------------------------------------------------------------------- // Fire on our target //----------------------------------------------------------------------------- bool CObjectSentrygun::Fire() { //NDebugOverlay::Cross3D( m_hEnemy->WorldSpaceCenter(), 10, 255, 0, 0, false, 0.1 ); Vector vecAimDir; // Level 3 Turrets fire rockets every 3 seconds if ( m_iUpgradeLevel == 3 && m_iAmmoRockets > 0 && m_flNextRocketAttack < gpGlobals->curtime ) { Vector vecSrc; QAngle vecAng; // alternate between the 2 rocket launcher ports. if ( m_iAmmoRockets & 1 ) { GetAttachment( m_iAttachments[SENTRYGUN_ATTACHMENT_ROCKET_L], vecSrc, vecAng ); } else { GetAttachment( m_iAttachments[SENTRYGUN_ATTACHMENT_ROCKET_R], vecSrc, vecAng ); } vecAimDir = m_hEnemy->WorldSpaceCenter() - vecSrc; vecAimDir.NormalizeInPlace(); // NOTE: vecAng is not actually set by GetAttachment!!! QAngle angDir; VectorAngles( vecAimDir, angDir ); EmitSound( "Building_Sentrygun.FireRocket" ); AddGesture( ACT_RANGE_ATTACK2 ); QAngle angAimDir; VectorAngles( vecAimDir, angAimDir ); CTFProjectile_SentryRocket *pProjectile = CTFProjectile_SentryRocket::Create( vecSrc, angAimDir, this, GetBuilder() ); if ( pProjectile ) { pProjectile->SetDamage( 100 ); } // Setup next rocket shot m_flNextRocketAttack = gpGlobals->curtime + 3; if ( !tf_sentrygun_ammocheat.GetBool() && !HasSpawnFlags( SF_SENTRY_INFINITE_AMMO ) ) { m_iAmmoRockets--; } if (m_iAmmoRockets == 10) ClientPrint( GetBuilder(), HUD_PRINTNOTIFY, "#Sentry_rocketslow"); if (m_iAmmoRockets == 0) ClientPrint( GetBuilder(), HUD_PRINTNOTIFY, "#Sentry_rocketsout"); } // All turrets fire shells if ( m_iAmmoShells > 0) { if ( !IsPlayingGesture( ACT_RANGE_ATTACK1 ) ) { RemoveGesture( ACT_RANGE_ATTACK1_LOW ); AddGesture( ACT_RANGE_ATTACK1 ); } Vector vecSrc; QAngle vecAng; int iAttachment; if ( m_iUpgradeLevel > 1 && (m_iAmmoShells & 1) ) { // level 2 and 3 turrets alternate muzzles each time they fizzy fizzy fire. iAttachment = m_iAttachments[SENTRYGUN_ATTACHMENT_MUZZLE_ALT]; } else { iAttachment = m_iAttachments[SENTRYGUN_ATTACHMENT_MUZZLE]; } GetAttachment( iAttachment, vecSrc, vecAng ); Vector vecMidEnemy = m_hEnemy->WorldSpaceCenter(); // If we cannot see their WorldSpaceCenter ( possible, as we do our target finding based // on the eye position of the target ) then fire at the eye position trace_t tr; UTIL_TraceLine( vecSrc, vecMidEnemy, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr); if ( !tr.m_pEnt || tr.m_pEnt->IsWorld() ) { // Hack it lower a little bit.. // The eye position is not always within the hitboxes for a standing TF Player vecMidEnemy = m_hEnemy->EyePosition() + Vector(0,0,-5); } vecAimDir = vecMidEnemy - vecSrc; float flDistToTarget = vecAimDir.Length(); vecAimDir.NormalizeInPlace(); //NDebugOverlay::Cross3D( vecSrc, 10, 255, 0, 0, false, 0.1 ); FireBulletsInfo_t info; info.m_vecSrc = vecSrc; info.m_vecDirShooting = vecAimDir; info.m_iTracerFreq = 1; info.m_iShots = 1; info.m_pAttacker = GetBuilder(); info.m_vecSpread = vec3_origin; info.m_flDistance = flDistToTarget + 100; info.m_iAmmoType = m_iAmmoType; info.m_flDamage = tf_sentrygun_damage.GetFloat(); FireBullets( info ); //NDebugOverlay::Line( vecSrc, vecSrc + vecAimDir * 1000, 255, 0, 0, false, 0.1 ); CEffectData data; data.m_nEntIndex = entindex(); data.m_nAttachmentIndex = iAttachment; data.m_fFlags = m_iUpgradeLevel; data.m_vOrigin = vecSrc; DispatchEffect( "TF_3rdPersonMuzzleFlash_SentryGun", data ); switch( m_iUpgradeLevel ) { case 1: default: EmitSound( "Building_Sentrygun.Fire" ); break; case 2: EmitSound( "Building_Sentrygun.Fire2" ); break; case 3: EmitSound( "Building_Sentrygun.Fire3" ); break; } if ( !tf_sentrygun_ammocheat.GetBool() && !HasSpawnFlags( SF_SENTRY_INFINITE_AMMO ) ) { m_iAmmoShells--; } } else { if ( m_iUpgradeLevel > 1 ) { if ( !IsPlayingGesture( ACT_RANGE_ATTACK1_LOW ) ) { RemoveGesture( ACT_RANGE_ATTACK1 ); AddGesture( ACT_RANGE_ATTACK1_LOW ); } } // Out of ammo, play a click EmitSound( "Building_Sentrygun.Empty" ); m_flNextAttack = gpGlobals->curtime + 0.2; } return true; }
//----------------------------------------------------------------------------- // 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); } } } }