void AvHBaseBuildable::UpdateDamageEffects() { if(GetGameRules()->GetGameStarted() && this->GetIsBuilt()) { // Add special effects for structures that are hurt or almost dead float theMaxHealth = GetGameRules()->GetBaseHealthForMessageID(this->GetMessageID()); float theHealthScalar = this->pev->health/theMaxHealth; float theTimeInterval = max(gpGlobals->time - this->mTimeOfLastDamageUpdate, .1f); const float kParticleSystemLifetime = 5.0f; int theAverageSoundInterval = -1; // If we're at 25% health or less, emit black smoke if(gpGlobals->time > (this->mTimeOfLastDamageEffect + kParticleSystemLifetime)) { if(theHealthScalar < .25f) { AvHSUPlayParticleEvent(kpsBuildableLightDamage, this->edict(), this->pev->origin); this->mTimeOfLastDamageEffect = gpGlobals->time; theAverageSoundInterval = 3; } // If we're at 50% health or less, emit light smoke else if(theHealthScalar < .5f) { AvHSUPlayParticleEvent(kpsBuildableLightDamage, this->edict(), this->pev->origin); this->mTimeOfLastDamageEffect = gpGlobals->time; theAverageSoundInterval = 5; } } // If we're at less then 75% health, spark occasionally if(theHealthScalar < .75f) { int theRandomChance = RANDOM_LONG(0, (float)8/theTimeInterval); if(theRandomChance == 0) { UTIL_Sparks(this->pev->origin); UTIL_Sparks(this->pev->origin); const char* theHurtSoundToPlay = kBuildableHurt1Sound; if(RANDOM_LONG(0, 1) == 1) { theHurtSoundToPlay = kBuildableHurt2Sound; } float theVolume = .3f; EMIT_SOUND(this->edict(), CHAN_AUTO, theHurtSoundToPlay, theVolume, ATTN_NORM); } } this->mTimeOfLastDamageUpdate = gpGlobals->time; } }
void CBeam::DoSparks( const Vector &start, const Vector &end ) { if( pev->spawnflags & ( SF_BEAM_SPARKSTART | SF_BEAM_SPARKEND ) ) { if( pev->spawnflags & SF_BEAM_SPARKSTART ) { UTIL_Sparks( start ); } if( pev->spawnflags & SF_BEAM_SPARKEND ) { UTIL_Sparks( end ); } } }
void CFuncLight :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { if( pev->takedamage == DAMAGE_NO ) return; if( m_iState == STATE_DEAD ) return; const char *pTextureName = NULL; Vector start = pevAttacker->origin + pevAttacker->view_ofs; Vector end = start + vecDir * 1024; edict_t *pHit = ptr->pHit; if( pHit ) pTextureName = TRACE_TEXTURE( pHit, start, end ); if( pTextureName != NULL && ( !Q_strncmp( pTextureName, "+0~", 3 ) || *pTextureName == '~' )) { // take damage only at light texture UTIL_Sparks( ptr->vecEndPos ); m_vecLastDmgPoint = ptr->vecEndPos; } CBreakable::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType ); }
//========================================================= // FScheduleValid - returns TRUE as long as the current // schedule is still the proper schedule to be executing, // taking into account all conditions //========================================================= BOOL CBaseMonster :: FScheduleValid ( void ) { if ( m_pSchedule == NULL ) { // schedule is empty, and therefore not valid. return FALSE; } if ( HasConditions( m_pSchedule->iInterruptMask | bits_COND_SCHEDULE_DONE | bits_COND_TASK_FAILED ) ) { #ifdef DEBUG if ( HasConditions ( bits_COND_TASK_FAILED ) && m_failSchedule == SCHED_NONE ) { // fail! Send a visual indicator. Vector tmp = pev->origin; tmp.z = pev->absmax.z + 16; UTIL_Sparks( tmp ); } #endif // DEBUG // some condition has interrupted the schedule, or the schedule is done return FALSE; } return TRUE; }
void CBreakable::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { // random spark if this is a 'computer' object if (RANDOM_LONG(0,1) ) { switch( m_Material ) { case matComputer: { UTIL_Sparks( ptr->vecEndPos ); float flVolume = RANDOM_FLOAT ( 0.7 , 1.0 );//random volume range switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; } } break; case matUnbreakableGlass: UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT(0.5,1.5) ); break; } } CBaseDelay::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType ); }
void COsprey::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { // ALERT( at_console, "%d %.0f\n", ptr->iHitgroup, flDamage ); // only so much per engine if (ptr->iHitgroup == 3) { if (m_flRightHealth < 0) return; else m_flRightHealth -= flDamage; m_iDoLeftSmokePuff = 3 + (flDamage / 5.0); } if (ptr->iHitgroup == 2) { if (m_flLeftHealth < 0) return; else m_flLeftHealth -= flDamage; m_iDoRightSmokePuff = 3 + (flDamage / 5.0); } // hit hard, hits cockpit, hits engines if (flDamage > 50 || ptr->iHitgroup == 1 || ptr->iHitgroup == 2 || ptr->iHitgroup == 3) { // ALERT( at_console, "%.0f\n", flDamage ); AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType ); } else { UTIL_Sparks( ptr->vecEndPos ); } }
void DoSpark(entvars_t *pev, const Vector &location) { Vector tmp = location + pev->size * 0.5; UTIL_Sparks(tmp); float flVolume = RANDOM_FLOAT(0.25, 0.75) * 0.4; //random volume range switch((int)(RANDOM_FLOAT(0, 1) * 6)) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark1.wav", flVolume, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark2.wav", flVolume, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark3.wav", flVolume, ATTN_NORM); break; case 3: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark4.wav", flVolume, ATTN_NORM); break; case 4: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; case 5: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; } }
void CFuncLight :: Flicker( void ) { if( m_iState == STATE_TURN_ON ) { LIGHT_STYLE( m_iStyle, "k" ); UTIL_FireTargets( pev->target, this, this, USE_ON ); m_iState = STATE_ON; DontThink(); return; } if( m_iFlickerMode == 1 ) { pev->frame = 1; LIGHT_STYLE( m_iStyle, "a" ); SetThink( NULL ); return; } if( m_iFlickerMode == 2 ) { switch( RANDOM_LONG( 0, 3 )) { case 0: LIGHT_STYLE( m_iStyle, "abcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); break; case 1: LIGHT_STYLE( m_iStyle, "acaaabaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); break; case 2: LIGHT_STYLE( m_iStyle, "aaafbaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); break; case 3: LIGHT_STYLE( m_iStyle, "aaaaaaaaaaaaagaaaaaaaaacaaaacaaaa" ); break; } m_flNextFlickerTime = RANDOM_FLOAT( 0.5f, 10.0f ); UTIL_Sparks( m_vecLastDmgPoint ); switch( RANDOM_LONG( 0, 2 )) { case 0: EMIT_SOUND( edict(), CHAN_VOICE, "buttons/spark1.wav", 0.4, ATTN_IDLE ); break; case 1: EMIT_SOUND( edict(), CHAN_VOICE, "buttons/spark2.wav", 0.3, ATTN_IDLE ); break; case 2: EMIT_SOUND( edict(), CHAN_VOICE, "buttons/spark3.wav", 0.35, ATTN_IDLE ); break; } if( m_flNextFlickerTime > 6.5f ) m_iFlickerMode = 1; // stop sparking } SetNextThink( m_flNextFlickerTime ); }
void CShower::Think( void ) { UTIL_Sparks( pev->origin ); pev->speed -= 0.1; if ( pev->speed > 0 ) SetNextThink( 0.1 ); else UTIL_Remove( this ); pev->flags &= ~FL_ONGROUND; }
void CShower::Think( void ) { UTIL_Sparks( GetAbsOrigin() ); SetSpeed( GetSpeed() - 0.1 ); if( GetSpeed() > 0 ) SetNextThink( gpGlobals->time + 0.1 ); else UTIL_Remove( this ); GetFlags().ClearFlags( FL_ONGROUND ); }
void CShower::Think( void ) { UTIL_Sparks( pev->origin ); pev->speed -= 0.1; if ( pev->speed > 0 ) pev->nextthink = gpGlobals->time + 0.1; else UTIL_Remove( this ); pev->flags &= ~FL_ONGROUND; }
void AvHBaseBuildable::Killed(entvars_t* pevAttacker, int iGib) { bool theInReset = GetGameRules()->GetIsGameInReset(); AvHBaseBuildable::SetHasBeenKilled(); GetGameRules()->RemoveEntityUnderAttack( this->entindex() ); this->mKilled = true; this->mInternalSetConstructionComplete = false; this->mTimeOfLastAutoHeal = -1; if (!theInReset) { // : 980 // Less smoke for recycled buildings this->TriggerDeathAudioVisuals(iGib == GIB_RECYCLED); if(!this->GetIsOrganic()) { // More sparks for recycled buildings int numSparks = ( iGib == GIB_RECYCLED ) ? 7 : 3; for ( int i=0; i < numSparks; i++ ) { Vector vecSrc = Vector( (float)RANDOM_FLOAT( pev->absmin.x, pev->absmax.x ), (float)RANDOM_FLOAT( pev->absmin.y, pev->absmax.y ), (float)0 ); vecSrc = vecSrc + Vector( (float)0, (float)0, (float)RANDOM_FLOAT( pev->origin.z, pev->absmax.z ) ); UTIL_Sparks(vecSrc); } } // : } this->TriggerRemoveTech(); AvHSURemoveEntityFromHotgroupsAndSelection(this->entindex()); if(pevAttacker) { const char* theClassName = STRING(this->pev->classname); AvHPlayer* inPlayer = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(ENT(pevAttacker))); if(inPlayer && theClassName) { inPlayer->LogPlayerAction("structure_destroyed", theClassName); GetGameRules()->RewardPlayerForKill(inPlayer, this); } } if(this->GetIsPersistent()) { this->SetInactive(); } else { CBaseAnimating::Killed(pevAttacker, iGib); } }
void CShower::__MAKE_VHOOK(Think)() { UTIL_Sparks(pev->origin); pev->speed -= 0.1f; if (pev->speed > 0) pev->nextthink = gpGlobals->time + 0.1f; else UTIL_Remove(this); pev->flags &= ~FL_ONGROUND; }
void CBreakable::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { // random spark if this is a 'computer' object if (RANDOM_LONG(0,1) ) { switch( m_Material ) { case matComputer: { UTIL_Sparks( ptr->vecEndPos ); float flVolume = RANDOM_FLOAT ( 0.7 , 1.0 );//random volume range switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; } } break; case matUnbreakableGlass: UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT(0.5,1.5) ); break; } } //LRC if (m_iszWhenHit) { if(m_pHitProxy==NULL){ //AJH may need to reset this as it's null after save/load m_pHitProxy = GetClassPtr( (CPointEntity*)NULL ); } m_pHitProxy->pev->origin = ptr->vecEndPos; if (pev->spawnflags&SF_BREAKABLE_INVERT){ //AJH vecDir.y=-vecDir.y; //vecDir.z=-vecDir.z; vecDir.x=-vecDir.x; //ALERT(at_debug,"INVERTING Breakables 'hit' vector (x&y components only) \n"); } m_pHitProxy->pev->velocity = vecDir; m_pHitProxy->pev->angles = UTIL_VecToAngles(vecDir); //AJH //ALERT(at_debug,"Func_breakable fires %s \n",STRING(m_iszWhenHit)); FireTargets( STRING(m_iszWhenHit), m_pHitProxy, this, USE_TOGGLE, 0 ); } CBaseDelay::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType ); }
void CElectrifiedWire::DoSpark( const size_t uiSegment, const bool bExertForce ) { const Vector vecOrigin = GetSegmentAttachmentPoint( uiSegment ); UTIL_Sparks( vecOrigin ); if( bExertForce ) { const Vector vecSparkForce( UTIL_RandomFloat( -m_iXJoltForce, m_iXJoltForce ), UTIL_RandomFloat( -m_iYJoltForce, m_iYJoltForce ), UTIL_RandomFloat( -m_iZJoltForce, m_iZJoltForce ) ); ApplyForceToSegment( vecSparkForce, uiSegment ); } }
void CGenericMonster::MakeGas( void ) { Vector posGun, angleGun; TraceResult tr; UTIL_MakeVectors( pev->angles ); { KillGas(); m_pBeam = CBeam::BeamCreate( "sprites/laserbeam.spr", 7 ); if ( m_pBeam ) { GetAttachment( 4, posGun, angleGun ); GetAttachment( 3, posGun, angleGun ); Vector vecEnd = (gpGlobals->v_forward * 5) + posGun; UTIL_TraceLine( posGun, vecEnd, dont_ignore_monsters, edict(), &tr ); m_pBeam->EntsInit( edict(), edict() ); m_pBeam->SetColor( 24, 121, 239 ); m_pBeam->SetBrightness( 190 ); m_pBeam->SetScrollRate( 20 ); m_pBeam->SetStartAttachment( 4 ); m_pBeam->SetEndAttachment( 3 ); m_pBeam->DamageDecal( 28 ); m_pBeam->DoSparks( tr.vecEndPos, posGun ); m_pBeam->SetFlags( FBEAM_SHADEIN ); m_pBeam->RelinkBeam(); UTIL_Sparks( tr.vecEndPos ); UTIL_DecalTrace(&tr, 28 + RANDOM_LONG(0,4)); } } // m_flNextAttack = gpGlobals->time + RANDOM_FLOAT( 0.5, 4.0 ); if ( int gas = 1 ) { pev->nextthink = gpGlobals->time; } }
void CBreakable::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { // random spark if this is a 'computer' object if (RANDOM_LONG(0,1) ) { switch( m_Material ) { case matComputer: { UTIL_Sparks( ptr->vecEndPos ); float flVolume = RANDOM_FLOAT ( 0.7 , 1.0 );//random volume range switch ( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; } } break; case matUnbreakableGlass: UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT(0.5,1.5) ); break; } } //LRC if (m_iszWhenHit) { m_pHitProxy->pev->origin = ptr->vecEndPos; m_pHitProxy->pev->velocity = vecDir; FireTargets( STRING(m_iszWhenHit), m_pHitProxy, this, USE_TOGGLE, 0 ); } CBaseDelay::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType ); }
void CFriend::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { // check for helmet shot if (ptr->iHitgroup == HITGROUP_HEAD) // si el daño es en la cabeza { if (GetBodygroup( 1 ) == HEAD_MASK && (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB))) { // absorb damage flDamage -= 20; if (flDamage <= 0) { UTIL_Ricochet( ptr->vecEndPos, 1.0 ); UTIL_Sparks( ptr->vecEndPos ); // Sonidos (precache en world.cpp) switch (RANDOM_LONG(0,2)) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet1.wav", 0.9, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet2.wav", 0.9, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet3.wav", 0.9, ATTN_NORM); break; } flDamage = 0.01; } } else if (GetBodygroup( 1 ) == HEAD_GRUNT && (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB))) { // absorb damage flDamage -= 20; if (flDamage <= 0) { UTIL_Ricochet( ptr->vecEndPos, 1.0 ); UTIL_Sparks( ptr->vecEndPos ); // Sonidos (precache en world.cpp) switch (RANDOM_LONG(0,2)) { case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet1.wav", 0.9, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet2.wav", 0.9, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/damage/helmet3.wav", 0.9, ATTN_NORM); break; } flDamage = 0.01; } } else { ALERT( at_console, "Human Grunt Headshot!\n" ); UTIL_BloodStream( ptr->vecEndPos, gpGlobals->v_forward * 10 + // -5 gpGlobals->v_up * 2, (unsigned short)73, 100 ); //-35 switch (RANDOM_LONG(0,2)) //ejecuta los siguientes sonidos al azar { case 0: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_headshot1.wav", 1, ATTN_NORM ); break; case 1: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_headshot2.wav", 1, ATTN_NORM ); break; case 2: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_headshot3.wav", 1, ATTN_NORM ); break; } } } else { switch (RANDOM_LONG(0,2)) //ejecuta los siguientes sonidos al azar { case 0: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_hit1.wav", 1, ATTN_NORM ); break; case 1: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_hit2.wav", 1, ATTN_NORM ); break; case 2: EMIT_SOUND (ENT(pev), CHAN_BODY, "fvox/m_hit3.wav", 1, ATTN_NORM ); break; } } CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType ); }
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 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 ); } }
// CS Vector CBaseEntity::FireBullets3( Vector vecSrc, Vector vecDirShooting, float flSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand ) { int originalPenetration = iPenetration; int penetrationPower; float penetrationDistance; int currentDamage = iDamage; float currentDistance; TraceResult tr; TraceResult tr2; Vector vecRight = gpGlobals->v_right; Vector vecUp = gpGlobals->v_up; bool hitMetal = false; switch( iBulletType ) { case BULLET_PLAYER_9MM: { penetrationPower = 21; penetrationDistance = 800; break; } case BULLET_PLAYER_45ACP: { penetrationPower = 15; penetrationDistance = 500; break; } case BULLET_PLAYER_50AE: { penetrationPower = 30; penetrationDistance = 1000; break; } case BULLET_PLAYER_762MM: { penetrationPower = 39; penetrationDistance = 5000; break; } case BULLET_PLAYER_556MM: { penetrationPower = 35; penetrationDistance = 4000; break; } case BULLET_PLAYER_338MAG: { penetrationPower = 45; penetrationDistance = 8000; break; } case BULLET_PLAYER_57MM: { penetrationPower = 30; penetrationDistance = 2000; break; } case BULLET_PLAYER_357SIG: { penetrationPower = 25; penetrationDistance = 800; break; } default: { penetrationPower = 0; penetrationDistance = 0; break; } } if( !pevAttacker ) { pevAttacker = pev; } gMultiDamage.type = DMG_BULLET | DMG_NEVERGIB; float x, y, z; if( IsPlayer() ) { 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 = vecDirShooting + x * flSpread * vecRight + y * flSpread * vecUp; Vector vecEnd = vecSrc + vecDir * flDistance; float damageModifier = 0.5; while( iPenetration ) { ClearMultiDamage(); UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &tr ); if( tr.flFraction != 1.0 ) { // TODO:Implement me. // TheBots->OnEvent( EVENT_BULLET_IMPACT, this, NULL ); } switch( UTIL_TextureHit( &tr, vecSrc, vecEnd ) ) { case CHAR_TEX_METAL: { hitMetal = true; penetrationPower *= 0.15; damageModifier = 0.2; break; } case CHAR_TEX_CONCRETE: { penetrationPower *= 0.25; break; } case CHAR_TEX_GRATE: { hitMetal = true; penetrationPower *= 0.5; damageModifier = 0.4; break; } case CHAR_TEX_VENT: { hitMetal = true; penetrationPower *= 0.5; damageModifier = 0.45; break; } case CHAR_TEX_TILE: { penetrationPower *= 0.65; damageModifier = 0.3; break; } case CHAR_TEX_COMPUTER: { hitMetal = true; penetrationPower *= 0.4; damageModifier = 0.45; break; } case CHAR_TEX_WOOD: { damageModifier = 0.6; break; } } if( tr.flFraction != 1.0 ) { CBaseEntity* pEntity = CBaseEntity::Instance( tr.pHit ); iPenetration--; currentDistance = tr.flFraction * flDistance; currentDamage *= pow( flRangeModifier, currentDistance / 500 ); if( currentDistance > penetrationDistance ) { iPenetration = 0; } if( tr.iHitgroup == HITGROUP_SHIELD ) { if( tr.flFraction != 1.0 ) { if( RANDOM_LONG( 0, 1 ) ) EMIT_SOUND( pEntity->edict(), CHAN_VOICE, "weapons/ric_metal-1.wav", VOL_NORM, ATTN_NORM ); else EMIT_SOUND( pEntity->edict(), CHAN_VOICE, "weapons/ric_metal-2.wav", VOL_NORM, ATTN_NORM ); UTIL_Sparks( tr.vecEndPos ); pEntity->pev->punchangle.x = currentDamage * RANDOM_FLOAT( -0.15, 0.15 ); pEntity->pev->punchangle.z = currentDamage * 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 distanceModifier; if( VARS( tr.pHit )->solid != SOLID_BSP || !iPenetration ) { penetrationPower = 42.0; distanceModifier = 0.75; damageModifier = 0.75; } else { distanceModifier = 0.75; } DecalGunshot( &tr, iBulletType, bPistol || RANDOM_LONG( 0, 3 ), pev, hitMetal ); vecSrc = tr.vecEndPos + ( vecDir * penetrationPower ); flDistance = ( flDistance - currentDistance ) * distanceModifier; vecEnd = vecSrc + ( vecDir * flDistance ); pEntity->TraceAttack( pevAttacker, currentDamage, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB); currentDamage *= damageModifier; } else { iPenetration = 0; } ApplyMultiDamage( pev, pevAttacker ); } return Vector( x * flSpread, y * flSpread, 0 ); }
void AvHBaseBuildable::WorldUpdate() { this->UpdateTechSlots(); // Organic buildings heal themselves if(this->GetIsOrganic()) { this->UpdateAutoHeal(); } else { //this->UpdateDamageEffects(); } // If we're electrified, set render mode if(GetHasUpgrade(this->pev->iuser4, MASK_UPGRADE_11)) { // Base marine building const int kElectrifyRenderMode = kRenderFxGlowShell; const int kElectrifyRenderAmount = 40; this->pev->renderfx = kElectrifyRenderMode; this->pev->renderamt = kElectrifyRenderAmount; this->pev->rendercolor.x = kTeamColors[this->pev->team][0]; this->pev->rendercolor.y = kTeamColors[this->pev->team][1]; this->pev->rendercolor.z = kTeamColors[this->pev->team][2]; // Check for enemy players/structures nearby CBaseEntity* theBaseEntity = NULL; int theNumEntsDamaged = 0; while(((theBaseEntity = UTIL_FindEntityInSphere(theBaseEntity, this->pev->origin, BALANCE_VAR(kElectricalRange))) != NULL) && (theNumEntsDamaged < BALANCE_VAR(kElectricalMaxTargets))) { // When "electric" cheat is enabled, shock all non-self entities, else shock enemies if((GetGameRules()->GetIsCheatEnabled(kcElectric) && (theBaseEntity != this)) || ((theBaseEntity->pev->team != this->pev->team) && theBaseEntity->IsAlive())) { // Make sure it's not blocked TraceResult theTraceResult; UTIL_TraceLine(this->pev->origin, theBaseEntity->pev->origin, ignore_monsters, dont_ignore_glass, this->edict(), &theTraceResult); if(theTraceResult.flFraction == 1.0f) { CBaseEntity* theAttacker = this->GetAttacker(); ASSERT(theAttacker); if(theBaseEntity->TakeDamage(this->pev, theAttacker->pev, BALANCE_VAR(kElectricalDamage), DMG_GENERIC) > 0) { MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE(TE_BEAMENTPOINT); WRITE_SHORT(theBaseEntity->entindex()); WRITE_COORD( this->pev->origin.x); WRITE_COORD( this->pev->origin.y); WRITE_COORD( this->pev->origin.z); WRITE_SHORT( this->mElectricalSprite ); WRITE_BYTE( 0 ); // framestart WRITE_BYTE( (int)15); // framerate WRITE_BYTE( (int)(2) ); // life WRITE_BYTE( 60 ); // width WRITE_BYTE( 15 ); // noise WRITE_BYTE( (int)this->pev->rendercolor.x ); // r, g, b WRITE_BYTE( (int)this->pev->rendercolor.y ); // r, g, b WRITE_BYTE( (int)this->pev->rendercolor.z ); // r, g, b WRITE_BYTE( 200 ); // brightness WRITE_BYTE( 10 ); // speed MESSAGE_END(); gSoundListManager.PlaySoundInList(kElectricSparkSoundList, this, CHAN_AUTO, .7f); UTIL_Sparks(theBaseEntity->pev->origin); theNumEntsDamaged++; } } } } } }
// this function only gets called in multiplayer void CCrossbow::FireSniperBolt() { m_flNextPrimaryAttack = gpGlobals->time + 0.75; if (m_iClip == 0) { PlayEmptySound( ); return; } TraceResult tr; m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; m_iClip--; // make twang sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/xbow_fire1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); if (m_iClip) { EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); SendWeaponAnim( CROSSBOW_FIRE1 ); } else if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) { SendWeaponAnim( CROSSBOW_FIRE3 ); } // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); Vector anglesAim = m_pPlayer->pev->viewangles + m_pPlayer->pev->punchangle; UTIL_MakeVectors( anglesAim ); Vector vecSrc = m_pPlayer->GetGunPosition( ) - gpGlobals->v_up * 2; Vector vecDir = gpGlobals->v_forward; UTIL_TraceLine(vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, m_pPlayer->edict(), &tr); if ( tr.pHit->v.takedamage ) { switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND( tr.pHit, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND( tr.pHit, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); break; } ClearMultiDamage( ); CBaseEntity::Instance(tr.pHit)->TraceAttack(m_pPlayer->pev, 120, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB ); ApplyMultiDamage( pev, m_pPlayer->pev ); } else { // create a bolt CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); pBolt->pev->origin = tr.vecEndPos - vecDir * 10; pBolt->pev->angles = UTIL_VecToAngles( vecDir ); pBolt->pev->solid = SOLID_NOT; pBolt->SetTouch( NULL ); pBolt->SetThink( SUB_Remove ); EMIT_SOUND( pBolt->edict(), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM ); if (UTIL_PointContents(tr.vecEndPos) != CONTENTS_WATER) { UTIL_Sparks( tr.vecEndPos ); } if ( FClassnameIs( tr.pHit, "worldspawn" ) ) { // let the bolt sit around for a while if it hit static architecture pBolt->pev->nextthink = gpGlobals->time + 5.0; } else { pBolt->pev->nextthink = gpGlobals->time; } } }
void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) { SetTouch( NULL ); SetThink( NULL ); if (pOther->pev->takedamage) { TraceResult tr = UTIL_GetGlobalTrace( ); entvars_t *pevOwner; pevOwner = VARS( pev->owner ); // UNDONE: this needs to call TraceAttack instead ClearMultiDamage( ); if ( pOther->IsPlayer() ) { pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowClient, pev->velocity.Normalize(), &tr, DMG_NEVERGIB ); } else { pOther->TraceAttack(pevOwner, gSkillData.plrDmgCrossbowMonster, pev->velocity.Normalize(), &tr, DMG_BULLET | DMG_NEVERGIB ); } ApplyMultiDamage( pev, pevOwner ); pev->velocity = Vector( 0, 0, 0 ); // play body "thwack" sound switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); break; } if ( !g_pGameRules->IsMultiplayer() ) { Killed( pev, GIB_NEVER ); } } else { EMIT_SOUND_DYN(ENT(pev), CHAN_BODY, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 98 + RANDOM_LONG(0,7)); SetThink( &CCrossbowBolt::SUB_Remove ); pev->nextthink = gpGlobals->time;// this will get changed below if the bolt is allowed to stick in what it hit. if ( FClassnameIs( pOther->pev, "worldspawn" ) ) { // if what we hit is static architecture, can stay around for a while. Vector vecDir = pev->velocity.Normalize( ); UTIL_SetOrigin( pev, pev->origin - vecDir * 12 ); pev->angles = UTIL_VecToAngles( vecDir ); pev->solid = SOLID_NOT; pev->movetype = MOVETYPE_FLY; pev->velocity = Vector( 0, 0, 0 ); pev->avelocity.z = 0; pev->angles.z = RANDOM_LONG(0,360); pev->nextthink = gpGlobals->time + 10.0; } if (UTIL_PointContents(pev->origin) != CONTENTS_WATER) { UTIL_Sparks( pev->origin ); } } if ( g_pGameRules->IsMultiplayer() ) { SetThink( &CCrossbowBolt::ExplodeThink ); pev->nextthink = gpGlobals->time + 0.1; } }
// 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 CDisc::DiscTouch ( CBaseEntity *pOther ) { // Push players backwards if ( pOther->IsPlayer() ) { if ( ((CBaseEntity*)m_hOwner) == pOther ) { if (m_fDontTouchOwner < gpGlobals->time) { // Play catch sound EMIT_SOUND_DYN( pOther->edict(), CHAN_WEAPON, "items/gunpickup2.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); ReturnToThrower(); } return; } else if ( m_fDontTouchEnemies < gpGlobals->time) { if ( pev->team != pOther->pev->team ) { ((CBasePlayer*)pOther)->m_LastHitGroup = HITGROUP_GENERIC; // Do freeze seperately so you can freeze and shatter a person with a single shot if ( m_iPowerupFlags & POW_FREEZE && ((CBasePlayer*)pOther)->m_iFrozen == FALSE ) { // Freeze the player and make them glow blue EMIT_SOUND_DYN( pOther->edict(), CHAN_WEAPON, "weapons/electro5.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); ((CBasePlayer*)pOther)->Freeze(); // If it's not a decap, return now. If it's a decap, continue to shatter if ( !m_bDecapitate ) { m_fDontTouchEnemies = gpGlobals->time + 2.0; return; } } // Decap or push if (m_bDecapitate) { // Decapitate! if ( m_bTeleported ) ((CBasePlayer*)pOther)->m_flLastDiscHitTeleport = gpGlobals->time; ((CBasePlayer*)pOther)->Decapitate( ((CBaseEntity*)m_hOwner)->pev ); m_fDontTouchEnemies = gpGlobals->time + 0.5; } else { // Play thwack sound switch( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND_DYN( pOther->edict(), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 1: EMIT_SOUND_DYN( pOther->edict(), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 2: EMIT_SOUND_DYN( pOther->edict(), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; } // Push the player Vector vecDir = pev->velocity.Normalize(); pOther->pev->flags &= ~FL_ONGROUND; ((CBasePlayer*)pOther)->m_vecHitVelocity = vecDir * DISC_PUSH_MULTIPLIER; // Shield flash only if the player isnt frozen if ( ((CBasePlayer*)pOther)->m_iFrozen == false ) { pOther->pev->renderfx = kRenderFxGlowShell; pOther->pev->rendercolor.x = 255; pOther->pev->renderamt = 150; } ((CBasePlayer*)pOther)->m_hLastPlayerToHitMe = m_hOwner; ((CBasePlayer*)pOther)->m_flLastDiscHit = gpGlobals->time; ((CBasePlayer*)pOther)->m_iLastDiscBounces = m_iBounces; if ( m_bTeleported ) ((CBasePlayer*)pOther)->m_flLastDiscHitTeleport = gpGlobals->time; m_fDontTouchEnemies = gpGlobals->time + 2.0; } } } } // Hit a disc? else if ( pOther->pev->iuser4 ) { // Enemy Discs destroy each other if ( pOther->pev->iuser4 != pev->iuser4 ) { // Play a warp sound and sprite CSprite *pSprite = CSprite::SpriteCreate( "sprites/discreturn.spr", pev->origin, TRUE ); pSprite->AnimateAndDie( 60 ); pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation ); pSprite->SetScale( 1 ); EMIT_SOUND_DYN( edict(), CHAN_ITEM, "dischit.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); // Return both discs to their owners ((CDisc*)pOther)->ReturnToThrower(); ReturnToThrower(); } else { // Friendly discs just pass through each other } } else { m_iBounces++; switch ( RANDOM_LONG( 0, 1 ) ) { case 0: EMIT_SOUND_DYN( edict(), CHAN_ITEM, "weapons/xbow_hit1.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 1: EMIT_SOUND_DYN( edict(), CHAN_ITEM, "weapons/xbow_hit2.wav", 1.0, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; } UTIL_Sparks( pev->origin, edict() ); } }