void CControllerHeadBall :: HuntThink( void ) { SetNextThink( 0.1 ); pev->renderamt -= 5; MESSAGE_BEGIN( MSG_BROADCAST, gmsgTempEntity ); WRITE_BYTE( TE_ELIGHT ); WRITE_SHORT( entindex( ) ); // entity, attachment WRITE_COORD( pev->origin.x ); // origin WRITE_COORD( pev->origin.y ); WRITE_COORD( pev->origin.z ); WRITE_COORD( pev->renderamt / 16 ); // radius WRITE_BYTE( 255 ); // R WRITE_BYTE( 255 ); // G WRITE_BYTE( 255 ); // B WRITE_BYTE( 2 ); // life * 10 WRITE_COORD( 0 ); // decay MESSAGE_END(); // check world boundaries if (gpGlobals->time - pev->dmgtime > 5 || pev->renderamt < 64 || m_hEnemy == NULL || m_hOwner == NULL || pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096) { SetTouch( NULL ); UTIL_Remove( this ); return; } MovetoTarget( m_hEnemy->Center( ) ); if ((m_hEnemy->Center() - pev->origin).Length() < 64) { TraceResult tr; UTIL_TraceLine( pev->origin, m_hEnemy->Center(), dont_ignore_monsters, ENT(pev), &tr ); CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if (pEntity != NULL && pEntity->pev->takedamage) { ClearMultiDamage( ); pEntity->TraceAttack( m_hOwner->pev, gSkillData.controllerDmgZap, pev->velocity, &tr, DMG_SHOCK ); ApplyMultiDamage( pev, m_hOwner->pev ); } MESSAGE_BEGIN( MSG_BROADCAST, gmsgTempEntity ); WRITE_BYTE( TE_BEAMENTPOINT ); WRITE_SHORT( entindex() ); WRITE_COORD( tr.vecEndPos.x ); WRITE_COORD( tr.vecEndPos.y ); WRITE_COORD( tr.vecEndPos.z ); WRITE_SHORT( g_sModelIndexLaser ); WRITE_BYTE( 0 ); // frame start WRITE_BYTE( 10 ); // framerate WRITE_BYTE( 3 ); // life WRITE_BYTE( 20 ); // width WRITE_BYTE( 0 ); // noise WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 255 ); // brightness WRITE_BYTE( 10 ); // speed MESSAGE_END(); UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) ); m_flNextAttack = gpGlobals->time + 3.0; SetThink(&CControllerHeadBall :: DieThink ); SetNextThink( 0.3 ); } // Crawl( ); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= int CTalkMonster :: FIdleSpeak ( void ) { // try to start a conversation, or make statement int pitch; const char *szIdleGroup; const char *szQuestionGroup; float duration; if (!FOkToSpeak()) return FALSE; // set idle groups based on pre/post disaster if (FBitSet(pev->spawnflags, SF_MONSTER_PREDISASTER)) { szIdleGroup = m_szGrp[TLK_PIDLE]; szQuestionGroup = m_szGrp[TLK_PQUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(4.8, 5.2); } else { szIdleGroup = m_szGrp[TLK_IDLE]; szQuestionGroup = m_szGrp[TLK_QUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(2.8, 3.2); } pitch = GetVoicePitch(); // player using this entity is alive and wounded? CBaseEntity *pTarget = m_hTargetEnt; if ( pTarget != NULL ) { if ( pTarget->IsPlayer() ) { if ( pTarget->IsAlive() ) { m_hTalkTarget = m_hTargetEnt; if (!FBitSet(m_bitsSaid, bit_saidDamageHeavy) && (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 8)) { //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT3], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT3], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageHeavy); return TRUE; } else if (!FBitSet(m_bitsSaid, bit_saidDamageMedium) && (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 4)) { //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT2], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT2], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageMedium); return TRUE; } else if (!FBitSet(m_bitsSaid, bit_saidDamageLight) && (m_hTargetEnt->pev->health <= m_hTargetEnt->pev->max_health / 2)) { //EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, m_szGrp[TLK_PLHURT1], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT1], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageLight); return TRUE; } } else { //!!!KELLY - here's a cool spot to have the talkmonster talk about the dead player if we want. // "Oh dear, Gordon Freeman is dead!" -Scientist // "Damn, I can't do this without you." -Barney } } } // if there is a friend nearby to speak to, play sentence, set friend's response time, return CBaseEntity *pFriend = FindNearestFriend(FALSE); if (pFriend && !(pFriend->IsMoving()) && (RANDOM_LONG(0,99) < 75)) { PlaySentence( szQuestionGroup, duration, VOL_NORM, ATTN_IDLE ); //SENTENCEG_PlayRndSz( ENT(pev), szQuestionGroup, 1.0, ATTN_IDLE, 0, pitch ); // force friend to answer CTalkMonster *pTalkMonster = (CTalkMonster *)pFriend; m_hTalkTarget = pFriend; pTalkMonster->SetAnswerQuestion( this ); // UNDONE: This is EVIL!!! pTalkMonster->m_flStopTalkTime = m_flStopTalkTime; m_nSpeak++; return TRUE; } // otherwise, play an idle statement, try to face client when making a statement. if ( RANDOM_LONG(0,1) ) { //SENTENCEG_PlayRndSz( ENT(pev), szIdleGroup, 1.0, ATTN_IDLE, 0, pitch ); CBaseEntity *pFriend = FindNearestFriend(TRUE); if ( pFriend ) { m_hTalkTarget = pFriend; PlaySentence( szIdleGroup, duration, VOL_NORM, ATTN_IDLE ); m_nSpeak++; return TRUE; } } // didn't speak Talk( 0 ); CTalkMonster::g_talkWaitTime = 0; return FALSE; }
void CTalkMonster :: RunTask( Task_t *pTask ) { switch( pTask->iTask ) { case TASK_TLK_CLIENT_STARE: case TASK_TLK_LOOK_AT_CLIENT: edict_t *pPlayer; // track head to the client for a while. if ( m_MonsterState == MONSTERSTATE_IDLE && !IsMoving() && !IsTalking() ) { // Get edict for one player pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if ( pPlayer ) { IdleHeadTurn( pPlayer->v.origin ); } } else { // started moving or talking TaskFail(); return; } if ( pTask->iTask == TASK_TLK_CLIENT_STARE ) { // fail out if the player looks away or moves away. if ( ( pPlayer->v.origin - pev->origin ).Length2D() > TLK_STARE_DIST ) { // player moved away. TaskFail(); } UTIL_MakeVectors( pPlayer->v.angles ); if ( UTIL_DotPoints( pPlayer->v.origin, pev->origin, gpGlobals->v_forward ) < m_flFieldOfView ) { // player looked away TaskFail(); } } if ( gpGlobals->time > m_flWaitFinished ) { TaskComplete(); } break; case TASK_FACE_PLAYER: { // Get edict for one player edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if ( pPlayer ) { MakeIdealYaw ( pPlayer->v.origin ); ChangeYaw ( pev->yaw_speed ); IdleHeadTurn( pPlayer->v.origin ); if ( gpGlobals->time > m_flWaitFinished && FlYawDiff() < 10 ) { TaskComplete(); } } else { TaskFail(); } } break; case TASK_TLK_EYECONTACT: if (!IsMoving() && IsTalking() && m_hTalkTarget != NULL) { // ALERT( at_console, "waiting %f\n", m_flStopTalkTime - gpGlobals->time ); IdleHeadTurn( m_hTalkTarget->pev->origin ); } else { TaskComplete(); } break; case TASK_WALK_PATH_FOR_UNITS: { float distance; distance = (m_vecLastPosition - pev->origin).Length2D(); // Walk path until far enough away if ( distance > pTask->flData || MovementIsComplete() ) { TaskComplete(); RouteClear(); // Stop moving } } break; case TASK_WAIT_FOR_MOVEMENT: if (IsTalking() && m_hTalkTarget != NULL) { // ALERT(at_console, "walking, talking\n"); IdleHeadTurn( m_hTalkTarget->pev->origin ); } else { IdleHeadTurn( pev->origin ); // override so that during walk, a scientist may talk and greet player FIdleHello(); if (RANDOM_LONG(0,m_nSpeak * 20) == 0) { FIdleSpeak(); } } CBaseMonster::RunTask( pTask ); if (TaskIsComplete()) IdleHeadTurn( pev->origin ); break; default: if (IsTalking() && m_hTalkTarget != NULL) { IdleHeadTurn( m_hTalkTarget->pev->origin ); } else { SetBoneController( 0, 0 ); } CBaseMonster::RunTask( pTask ); } }
//========================================================= // Leader boids use this think every tenth //========================================================= void CFlockingFlyer :: FlockLeaderThink( void ) { TraceResult tr; Vector vecDist;// used for general measurements Vector vecDir;// used for general measurements int cProcessed = 0;// keep track of how many other boids we've processed float flLeftSide; float flRightSide; pev->nextthink = gpGlobals->time + 0.1; UTIL_MakeVectors ( GetAbsAngles() ); // is the way ahead clear? if ( !FPathBlocked () ) { // if the boid is turning, stop the trend. if ( m_fTurning ) { m_fTurning = FALSE; Vector avelocity = GetLocalAvelocity(); avelocity.y = 0; SetLocalAvelocity( avelocity ); } m_fPathBlocked = FALSE; if (pev->speed <= AFLOCK_FLY_SPEED ) pev->speed+= 5; SetAbsVelocity( gpGlobals->v_forward * pev->speed ); BoidAdvanceFrame( ); return; } // IF we get this far in the function, the leader's path is blocked! m_fPathBlocked = TRUE; if ( !m_fTurning)// something in the way and boid is not already turning to avoid { // measure clearance on left and right to pick the best dir to turn UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - GetAbsOrigin()); flRightSide = vecDist.Length(); UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - GetAbsOrigin()); flLeftSide = vecDist.Length(); // turn right if more clearance on right side if ( flRightSide > flLeftSide ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = -AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); m_fTurning = TRUE; } // default to left turn :) else if ( flLeftSide > flRightSide ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); m_fTurning = TRUE; } else { // equidistant. Pick randomly between left and right. m_fTurning = TRUE; if ( RANDOM_LONG( 0, 1 ) == 0 ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); } else { Vector avelocity = GetLocalAvelocity(); avelocity.y = -AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); } } } SpreadFlock( ); SetAbsVelocity( gpGlobals->v_forward * pev->speed ); // check and make sure we aren't about to plow into the ground, don't let it happen UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() - gpGlobals->v_up * 16, ignore_monsters, ENT(pev), &tr); if (tr.flFraction != 1.0 && GetAbsVelocity().z < 0 ) { Vector velocity = GetAbsVelocity(); velocity.z = 0; SetAbsVelocity( velocity ); } // maybe it did, though. if ( FBitSet (pev->flags, FL_ONGROUND) ) { UTIL_SetOrigin (this, GetAbsOrigin() + Vector ( 0 , 0 , 1 ) ); Vector velocity = GetAbsVelocity(); velocity.z = 0; SetAbsVelocity( velocity ); } if ( m_flFlockNextSoundTime < gpGlobals->time ) { MakeSound(); m_flFlockNextSoundTime = gpGlobals->time + RANDOM_FLOAT( 1, 3 ); } BoidAdvanceFrame( ); return; }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CZombie :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case ZOMBIE_AE_ATTACK_RIGHT: { // do stuff for this event. // ALERT( at_console, "Slash right!\n" ); CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgOneSlash, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = -18; pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 100; } // Play a random attack hit sound EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); } else // Play a random attack miss sound EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); if (RANDOM_LONG(0,1)) AttackSound(); } break; case ZOMBIE_AE_ATTACK_LEFT: { // do stuff for this event. // ALERT( at_console, "Slash left!\n" ); CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgOneSlash, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = 18; pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 100; } EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); } else EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); if (RANDOM_LONG(0,1)) AttackSound(); } break; case ZOMBIE_AE_ATTACK_BOTH: { // do stuff for this event. CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgBothSlash, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * -100; } EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); } else EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); if (RANDOM_LONG(0,1)) AttackSound(); } break; default: CBaseMonster::HandleAnimEvent( pEvent ); break; } }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. // // Returns number of events handled, 0 if none. //========================================================= void CBigMomma::HandleAnimEvent(MonsterEvent_t *pEvent) { switch(pEvent->event) { case BIG_AE_MELEE_ATTACKBR: case BIG_AE_MELEE_ATTACKBL: case BIG_AE_MELEE_ATTACK1: { Vector forward, right; UTIL_MakeVectorsPrivate(pev->angles, forward, right, NULL); Vector center = pev->origin + forward * 128; Vector mins = center - Vector(64, 64, 0); Vector maxs = center + Vector(64, 64, 64); CBaseEntity *pList[8]; int count = UTIL_EntitiesInBox(pList, 8, mins, maxs, FL_MONSTER | FL_CLIENT); CBaseEntity *pHurt = NULL; for(int i = 0; i < count && !pHurt; i++) { if(pList[i] != this) { if(pList[i]->pev->owner != edict()) pHurt = pList[i]; } } if(pHurt) { pHurt->TakeDamage(pev, pev, gSkillData.bigmommaDmgSlash, DMG_CRUSH | DMG_SLASH); pHurt->pev->punchangle.x = 15; switch(pEvent->event) { case BIG_AE_MELEE_ATTACKBR: pHurt->pev->velocity = pHurt->pev->velocity + (forward * 150) + Vector(0, 0, 250) - (right * 200); break; case BIG_AE_MELEE_ATTACKBL: pHurt->pev->velocity = pHurt->pev->velocity + (forward * 150) + Vector(0, 0, 250) + (right * 200); break; case BIG_AE_MELEE_ATTACK1: pHurt->pev->velocity = pHurt->pev->velocity + (forward * 220) + Vector(0, 0, 200); break; } pHurt->pev->flags &= ~FL_ONGROUND; EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); } } break; case BIG_AE_SCREAM: EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pAlertSounds); break; case BIG_AE_PAIN_SOUND: EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pPainSounds); break; case BIG_AE_ATTACK_SOUND: EMIT_SOUND_ARRAY_DYN(CHAN_WEAPON, pAttackSounds); break; case BIG_AE_BIRTH_SOUND: EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pBirthSounds); break; case BIG_AE_SACK: if(RANDOM_LONG(0, 100) < 30) EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pSackSounds); break; case BIG_AE_DEATHSOUND: EMIT_SOUND_ARRAY_DYN(CHAN_VOICE, pDeathSounds); break; case BIG_AE_STEP1: // Footstep left case BIG_AE_STEP3: // Footstep back left EMIT_SOUND_ARRAY_DYN(CHAN_ITEM, pFootSounds); break; case BIG_AE_STEP4: // Footstep back right case BIG_AE_STEP2: // Footstep right EMIT_SOUND_ARRAY_DYN(CHAN_BODY, pFootSounds); break; case BIG_AE_MORTAR_ATTACK1: LaunchMortar(); break; case BIG_AE_LAY_CRAB: LayHeadcrab(); break; case BIG_AE_JUMP_FORWARD: ClearBits(pev->flags, FL_ONGROUND); UTIL_SetOrigin(pev, pev->origin + Vector(0, 0, 1)); // take him off ground so engine doesn't instantly reset onground UTIL_MakeVectors(pev->angles); pev->velocity = (gpGlobals->v_forward * 200) + gpGlobals->v_up * 500; break; case BIG_AE_EARLY_TARGET: { CBaseEntity *pTarget = m_hTargetEnt; if(pTarget && pTarget->pev->message) FireTargets(STRING(pTarget->pev->message), this, this, USE_TOGGLE, 0); Remember(bits_MEMORY_FIRED_NODE); } break; default: CBaseMonster::HandleAnimEvent(pEvent); break; } }
void CBigMomma::LaunchMortar(void) { m_mortarTime = gpGlobals->time + RANDOM_FLOAT(2, 15); Vector startPos = pev->origin; startPos.z += 180; EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pSackSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); CBMortar *pBomb = CBMortar::Shoot(edict(), startPos, pev->movedir); pBomb->pev->gravity = 1.0; MortarSpray(startPos, Vector(0, 0, 1), gSpitSprite, 24); }
void CHandGrenade::WeaponIdle(void) { if (m_flTimeUpdate < UTIL_GlobalTimeBase() && m_iChargeLevel) { // we've finished the throw, restart. m_flStartThrow = 0; m_iChargeLevel = 0; if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) SendWeaponAnim(HANDGRENADE_DRAW); else { RetireWeapon(); return; } m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + RANDOM_LONG(10, 15); return; } if (m_flTimeWeaponIdle > UTIL_GlobalTimeBase()) return; if (m_flStartThrow) { 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 - angThrow.x) * 4; if (flVel > 500) flVel = 500; 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; // alway explode 3 seconds after the pin was pulled float time = m_flStartThrow - UTIL_GlobalTimeBase() + 3.0; if (time < 0) time = 0; CGrenade::ShootTimed(m_pPlayer->pev, vecSrc, vecThrow, time); if (flVel < 500) SendWeaponAnim(HANDGRENADE_THROW1); else if (flVel < 1000) SendWeaponAnim(HANDGRENADE_THROW2); else SendWeaponAnim(HANDGRENADE_THROW3); // player "shoot" animation m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_flStartThrow = 0; m_iChargeLevel = 1; m_flNextPrimaryAttack = UTIL_GlobalTimeBase() + 0.5; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + 0.5; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { // 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. m_flTimeWeaponIdle = m_flNextSecondaryAttack = m_flNextPrimaryAttack = UTIL_GlobalTimeBase() + 0.5;// ensure that the animation can finish playing } m_flTimeUpdate = m_flNextSecondaryAttack = m_flNextPrimaryAttack = UTIL_GlobalTimeBase() + 1.0; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + 3.0; return; } if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) { int iAnim; float flRand = RANDOM_FLOAT(0, 1); if (flRand <= 0.75) { iAnim = HANDGRENADE_IDLE; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + RANDOM_LONG(10, 15);// how long till we do this again. } else { iAnim = HANDGRENADE_FIDGET; m_flTimeWeaponIdle = UTIL_GlobalTimeBase() + 75.0 / 30.0; } SendWeaponAnim(iAnim); } }
// // TentacleThink // void CTentacle :: Cycle( void ) { SetNextThink( 0.1 ); // ALERT( at_console, "%s %d %d %d %f %f\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim, m_iDir, pev->framerate, pev->health ); if (m_MonsterState == MONSTERSTATE_SCRIPT || m_IdealMonsterState == MONSTERSTATE_SCRIPT) { Vector angles = GetAbsAngles(); angles.y = m_flInitialYaw; SetAbsAngles( angles ); pev->ideal_yaw = m_flInitialYaw; ClearConditions( IgnoreConditions() ); MonsterThink( ); m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; return; } DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( pev->yaw_speed ); CSound *pSound; Listen( ); // Listen will set this if there's something in my sound list if ( HasConditions( bits_COND_HEAR_SOUND ) ) pSound = PBestSound(); else pSound = NULL; if ( pSound ) { Vector vecDir; if (gpGlobals->time - m_flPrevSoundTime < 0.5) { float dt = gpGlobals->time - m_flPrevSoundTime; vecDir = pSound->m_vecOrigin + (pSound->m_vecOrigin - m_vecPrevSound) / dt - GetAbsOrigin(); } else { vecDir = pSound->m_vecOrigin - GetAbsOrigin(); } m_flPrevSoundTime = gpGlobals->time; m_vecPrevSound = pSound->m_vecOrigin; m_flSoundYaw = UTIL_VecToYaw ( vecDir ) - m_flInitialYaw; m_iSoundLevel = Level( vecDir.z ); if (m_flSoundYaw < -180) m_flSoundYaw += 360; if (m_flSoundYaw > 180) m_flSoundYaw -= 360; // ALERT( at_console, "sound %d %.0f\n", m_iSoundLevel, m_flSoundYaw ); if (m_flSoundTime < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_alert1.wav"; break; case 1: sound = "tentacle/te_alert2.wav"; break; } // UTIL_EmitAmbientSound(ENT(pev), GetAbsOrigin() + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); } m_flSoundTime = gpGlobals->time + RANDOM_FLOAT( 5.0, 10.0 ); } // clip ideal_yaw float dy = m_flSoundYaw; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: if (dy < 0 && dy > -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > 0 && dy < m_flMaxYaw) dy = m_flMaxYaw; break; default: if (dy < -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > m_flMaxYaw) dy = m_flMaxYaw; } pev->ideal_yaw = m_flInitialYaw + dy; if (m_fSequenceFinished) { // ALERT( at_console, "%s done %d %d\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim ); if (pev->health <= 1) { m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { pev->health = 75; } } else if ( m_flSoundTime > gpGlobals->time ) { if (m_flSoundYaw >= -(m_flMaxYaw + 30) && m_flSoundYaw <= (m_flMaxYaw + 30)) { // strike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else if (m_flSoundYaw >= -m_flMaxYaw * 2 && m_flSoundYaw <= m_flMaxYaw * 2) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } else { // go into rear idle m_iGoalAnim = LookupActivity( ACT_T_REARIDLE + m_iSoundLevel ); } } else if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { // stay in pit until hear noise m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; } else if (pev->sequence == m_iGoalAnim) { if (MyLevel() >= 0 && gpGlobals->time < m_flSoundTime) { if (RANDOM_LONG(0,9) < m_flSoundTime - gpGlobals->time) { // continue stike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } } else if (MyLevel( ) < 0) { m_iGoalAnim = LookupActivity( ACT_T_IDLE + 0 ); } else { if (m_flNextSong < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_sing1.wav"; break; case 1: sound = "tentacle/te_sing2.wav"; break; } EMIT_SOUND(ENT(pev), CHAN_VOICE, sound, 1.0, ATTN_NORM); m_flNextSong = gpGlobals->time + RANDOM_FLOAT( 10, 20 ); } if (RANDOM_LONG(0,15) == 0) { // idle on new level m_iGoalAnim = LookupActivity( ACT_T_IDLE + RANDOM_LONG(0,3) ); } else if (RANDOM_LONG(0,3) == 0) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + MyLevel( ) ); } else { // idle m_iGoalAnim = LookupActivity( ACT_T_IDLE + MyLevel( ) ); } } if (m_flSoundYaw < 0) m_flSoundYaw += RANDOM_FLOAT( 2, 8 ); else m_flSoundYaw -= RANDOM_FLOAT( 2, 8 ); } pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); if (m_iDir > 0) { pev->frame = 0; } else { m_iDir = -1; // just to safe pev->frame = 255; } ResetSequenceInfo( ); m_flFramerateAdj = RANDOM_FLOAT( -0.2, 0.2 ); pev->framerate = m_iDir * 1.0 + m_flFramerateAdj; switch( pev->sequence) { case TENTACLE_ANIM_Floor_Tap: case TENTACLE_ANIM_Lev1_Tap: case TENTACLE_ANIM_Lev2_Tap: case TENTACLE_ANIM_Lev3_Tap: { Vector vecSrc; UTIL_MakeVectors( GetAbsAngles() ); TraceResult tr1, tr2; vecSrc = GetAbsOrigin() + Vector( 0, 0, MyHeight() - 4); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr1 ); vecSrc = GetAbsOrigin() + Vector( 0, 0, MyHeight() + 8); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr2 ); // ALERT( at_console, "%f %f\n", tr1.flFraction * 512, tr2.flFraction * 512 ); m_flTapRadius = SetBlending( 0, RANDOM_FLOAT( tr1.flFraction * 512, tr2.flFraction * 512 ) ); } break; default: m_flTapRadius = 336; // 400 - 64 break; } pev->view_ofs.z = MyHeight( ); // ALERT( at_console, "seq %d\n", pev->sequence ); } if (m_flPrevSoundTime + 2.0 > gpGlobals->time) { // 1.5 normal speed if hears sounds pev->framerate = m_iDir * 1.5 + m_flFramerateAdj; } else if (m_flPrevSoundTime + 5.0 > gpGlobals->time) { // slowdown to normal pev->framerate = m_iDir + m_iDir * (5 - (gpGlobals->time - m_flPrevSoundTime)) / 2 + m_flFramerateAdj; } }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. // // Returns number of events handled, 0 if none. //========================================================= void CISlave :: HandleAnimEvent( MonsterEvent_t *pEvent ) { // ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame ); switch( pEvent->event ) { case ISLAVE_AE_CLAW: { // SOUND HERE! CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.slaveDmgClaw, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = -18; pHurt->pev->punchangle.x = 5; } // Play a random attack hit sound EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch ); } else { // Play a random attack miss sound EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch ); } } break; case ISLAVE_AE_CLAWRAKE: { CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.slaveDmgClawrake, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = -18; pHurt->pev->punchangle.x = 5; } EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch ); } else { EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch ); } } break; case ISLAVE_AE_ZAP_POWERUP: { // speed up attack when on hard if (g_iSkillLevel == SKILL_HARD) pev->framerate = 1.5; UTIL_MakeAimVectors( pev->angles ); if (m_iBeams == 0) { Vector vecSrc = pev->origin + gpGlobals->v_forward * 2; MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc ); WRITE_BYTE(TE_DLIGHT); WRITE_COORD(vecSrc.x); // X WRITE_COORD(vecSrc.y); // Y WRITE_COORD(vecSrc.z); // Z WRITE_BYTE( 12 ); // radius * 0.1 WRITE_BYTE( 255 ); // r WRITE_BYTE( 180 ); // g WRITE_BYTE( 96 ); // b WRITE_BYTE( 20 / pev->framerate ); // time * 10 WRITE_BYTE( 0 ); // decay * 0.1 MESSAGE_END( ); } if (m_hDead != NULL) { WackBeam( -1, m_hDead ); WackBeam( 1, m_hDead ); } else { ArmBeam( -1 ); ArmBeam( 1 ); BeamGlow( ); } EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 ); pev->skin = m_iBeams / 2; } break; case ISLAVE_AE_ZAP_SHOOT: { ClearBeams( ); if (m_hDead != NULL) { Vector vecDest = m_hDead->pev->origin + Vector( 0, 0, 38 ); TraceResult trace; UTIL_TraceHull( vecDest, vecDest, dont_ignore_monsters, human_hull, m_hDead->edict(), &trace ); if ( !trace.fStartSolid ) { CBaseEntity *pNew = Create( "monster_alien_slave", m_hDead->pev->origin, m_hDead->pev->angles ); CBaseMonster *pNewMonster = pNew->MyMonsterPointer( ); pNew->pev->spawnflags |= 1; WackBeam( -1, pNew ); WackBeam( 1, pNew ); UTIL_Remove( m_hDead ); EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) ); /* CBaseEntity *pEffect = Create( "test_effect", pNew->Center(), pev->angles ); pEffect->Use( this, this, USE_ON, 1 ); */ break; } } ClearMultiDamage(); UTIL_MakeAimVectors( pev->angles ); ZapBeam( -1 ); ZapBeam( 1 ); EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) ); // STOP_SOUND( ENT(pev), CHAN_WEAPON, "debris/zap4.wav" ); ApplyMultiDamage(pev, pev); m_flNextAttack = gpGlobals->time + RANDOM_FLOAT( 0.5, 4.0 ); } break; case ISLAVE_AE_ZAP_DONE: { ClearBeams( ); } break; default: CSquadMonster::HandleAnimEvent( pEvent ); break; } }
//========================================================= // ZapBeam - heavy damage directly forward //========================================================= void CISlave :: ZapBeam( int side ) { Vector vecSrc, vecAim; TraceResult tr; CBaseEntity *pEntity; if (m_iBeams >= ISLAVE_MAX_BEAMS) return; vecSrc = pev->origin + gpGlobals->v_up * 36; vecAim = ShootAtEnemy( vecSrc ); float deflection = 0.01; vecAim = vecAim + side * gpGlobals->v_right * RANDOM_FLOAT( 0, deflection ) + gpGlobals->v_up * RANDOM_FLOAT( -deflection, deflection ); UTIL_TraceLine ( vecSrc, vecSrc + vecAim * 1024, dont_ignore_monsters, ENT( pev ), &tr); m_pBeam[m_iBeams] = CBeam::BeamCreate( "sprites/lgtning.spr", 50 ); if (!m_pBeam[m_iBeams]) return; m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex( ) ); m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 ); m_pBeam[m_iBeams]->SetColor( 180, 255, 96 ); m_pBeam[m_iBeams]->SetBrightness( 255 ); m_pBeam[m_iBeams]->SetNoise( 20 ); m_iBeams++; pEntity = CBaseEntity::Instance(tr.pHit); if (pEntity != NULL && pEntity->pev->takedamage) { pEntity->TraceAttack( pev, gSkillData.slaveDmgZap, vecAim, &tr, DMG_SHOCK ); } UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) ); }
void CISlave :: DeathSound( void ) { EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pDeathSounds[ RANDOM_LONG(0,ARRAYSIZE(pDeathSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch ); }
void CController :: PainSound( void ) { if (RANDOM_LONG(0,5) < 2) EMIT_SOUND_ARRAY_DYN( CHAN_VOICE, pPainSounds ); }
void CControllerZapBall::ExplodeTouch( CBaseEntity *pOther ) { if (pOther->pev->takedamage) { TraceResult tr = UTIL_GetGlobalTrace( ); entvars_t *pevOwner; if (m_hOwner != NULL) { pevOwner = m_hOwner->pev; } else { pevOwner = pev; } ClearMultiDamage( ); pOther->TraceAttack(pevOwner, gSkillData.controllerDmgBall, pev->velocity.Normalize(), &tr, DMG_ENERGYBEAM ); ApplyMultiDamage( pevOwner, pevOwner ); UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.3, ATTN_NORM, 0, RANDOM_LONG( 90, 99 ) ); } UTIL_Remove( this ); }
// Go to the trouble of combining multiple pellets into a single damage call. // This version is used by Players, uses the random seed generator to sync client and server side shots. Vector CBaseEntity::FireBullets3(Vector vecSrc, Vector vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand) { int iOriginalPenetration = iPenetration; int iPenetrationPower; float flPenetrationDistance; int iCurrentDamage = iDamage; float flCurrentDistance; TraceResult tr, tr2; Vector vecRight, vecUp; bool bHitMetal = false; int iSparksAmount = 1; vecRight = gpGlobals->v_right; vecUp = gpGlobals->v_up; switch (iBulletType) { case BULLET_PLAYER_9MM: iPenetrationPower = 21; flPenetrationDistance = 800; break; case BULLET_PLAYER_45ACP: iPenetrationPower = 15; flPenetrationDistance = 500; break; case BULLET_PLAYER_50AE: iPenetrationPower = 30; flPenetrationDistance = 1000; break; case BULLET_PLAYER_762MM: iPenetrationPower = 39; flPenetrationDistance = 5000; break; case BULLET_PLAYER_556MM: iPenetrationPower = 35; flPenetrationDistance = 4000; break; case BULLET_PLAYER_338MAG: iPenetrationPower = 45; flPenetrationDistance = 8000; break; case BULLET_PLAYER_57MM: iPenetrationPower = 30; flPenetrationDistance = 2000; break; case BULLET_PLAYER_357SIG: iPenetrationPower = 25; flPenetrationDistance = 800; break; default: iPenetrationPower = 0; flPenetrationDistance = 0; break; } if (!pevAttacker) { // the default attacker is ourselves pevAttacker = pev; } gMultiDamage.type = (DMG_BULLET | DMG_NEVERGIB); float x, y, z; if (IsPlayer()) { // Use player's random seed. // get circular gaussian spread x = UTIL_SharedRandomFloat(shared_rand, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 1, -0.5, 0.5); y = UTIL_SharedRandomFloat(shared_rand + 2, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 3, -0.5, 0.5); } else { do { x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); z = x * x + y * y; } while (z > 1); } Vector vecDir, vecEnd; Vector vecOldSrc, vecNewSrc; vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; vecEnd = vecSrc + vecDir * flDistance; float flDamageModifier = 0.5; while (iPenetration != 0) { ClearMultiDamage(); UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr); if (TheBots != NULL && tr.flFraction != 1.0f) { TheBots->OnEvent(EVENT_BULLET_IMPACT, this, (CBaseEntity *)&tr.vecEndPos); } char cTextureType = UTIL_TextureHit(&tr, vecSrc, vecEnd); bool bSparks = false; switch (cTextureType) { case CHAR_TEX_METAL: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.15; flDamageModifier = 0.2; break; case CHAR_TEX_CONCRETE: iPenetrationPower *= 0.25; break; case CHAR_TEX_GRATE: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.5; flDamageModifier = 0.4; break; case CHAR_TEX_VENT: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.5; flDamageModifier = 0.45; break; case CHAR_TEX_TILE: iPenetrationPower *= 0.65; flDamageModifier = 0.3; break; case CHAR_TEX_COMPUTER: bHitMetal = true; bSparks = true; iPenetrationPower *= 0.4; flDamageModifier = 0.45; break; case CHAR_TEX_WOOD: flDamageModifier = 0.6; break; default: break; } if (tr.flFraction != 1.0f) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); iPenetration--; flCurrentDistance = tr.flFraction * flDistance; iCurrentDamage *= Q_pow(flRangeModifier, flCurrentDistance / 500); if (flCurrentDistance > flPenetrationDistance) { iPenetration = 0; } if (tr.iHitgroup == HITGROUP_SHIELD) { EMIT_SOUND(pEntity->edict(), CHAN_VOICE, (RANDOM_LONG(0, 1) == 1) ? "weapons/ric_metal-1.wav" : "weapons/ric_metal-2.wav", VOL_NORM, ATTN_NORM); UTIL_Sparks(tr.vecEndPos); pEntity->pev->punchangle.x = iCurrentDamage * RANDOM_FLOAT(-0.15, 0.15); pEntity->pev->punchangle.z = iCurrentDamage * RANDOM_FLOAT(-0.15, 0.15); if (pEntity->pev->punchangle.x < 4) { pEntity->pev->punchangle.x = -4; } if (pEntity->pev->punchangle.z < -5) { pEntity->pev->punchangle.z = -5; } else if (pEntity->pev->punchangle.z > 5) { pEntity->pev->punchangle.z = 5; } break; } float flDistanceModifier; if (VARS(tr.pHit)->solid != SOLID_BSP || !iPenetration) { iPenetrationPower = 42; flDamageModifier = 0.75; flDistanceModifier = 0.75; } else flDistanceModifier = 0.5; DecalGunshot(&tr, iBulletType, (!bPistol && RANDOM_LONG(0, 3)), pev, bHitMetal); vecSrc = tr.vecEndPos + (vecDir * iPenetrationPower); flDistance = (flDistance - flCurrentDistance) * flDistanceModifier; vecEnd = vecSrc + (vecDir * flDistance); pEntity->TraceAttack(pevAttacker, iCurrentDamage, vecDir, &tr, (DMG_BULLET | DMG_NEVERGIB)); iCurrentDamage *= flDamageModifier; } else iPenetration = 0; ApplyMultiDamage(pev, pevAttacker); } return Vector(x * vecSpread, y * vecSpread, 0); }
void CTentacle :: DieThink( void ) { pev->nextthink = gpGlobals-> time + 0.1; DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( 24 ); if (m_fSequenceFinished) { if (pev->sequence == m_iGoalAnim) { switch( m_iGoalAnim ) { case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: m_iGoalAnim = TENTACLE_ANIM_Engine_Sway + RANDOM_LONG( 0, 2 ); break; case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: UTIL_Remove( this ); return; } } // ALERT( at_console, "%d : %d => ", pev->sequence, m_iGoalAnim ); pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); // ALERT( at_console, "%d\n", pev->sequence ); if (m_iDir > 0) { pev->frame = 0; } else { pev->frame = 255; } ResetSequenceInfo( ); float dy; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: pev->framerate = RANDOM_FLOAT( m_iDir - 0.2, m_iDir + 0.2 ); dy = 180; break; default: pev->framerate = 1.5; dy = 0; break; } pev->ideal_yaw = m_flInitialYaw + dy; } }
//========================================================= // 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( &CBaseEntity::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( pev->origin ); } else { m_vecEnemyLKP = m_vecEnemyLKP + pev->velocity * m_flFlySpeed * 0.1; } vecDirToEnemy = ( m_vecEnemyLKP - pev->origin ).Normalize(); if( pev->velocity.Length() < 0.1 ) vecFlightDir = vecDirToEnemy; else vecFlightDir = pev->velocity.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; } pev->velocity = ( vecFlightDir + vecDirToEnemy ).Normalize(); if( pev->owner && ( pev->owner->v.flags & FL_MONSTER ) ) { // random pattern only applies to hornets fired by monsters, not players. pev->velocity.x += RANDOM_FLOAT( -0.10, 0.10 );// scramble the flight dir a bit. pev->velocity.y += RANDOM_FLOAT( -0.10, 0.10 ); pev->velocity.z += RANDOM_FLOAT( -0.10, 0.10 ); } switch( m_iHornetType ) { case HORNET_TYPE_RED: pev->velocity = pev->velocity * ( 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: pev->velocity = pev->velocity * m_flFlySpeed;// do not have to slow down to turn. pev->nextthink = gpGlobals->time + 0.1;// fixed think time break; } pev->angles = UTIL_VecToAngles( pev->velocity ); 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 && ( pev->origin - m_vecEnemyLKP ).Length() <= 300 ) { MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin ); WRITE_BYTE( TE_SPRITE ); WRITE_COORD( pev->origin.x ); // pos WRITE_COORD( pev->origin.y ); WRITE_COORD( pev->origin.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; } pev->velocity = pev->velocity * 2; pev->nextthink = gpGlobals->time + 1.0; // don't attack again m_flStopAttack = gpGlobals->time; } } }
void CTentacle :: HandleAnimEvent( MonsterEvent_t *pEvent ) { char *sound; switch( pEvent->event ) { case 1: // bang { Vector vecSrc, vecAngles; GetAttachment( 0, vecSrc, vecAngles ); switch( m_iTapSound ) { case TE_SILO: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitSilo ), 1.0, ATTN_NORM, 0, 100 ); break; case TE_NONE: break; case TE_DIRT: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitDirt ), 1.0, ATTN_NORM, 0, 100 ); break; case TE_WATER: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitWater ), 1.0, ATTN_NORM, 0, 100 ); break; } gpGlobals->force_retouch++; } break; case 3: // start killing swing m_iHitDmg = 200; // UTIL_EmitAmbientSound( edict(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), "tentacle/te_swing1.wav", 1.0, ATTN_NORM, 0, 100 ); break; case 4: // end killing swing m_iHitDmg = 25; break; case 5: // just "whoosh" sound // UTIL_EmitAmbientSound( edict(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), "tentacle/te_swing2.wav", 1.0, ATTN_NORM, 0, 100 ); break; case 2: // tap scrape case 6: // light tap { Vector vecSrc = GetAbsOrigin() + m_flTapRadius * Vector( cos( GetAbsAngles().y * (M_PI / 180.0) ), sin( GetAbsAngles().y * (M_PI / 180.0) ), 0.0 ); vecSrc.z += MyHeight( ); float flVol = RANDOM_FLOAT( 0.3, 0.5 ); switch( m_iTapSound ) { case TE_SILO: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitSilo ), flVol, ATTN_NORM, 0, 100); break; case TE_NONE: break; case TE_DIRT: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitDirt ), flVol, ATTN_NORM, 0, 100); break; case TE_WATER: UTIL_EmitAmbientSound( edict(), vecSrc, RANDOM_SOUND_ARRAY( pHitWater ), flVol, ATTN_NORM, 0, 100); break; } } break; case 7: // roar switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_roar1.wav"; break; case 1: sound = "tentacle/te_roar2.wav"; break; } UTIL_EmitAmbientSound( edict(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); break; case 8: // search switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_search1.wav"; break; case 1: sound = "tentacle/te_search2.wav"; break; } UTIL_EmitAmbientSound( edict(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); break; case 9: // swing switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_move1.wav"; break; case 1: sound = "tentacle/te_move2.wav"; break; } UTIL_EmitAmbientSound( edict(), GetAbsOrigin() + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); break; default: CBaseMonster::HandleAnimEvent( pEvent ); } }
void CBigMomma::LayHeadcrab(void) { CBaseEntity *pChild = CBaseEntity::Create(BIG_CHILDCLASS, pev->origin, pev->angles, edict()); pChild->pev->spawnflags |= SF_MONSTER_FALL_TO_GROUND; // Is this the second crab in a pair? if(HasMemory(bits_MEMORY_CHILDPAIR)) { m_crabTime = gpGlobals->time + RANDOM_FLOAT(5, 10); Forget(bits_MEMORY_CHILDPAIR); } else { m_crabTime = gpGlobals->time + RANDOM_FLOAT(0.5, 2.5); Remember(bits_MEMORY_CHILDPAIR); } TraceResult tr; UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 100), ignore_monsters, edict(), &tr); UTIL_DecalTrace(&tr, DECAL_MOMMABIRTH); EMIT_SOUND_DYN(edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBirthSounds), 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5, 5)); m_crabCount++; }
//========================================================= // sit, do stuff //========================================================= void CSittingScientist :: SittingThink( void ) { CBaseEntity *pent; StudioFrameAdvance( ); // try to greet player if (FIdleHello()) { pent = FindNearestFriend(TRUE); if (pent) { float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw > 0) pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; else pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; ResetSequenceInfo( ); pev->frame = 0; SetBoneController( 0, 0 ); } } else if (m_fSequenceFinished) { int i = RANDOM_LONG(0,99); m_headTurn = 0; if (m_flResponseDelay && gpGlobals->time > m_flResponseDelay) { // respond to question IdleRespond(); pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; m_flResponseDelay = 0; } else if (i < 30) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; // turn towards player or nearest friend and speak if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) pent = FindNearestFriend(TRUE); else pent = FindNearestFriend(FALSE); if (!FIdleSpeak() || !pent) { m_headTurn = RANDOM_LONG(0,8) * 10 - 40; pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; } else { // only turn head if we spoke float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw > 0) pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; else pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; //ALERT(at_console, "sitting speak\n"); } } else if (i < 60) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; m_headTurn = RANDOM_LONG(0,8) * 10 - 40; if (RANDOM_LONG(0,99) < 5) { //ALERT(at_console, "sitting speak2\n"); FIdleSpeak(); } } else if (i < 80) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting2; } else if (i < 100) { pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; } ResetSequenceInfo( ); pev->frame = 0; SetBoneController( 0, m_headTurn ); } SetNextThink( 0.1 ); }
BOOL CEgon::Deploy( void ) { 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)); m_deployed = FALSE; m_fireState = FIRE_OFF; return DefaultDeploy( "models/weapons/egon/v_egon.mdl", "models/weapons/egon/p_egon.mdl", EGON_DRAW, "egon" ); }
void CScientist :: RunTask( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_RUN_PATH_SCARED: if ( MovementIsComplete() ) TaskComplete(); if ( RANDOM_LONG(0,31) < 8 ) Scream(); break; case TASK_MOVE_TO_TARGET_RANGE_SCARED: { if ( RANDOM_LONG(0,63)< 8 ) Scream(); if ( m_hEnemy == NULL ) { TaskFail(); } else { float distance; distance = ( m_vecMoveGoal - pev->origin ).Length2D(); // Re-evaluate when you think your finished, or the target has moved too far if ( (distance < pTask->flData) || (m_vecMoveGoal - m_hTargetEnt->pev->origin).Length() > pTask->flData * 0.5 ) { m_vecMoveGoal = m_hTargetEnt->pev->origin; distance = ( m_vecMoveGoal - pev->origin ).Length2D(); FRefreshRoute(); } // Set the appropriate activity based on an overlapping range // overlap the range to prevent oscillation if ( distance < pTask->flData ) { TaskComplete(); RouteClear(); // Stop moving } else if ( distance < 190 && m_movementActivity != ACT_WALK_SCARED ) m_movementActivity = ACT_WALK_SCARED; else if ( distance >= 270 && m_movementActivity != ACT_RUN_SCARED ) m_movementActivity = ACT_RUN_SCARED; } } break; case TASK_HEAL: if ( m_fSequenceFinished ) { TaskComplete(); } else { if ( TargetDistance() > 90 ) TaskComplete(); pev->ideal_yaw = UTIL_VecToYaw( m_hTargetEnt->pev->origin - pev->origin ); ChangeYaw( pev->yaw_speed ); } break; default: CTalkMonster::RunTask( pTask ); break; } }
void CZombie :: AlertSound( void ) { int pitch = 95 + RANDOM_LONG(0,9); EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAlertSounds[ RANDOM_LONG(0,ARRAYSIZE(pAlertSounds)-1) ], 1.0, ATTN_NORM, 0, pitch ); }
BOOL CElite::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/pistol/v_pistol.mdl", "models/weapons/pistol/p_pistol.mdl", PISTOL_DEPLOY, "9mm", 2.50f); }
BOOL CEpipen::Deploy( ) { m_pPlayer->m_fCrosshairOff = TRUE; 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)); // m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1.0; return DefaultDeploy("models/weapons/epipen/v_epipen.mdl", "models/null.mdl", EPIPEN_DEPLOY, "mp5a4" ); }
void CGib::SpawnRandomGibs(entvars_t *pevVictim, int cGibs, int human) { int cSplat; for (cSplat = 0; cSplat < cGibs; ++cSplat) { CGib *pGib = GetClassPtr<CCSGib>((CGib *)NULL); if (g_Language == LANGUAGE_GERMAN) { pGib->Spawn("models/germangibs.mdl"); pGib->pev->body = RANDOM_LONG(0, GERMAN_GIB_COUNT - 1); } else { if (human) { // human pieces pGib->Spawn("models/hgibs.mdl"); // start at one to avoid throwing random amounts of skulls (0th gib) pGib->pev->body = RANDOM_LONG(1, HUMAN_GIB_COUNT - 1); } else { // aliens pGib->Spawn("models/agibs.mdl"); pGib->pev->body = RANDOM_LONG(0, ALIEN_GIB_COUNT - 1); } } if (pevVictim) { // spawn the gib somewhere in the monster's bounding volume pGib->pev->origin.x = pevVictim->absmin.x + pevVictim->size.x * (RANDOM_FLOAT(0, 1)); pGib->pev->origin.y = pevVictim->absmin.y + pevVictim->size.y * (RANDOM_FLOAT(0, 1)); // absmin.z is in the floor because the engine subtracts 1 to enlarge the box pGib->pev->origin.z = pevVictim->absmin.z + pevVictim->size.z * (RANDOM_FLOAT(0, 1)) + 1; // make the gib fly away from the attack vector pGib->pev->velocity = g_vecAttackDir * -1; // mix in some noise pGib->pev->velocity.x += RANDOM_FLOAT(-0.25, 0.25); pGib->pev->velocity.y += RANDOM_FLOAT(-0.25, 0.25); pGib->pev->velocity.z += RANDOM_FLOAT(-0.25, 0.25); pGib->pev->velocity = pGib->pev->velocity * RANDOM_FLOAT(300, 400); pGib->pev->avelocity.x = RANDOM_FLOAT(100, 200); pGib->pev->avelocity.y = RANDOM_FLOAT(100, 300); // copy owner's blood color pGib->m_bloodColor = (CBaseEntity::Instance(pevVictim))->BloodColor(); if (pevVictim->health > -50) pGib->pev->velocity = pGib->pev->velocity * 0.7; else if (pevVictim->health > -200) pGib->pev->velocity = pGib->pev->velocity * 2; else pGib->pev->velocity = pGib->pev->velocity * 4; pGib->pev->solid = SOLID_BBOX; UTIL_SetSize(pGib->pev, Vector(0, 0, 0), Vector(0, 0, 0)); } pGib->LimitVelocity(); } }
Schedule_t* CTalkMonster :: GetScheduleOfType ( int Type ) { switch( Type ) { case SCHED_MOVE_AWAY: return slMoveAway; case SCHED_MOVE_AWAY_FOLLOW: return slMoveAwayFollow; case SCHED_MOVE_AWAY_FAIL: return slMoveAwayFail; case SCHED_TARGET_FACE: // speak during 'use' if (RANDOM_LONG(0,99) < 2) //ALERT ( at_console, "target chase speak\n" ); return slIdleSpeakWait; else return slIdleStand; case SCHED_IDLE_STAND: { // if never seen player, try to greet him if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) { return slIdleHello; } // sustained light wounds? if (!FBitSet(m_bitsSaid, bit_saidWoundLight) && (pev->health <= (pev->max_health * 0.75))) { //SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_WOUND], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); PlaySentence( m_szGrp[TLK_WOUND], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidWoundLight); return slIdleStand; } // sustained heavy wounds? else if (!FBitSet(m_bitsSaid, bit_saidWoundHeavy) && (pev->health <= (pev->max_health * 0.5))) { //SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_MORTAL], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); PlaySentence( m_szGrp[TLK_MORTAL], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidWoundHeavy); return slIdleStand; } // talk about world if (FOkToSpeak() && RANDOM_LONG(0,m_nSpeak * 2) == 0) { //ALERT ( at_console, "standing idle speak\n" ); return slIdleSpeak; } if ( !IsTalking() && HasConditions ( bits_COND_SEE_CLIENT ) && RANDOM_LONG( 0, 6 ) == 0 ) { edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if ( pPlayer ) { // watch the client. UTIL_MakeVectors ( pPlayer->v.angles ); if ( ( pPlayer->v.origin - pev->origin ).Length2D() < TLK_STARE_DIST && UTIL_DotPoints( pPlayer->v.origin, pev->origin, gpGlobals->v_forward ) >= m_flFieldOfView ) { // go into the special STARE schedule if the player is close, and looking at me too. return &slTlkIdleWatchClient[ 1 ]; } return slTlkIdleWatchClient; } } else { if (IsTalking()) // look at who we're talking to return slTlkIdleEyecontact; else // regular standing idle return slIdleStand; } // NOTE - caller must first CTalkMonster::GetScheduleOfType, // then check result and decide what to return ie: if sci gets back // slIdleStand, return slIdleSciStand } break; } return CBaseMonster::GetScheduleOfType( Type ); }
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker) { static int tracerCount; int tracer; TraceResult tr; Vector vecRight, vecUp; bool m_bCreatedShotgunSpark = true; vecRight = gpGlobals->v_right; vecUp = gpGlobals->v_up; if (!pevAttacker) { // the default attacker is ourselves pevAttacker = pev; } ClearMultiDamage(); gMultiDamage.type = (DMG_BULLET | DMG_NEVERGIB); for (ULONG iShot = 1; iShot <= cShots; ++iShot) { int spark = 0; // get circular gaussian spread float x, y, z; do { x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); z = x * x + y * y; } while (z > 1); Vector vecDir, vecEnd; vecDir = vecDirShooting + x * vecSpread.x * vecRight + y * vecSpread.y * vecUp; vecEnd = vecSrc + vecDir * flDistance; UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr); tracer = 0; if (iTracerFreq != 0 && !(tracerCount++ % iTracerFreq)) { Vector vecTracerSrc; if (IsPlayer()) { // adjust tracer position for player vecTracerSrc = vecSrc + Vector(0, 0, -4) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16; } else { vecTracerSrc = vecSrc; } // guns that always trace also always decal if (iTracerFreq != 1) tracer = 1; MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, vecTracerSrc); WRITE_BYTE(TE_TRACER); WRITE_COORD(vecTracerSrc.x); WRITE_COORD(vecTracerSrc.y); WRITE_COORD(vecTracerSrc.z); WRITE_COORD(tr.vecEndPos.x); WRITE_COORD(tr.vecEndPos.y); WRITE_COORD(tr.vecEndPos.z); MESSAGE_END(); } // do damage, paint decals if (tr.flFraction != 1.0f) { CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if (iDamage) { pEntity->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB)); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); } else { float flDamage; switch (iBulletType) { case BULLET_PLAYER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmgMP5, vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_BUCKSHOT: flDamage = ((1 - tr.flFraction) * 20); pEntity->TraceAttack(pevAttacker, int(flDamage), vecDir, &tr, DMG_BULLET); break; case BULLET_PLAYER_357: pEntity->TraceAttack(pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET); break; case BULLET_MONSTER_9MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); break; case BULLET_MONSTER_MP5: pEntity->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); break; case BULLET_MONSTER_12MM: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET); if (!tracer) { TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); DecalGunshot(&tr, iBulletType, false, pev, false); } break; case BULLET_NONE: flDamage = 50; pEntity->TraceAttack(pevAttacker, flDamage, vecDir, &tr, DMG_CLUB); TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType); // only decal glass if (!FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != kRenderNormal) { UTIL_DecalTrace(&tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0, 2)); } break; default: pEntity->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET); break; } } } // make bullet trails UTIL_BubbleTrail(vecSrc, tr.vecEndPos, int((flDistance * tr.flFraction) / 64)); } ApplyMultiDamage(pev, pevAttacker); }
int CTalkMonster :: GetVoicePitch( void ) { return m_voicePitch + RANDOM_LONG(0,3); }
void CBaseTurret::ActiveThink(void) { int fAttack = 0; Vector vecDirToEnemy; pev->nextthink = gpGlobals->time + 0.1; StudioFrameAdvance( ); if ((!m_iOn) || FNullEnt(m_hEnemy)) { 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 bool theEnemyHasCloaking = false;//GetHasUpgrade(m_hEnemy->pev->iuser4, MASK_ALIEN_UPGRADE_10); if(theEnemyHasCloaking) { int a = 0; } int fEnemyVisible = FBoxVisible(pev, m_hEnemy->pev, vecMidEnemy) || !this->NeedsLineOfSight(); vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy float flDistToEnemy = vecDirToEnemy.Length(); Vector vec = UTIL_VecToAngles(vecMidEnemy - vecMid); // Current enemy is not visible. if (!fEnemyVisible || (flDistToEnemy > this->GetRange()) || theEnemyHasCloaking) { 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); this->StopShooting(); } //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(); }