Vector CNPC_Hydra::TestPosition( float t ) { // return GetAbsOrigin( ) + Vector( sin( (m_seed + t) * 2.3 ) * 15, cos( (m_seed + t) * 2.4 ) * 150, sin( ( m_seed + t ) * 1.8 ) * 50 ) + m_vecOutward * sv_hydraLength.GetFloat();; t = (int)(t * 0.2); #if 1 Vector tmp = Vector( sin( (m_seed + t) * 0.8 ) * 15, cos( (m_seed + t) * 0.9 ) * 150, sin( ( m_seed + t ) * 0.4 ) * 50 ); tmp += Vector( sin( (m_seed + t) * 1.0 ) * 4, cos( (m_seed + t) * 0.9 ) * 4, sin( ( m_seed + t ) * 1.1 ) * 6 ); tmp += GetAbsOrigin( ) + m_vecOutward * sv_hydraLength.GetFloat(); return tmp; #else Vector tmp; tmp.Init; CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetLocalPlayer(); if ( pPlayer ) { tmp = pPlayer->EyePosition( ); Vector delta = (tmp - GetAbsOrigin( )); if (delta.Length() > 200) { tmp = GetAbsOrigin( ) + Vector( 0, 0, 200 ); } m_vecHeadDir = (pPlayer->EyePosition( ) - m_body[m_body.Count()-2].vecPos); VectorNormalize( m_vecHeadDir ); } return tmp; #endif // m_vecHeadGoal = GetAbsOrigin( ) + Vector( sin( gpGlobals->curtime * 0.3 ) * 15, cos( gpGlobals->curtime * 0.4 ) * 150, sin( gpGlobals->curtime * 0.2 ) * 50 + dt ); }
//--------------------------------------------------------- //--------------------------------------------------------- bool CAI_FreePass::ShouldAllowFVisible(bool bBaseResult ) { CBaseEntity * pTarget = GetPassTarget(); AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); if ( !bBaseResult || HasPass() ) return false; bool bIsVisible = true; // Peek logic if ( m_Params.peekTime > 0.1 ) { float lastTimeSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; if ( ( lastTimeSeen == AI_INVALID_TIME || gpGlobals->curtime - lastTimeSeen > m_Params.peekTime ) && ( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.peekTimeAfterDamage ) ) { Vector vToTarget; VectorSubtract( pTarget->EyePosition(), GetOuter()->EyePosition(), vToTarget ); vToTarget.z = 0.0f; VectorNormalize( vToTarget ); Vector vecRight( -vToTarget.y, vToTarget.x, 0.0f ); trace_t tr; UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_OPAQUE, GetOuter(), COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) { if ( free_pass_peek_debug.GetBool() ) NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); bIsVisible = false; } if ( bIsVisible ) { UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (-vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_OPAQUE, GetOuter(), COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) { if ( free_pass_peek_debug.GetBool() ) NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); bIsVisible = false; } } } if ( bIsVisible && free_pass_peek_debug.GetBool() ) NDebugOverlay::Line( GetOuter()->EyePosition(), pTarget->EyePosition() - Vector( 0, 0, 2), 255, 0, 0, false, 0.1 ); } return bIsVisible; }
Vector CCalcPosition::CalcPosition( CBaseEntity *pLocus ) { CBaseEntity *pSubject = UTIL_FindEntityByTargetname(NULL, STRING(pev->netname), pLocus); Vector vecOffset = CalcLocus_Velocity( this, pLocus, STRING(pev->message)); Vector vecPosition; Vector vecJunk; Vector vecResult; switch (pev->impulse) { case 1: //eyes vecResult = vecOffset + pSubject->EyePosition(); //ALERT(at_console, "calc_subpos returns %f %f %f\n", vecResult.x, vecResult.y, vecResult.z); return vecResult; //return vecOffset + pLocus->EyePosition(); case 2: // top return vecOffset + pSubject->pev->origin + Vector( (pSubject->pev->mins.x + pSubject->pev->maxs.x)/2, (pSubject->pev->mins.y + pSubject->pev->maxs.y)/2, pSubject->pev->maxs.z ); case 3: // centre return vecOffset + pSubject->pev->origin + Vector( (pSubject->pev->mins.x + pSubject->pev->maxs.x)/2, (pSubject->pev->mins.y + pSubject->pev->maxs.y)/2, (pSubject->pev->mins.z + pSubject->pev->maxs.z)/2 ); case 4: // bottom return vecOffset + pSubject->pev->origin + Vector( (pSubject->pev->mins.x + pSubject->pev->maxs.x)/2, (pSubject->pev->mins.y + pSubject->pev->maxs.y)/2, pSubject->pev->mins.z ); case 5: // this could cause problems. // is there a good way to check whether it's really a CBaseAnimating? ((CBaseAnimating*)pSubject)->GetAttachment( 0, vecPosition, vecJunk ); return vecOffset + vecPosition; case 6: ((CBaseAnimating*)pSubject)->GetAttachment( 1, vecPosition, vecJunk ); return vecOffset + vecPosition; case 7: ((CBaseAnimating*)pSubject)->GetAttachment( 2, vecPosition, vecJunk ); return vecOffset + vecPosition; case 8: ((CBaseAnimating*)pSubject)->GetAttachment( 3, vecPosition, vecJunk ); return vecOffset + vecPosition; case 9: return vecOffset + pSubject->pev->origin + Vector( RANDOM_FLOAT(pSubject->pev->mins.x, pSubject->pev->maxs.x), RANDOM_FLOAT(pSubject->pev->mins.y, pSubject->pev->maxs.y), RANDOM_FLOAT(pSubject->pev->mins.z, pSubject->pev->maxs.z) ); default: return vecOffset + pSubject->pev->origin; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponMedigun::MaintainTargetInSlot() { CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() ); if ( !pOwner ) return; CBaseEntity *pTarget = m_hHealingTarget; Assert( pTarget ); // Make sure the guy didn't go out of range. bool bLostTarget = true; Vector vecSrc = pOwner->Weapon_ShootPosition( ); Vector vecTargetPoint = pTarget->WorldSpaceCenter(); Vector vecPoint; // If it's brush built, use absmins/absmaxs pTarget->CollisionProp()->CalcNearestPoint( vecSrc, &vecPoint ); float flDistance = (vecPoint - vecSrc).Length(); if ( flDistance < GetStickRange() ) { if ( m_flNextTargetCheckTime > gpGlobals->curtime ) return; m_flNextTargetCheckTime = gpGlobals->curtime + 1.0f; trace_t tr; CMedigunFilter drainFilter( pOwner ); Vector vecAiming; pOwner->EyeVectors( &vecAiming ); Vector vecEnd = vecSrc + vecAiming * GetTargetRange(); UTIL_TraceLine( vecSrc, vecEnd, (MASK_SHOT & ~CONTENTS_HITBOX), pOwner, DMG_GENERIC, &tr ); // Still visible? if ( tr.m_pEnt == pTarget ) return; UTIL_TraceLine( vecSrc, vecTargetPoint, MASK_SHOT, &drainFilter, &tr ); // Still visible? if (( tr.fraction == 1.0f) || (tr.m_pEnt == pTarget)) return; // If we failed, try the target's eye point as well UTIL_TraceLine( vecSrc, pTarget->EyePosition(), MASK_SHOT, &drainFilter, &tr ); if (( tr.fraction == 1.0f) || (tr.m_pEnt == pTarget)) return; } // We've lost this guy if ( bLostTarget ) { RemoveHealingTarget(); } }
int CASW_Parasite::RangeAttack1Conditions( float flDot, float flDist ) { if ( gpGlobals->curtime < m_flNextAttack ) return 0; if ( ( GetFlags() & FL_ONGROUND ) == false ) return 0; // This code stops lots of headcrabs swarming you and blocking you // whilst jumping up and down in your face over and over. It forces // them to back up a bit. If this causes problems, consider using it // for the fast headcrabs only, rather than just removing it.(sjb) if ( flDist < ASW_PARASITE_MIN_JUMP_DIST ) return COND_TOO_CLOSE_TO_ATTACK; if ( flDist > ASW_PARASITE_MAX_JUMP_DIST ) return COND_TOO_FAR_TO_ATTACK; // Make sure the way is clear! CBaseEntity *pEnemy = GetEnemy(); if( pEnemy ) { bool bEnemyIsBullseye = ( dynamic_cast<CNPC_Bullseye *>(pEnemy) != NULL ); trace_t tr; AI_TraceLine( EyePosition(), pEnemy->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt != GetEnemy() ) { if ( !bEnemyIsBullseye || tr.m_pEnt != NULL ) return COND_NONE; } if( GetEnemy()->EyePosition().z - 36.0f > GetAbsOrigin().z ) { // Only run this test if trying to jump at a player who is higher up than me, else this // code will always prevent a headcrab from jumping down at an enemy, and sometimes prevent it // jumping just slightly up at an enemy. Vector vStartHullTrace = GetAbsOrigin(); vStartHullTrace.z += 1.0; Vector vEndHullTrace = GetEnemy()->EyePosition() - GetAbsOrigin(); vEndHullTrace.NormalizeInPlace(); vEndHullTrace *= 8.0; vEndHullTrace += GetAbsOrigin(); AI_TraceHull( vStartHullTrace, vEndHullTrace,GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); if ( tr.m_pEnt != NULL && tr.m_pEnt != GetEnemy() ) { return COND_TOO_CLOSE_TO_ATTACK; } } } return COND_CAN_RANGE_ATTACK1; }
void CASW_Parasite::HandleAnimEvent( animevent_t *pEvent ) { int nEvent = pEvent->Event(); if ( nEvent == AE_HEADCRAB_JUMPATTACK ) { // Ignore if we're in mid air if ( m_bMidJump ) return; CBaseEntity *pEnemy = GetEnemy(); if ( pEnemy ) { if ( m_bCommittedToJump ) { JumpAttack( false, m_vecCommittedJumpPos ); } else { // Jump at my enemy's eyes. JumpAttack( false, pEnemy->EyePosition() ); } m_bCommittedToJump = false; } else { // Jump hop, don't care where. JumpAttack( true ); } return; } else if ( nEvent == AE_PARASITE_INFEST_SPURT) { // spurt some blood from our front claws Vector vecBloodPos; if( GetAttachment( "leftclaw", vecBloodPos ) ) UTIL_ASW_BloodDrips( vecBloodPos, Vector(1,0,0), BLOOD_COLOR_RED, 1 ); if( GetAttachment( "rightclaw", vecBloodPos ) ) UTIL_ASW_BloodDrips( vecBloodPos, Vector(1,0,0), BLOOD_COLOR_RED, 1 ); return; } else if ( nEvent == AE_PARASITE_INFEST) { // we're done infesting, make ourselves vanish FinishedInfesting(); return; } BaseClass::HandleAnimEvent( pEvent ); }
void C_SDKPlayer::ClientThink() { UpdateSoundEvents(); // Pass on through to the base class. BaseClass::ClientThink(); bool bFoundViewTarget = false; Vector vForward; AngleVectors( GetLocalAngles(), &vForward ); for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient ) { CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient ); if(!pEnt || !pEnt->IsPlayer()) continue; if ( pEnt->entindex() == entindex() ) continue; Vector vTargetOrigin = pEnt->GetAbsOrigin(); Vector vMyOrigin = GetAbsOrigin(); Vector vDir = vTargetOrigin - vMyOrigin; if ( vDir.Length() > 128 ) continue; VectorNormalize( vDir ); if ( DotProduct( vForward, vDir ) < 0.0f ) continue; m_vLookAtTarget = pEnt->EyePosition(); bFoundViewTarget = true; break; } if ( bFoundViewTarget == false ) { m_vLookAtTarget = GetAbsOrigin() + vForward * 512; } UpdateIDTarget(); // Avoidance if ( gpGlobals->curtime >= m_fNextThinkPushAway ) { PerformObstaclePushaway( this ); m_fNextThinkPushAway = gpGlobals->curtime + PUSHAWAY_THINK_INTERVAL; } }
BOOL CSoldier::MonsterCheckAttack( void ) { Vector spot1, spot2; CBaseEntity *pTarg; float chance; pTarg = m_hEnemy; // see if any entities are in the way of the shot spot1 = EyePosition(); spot2 = pTarg->EyePosition(); TraceResult tr; UTIL_TraceLine( spot1, spot2, dont_ignore_monsters, dont_ignore_glass, ENT(pev), &tr ); if (tr.fInOpen && tr.fInWater) return FALSE; // sight line crossed contents if (tr.pHit != pTarg->edict()) return FALSE; // don't have a clear shot // missile attack if (gpGlobals->time < m_flAttackFinished) return FALSE; if (m_iEnemyRange == RANGE_FAR) return FALSE; if (m_iEnemyRange == RANGE_MELEE) chance = 0.9f; else if (m_iEnemyRange == RANGE_NEAR) chance = 0.4f; else if (m_iEnemyRange == RANGE_MID) chance = 0.05f; else chance = 0; if (RANDOM_FLOAT(0, 1) < chance) { MonsterMissileAttack(); AttackFinished (1 + RANDOM_FLOAT(0, 1)); if (RANDOM_FLOAT(0, 1) < 0.3f) m_fLeftY = !m_fLeftY; return TRUE; } return FALSE; }
//========================================================= // CheckRangeAttack2 - check bravery and try to resurect dead comrades //========================================================= BOOL CISlave :: CheckRangeAttack2 ( float flDot, float flDist ) { // if ( mp_am_movecorpses.value = 0 ) //si DESACTIVADO // { // return FALSE; // } //SP: regeneracion de colegas activada! if (m_flNextAttack > gpGlobals->time) { return FALSE; } m_hDead = NULL; m_iBravery = 0; CBaseEntity *pEntity = NULL; // while (pEntity = UTIL_FindEntityByClassname( pEntity, m_IslaveFriends )) while ((pEntity = UTIL_FindEntityByClassname( pEntity, "monster_alien_slave" )) != NULL) { TraceResult tr; UTIL_TraceLine( EyePosition( ), pEntity->EyePosition( ), ignore_monsters, ENT(pev), &tr ); if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict()) { if (pEntity->pev->deadflag == DEAD_DEAD) { float d = (pev->origin - pEntity->pev->origin).Length(); if (d < flDist) { m_hDead = pEntity; flDist = d; } m_iBravery--; } else { m_iBravery++; } } } if (m_hDead != NULL) return TRUE; else return FALSE; }
//========================================================= // CheckRangeAttack2 - check bravery and try to resurect dead comrades //========================================================= BOOL CISlave::CheckRangeAttack2(float flDot, float flDist) { return FALSE; if(m_flNextAttack > gpGlobals->time) { return FALSE; } m_hDead = NULL; m_iBravery = 0; CBaseEntity *pEntity = NULL; while((pEntity = UTIL_FindEntityByClassname(pEntity, "monster_alien_slave")) != NULL) { TraceResult tr; UTIL_TraceLine(EyePosition(), pEntity->EyePosition(), ignore_monsters, ENT(pev), &tr); if(tr.flFraction == 1.0 || tr.pHit == pEntity->edict()) { if(pEntity->pev->deadflag == DEAD_DEAD) { float d = (pev->origin - pEntity->pev->origin).Length(); if(d < flDist) { m_hDead = pEntity; flDist = d; } m_iBravery--; } else { m_iBravery++; } } } if(m_hDead != NULL) return TRUE; else return FALSE; }
void C_MSS_Player::ClientThink( void ) { bool bFoundViewTarget = false; Vector vForward; AngleVectors( GetLocalAngles(), &vForward ); for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient ) { CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient ); if(!pEnt || !pEnt->IsPlayer()) continue; if ( pEnt->entindex() == entindex() ) continue; Vector vTargetOrigin = pEnt->GetAbsOrigin(); Vector vMyOrigin = GetAbsOrigin(); Vector vDir = vTargetOrigin - vMyOrigin; if ( vDir.Length() > 128 ) continue; VectorNormalize( vDir ); if ( DotProduct( vForward, vDir ) < 0.0f ) continue; m_vLookAtTarget = pEnt->EyePosition(); bFoundViewTarget = true; break; } if ( bFoundViewTarget == false ) { m_vLookAtTarget = GetAbsOrigin() + vForward * 512; } UpdateIDTarget(); }
void CWalkerMiniStrider::FireMachineGun() { CBaseEntity *pDriver = GetPassenger( VEHICLE_DRIVER ); if ( pDriver ) { // Alternate the gun we're firing char *attachmentNames[2] = { "MachineGun_Left", "MachineGun_Right" }; int iAttachment = LookupAttachment( attachmentNames[!m_bFiringLeftGun] ); m_bFiringLeftGun = !m_bFiringLeftGun; Vector vAttachmentPos; QAngle vAttachmentAngles; GetAttachment( iAttachment, vAttachmentPos, vAttachmentAngles ); Vector vEyePos = pDriver->EyePosition(); Vector vEyeForward; QAngle vecAngles = pDriver->LocalEyeAngles(); // Use the skirmisher's yaw vecAngles[YAW] = GetAbsAngles()[YAW]; AngleVectors( vecAngles, &vEyeForward ); // Trace ahead to find out where the crosshair is aiming trace_t trace; float flMaxRange = tf_skirmisher_machinegun_range.GetFloat(); UTIL_TraceLine( vEyePos, vEyePos + vEyeForward * flMaxRange, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace ); Vector vecDir; if ( trace.fraction < 1.0 ) { vecDir = (trace.endpos - vAttachmentPos ); VectorNormalize( vecDir ); } else { vecDir = vEyeForward; } // Shoot! TFGameRules()->FireBullets( CTakeDamageInfo( this, pDriver, tf_skirmisher_machinegun_damage.GetFloat(), DMG_BULLET ), 1, // Num shots vAttachmentPos, vecDir, VECTOR_CONE_3DEGREES, // Spread flMaxRange, // Range DMG_BULLET, 1, // Tracer freq entindex(), iAttachment, // Attachment ID "MinigunTracer" ); m_flNextShootTime += (1.0f / tf_skirmisher_machinegun_rof.GetFloat()); // Play the fire sound. Vector vCenter = WorldSpaceCenter(); CPASAttenuationFilter filter( this, "Skirmisher.GunSound" ); EmitSound( filter, 0, "Skirmisher.GunSound", &vCenter ); } }
//----------------------------------------------------------------------------- // Purpose: Catches the monster-specific messages that occur when tagged // animation frames are played. // Input : *pEvent - //----------------------------------------------------------------------------- void CNPC_Headcrab::HandleAnimEvent( animevent_t *pEvent ) { switch ( pEvent->event ) { case HC_AE_JUMPATTACK: { RemoveFlag( FL_ONGROUND ); // // Take him off ground so engine doesn't instantly reset FL_ONGROUND. // UTIL_SetOrigin( this, GetAbsOrigin() + Vector( 0 , 0 , 1 )); Vector vecJumpDir; CBaseEntity *pEnemy = GetEnemy(); if ( pEnemy ) { Vector vecEnemyEyePos = pEnemy->EyePosition(); float gravity = sv_gravity.GetFloat(); if ( gravity <= 1 ) { gravity = 1; } // // How fast does the headcrab need to travel to reach my enemy's eyes given gravity? // float height = ( vecEnemyEyePos.z - GetAbsOrigin().z ); if ( height < 16 ) { height = 16; } else if ( height > 120 ) { height = 120; } float speed = sqrt( 2 * gravity * height ); float time = speed / gravity; // // Scale the sideways velocity to get there at the right time // vecJumpDir = vecEnemyEyePos - GetAbsOrigin(); vecJumpDir = vecJumpDir / time; // // Speed to offset gravity at the desired height. // vecJumpDir.z = speed; // // Don't jump too far/fast. // float distance = vecJumpDir.Length(); if ( distance > 650 ) { vecJumpDir = vecJumpDir * ( 650.0 / distance ); } } else { // // Jump hop, don't care where. // Vector forward, up; AngleVectors( GetAbsAngles(), &forward, NULL, &up ); vecJumpDir = Vector( forward.x, forward.y, up.z ) * 350; } int iSound = random->RandomInt( 0 , 1 ); if ( iSound != 0 ) { AttackSound(); } SetAbsVelocity( vecJumpDir ); m_flNextAttack = gpGlobals->curtime + 2; break; } default: { CAI_BaseNPC::HandleAnimEvent( pEvent ); break; } } }
void CNPC_Hydra::RunTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_HYDRA_DEPLOY: { m_flHeadGoalInfluence = 1.0; float dist = (EyePosition() - m_vecHeadGoal).Length(); if (dist < m_idealSegmentLength) { TaskComplete(); } AimHeadInTravelDirection( 0.2 ); } break; case TASK_HYDRA_PREP_STAB: { int i; if (m_body.Count() < 2) { TaskFail( "hydra is too short to begin stab" ); return; } CBaseEntity *pTarget = GetTarget(); if (pTarget == NULL) { TaskFail( FAIL_NO_TARGET ); } if (pTarget->IsPlayer()) { m_vecTarget = pTarget->EyePosition( ); } else { m_vecTarget = pTarget->BodyTarget( EyePosition( ) ); } float distToTarget = (m_vecTarget - m_vecHeadGoal).Length(); float distToBase = (m_vecHeadGoal - GetAbsOrigin()).Length(); m_idealLength = distToTarget + distToBase * 0.5; if (m_idealLength > HYDRA_MAX_LENGTH) m_idealLength = HYDRA_MAX_LENGTH; if (distToTarget < 100.0) { m_vecTargetDir = (m_vecTarget - m_vecHeadGoal); VectorNormalize( m_vecTargetDir ); m_vecHeadGoal = m_vecHeadGoal - m_vecTargetDir * (100 - distToTarget) * 0.5; } else if (distToTarget > 200.0) { m_vecTargetDir = (m_vecTarget - m_vecHeadGoal); VectorNormalize( m_vecTargetDir ); m_vecHeadGoal = m_vecHeadGoal - m_vecTargetDir * (200.0 - distToTarget) * 0.5; } // face enemy m_vecTargetDir = (m_vecTarget - m_body[m_body.Count()-1].vecPos); VectorNormalize( m_vecTargetDir ); m_vecHeadDir = m_vecHeadDir * 0.6 + m_vecTargetDir * 0.4; VectorNormalize( m_vecHeadDir.GetForModify() ); // build tension towards strike time float influence = 1.0 - (m_flTaskEndTime - gpGlobals->curtime) / pTask->flTaskData; if (influence > 1) influence = 1.0; influence = influence * influence * influence; m_flHeadGoalInfluence = influence; // keep head segment straight i = m_body.Count() - 2; m_body[i].vecGoalPos = m_vecHeadGoal - m_vecHeadDir * m_body[i].flActualLength; m_body[i].flGoalInfluence = influence; // curve neck into spiral float distBackFromHead = m_body[i].flActualLength; Vector right, up; VectorVectors( m_vecHeadDir, right, up ); for (i = i - 1; i > 1 && distBackFromHead < distToTarget; i--) { distBackFromHead += m_body[i].flActualLength; float r = (distBackFromHead / 200) * 3.1415 * 2; // spiral Vector p0 = m_vecHeadGoal - m_vecHeadDir * distBackFromHead * 0.5 + cos( r ) * m_body[i].flActualLength * right + sin( r ) * m_body[i].flActualLength * up; // base r = (distBackFromHead / m_idealLength) * 3.1415 * 0.2; r = sin( r ); p0 = p0 * (1 - r) + r * GetAbsOrigin(); m_body[i].vecGoalPos = p0; m_body[i].flGoalInfluence = influence * (1.0 - (distBackFromHead / distToTarget)); /* if ( (pEnemy->EyePosition( ) - m_body[i].vecPos).Length() < distBackFromHead) { if ( gpGlobals->curtime - m_flLastAttackTime > 4.0) { TaskComplete(); } return; } */ } // look to see if any of the goal positions are stuck for (i = i; i < m_body.Count() - 1; i++) { if (m_body[i].bStuck) { Vector delta = DotProduct( m_body[i].vecGoalPos - m_body[i].vecPos, m_vecHeadDir) * m_vecHeadDir; m_vecHeadGoal -= delta * m_body[i].flGoalInfluence; break; } } if ( gpGlobals->curtime >= m_flTaskEndTime ) { if (distToTarget < 500) { TaskComplete( ); return; } else { TaskFail( "target is too far away" ); return; } } } return; case TASK_HYDRA_STAB: { int i; if (m_body.Count() < 2) { TaskFail( "hydra is too short to begin stab" ); return; } if (m_flTaskEndTime <= gpGlobals->curtime) { TaskComplete( ); return; } m_flHeadGoalInfluence = 1.0; // face enemy //m_vecHeadDir = (pEnemy->EyePosition( ) - m_body[m_body.Count()-1].vecPos); //VectorNormalize( m_vecHeadDir.GetForModify() ); // keep head segment straight i = m_body.Count() - 2; m_body[i].vecGoalPos = m_vecHeadGoal + m_vecHeadDir * m_body[i].flActualLength; m_body[i].flGoalInfluence = 1.0; Vector vecToTarget = (m_vecTarget - EyePosition( )); // check to see if we went past target if (DotProduct( vecToTarget, m_vecHeadDir ) < 0.0) { TaskComplete( ); return; } float distToTarget = vecToTarget.Length(); float distToBase = (EyePosition( ) - GetAbsOrigin()).Length(); m_idealLength = distToTarget + distToBase; /* if (distToTarget < 20) { m_vecHeadGoal = m_vecTarget; SetLastAttackTime( gpGlobals->curtime ); TaskComplete(); return; } else */ { // hit enemy m_vecHeadGoal = m_vecTarget + m_vecHeadDir * 300; } if (m_idealLength > HYDRA_MAX_LENGTH) m_idealLength = HYDRA_MAX_LENGTH; // curve neck into spiral float distBackFromHead = m_body[i].flActualLength; Vector right, up; VectorVectors( m_vecHeadDir, right, up ); #if 1 for (i = i - 1; i > 1 && distBackFromHead < distToTarget; i--) { Vector p0 = m_vecHeadGoal - m_vecHeadDir * distBackFromHead * 1.0; m_body[i].vecGoalPos = p0; if ((m_vecTarget - m_body[i].vecPos).Length() > distToTarget + distBackFromHead) { m_body[i].flGoalInfluence = 1.0 - (distBackFromHead / distToTarget); } else { m_body[i].vecGoalPos = EyePosition( ) - m_vecHeadDir * distBackFromHead; m_body[i].flGoalInfluence = 1.0 - (distBackFromHead / distToTarget); } distBackFromHead += m_body[i].flActualLength; } #endif } return; case TASK_HYDRA_PULLBACK: { if (m_body.Count() < 2) { TaskFail( "hydra is too short to begin stab" ); return; } CBaseEntity *pEnemy = (CBaseEntity *)UTIL_GetLocalPlayer(); if (GetEnemy() != NULL) { pEnemy = GetEnemy(); } AimHeadInTravelDirection( 0.2 ); // float dist = (EyePosition() - m_vecHeadGoal).Length(); if (m_flCurrentLength < m_idealLength + m_idealSegmentLength) { TaskComplete(); } } break; default: BaseClass::RunTask( pTask ); break; } }
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 CAI_FreePass::Update( ) { CBaseEntity *pTarget = GetPassTarget(); if ( !pTarget || m_Params.duration < 0.1 ) return; //--------------------------------- // // Free pass logic // AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); // This works with old data because need to do before base class so as to not choose as enemy if ( !HasPass() ) { float timePlayerLastSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; if ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > .15 ) // If didn't see the player last think { trace_t tr; UTIL_TraceLine( pTarget->EyePosition(), GetOuter()->EyePosition(), MASK_OPAQUE, GetOuter(), COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) { float dist = (tr.endpos - tr.startpos).Length() * tr.fraction; if ( dist < m_Params.coverDist ) { if ( ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > m_Params.timeToTrigger ) && ( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.timeToTrigger ) ) { m_FreePassTimeRemaining = m_Params.duration; m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); } } } } } else { float temp = m_FreePassTimeRemaining; m_FreePassTimeRemaining = 0; CAI_Senses *pSenses = GetOuter()->GetSenses(); bool bCanSee = ( pSenses && pSenses->ShouldSeeEntity( pTarget ) && pSenses->CanSeeEntity( pTarget ) ); m_FreePassTimeRemaining = temp; if ( bCanSee ) { if ( !m_FreePassMoveMonitor.TargetMoved( pTarget ) ) m_FreePassTimeRemaining -= 0.1; else Revoke( true ); } else { m_FreePassTimeRemaining += 0.1 * m_Params.refillRate; if ( m_FreePassTimeRemaining > m_Params.duration ) m_FreePassTimeRemaining = m_Params.duration; m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); } } }
void CAI_StandoffBehavior::StartTask( const Task_t *pTask ) { bool fCallBase = false; switch ( pTask->iTask ) { case TASK_RANGE_ATTACK1: { m_ShotRegulator.OnFiredWeapon(); fCallBase = true; break; } case TASK_FIND_COVER_FROM_ENEMY: { StandoffMsg( "TASK_FIND_COVER_FROM_ENEMY\n" ); // If within time window to force change if ( !m_params.fStayAtCover && (!m_TimeForceCoverHint.Expired() || m_RandomCoverChangeTimer.Expired()) ) { m_TimeForceCoverHint.Force(); m_RandomCoverChangeTimer.Set( 8, 16, false ); // @TODO (toml 03-24-03): clean this up be tool-izing base tasks. Right now, this is here to force to not use lateral cover search CBaseEntity *pEntity = GetEnemy(); if ( pEntity == NULL ) { // Find cover from self if no enemy available pEntity = GetOuter(); } CBaseEntity *pLeader = GetPlayerLeader(); if ( pLeader ) { m_PlayerMoveMonitor.SetMark( pLeader, 60 ); } Vector coverPos = vec3_origin; CAI_TacticalServices * pTacticalServices = GetTacticalServices(); const Vector & enemyPos = pEntity->GetAbsOrigin(); Vector enemyEyePos = pEntity->EyePosition(); float coverRadius = GetOuter()->CoverRadius(); const Vector & goalPos = GetStandoffGoalPosition(); bool bTryGoalPosFirst = true; if( pLeader && m_vecStandoffGoalPosition == GOAL_POSITION_INVALID ) { if( random->RandomInt(1, 100) <= 50 ) { // Half the time, if the player is leading, try to find a spot near them bTryGoalPosFirst = false; StandoffMsg( "Not trying goal pos\n" ); } } if( bTryGoalPosFirst ) { // Firstly, try to find cover near the goal position. pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 0, 15*12, &coverPos ); if ( coverPos == vec3_origin ) pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 15*12-0.1, 40*12, &coverPos ); StandoffMsg1( "Trying goal pos, %s\n", ( coverPos == vec3_origin ) ? "failed" : "succeeded" ); } if ( coverPos == vec3_origin ) { // Otherwise, find a node near to self StandoffMsg( "Looking for near cover\n" ); if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) { // Try local lateral cover if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, &coverPos ) ) { // At this point, try again ignoring front lines. Any cover probably better than hanging out in the open m_fIgnoreFronts = true; if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) { if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, &coverPos ) ) { Assert( coverPos == vec3_origin ); } } m_fIgnoreFronts = false; } } } if ( coverPos != vec3_origin ) { AI_NavGoal_t goal(GOALTYPE_COVER, coverPos, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS); GetNavigator()->SetGoal( goal ); GetOuter()->m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; TaskComplete(); } else TaskFail(FAIL_NO_COVER); } else { fCallBase = true; } break; } default: { fCallBase = true; } } if ( fCallBase ) BaseClass::StartTask( pTask ); }
void RadiusFlash( Vector vecSrc, CBaseEntity *pevInflictor, CBaseEntity *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType) { vecSrc.z += 1;// in case grenade is lying on the ground if (!pevAttacker) pevAttacker = pevInflictor; trace_t tr; float flAdjustedDamage; variant_t var; Vector vecEyePos; float fadeTime, fadeHold; Vector vForward; Vector vecLOS; float flDot; CBaseEntity *pEntity = NULL; static float flRadius = 1500; float falloff = flDamage / flRadius; bool bInWater = (UTIL_PointContents(vecSrc) == CONTENTS_WATER); // iterate on all entities in the vicinity. while ((pEntity = gEntList.FindEntityInSphere(pEntity, vecSrc, flRadius)) != NULL) { bool bPlayer = pEntity->IsPlayer(); bool bHostage = (Q_stricmp(pEntity->GetClassname(), "hostage_entity") == 0); if (!bPlayer && !bHostage) continue; vecEyePos = pEntity->EyePosition(); // blasts don't travel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; float percentageOfFlash = PercentageOfFlashForPlayer(pEntity, vecSrc, pevInflictor); if (percentageOfFlash > 0.0) { // decrease damage for an ent that's farther from the grenade flAdjustedDamage = flDamage - (vecSrc - pEntity->EyePosition()).Length() * falloff; if (flAdjustedDamage > 0) { // See if we were facing the flash AngleVectors(pEntity->EyeAngles(), &vForward); vecLOS = (vecSrc - vecEyePos); //float flDistance = vecLOS.Length(); // Normalize both vectors so the dotproduct is in the range -1.0 <= x <= 1.0 vecLOS.NormalizeInPlace(); flDot = DotProduct(vecLOS, vForward); float startingAlpha = 255; // if target is facing the bomb, the effect lasts longer if (flDot >= 0.5) { // looking at the flashbang fadeTime = flAdjustedDamage * 2.5f; fadeHold = flAdjustedDamage * 1.25f; } else if (flDot >= -0.5) { // looking to the side fadeTime = flAdjustedDamage * 1.75f; fadeHold = flAdjustedDamage * 0.8f; } else { // facing away fadeTime = flAdjustedDamage * 1.0f; fadeHold = flAdjustedDamage * 0.75f; startingAlpha = 200; } fadeTime *= percentageOfFlash; fadeHold *= percentageOfFlash; if (bPlayer) { //MOM_TODO: do we want this functionality? // blind players and bots //CMomentumPlayer *player = static_cast<CMomentumPlayer *>(pEntity); //player->Blind( fadeHold, fadeTime, startingAlpha ); // deafen players and bots //player->Deafen( flDistance ); } else if (bHostage) { variant_t val; val.SetFloat(fadeTime); pEntity->AcceptInput("flashbang", pevInflictor, pevAttacker, val, 0); } } } } CPVSFilter filter(vecSrc); te->DynamicLight(filter, 0.0, &vecSrc, 255, 255, 255, 2, 400, 0.1, 768); }
void C_SDKPlayer::ClientThink() { UpdateSoundEvents(); // Pass on through to the base class. BaseClass::ClientThink(); bool bFoundViewTarget = false; Vector vForward; AngleVectors( GetLocalAngles(), &vForward ); for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient ) { CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient ); if(!pEnt || !pEnt->IsPlayer()) continue; if ( pEnt->entindex() == entindex() ) continue; Vector vTargetOrigin = pEnt->GetAbsOrigin(); Vector vMyOrigin = GetAbsOrigin(); Vector vDir = vTargetOrigin - vMyOrigin; if ( vDir.Length() > 128 ) continue; VectorNormalize( vDir ); if ( DotProduct( vForward, vDir ) < 0.0f ) continue; m_vLookAtTarget = pEnt->EyePosition(); bFoundViewTarget = true; break; } if ( bFoundViewTarget == false ) { m_vLookAtTarget = GetAbsOrigin() + vForward * 512; } UpdateIDTarget(); // Avoidance if ( gpGlobals->curtime >= m_fNextThinkPushAway ) { PerformObstaclePushaway( this ); m_fNextThinkPushAway = gpGlobals->curtime + PUSHAWAY_THINK_INTERVAL; } if (Q_strcmp(m_szColorCorrectionFile, cl_colorcorrection_file.GetString())) { if (m_hColorCorrection != INVALID_CLIENT_CCHANDLE) g_pColorCorrectionMgr->RemoveColorCorrection(m_hColorCorrection); m_hColorCorrection = g_pColorCorrectionMgr->AddColorCorrection(VarArgs("materials/correction/%s.raw", cl_colorcorrection_file.GetString())); Q_strncpy(m_szColorCorrectionFile, cl_colorcorrection_file.GetString(), sizeof(m_szColorCorrectionFile)); } g_pColorCorrectionMgr->SetColorCorrectionWeight(m_hColorCorrection, cl_colorcorrection_weight.GetFloat()); }
void C_SDKPlayer::ClientThink() { UpdateSoundEvents(); // Pass on through to the base class. BaseClass::ClientThink(); bool bFoundViewTarget = false; Vector vForward; AngleVectors( GetLocalAngles(), &vForward ); for( int iClient = 1; iClient <= gpGlobals->maxClients; ++iClient ) { CBaseEntity *pEnt = UTIL_PlayerByIndex( iClient ); if(!pEnt || !pEnt->IsPlayer()) continue; if ( pEnt->entindex() == entindex() ) continue; Vector vTargetOrigin = pEnt->GetAbsOrigin(); Vector vMyOrigin = GetAbsOrigin(); Vector vDir = vTargetOrigin - vMyOrigin; if ( vDir.Length() > 128 ) continue; VectorNormalize( vDir ); if ( DotProduct( vForward, vDir ) < 0.0f ) continue; m_vLookAtTarget = pEnt->EyePosition(); bFoundViewTarget = true; break; } if ( bFoundViewTarget == false ) { m_vLookAtTarget = GetAbsOrigin() + vForward * 512; } UpdateIDTarget(); if(isInvisible){ float iAlpha; if(invEnd < gpGlobals->curtime){ GetViewModel()->SetRenderColorA(255); GetViewModel()->SetRenderMode( kRenderNormal ); isInvisible = false; } else if (gpGlobals->curtime-invStart > 0){ iAlpha = min((gpGlobals->curtime-invStart),0.8f)/ 0.8f; GetViewModel()->SetRenderMode( kRenderTransAlpha ); GetViewModel()->SetRenderColorA(255- 200.0f * iAlpha); } } // Avoidance if ( gpGlobals->curtime >= m_fNextThinkPushAway ) { PerformObstaclePushaway( this ); m_fNextThinkPushAway = gpGlobals->curtime + PUSHAWAY_THINK_INTERVAL; } }
//----------------------------------------------------------------------------- // Purpose: Jump at the enemy!! (stole this from the headcrab) // // //----------------------------------------------------------------------------- void CFastZombie::LeapAttack( void ) { RemoveFlag( FL_ONGROUND ); BeginAttackJump(); LeapAttackSound(); // // Take him off ground so engine doesn't instantly reset FL_ONGROUND. // UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); Vector vecJumpDir; CBaseEntity *pEnemy = GetEnemy(); if ( pEnemy ) { Vector vecEnemyEyePos = pEnemy->EyePosition(); float gravity = sv_gravity.GetFloat(); if ( gravity <= 1 ) { gravity = 1; } // // How fast does the zombie need to travel to reach my enemy's eyes given gravity? // float height = ( vecEnemyEyePos.z - GetAbsOrigin().z ); if ( height < 16 ) { height = 16; } else if ( height > 120 ) { height = 120; } float speed = sqrt( 2 * gravity * height ); float time = speed / gravity; // // Scale the sideways velocity to get there at the right time // vecJumpDir = vecEnemyEyePos - GetAbsOrigin(); vecJumpDir = vecJumpDir / time; // // Speed to offset gravity at the desired height. // vecJumpDir.z = speed * 0.75; // quick fix for now. ZOmbie is jumping too high! (sjb) // // Don't jump too far/fast. // #define CLAMP 1000.0 float distance = vecJumpDir.Length(); if ( distance > CLAMP ) { vecJumpDir = vecJumpDir * ( CLAMP / distance ); } // try speeding up a bit. SetAbsVelocity( vecJumpDir ); m_flNextAttack = gpGlobals->curtime + 2; } }
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 } }
//----------------------------------------------------------------------------- // Purpose: Catches the monster-specific events that occur when tagged animation // frames are played. // Input : pEvent - //----------------------------------------------------------------------------- void CNPC_PoisonZombie::HandleAnimEvent( animevent_t *pEvent ) { if ( pEvent->event == AE_ZOMBIE_POISON_PICKUP_CRAB ) { EnableCrab( m_nThrowCrab, false ); SetBodygroup( ZOMBIE_BODYGROUP_THROW, 1 ); return; } if ( pEvent->event == AE_ZOMBIE_POISON_THROW_WARN_SOUND ) { BreatheOffShort(); EmitSound( "NPC_PoisonZombie.ThrowWarn" ); return; } if ( pEvent->event == AE_ZOMBIE_POISON_THROW_SOUND ) { BreatheOffShort(); EmitSound( "NPC_PoisonZombie.Throw" ); return; } if ( pEvent->event == AE_ZOMBIE_POISON_THROW_CRAB ) { SetBodygroup( ZOMBIE_BODYGROUP_THROW, 0 ); CBlackHeadcrab *pCrab = (CBlackHeadcrab *)CreateNoSpawn( GetHeadcrabClassname(), EyePosition(), vec3_angle, this ); pCrab->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); // Fade if our parent is supposed to if ( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) { pCrab->AddSpawnFlags( SF_NPC_FADE_CORPSE ); } // make me the crab's owner to avoid collision issues pCrab->SetOwnerEntity( this ); pCrab->Spawn(); pCrab->SetLocalAngles( GetLocalAngles() ); pCrab->SetActivity( ACT_RANGE_ATTACK1 ); pCrab->SetNextThink( gpGlobals->curtime ); pCrab->PhysicsSimulate(); pCrab->GetMotor()->SetIdealYaw( GetAbsAngles().y ); if ( IsOnFire() ) { pCrab->Ignite( 100.0 ); } CBaseEntity *pEnemy = GetEnemy(); if ( pEnemy ) { Vector vecEnemyEyePos = pEnemy->EyePosition(); pCrab->ThrowAt( vecEnemyEyePos ); } if (m_nCrabCount == 0) { CapabilitiesRemove( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 ); } m_flNextCrabThrowTime = gpGlobals->curtime + random->RandomInt( ZOMBIE_THROW_MIN_DELAY, ZOMBIE_THROW_MAX_DELAY ); return; } if ( pEvent->event == AE_ZOMBIE_POISON_SPIT ) { Vector forward; QAngle qaPunch( 45, random->RandomInt(-5, 5), random->RandomInt(-5, 5) ); AngleVectors( GetLocalAngles(), &forward ); forward = forward * 200; ClawAttack( GetClawAttackRange(), sk_zombie_poison_dmg_spit.GetFloat(), qaPunch, forward, ZOMBIE_BLOOD_BITE ); return; } BaseClass::HandleAnimEvent( pEvent ); }
//========================================================= //========================================================= void CBarnacle :: BarnacleThink ( void ) { CBaseEntity *pTouchEnt; CBaseMonster *pVictim; float flLength; SetNextThink( 0.1 ); if ( m_hEnemy != NULL ) { // barnacle has prey. if ( !m_hEnemy->IsAlive() ) { // someone (maybe even the barnacle) killed the prey. Reset barnacle. m_fLiftingPrey = FALSE;// indicate that we're not lifting prey. m_hEnemy = NULL; return; } if ( m_fLiftingPrey ) { if ( m_hEnemy != NULL && m_hEnemy->pev->deadflag != DEAD_NO ) { // crap, someone killed the prey on the way up. m_hEnemy = NULL; m_fLiftingPrey = FALSE; return; } // still pulling prey. Vector vecNewEnemyOrigin = m_hEnemy->pev->origin; vecNewEnemyOrigin.x = pev->origin.x; vecNewEnemyOrigin.y = pev->origin.y; // guess as to where their neck is vecNewEnemyOrigin.x -= 6 * cos(m_hEnemy->pev->angles.y * M_PI/180.0); vecNewEnemyOrigin.y -= 6 * sin(m_hEnemy->pev->angles.y * M_PI/180.0); m_flAltitude -= BARNACLE_PULL_SPEED; vecNewEnemyOrigin.z += BARNACLE_PULL_SPEED; if ( fabs( pev->origin.z - ( vecNewEnemyOrigin.z + m_hEnemy->pev->view_ofs.z - 8 ) ) < BARNACLE_BODY_HEIGHT ) { // prey has just been lifted into position ( if the victim origin + eye height + 8 is higher // than the bottom of the barnacle, it is assumed that the head is within barnacle's body ) m_fLiftingPrey = FALSE; EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_bite3.wav", 1, ATTN_NORM ); pVictim = m_hEnemy->MyMonsterPointer(); m_flKillVictimTime = gpGlobals->time + 10;// now that the victim is in place, the killing bite will be administered in 10 seconds. if ( pVictim ) { pVictim->BarnacleVictimBitten( pev ); SetActivity ( ACT_EAT ); } } UTIL_SetOrigin ( m_hEnemy, vecNewEnemyOrigin ); } else { // prey is lifted fully into feeding position and is dangling there. pVictim = m_hEnemy->MyMonsterPointer(); if ( m_flKillVictimTime != -1 && gpGlobals->time > m_flKillVictimTime ) { // kill! if ( pVictim ) { pVictim->TakeDamage ( pev, pev, pVictim->pev->health, DMG_SLASH | DMG_ALWAYSGIB ); m_cGibs = 3; } return; } // bite prey every once in a while if ( pVictim && ( RANDOM_LONG(0,49) == 0 ) ) { switch ( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break; case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM ); break; case 2: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM ); break; } pVictim->BarnacleVictimBitten( pev ); } } } else { // barnacle has no prey right now, so just idle and check to see if anything is touching the tongue. // If idle and no nearby client, don't think so often if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) && !HaveCamerasInPVS( edict() ) ) SetNextThink( RANDOM_FLOAT(1,1.5) ); // Stagger a bit to keep barnacles from thinking on the same frame if ( m_fSequenceFinished ) {// this is done so barnacle will fidget. SetActivity ( ACT_IDLE ); m_flTongueAdj = -100; } if ( m_cGibs && RANDOM_LONG(0,99) == 1 ) { // cough up a gib. CGib::SpawnRandomGibs( this, 1, 1 ); m_cGibs--; switch ( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break; case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM ); break; case 2: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM ); break; } } pTouchEnt = TongueTouchEnt( &flLength ); if ( pTouchEnt != NULL && m_fTongueExtended ) { // tongue is fully extended, and is touching someone. if ( pTouchEnt->FBecomeProne() ) { EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_alert2.wav", 1, ATTN_NORM ); SetSequenceByName ( "attack1" ); m_flTongueAdj = -20; m_hEnemy = pTouchEnt; pTouchEnt->pev->movetype = MOVETYPE_FLY; pTouchEnt->pev->velocity = pev->velocity; //LRC- make him come _with_ me pTouchEnt->pev->basevelocity = pev->velocity; //LRC pTouchEnt->pev->origin.x = pev->origin.x; pTouchEnt->pev->origin.y = pev->origin.y; m_fLiftingPrey = TRUE;// indicate that we should be lifting prey. m_flKillVictimTime = -1;// set this to a bogus time while the victim is lifted. m_flAltitude = (pev->origin.z - pTouchEnt->EyePosition().z); } } else { // calculate a new length for the tongue to be clear of anything else that moves under it. if ( m_flAltitude < flLength ) { // if tongue is higher than is should be, lower it kind of slowly. m_flAltitude += BARNACLE_PULL_SPEED; m_fTongueExtended = FALSE; } else { m_flAltitude = flLength; m_fTongueExtended = TRUE; } } } // ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj ); SetBoneController( 0, -(m_flAltitude + m_flTongueAdj) ); StudioFrameAdvance( 0.1 ); }