CBaseMonster *COsprey :: MakeGrunt( Vector vecSrc ) { CBaseEntity *pEntity; CBaseMonster *pGrunt; TraceResult tr; UTIL_TraceLine( vecSrc, vecSrc + Vector( 0, 0, -4096.0), dont_ignore_monsters, ENT(pev), &tr); if ( tr.pHit && Instance( tr.pHit )->pev->solid != SOLID_BSP) return NULL; for (int i = 0; i < m_iUnits; i++) { if (m_hGrunt[i] == NULL || !m_hGrunt[i]->IsAlive()) { if (m_hGrunt[i] != NULL && m_hGrunt[i]->pev->rendermode == kRenderNormal) { m_hGrunt[i]->SUB_StartFadeOut( ); } pEntity = Create( "monster_human_grunt", vecSrc, pev->angles ); pGrunt = pEntity->MyMonsterPointer( ); pGrunt->pev->movetype = MOVETYPE_FLY; pGrunt->pev->velocity = Vector( 0, 0, RANDOM_FLOAT( -196, -128 ) ); pGrunt->SetActivity( ACT_GLIDE ); CBeam *pBeam = CBeam::BeamCreate( "sprites/rope.spr", 10 ); pBeam->PointEntInit( vecSrc + Vector(0,0,112), pGrunt->entindex() ); pBeam->SetFlags( BEAM_FSOLID ); pBeam->SetColor( 255, 255, 255 ); pBeam->SetThink( SUB_Remove ); pBeam->pev->nextthink = gpGlobals->time + -4096.0 * tr.flFraction / pGrunt->pev->velocity.z + 0.5; // ALERT( at_console, "%d at %.0f %.0f %.0f\n", i, m_vecOrigin[i].x, m_vecOrigin[i].y, m_vecOrigin[i].z ); pGrunt->m_vecLastPosition = m_vecOrigin[i]; m_hGrunt[i] = pGrunt; return pGrunt; } } // ALERT( at_console, "none dead\n"); return NULL; }
void CBigMomma::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { if(ptr->iHitgroup != 1) { // didn't hit the sack? if(pev->dmgtime != gpGlobals->time || (RANDOM_LONG(0, 10) < 1)) { UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(1, 2)); pev->dmgtime = gpGlobals->time; } flDamage = 0.1; // don't hurt the monster much, but allow bits_COND_LIGHT_DAMAGE to be generated } else if(gpGlobals->time > m_painSoundTime) { m_painSoundTime = gpGlobals->time + RANDOM_LONG(1, 3); EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pPainSounds); } CBaseMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType); }
void CXenTree :: Think( void ) { float flInterval = StudioFrameAdvance(); pev->nextthink = gpGlobals->time + 0.1; DispatchAnimEvents( flInterval ); switch( GetActivity() ) { case ACT_MELEE_ATTACK1: if ( m_fSequenceFinished ) { SetActivity( ACT_IDLE ); pev->framerate = RANDOM_FLOAT( 0.6, 1.4 ); } break; default: case ACT_IDLE: break; } }
void CBiorifle::WeaponIdle( void ) { if ( m_flTimeWeaponIdle > gpGlobals->time ) return; int iAnim; switch ( RANDOM_LONG( 0, 2 )) { case 0: iAnim = BIORIFLE_IDLE2; break; case 1: iAnim = BIORIFLE_IDLE3; break; case 2: iAnim = BIORIFLE_IDLE; break; } SendWeaponAnim( iAnim ); m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT (10, 15); }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CHellKnight :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case HKNIGHT_IDLE_SOUND: if( m_Activity == ACT_RUN ) CheckForCharge (); if( RANDOM_FLOAT( 0.0f, 1.0f ) < 0.1f ) EMIT_SOUND( edict(), CHAN_VOICE, "hknight/idle.wav", 1.0, ATTN_IDLE ); break; case HKNIGHT_SHOT_SPIKES: ShootSpike( atof( pEvent->options )); break; case HKNIGHT_MELEE_ATTACK: AI_Melee (); break; default: CQuakeMonster::HandleAnimEvent( pEvent ); break; } }
void CTriggerHurt :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if (useType == USE_TOGGLE) { if(m_iState) useType = USE_OFF; else useType = USE_ON; } if (useType == USE_ON) { pev->solid = SOLID_TRIGGER; gpGlobals->force_retouch++; UTIL_SetOrigin( this, pev->origin ); if (pev->button & DMG_RADIATION) SetNextThink( RANDOM_FLOAT(0.0, 0.5) ); m_iState = STATE_ON; } else if (useType == USE_OFF) { pev->solid = SOLID_NOT; UTIL_SetOrigin( this, pev->origin ); if (pev->button & DMG_RADIATION) DontThink(); m_iState = STATE_OFF; } else if (useType == USE_SET) { pev->dmg = value;//set dmg level } else if (useType == USE_RESET) { pev->dmg = 0;//reset dmg level } else if (useType == USE_SHOWINFO) { DEBUGHEAD; ALERT( at_console, "State: %s, Dmg value %g\n", GetStringForState( GetState()), pev->dmg ); PrintStringForDamage( pev->button ); } }
void CRpg::WeaponIdle(void) { UpdateSpot(); if (m_flTimeWeaponIdle > UTIL_GlobalTimeBase()) return; if (m_iClip && !m_iOverloadLevel) { int iAnim; float flRand = RANDOM_FLOAT(0, 1); if (flRand <= 0.75) { iAnim = RPG_IDLE; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + 6.3; } else { iAnim = RPG_IDLE2; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + 6.3; } SendWeaponAnim(iAnim); } }
void Cawp::PrimaryAttack() { if (m_pPlayer->pev->waterlevel == 3 || m_iClip <= 0) { PlayEmptySound( ); m_flNextPrimaryAttack = gpGlobals->time + 0.5; return; } m_iClip--; m_iFiredAmmo++; m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); m_pPlayer->FireMagnumBullets(m_pPlayer->GetGunPosition(), gpGlobals->v_forward, VECTOR_CONE_0DEGREES, 16384, BULLET_338Magnum, m_pPlayer->pev); FX_FireGun(m_pPlayer->pev->v_angle, m_pPlayer->entindex(), (m_pPlayer->m_fHeavyArmor)?AWP_FIRE_SOLID:AWP_FIRE, m_pPlayer->m_fHeavyArmor?1:0, FIREGUN_AWP ); SetThink( shellcasing ); (m_pPlayer->m_fHeavyArmor)?pev->nextthink = gpGlobals->time + 0.6:pev->nextthink = gpGlobals->time + 1.15; (m_pPlayer->m_fHeavyArmor)?m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.2:m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.8; m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT (8, 12); }
/* ========================= HUD_StudioEvent The entity's studio model description indicated an event was fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound ) ========================= */ void HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity ) { switch( event->event ) { case 5001: gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[0], Q_atoi( event->options )); break; case 5011: gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[1], Q_atoi( event->options )); break; case 5021: gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[2], Q_atoi( event->options )); break; case 5031: gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[3], Q_atoi( event->options )); break; case 5002: gEngfuncs.pEfxAPI->R_SparkEffect( (float *)&entity->attachment[0], Q_atoi( event->options ), -100, 100 ); break; case 5004: // client side sound gEngfuncs.pfnPlaySoundByNameAtLocation( (char *)event->options, 1.0, (float *)&entity->attachment[0] ); break; case 5005: // client side sound with random pitch gEngfuncs.pEventAPI->EV_PlaySound( entity->index, (float *)&entity->attachment[0], CHAN_WEAPON, (char *)event->options, RANDOM_FLOAT( 0.7f, 0.9f ), ATTN_NORM, 0, 85 + RANDOM_LONG( 0, 0x1f )); break; case 5050: // Special event for displacer HUD_DrawBeam(); break; case 5060: HUD_EjectShell( event, entity ); break; default: ALERT( at_error, "Unknown event %i with options %i\n", event->event, event->options ); break; } }
BOOL CMP5::Deploy( ) { // m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.3; //delay before fire EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/weapon_deploy.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); if ( m_fDefaultAnim == SILENCER_OFF_FULLAUTO || m_fDefaultAnim == SILENCER_OFF_SEMI ) { if (!FStringNull (v_model) ) { m_pPlayer->pev->viewmodel = v_model; // m_pPlayer->pev->weaponmodel = p_model; SendWeaponAnim( A2_DEPLOY, 1, 0 ); return TRUE; } else return DefaultDeploy("models/weapons/MP5/v_MP5.mdl", "models/weapons/MP5/p_MP5.mdl", A2_DEPLOY, "mp5", 3.50f ); //"mp5a4", 3.50f ); } else { if (!FStringNull (v_model) ) { m_pPlayer->pev->viewmodel = v_model; // m_pPlayer->pev->weaponmodel = p_model; SendWeaponAnim( SD2_DEPLOY, 1, 0 ); return TRUE; } else return DefaultDeploy("models/weapons/MP5/v_MP5.mdl", "models/weapons/MP5/p_MP5_2.mdl", SD2_DEPLOY, "mp5", 3.50f ); } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); // return DefaultDeploy("models/weapons/MP5/v_MP5.mdl", "models/weapons/MP5/p_MP5.mdl", A2_DEPLOY, "mp5a4" ); }
void CGauss::WeaponIdle( void ) { if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase()) return; if (m_fInAttack != 0) { StartFire(); m_fInAttack = 0; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0; } else { int iAnim; switch ( RANDOM_LONG( 0, 2 ) ) { case 0: iAnim = GAUSS_IDLE; break; case 1: iAnim = GAUSS_IDLE2; break; default: case 2: iAnim = GAUSS_FIDGET; break; } SendWeaponAnim( iAnim ); m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); } }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CSoldier :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case ARMY_SHOOT: MonsterFire(); break; case ARMY_END_ATTACK: m_fInAttack = TRUE; m_fAttackFinished = TRUE; break; case ARMY_DROP_BACKPACK: ammo_shells = 5; CWeaponBox::DropBackpack( this, 0 ); break; case ARMY_IDLE_SOUND: if( RANDOM_FLOAT( 0.0f, 1.0f ) < 0.2f ) EMIT_SOUND( edict(), CHAN_VOICE, "soldier/idle.wav", 1.0, ATTN_IDLE ); break; default: CQuakeMonster::HandleAnimEvent( pEvent ); break; } }
void CHellKnight :: MonsterPain( CBaseEntity *pAttacker, float flDamage ) { if( pev->pain_finished > gpGlobals->time ) return; EMIT_SOUND( edict(), CHAN_VOICE, "hknight/pain1.wav", 1.0, ATTN_NORM ); if(( gpGlobals->time - pev->pain_finished ) > 5 ) { // allways go into pain frame if it has been a while m_iAIState = STATE_PAIN; SetActivity( ACT_BIG_FLINCH ); pev->pain_finished = gpGlobals->time + 1; return; } if( RANDOM_FLOAT( 0.0f, 30.0f ) > flDamage ) return; // didn't flinch m_iAIState = STATE_PAIN; SetActivity( ACT_BIG_FLINCH ); pev->pain_finished = gpGlobals->time + 1; }
// Grenade launcher void CBasePlayer::W_FireGrenade(int iQuadSound) { PLAYBACK_EVENT_FULL(FEV_NOTHOST, edict(), m_usGrenade, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0); if(gpGlobals->deathmatch != 4) *m_pCurrentAmmo -= 1; // Get initial velocity UTIL_MakeVectors(pev->v_angle); Vector vecVelocity; if(pev->v_angle.x) { vecVelocity = gpGlobals->v_forward * 600 + gpGlobals->v_up * 200 + RANDOM_FLOAT(-1, 1) * gpGlobals->v_right * 10 + RANDOM_FLOAT(-1, 1) * gpGlobals->v_up * 10; } else { vecVelocity = GetAutoaimVector(AUTOAIM_5DEGREES); vecVelocity = vecVelocity * 600; vecVelocity.z = 200; } // Create the grenade CQuakeRocket *pRocket = CQuakeRocket::CreateGrenade(pev->origin, vecVelocity, this); }
void CTripmine::WeaponIdle( void ) { if (m_flTimeWeaponIdle > gpGlobals->time) return; if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0) { SendWeaponAnim( TRIPMINE_DRAW ); } else { RetireWeapon(); return; } int iAnim; float flRand = RANDOM_FLOAT(0, 1); if (flRand <= 0.25) { iAnim = TRIPMINE_IDLE1; m_flTimeWeaponIdle = gpGlobals->time + 90.0 / 30.0; } else if (flRand <= 0.75) { iAnim = TRIPMINE_IDLE2; m_flTimeWeaponIdle = gpGlobals->time + 60.0 / 30.0; } else { iAnim = TRIPMINE_FIDGET; m_flTimeWeaponIdle = gpGlobals->time + 100.0 / 30.0; } SendWeaponAnim( iAnim ); }
bool CCSBot::Initialize(const BotProfile *profile) { // extend CBot::Initialize(profile); // CS bot initialization m_diedLastRound = false; m_morale = POSITIVE; // starting a new round makes everyone a little happy m_combatRange = RANDOM_FLOAT(325, 425); m_navNodeList = NULL; m_currentNode = NULL; // set initial safe time guess for this map m_safeTime = 15.0f + 5.0f * GetProfile()->GetAggression(); m_name[0] = '\0'; ResetValues(); StartNormalProcess(); return true; }
void CHostageImprov::UpdateVision() { if (!m_visionTimer.IsElapsed()) return; m_visiblePlayerCount = 0; for (int i = 1; i <= gpGlobals->maxClients; ++i) { CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i)); if (player == NULL) continue; if (FNullEnt(player->pev)) continue; if (FStrEq(STRING(player->pev->netname), "")) continue; if (player->IsAlive() && IsVisible(player->pev->origin, true)) { m_visiblePlayer[m_visiblePlayerCount] = player; if (player->m_iTeam == TERRORIST) m_lastSawT.Start(); else m_lastSawCT.Start(); if (++m_visiblePlayerCount == ARRAYSIZE(m_visiblePlayer)) break; } } m_visionTimer.Start(RANDOM_FLOAT(0.4f, 0.6f)); }
void CLightning::RandomArea( void ) { int iLoops = 0; for (iLoops = 0; iLoops < 10; iLoops++) { Vector vecSrc = pev->origin; Vector vecDir1 = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) ); vecDir1 = vecDir1.Normalize(); TraceResult tr1; UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, ignore_monsters, ENT(pev), &tr1 ); if (tr1.flFraction == 1.0) continue; Vector vecDir2; do { vecDir2 = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) ); } while (DotProduct(vecDir1, vecDir2 ) > 0); vecDir2 = vecDir2.Normalize(); TraceResult tr2; UTIL_TraceLine( vecSrc, vecSrc + vecDir2 * m_radius, ignore_monsters, ENT(pev), &tr2 ); if (tr2.flFraction == 1.0) continue; if ((tr1.vecEndPos - tr2.vecEndPos).Length() < m_radius * 0.1) continue; UTIL_TraceLine( tr1.vecEndPos, tr2.vecEndPos, ignore_monsters, ENT(pev), &tr2 ); if (tr2.flFraction != 1.0) continue; Zap( tr1.vecEndPos, tr2.vecEndPos ); break; } }
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(); }
void CSentry :: SentryDeath( 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); SetBoneController( 0, 0 ); SetBoneController( 1, 0 ); SetTurretAnim(TURRET_ANIM_DIE); pev->solid = SOLID_NOT; pev->angles.y = UTIL_AngleMod( pev->angles.y + RANDOM_LONG( 0, 2 ) * 120 ); EyeOn( ); } EyeOff( ); Vector vecSrc, vecAng; GetAttachment( 1, vecSrc, vecAng ); if (pev->dmgtime + RANDOM_FLOAT( 0, 2 ) > gpGlobals->time) { // lots of smoke MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_SMOKE ); WRITE_COORD( vecSrc.x + RANDOM_FLOAT( -16, 16 ) ); WRITE_COORD( vecSrc.y + RANDOM_FLOAT( -16, 16 ) ); WRITE_COORD( vecSrc.z - 32 ); WRITE_SHORT( g_sModelIndexSmoke ); WRITE_BYTE( 15 ); // scale * 10 WRITE_BYTE( 8 ); // framerate MESSAGE_END(); } if (pev->dmgtime + RANDOM_FLOAT( 0, 8 ) > gpGlobals->time) { UTIL_Sparks( vecSrc ); } if (m_fSequenceFinished && pev->dmgtime + 5 < gpGlobals->time) { pev->framerate = 0; SetThink( NULL ); } }
//========================================================= // Hornet is flying, gently tracking target //========================================================= void CHornet :: TrackTarget ( void ) { Vector vecFlightDir; Vector vecDirToEnemy; float flDelta; StudioFrameAdvance( ); if (gpGlobals->time > m_flStopAttack) { SetTouch( NULL ); SetThink( SUB_Remove ); pev->nextthink = gpGlobals->time + 0.1; return; } // UNDONE: The player pointer should come back after returning from another level if ( m_hEnemy == NULL ) {// enemy is dead. Look( 512 ); m_hEnemy = BestVisibleEnemy( ); } if ( m_hEnemy != NULL && FVisible( m_hEnemy )) { m_vecEnemyLKP = m_hEnemy->BodyTarget( GetAbsOrigin() ); } else { m_vecEnemyLKP = m_vecEnemyLKP + GetAbsVelocity() * m_flFlySpeed * 0.1; } vecDirToEnemy = ( m_vecEnemyLKP - GetAbsOrigin() ).Normalize(); if (GetAbsVelocity().Length() < 0.1) vecFlightDir = vecDirToEnemy; else vecFlightDir = GetAbsVelocity().Normalize(); // measure how far the turn is, the wider the turn, the slow we'll go this time. flDelta = DotProduct ( vecFlightDir, vecDirToEnemy ); if ( flDelta < 0.5 ) {// hafta turn wide again. play sound switch (RANDOM_LONG(0,2)) { case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; } } if ( flDelta <= 0 && m_iHornetType == HORNET_TYPE_RED ) {// no flying backwards, but we don't want to invert this, cause we'd go fast when we have to turn REAL far. flDelta = 0.25; } SetAbsVelocity(( vecFlightDir + vecDirToEnemy).Normalize() ); if( pev->owner && ( pev->owner->v.flags & FL_MONSTER )) { // random pattern only applies to hornets fired by monsters, not players. Vector vecVelocity = GetAbsVelocity(); vecVelocity.x += RANDOM_FLOAT ( -0.10, 0.10 );// scramble the flight dir a bit. vecVelocity.y += RANDOM_FLOAT ( -0.10, 0.10 ); vecVelocity.z += RANDOM_FLOAT ( -0.10, 0.10 ); SetAbsVelocity( vecVelocity ); } switch ( m_iHornetType ) { case HORNET_TYPE_RED: SetAbsVelocity( GetAbsVelocity() * ( m_flFlySpeed * flDelta ));// scale the dir by the ( speed * width of turn ) pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.1, 0.3 ); break; case HORNET_TYPE_ORANGE: SetAbsVelocity( GetAbsVelocity() * m_flFlySpeed ); // do not have to slow down to turn. pev->nextthink = gpGlobals->time + 0.1;// fixed think time break; } SetAbsAngles( UTIL_VecToAngles( GetAbsVelocity())); pev->solid = SOLID_BBOX; // if hornet is close to the enemy, jet in a straight line for a half second. // (only in the single player game) if ( m_hEnemy != NULL && !g_pGameRules->IsMultiplayer() ) { if ( flDelta >= 0.4 && ( GetAbsOrigin() - m_vecEnemyLKP ).Length() <= 300 ) { Vector vecOrigin = GetAbsOrigin(); MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecOrigin ); WRITE_BYTE( TE_SPRITE ); WRITE_COORD( vecOrigin.x ); // pos WRITE_COORD( vecOrigin.y ); WRITE_COORD( vecOrigin.z ); WRITE_SHORT( iHornetPuff ); // model // WRITE_BYTE( 0 ); // life * 10 WRITE_BYTE( 2 ); // size * 10 WRITE_BYTE( 128 ); // brightness MESSAGE_END(); switch( RANDOM_LONG( 0, 2 )) { case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM ); break; case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM ); break; case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM ); break; } SetAbsVelocity( GetAbsVelocity() * 2 ); pev->nextthink = gpGlobals->time + 1.0; // don't attack again m_flStopAttack = gpGlobals->time; } } }
void CStomp::Think( void ) { TraceResult tr; pev->nextthink = gpGlobals->time + 0.1; // Do damage for this frame Vector vecStart = pev->origin; vecStart.z += 30; Vector vecEnd = vecStart + (pev->movedir * pev->speed * gpGlobals->frametime); UTIL_TraceHull( vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT(pev), &tr ); if ( tr.pHit && tr.pHit != pev->owner ) { entvars_t *pevOwner = pev; if ( pev->owner ) pevOwner = VARS(pev->owner); if ( tr.pHit && tr.pHit->v.health > 0) { if (UTIL_IsPlayer(tr.pHit)) { UTIL_TakeDamage( tr.pHit,pev, pevOwner, gSkillData.gargantuaDmgStomp, DMG_SONIC ); } else if (tr.pHit->v.euser4 != NULL) { CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(tr.pHit)); pMonster->TakeDamage(pev, pevOwner, gSkillData.gargantuaDmgStomp, DMG_SONIC ); } } } // Accelerate the effect pev->speed = pev->speed + (gpGlobals->frametime) * pev->framerate; pev->framerate = pev->framerate + (gpGlobals->frametime) * 1500; // Move and spawn trails while ( gpGlobals->time - pev->dmgtime > STOMP_INTERVAL ) { pev->origin = pev->origin + pev->movedir * pev->speed * STOMP_INTERVAL; for ( int i = 0; i < 2; i++ ) { CMSprite *pSprite = CMSprite::SpriteCreate( GARG_STOMP_SPRITE_NAME, pev->origin, TRUE ); if ( pSprite ) { UTIL_TraceLine( pev->origin, pev->origin - Vector(0,0,500), ignore_monsters, edict(), &tr ); pSprite->pev->origin = tr.vecEndPos; pSprite->pev->velocity = Vector(RANDOM_FLOAT(-200,200),RANDOM_FLOAT(-200,200),175); // pSprite->AnimateAndDie( RANDOM_FLOAT( 8.0, 12.0 ) ); pSprite->pev->nextthink = gpGlobals->time + 0.3; pSprite->SetThink( SUB_Remove ); pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxFadeFast ); } } pev->dmgtime += STOMP_INTERVAL; // Scale has the "life" of this effect pev->scale -= STOMP_INTERVAL * pev->speed; if ( pev->scale <= 0 ) { // Life has run out UTIL_Remove(this->edict()); STOP_SOUND( edict(), CHAN_BODY, GARG_STOMP_BUZZ_SOUND ); } } }
void EXPORT CEnvSpark::SparkStart(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { SetUse(&CEnvSpark::SparkStop); SetThink(&CEnvSpark::SparkThink); pev->nextthink = gpGlobals->time + (0.1 + RANDOM_FLOAT ( 0, m_flDelay)); }
void CBreakable::DamageSound( void ) { int pitch; float fvol; char *rgpsz[6]; int i; int material = m_Material; // if (RANDOM_LONG(0,1)) // return; if (RANDOM_LONG(0,2)) pitch = PITCH_NORM; else pitch = 95 + RANDOM_LONG(0,34); fvol = RANDOM_FLOAT(0.75, 1.0); if (material == matComputer && RANDOM_LONG(0,1)) material = matMetal; switch (material) { case matComputer: case matGlass: case matUnbreakableGlass: rgpsz[0] = "debris/glass1.wav"; rgpsz[1] = "debris/glass2.wav"; rgpsz[2] = "debris/glass3.wav"; i = 3; break; case matWood: rgpsz[0] = "debris/wood1.wav"; rgpsz[1] = "debris/wood2.wav"; rgpsz[2] = "debris/wood3.wav"; i = 3; break; case matMetal: rgpsz[0] = "debris/metal1.wav"; rgpsz[1] = "debris/metal3.wav"; rgpsz[2] = "debris/metal2.wav"; i = 2; break; case matFlesh: rgpsz[0] = "debris/flesh1.wav"; rgpsz[1] = "debris/flesh2.wav"; rgpsz[2] = "debris/flesh3.wav"; rgpsz[3] = "debris/flesh5.wav"; rgpsz[4] = "debris/flesh6.wav"; rgpsz[5] = "debris/flesh7.wav"; i = 6; break; case matRocks: case matCinderBlock: rgpsz[0] = "debris/concrete1.wav"; rgpsz[1] = "debris/concrete2.wav"; rgpsz[2] = "debris/concrete3.wav"; i = 3; break; case matCeilingTile: // UNDONE: no ceiling tile shard sound yet i = 0; break; } if (i) EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, rgpsz[RANDOM_LONG(0,i-1)], fvol, ATTN_NORM, 0, pitch); }
BOOL CSaw :: Deploy ( ) { EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/weapon_deploy.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); return DefaultDeploy("models/weapons/saw/v_saw.mdl", "models/weapons/saw/p_saw.mdl", M249_DRAW, "xm4", 3.50f ); }
void EXPORT CEnvSpark::SparkThink(void) { pev->nextthink = gpGlobals->time + 0.1 + RANDOM_FLOAT (0, m_flDelay); DoSpark( pev, pev->origin ); }
void CBreakable::Die( void ) { Vector vecSpot;// shard origin Vector vecVelocity;// shard velocity CBaseEntity *pEntity = NULL; char cFlag = 0; int pitch; float fvol; pitch = 95 + RANDOM_LONG(0,29); if (pitch > 97 && pitch < 103) pitch = 100; // The more negative pev->health, the louder // the sound should be. fvol = RANDOM_FLOAT(0.85, 1.0) + (abs(pev->health) / 100.0); if (fvol > 1.0) fvol = 1.0; switch (m_Material) { case matGlass: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustglass2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_GLASS; break; case matWood: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustcrate2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_WOOD; break; case matComputer: case matMetal: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustmetal2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_METAL; break; case matFlesh: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustflesh2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_FLESH; break; case matRocks: case matCinderBlock: switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete1.wav", fvol, ATTN_NORM, 0, pitch); break; case 1: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustconcrete2.wav", fvol, ATTN_NORM, 0, pitch); break; } cFlag = BREAK_CONCRETE; break; case matCeilingTile: EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "debris/bustceiling.wav", fvol, ATTN_NORM, 0, pitch); break; } if (m_Explosion == expDirected) vecVelocity = g_vecAttackDir * 200; else { vecVelocity.x = 0; vecVelocity.y = 0; vecVelocity.z = 0; } vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5; MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_BREAKMODEL); // position WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z ); // size WRITE_COORD( pev->size.x); WRITE_COORD( pev->size.y); WRITE_COORD( pev->size.z); // velocity WRITE_COORD( vecVelocity.x ); WRITE_COORD( vecVelocity.y ); WRITE_COORD( vecVelocity.z ); // randomization WRITE_BYTE( 10 ); // Model WRITE_SHORT( m_idShard ); //model id# // # of shards WRITE_BYTE( 0 ); // let client decide // duration WRITE_BYTE( 25 );// 2.5 seconds // flags WRITE_BYTE( cFlag ); MESSAGE_END(); float size = pev->size.x; if ( size < pev->size.y ) size = pev->size.y; if ( size < pev->size.z ) size = pev->size.z; // !!! HACK This should work! // Build a box above the entity that looks like an 8 pixel high sheet Vector mins = pev->absmin; Vector maxs = pev->absmax; mins.z = pev->absmax.z; maxs.z += 8; // BUGBUG -- can only find 256 entities on a breakable -- should be enough CBaseEntity *pList[256]; int count = UTIL_EntitiesInBox( pList, 256, mins, maxs, FL_ONGROUND ); if ( count ) { for ( int i = 0; i < count; i++ ) { ClearBits( pList[i]->pev->flags, FL_ONGROUND ); pList[i]->pev->groundentity = NULL; } } // Don't fire something that could fire myself pev->targetname = 0; pev->solid = SOLID_NOT; // Fire targets on break SUB_UseTargets( NULL, USE_TOGGLE, 0 ); SetThink( &CBreakable::SUB_Remove ); pev->nextthink = pev->ltime + 0.1; if ( m_iszSpawnObject ) CBaseEntity::Create( (char *)STRING(m_iszSpawnObject), VecBModelOrigin(pev), pev->angles, edict() ); if ( Explodable() ) { ExplosionCreate( Center(), pev->angles, edict(), ExplosionMagnitude(), TRUE ); } }
void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other) { GetGameState()->OnEvent(event, entity, other); GetChatter()->OnEvent(event, entity, other); // Morale adjustments happen even for dead players switch (event) { case EVENT_TERRORISTS_WIN: if (m_iTeam == CT) { DecreaseMorale(); } else { IncreaseMorale(); } break; case EVENT_CTS_WIN: if (m_iTeam == CT) { IncreaseMorale(); } else { DecreaseMorale(); } break; } if (!IsAlive()) return; CBasePlayer *player = static_cast<CBasePlayer *>(entity); // If we just saw a nearby friend die, and we haven't yet acquired an enemy // automatically acquire our dead friend's killer if (!IsAttacking() && (GetDisposition() == ENGAGE_AND_INVESTIGATE || GetDisposition() == OPPORTUNITY_FIRE)) { if (event == EVENT_PLAYER_DIED) { if (BotRelationship(player) == BOT_TEAMMATE) { CBasePlayer *killer = static_cast<CBasePlayer *>(other); // check that attacker is an enemy (for friendly fire, etc) if (killer != NULL && killer->IsPlayer()) { // check if we saw our friend die - dont check FOV - assume we're aware of our surroundings in combat // snipers stay put if (!IsSniper() && IsVisible(&player->pev->origin)) { // people are dying - we should hurry Hurry(RANDOM_FLOAT(10.0f, 15.0f)); // if we're hiding with only our knife, be a little more cautious const float knifeAmbushChance = 50.0f; if (!IsHiding() || !IsUsingKnife() || RANDOM_FLOAT(0, 100) < knifeAmbushChance) { PrintIfWatched("Attacking our friend's killer!\n"); Attack(killer); return; } } } } } } switch (event) { case EVENT_PLAYER_DIED: { CBasePlayer *victim = player; CBasePlayer *killer = (other != NULL && other->IsPlayer()) ? static_cast<CBasePlayer *>(other) : NULL; // if the human player died in the single player game, tell the team if (CSGameRules()->IsCareer() && !victim->IsBot() && BotRelationship(victim) == BOT_TEAMMATE) { GetChatter()->Say("CommanderDown", 20.0f); } // keep track of the last player we killed if (killer == this) { m_lastVictimID = victim->entindex(); } // react to teammate death if (BotRelationship(victim) == BOT_TEAMMATE) { // chastise friendly fire from humans if (killer != NULL && !killer->IsBot() && BotRelationship(killer) == BOT_TEAMMATE && killer != this) { GetChatter()->KilledFriend(); } if (IsHunting()) { PrintIfWatched("Rethinking hunt due to teammate death\n"); Idle(); return; } if (IsAttacking()) { if (GetTimeSinceLastSawEnemy() > 0.4f) { PrintIfWatched("Rethinking my attack due to teammate death\n"); // allow us to sneak past windows, doors, etc IgnoreEnemies(1.0f); // move to last known position of enemy - this could cause us to flank if // the danger has changed due to our teammate's recent death SetTask(MOVE_TO_LAST_KNOWN_ENEMY_POSITION, GetEnemy()); MoveTo(&GetLastKnownEnemyPosition()); return; } } } // an enemy was killed else { if (killer != NULL && BotRelationship(killer) == BOT_TEAMMATE) { // only chatter about enemy kills if we see them occur, and they were the last one we see if (GetNearbyEnemyCount() <= 1) { // report if number of enemies left is few and we killed the last one we saw locally GetChatter()->EnemiesRemaining(); if (IsVisible(&victim->pev->origin, CHECK_FOV)) { // congratulate teammates on their kills if (killer != this) { float delay = RANDOM_FLOAT(2.0f, 3.0f); if (killer->IsBot()) { if (RANDOM_FLOAT(0.0f, 100.0f) < 40.0f) GetChatter()->Say("NiceShot", 3.0f, delay); } else { // humans get the honorific if (CSGameRules()->IsCareer()) GetChatter()->Say("NiceShotCommander", 3.0f, delay); else GetChatter()->Say("NiceShotSir", 3.0f, delay); } } } } } } return; } case EVENT_TERRORISTS_WIN: if (m_iTeam == TERRORIST) GetChatter()->CelebrateWin(); return; case EVENT_CTS_WIN: if (m_iTeam == CT) GetChatter()->CelebrateWin(); return; case EVENT_BOMB_DEFUSED: if (m_iTeam == CT && TheCSBots()->GetBombTimeLeft() < 2.0) GetChatter()->Say("BarelyDefused"); return; case EVENT_BOMB_PICKED_UP: { if (m_iTeam == CT && player != NULL) { // check if we're close enough to hear it const float bombPickupHearRangeSq = 1000.0f * 1000.0f; if ((pev->origin - player->pev->origin).LengthSquared() < bombPickupHearRangeSq) { GetChatter()->TheyPickedUpTheBomb(); } } return; } case EVENT_BOMB_BEEP: { // if we don't know where the bomb is, but heard it beep, we've discovered it if (GetGameState()->IsPlantedBombLocationKnown() == false) { // check if we're close enough to hear it const float bombBeepHearRangeSq = 1000.0f * 1000.0f; if ((pev->origin - entity->pev->origin).LengthSquared() < bombBeepHearRangeSq) { // radio the news to our team if (m_iTeam == CT && GetGameState()->GetPlantedBombsite() == CSGameState::UNKNOWN) { const CCSBotManager::Zone *zone = TheCSBots()->GetZone(&entity->pev->origin); if (zone != NULL) GetChatter()->FoundPlantedBomb(zone->m_index); } // remember where the bomb is GetGameState()->UpdatePlantedBomb(&entity->pev->origin); } } return; } case EVENT_BOMB_PLANTED: { // if we're a CT, forget what we're doing and go after the bomb if (m_iTeam == CT) { Idle(); } // if we are following someone, stop following if (IsFollowing()) { StopFollowing(); Idle(); } OnEvent(EVENT_BOMB_BEEP, other); return; } case EVENT_BOMB_DEFUSE_ABORTED: PrintIfWatched("BOMB DEFUSE ABORTED\n"); return; case EVENT_WEAPON_FIRED: case EVENT_WEAPON_FIRED_ON_EMPTY: case EVENT_WEAPON_RELOADED: { if (m_enemy == entity && IsUsingKnife()) ForceRun(5.0f); break; } default: break; } // Process radio events from our team if (player != NULL && BotRelationship(player) == BOT_TEAMMATE && event > EVENT_START_RADIO_1 && event < EVENT_END_RADIO) { // TODO: Distinguish between radio commands and responses if (event != EVENT_RADIO_AFFIRMATIVE && event != EVENT_RADIO_NEGATIVE && event != EVENT_RADIO_REPORTING_IN) { m_lastRadioCommand = event; m_lastRadioRecievedTimestamp = gpGlobals->time; m_radioSubject = player; m_radioPosition = player->pev->origin; } } // player_follows needs a player if (player == NULL) return; if (!IsRogue() && event == EVENT_HOSTAGE_CALLED_FOR_HELP && m_iTeam == CT && IsHunting()) { if ((entity->pev->origin - pev->origin).IsLengthGreaterThan(1000.0f)) return; if (IsVisible(&entity->Center())) { m_task = COLLECT_HOSTAGES; m_taskEntity = NULL; Run(); m_goalEntity = entity; MoveTo(&entity->pev->origin, m_hostageEscortCount == 0 ? SAFEST_ROUTE : FASTEST_ROUTE); PrintIfWatched("I'm fetching a hostage that called out to me\n"); return; } } // don't pay attention to noise that friends make if (!IsEnemy(player)) return; float range; PriorityType priority; bool isHostile; if (IsGameEventAudible(event, entity, other, &range, &priority, &isHostile) == false) return; if (event == EVENT_HOSTAGE_USED) { if (m_iTeam == CT) return; if ((entity->pev->origin - pev->origin).IsLengthGreaterThan(range)) return; GetChatter()->HostagesBeingTaken(); if (!GetGameState()->GetNearestVisibleFreeHostage() && m_task != GUARD_HOSTAGE_RESCUE_ZONE && GuardRandomZone()) { m_task = GUARD_HOSTAGE_RESCUE_ZONE; m_taskEntity = NULL; SetDisposition(OPPORTUNITY_FIRE); PrintIfWatched("Trying to beat them to an escape zone!\n"); } } // check if noise is close enough for us to hear const Vector *newNoisePosition = &player->pev->origin; float newNoiseDist = (pev->origin - *newNoisePosition).Length(); if (newNoiseDist < range) { // we heard the sound if ((IsLocalPlayerWatchingMe() && cv_bot_debug.value == 3.0f) || cv_bot_debug.value == 4.0f) { PrintIfWatched("Heard noise (%s from %s, pri %s, time %3.1f)\n", (event == EVENT_WEAPON_FIRED) ? "Weapon fire " : "", STRING(player->pev->netname), (priority == PRIORITY_HIGH) ? "HIGH" : ((priority == PRIORITY_MEDIUM) ? "MEDIUM" : "LOW"), gpGlobals->time); } if (event == EVENT_PLAYER_FOOTSTEP && IsUsingSniperRifle() && newNoiseDist < 300.0) EquipPistol(); // should we pay attention to it // if noise timestamp is zero, there is no prior noise if (m_noiseTimestamp > 0.0f) { // only overwrite recent sound if we are louder (closer), or more important - if old noise was long ago, its faded const float shortTermMemoryTime = 3.0f; if (gpGlobals->time - m_noiseTimestamp < shortTermMemoryTime) { // prior noise is more important - ignore new one if (priority < m_noisePriority) return; float oldNoiseDist = (pev->origin - m_noisePosition).Length(); if (newNoiseDist >= oldNoiseDist) return; } } // find the area in which the noise occured // TODO: Better handle when noise occurs off the nav mesh // TODO: Make sure noise area is not through a wall or ceiling from source of noise // TODO: Change GetNavTravelTime to better deal with NULL destination areas CNavArea *noiseArea = TheNavAreaGrid.GetNavArea(newNoisePosition); if (noiseArea == NULL) noiseArea = TheNavAreaGrid.GetNearestNavArea(newNoisePosition); if (noiseArea == NULL) { PrintIfWatched(" *** Noise occurred off the nav mesh - ignoring!\n"); return; } m_noiseArea = noiseArea; // remember noise priority m_noisePriority = priority; // randomize noise position in the area a bit - hearing isn't very accurate // the closer the noise is, the more accurate our placement // TODO: Make sure not to pick a position on the opposite side of ourselves. const float maxErrorRadius = 400.0f; const float maxHearingRange = 2000.0f; float errorRadius = maxErrorRadius * newNoiseDist / maxHearingRange; m_noisePosition.x = newNoisePosition->x + RANDOM_FLOAT(-errorRadius, errorRadius); m_noisePosition.y = newNoisePosition->y + RANDOM_FLOAT(-errorRadius, errorRadius); // make sure noise position remains in the same area m_noiseArea->GetClosestPointOnArea(&m_noisePosition, &m_noisePosition); m_isNoiseTravelRangeChecked = false; // note when we heard the noise m_noiseTimestamp = gpGlobals->time; } }
void CHEGrenade::__MAKE_VHOOK(WeaponIdle)() { if (m_flReleaseThrow == 0 && m_flStartThrow != 0.0f) m_flReleaseThrow = gpGlobals->time; if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase()) return; if (m_flStartThrow) { m_pPlayer->Radio("%!MRAD_FIREINHOLE", "#Fire_in_the_hole"); Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; if (angThrow.x < 0) angThrow.x = -10 + angThrow.x * ((90 - 10) / 90.0); else angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0); float flVel = (90.0f - angThrow.x) * 6.0f; if (flVel > 750.0f) flVel = 750.0f; UTIL_MakeVectors(angThrow); Vector vecSrc = m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16; Vector vecThrow = gpGlobals->v_forward * flVel + m_pPlayer->pev->velocity; CGrenade::ShootTimed2(m_pPlayer->pev, vecSrc, vecThrow, 1.5, m_pPlayer->m_iTeam, m_usCreateExplosion); SendWeaponAnim(HEGRENADE_THROW, UseDecrement() != FALSE); SetPlayerShieldAnim(); // player "shoot" animation m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_flStartThrow = 0; m_flNextPrimaryAttack = GetNextAttackDelay(0.5); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75f; if (--m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) { // just threw last grenade // set attack times in the future, and weapon idle in the future so we can see the whole throw // animation, weapon idle will automatically retire the weapon for us. // ensure that the animation can finish playing m_flTimeWeaponIdle = m_flNextSecondaryAttack = m_flNextPrimaryAttack = GetNextAttackDelay(0.5); } ResetPlayerShieldAnim(); } else if (m_flReleaseThrow > 0) { // we've finished the throw, restart. m_flStartThrow = 0; if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { SendWeaponAnim(HEGRENADE_DRAW, UseDecrement() != FALSE); } else { RetireWeapon(); return; } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT(10, 15); m_flReleaseThrow = -1.0f; } else if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { if (m_pPlayer->HasShield()) { m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 20.0f; if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) { SendWeaponAnim(SHIELDREN_IDLE, UseDecrement() != FALSE); } } else { SendWeaponAnim(HEGRENADE_IDLE, UseDecrement() != FALSE); // how long till we do this again. m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT(10, 15); } } }