// If connected to a table, then use the table controllers, else hit where the trigger is. void CFuncMortarField :: FieldUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { Vector vecStart; vecStart.x = RANDOM_FLOAT( pev->mins.x, pev->maxs.x ); vecStart.y = RANDOM_FLOAT( pev->mins.y, pev->maxs.y ); vecStart.z = pev->maxs.z; switch( m_fControl ) { case 0: // random break; case 1: // Trigger Activator if (pActivator != NULL) { vecStart.x = pActivator->pev->origin.x; vecStart.y = pActivator->pev->origin.y; } break; case 2: // table { CBaseEntity *pController; if (!FStringNull(m_iszXController)) { pController = UTIL_FindEntityByTargetname( NULL, STRING(m_iszXController)); if (pController != NULL) { vecStart.x = pev->mins.x + pController->pev->ideal_yaw * (pev->size.x); } } if (!FStringNull(m_iszYController)) { pController = UTIL_FindEntityByTargetname( NULL, STRING(m_iszYController)); if (pController != NULL) { vecStart.y = pev->mins.y + pController->pev->ideal_yaw * (pev->size.y); } } } break; } int pitch = RANDOM_LONG(95,124); EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/mortar.wav", 1.0, ATTN_NONE, 0, pitch); float t = 2.5; for (int i = 0; i < m_iCount; i++) { Vector vecSpot = vecStart; vecSpot.x += RANDOM_FLOAT( -m_flSpread, m_flSpread ); vecSpot.y += RANDOM_FLOAT( -m_flSpread, m_flSpread ); TraceResult tr; UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -1 ) * 4096, ignore_monsters, ENT(pev), &tr ); edict_t *pentOwner = NULL; if (pActivator) pentOwner = pActivator->edict(); CBaseEntity *pMortar = Create("monster_mortar", tr.vecEndPos, Vector( 0, 0, 0 ), pentOwner ); pMortar->pev->nextthink = gpGlobals->time + t; t += RANDOM_FLOAT( 0.2, 0.5 ); if (i == 0) CSoundEnt::InsertSound ( bits_SOUND_DANGER, tr.vecEndPos, 400, 0.3 ); } }
void CGlowOverlay::UpdateGlowObstruction( const Vector &vToGlow, bool bCacheFullSceneState ) { // If we already cached the glow obstruction and are still using that, early-out if ( bCacheFullSceneState && m_bCacheGlowObstruction ) return; if ( bCacheFullSceneState && !m_bCacheGlowObstruction ) // If turning on sky obstruction caching mode { m_bCacheGlowObstruction = true; } if ( !bCacheFullSceneState && m_bCacheGlowObstruction ) { m_bCacheGlowObstruction = false; } if ( PixelVisibility_IsAvailable() ) { if ( m_bInSky ) { const CViewSetup *pViewSetup = view->GetViewSetup(); Vector pos = CurrentViewOrigin() + m_vDirection * (pViewSetup->zFar * 0.99f); // GSTRINGMIGRATION pixelvis_queryparams_t params; params.Init( pos, m_flProxyRadius, CalcGlowAspect() ); params.bSizeInScreenspace = true; // use a pixel query to occlude with models m_flGlowObstructionScale = PixelVisibility_FractionVisible( params, &m_queryHandle ) * m_skyObstructionScale; } else { // If it's not in the sky, then we need a valid position or else we don't // know what's in front of it. Assert( !m_bDirectional ); pixelvis_queryparams_t params; params.Init( m_vPos, m_flProxyRadius, CalcGlowAspect() ); m_flGlowObstructionScale = PixelVisibility_FractionVisible( params, &m_queryHandle ); } return; } bool bFade = false; if ( m_bInSky ) { // Trace a ray at the object. trace_t trace; UTIL_TraceLine( CurrentViewOrigin(), CurrentViewOrigin() + (vToGlow*MAX_TRACE_LENGTH), CONTENTS_SOLID, NULL, COLLISION_GROUP_NONE, &trace ); bFade = (trace.fraction < 1 && !(trace.surface.flags & SURF_SKY)); } else { // If it's not in the sky, then we need a valid position or else we don't // know what's in front of it. Assert( !m_bDirectional ); pixelvis_queryparams_t params; params.Init( m_vPos, m_flProxyRadius ); bFade = PixelVisibility_FractionVisible( params, &m_queryHandle ) < 1.0f ? true : false; } if ( bFade ) { if ( building_cubemaps.GetBool() ) { m_flGlowObstructionScale = 0.0f; } else { m_flGlowObstructionScale -= gpGlobals->frametime / cl_sun_decay_rate.GetFloat(); m_flGlowObstructionScale = MAX( m_flGlowObstructionScale, 0.0f ); } } else { if ( building_cubemaps.GetBool() ) { m_flGlowObstructionScale = 1.0f; } else { m_flGlowObstructionScale += gpGlobals->frametime / cl_sun_decay_rate.GetFloat(); m_flGlowObstructionScale = MIN( m_flGlowObstructionScale, 1.0f ); } } }
void CGETKnife::DamageTouch( CBaseEntity *pOther ) { if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( !PassServerEntityFilter( this, pOther) ) return; if ( !g_pGameRules->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; if (!pOther->IsPlayer() && !pOther->IsNPC()) return; Vector vecAiming; VPhysicsGetObject()->GetVelocity( &vecAiming, NULL ); VectorNormalize( vecAiming ); trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + (vecAiming * 24), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); // We didn't hit the player again with our damage cast. Do a cast to the player's center to get a proper hit. if (tr.m_pEnt != pOther) { Vector TargetVec = pOther->GetAbsOrigin(); TargetVec.z = min(GetAbsOrigin().z, pOther->EyePosition().z); //Make sure we don't cast over their head. UTIL_TraceLine(GetAbsOrigin(), pOther->GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); } // TEMPORARY DEBUGGING PURPOSES // DebugDrawLine( tr.startpos, tr.endpos, 0, 255, 0, true, 5.0f ); // debugoverlay->AddSweptBoxOverlay( tr.startpos, tr.endpos, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), GetAbsAngles(), 0, 0, 255, 100, 5.0f ); // END TEMPORARY // If our target can take damage and the trace actually hit our target if ( pOther->m_takedamage != DAMAGE_NO && tr.fraction < 1.0f && tr.m_pEnt == pOther ) { ClearMultiDamage(); CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), GetDamage(), DMG_SLASH | DMG_NEVERGIB ); CalculateMeleeDamageForce( &dmgInfo, vecAiming, tr.endpos, TKNIFE_FORCE_SCALE ); dmgInfo.SetDamagePosition( tr.endpos ); if ( this->GetOwnerEntity() && this->GetOwnerEntity()->IsPlayer() ) { CBasePlayer *pPlayer = ToBasePlayer( this->GetOwnerEntity() ); dmgInfo.SetWeapon( pPlayer->Weapon_OwnsThisType( "weapon_knife_throwing" ) ); } pOther->DispatchTraceAttack( dmgInfo, vecAiming, &tr ); ApplyMultiDamage(); SetAbsVelocity( vec3_origin ); SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); } }
void CTestEffect::TestThink( void ) { int i; float t = (gpGlobals->time - m_flStartTime); if (m_iBeam < 24) { CBeam *pbeam = CBeam::BeamCreate( "sprites/lgtning.spr", 100 ); TraceResult tr; Vector vecSrc = pev->origin; Vector vecDir = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) ); vecDir = vecDir.Normalize(); UTIL_TraceLine( vecSrc, vecSrc + vecDir * 128, ignore_monsters, ENT(pev), &tr); pbeam->PointsInit( vecSrc, tr.vecEndPos ); // pbeam->SetColor( 80, 100, 255 ); pbeam->SetColor( 255, 180, 100 ); pbeam->SetWidth( 100 ); pbeam->SetScrollRate( 12 ); m_flBeamTime[m_iBeam] = gpGlobals->time; m_pBeam[m_iBeam] = pbeam; m_iBeam++; #if 0 Vector vecMid = (vecSrc + tr.vecEndPos) * 0.5; MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE(TE_DLIGHT); WRITE_COORD(vecMid.x); // X WRITE_COORD(vecMid.y); // Y WRITE_COORD(vecMid.z); // Z WRITE_BYTE( 20 ); // radius * 0.1 WRITE_BYTE( 255 ); // r WRITE_BYTE( 180 ); // g WRITE_BYTE( 100 ); // b WRITE_BYTE( 20 ); // time * 10 WRITE_BYTE( 0 ); // decay * 0.1 MESSAGE_END( ); #endif } if (t < 3.0) { for (i = 0; i < m_iBeam; i++) { t = (gpGlobals->time - m_flBeamTime[i]) / ( 3 + m_flStartTime - m_flBeamTime[i]); m_pBeam[i]->SetBrightness( 255 * t ); // m_pBeam[i]->SetScrollRate( 20 * t ); } pev->nextthink = gpGlobals->time + 0.1; } else { for (i = 0; i < m_iBeam; i++) { UTIL_Remove( m_pBeam[i] ); } m_flStartTime = gpGlobals->time; m_iBeam = 0; // pev->nextthink = gpGlobals->time; SetThink( NULL ); } }
void CASW_Alien::DoBloodDecal( float flDamage, const Vector &vecPos, const Vector &vecDir, trace_t *ptr, int bitsDamageType ) { if ( ( BloodColor() == DONT_BLEED) || ( BloodColor() == BLOOD_COLOR_MECH ) ) { return; } if (flDamage == 0) return; if ( !( bitsDamageType & ( DMG_CRUSH | DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_AIRBOAT ) ) ) return; // make blood decal on the wall! trace_t Bloodtr; Vector vecTraceDir; float flNoise; int cCount; int i; #ifdef GAME_DLL if ( !IsAlive() ) { // dealing with a dead npc. if ( GetMaxHealth() <= 0 ) { // no blood decal for a npc that has already decalled its limit. return; } else { m_iMaxHealth -= 1; } } #endif if (flDamage < 10) { flNoise = 0.1; cCount = 1; } else if (flDamage < 25) { flNoise = 0.2; cCount = 2; } else { flNoise = 0.3; cCount = 4; } float flTraceDist = (bitsDamageType & DMG_AIRBOAT) ? 384 : 172; for ( i = 0 ; i < cCount ; i++ ) { vecTraceDir = vecDir * -1;// trace in the opposite direction the shot came from (the direction the shot is going) vecTraceDir.x += random->RandomFloat( -flNoise, flNoise ); vecTraceDir.y += random->RandomFloat( -flNoise, flNoise ); vecTraceDir.z += random->RandomFloat( -flNoise, flNoise ); // Don't bleed on grates. UTIL_TraceLine( vecPos, vecPos + vecTraceDir * -flTraceDist, MASK_SOLID_BRUSHONLY & ~CONTENTS_GRATE, this, COLLISION_GROUP_NONE, &Bloodtr); if ( Bloodtr.fraction != 1.0 ) { UTIL_BloodDecalTrace( &Bloodtr, BloodColor() ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_HL2MP_Player::AddEntity( void ) { BaseClass::AddEntity(); QAngle vTempAngles = GetLocalAngles(); vTempAngles[PITCH] = m_angEyeAngles[PITCH]; SetLocalAngles( vTempAngles ); m_PlayerAnimState.Update(); // Zero out model pitch, blending takes care of all of it. SetLocalAnglesDim( X_INDEX, 0 ); if( this != C_BasePlayer::GetLocalPlayer() ) { if ( IsEffectActive( EF_DIMLIGHT ) ) { int iAttachment = LookupAttachment( "anim_attachment_RH" ); if ( iAttachment < 0 ) return; Vector vecOrigin; QAngle eyeAngles = m_angEyeAngles; GetAttachment( iAttachment, vecOrigin, eyeAngles ); Vector vForward; AngleVectors( eyeAngles, &vForward ); trace_t tr; UTIL_TraceLine( vecOrigin, vecOrigin + (vForward * 200), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if( !m_pFlashlightBeam ) { BeamInfo_t beamInfo; beamInfo.m_nType = TE_BEAMPOINTS; beamInfo.m_vecStart = tr.startpos; beamInfo.m_vecEnd = tr.endpos; beamInfo.m_pszModelName = "sprites/glow01.vmt"; beamInfo.m_pszHaloName = "sprites/glow01.vmt"; beamInfo.m_flHaloScale = 3.0; beamInfo.m_flWidth = 8.0f; beamInfo.m_flEndWidth = 35.0f; beamInfo.m_flFadeLength = 300.0f; beamInfo.m_flAmplitude = 0; beamInfo.m_flBrightness = 60.0; beamInfo.m_flSpeed = 0.0f; beamInfo.m_nStartFrame = 0.0; beamInfo.m_flFrameRate = 0.0; beamInfo.m_flRed = 255.0; beamInfo.m_flGreen = 255.0; beamInfo.m_flBlue = 255.0; beamInfo.m_nSegments = 8; beamInfo.m_bRenderable = true; beamInfo.m_flLife = 0.5; beamInfo.m_nFlags = FBEAM_FOREVER | FBEAM_ONLYNOISEONCE | FBEAM_NOTILE | FBEAM_HALOBEAM; m_pFlashlightBeam = beams->CreateBeamPoints( beamInfo ); } if( m_pFlashlightBeam ) { BeamInfo_t beamInfo; beamInfo.m_vecStart = tr.startpos; beamInfo.m_vecEnd = tr.endpos; beamInfo.m_flRed = 255.0; beamInfo.m_flGreen = 255.0; beamInfo.m_flBlue = 255.0; beams->UpdateBeamInfo( m_pFlashlightBeam, beamInfo ); dlight_t *el = effects->CL_AllocDlight( 0 ); el->origin = tr.endpos; el->radius = 50; el->color.r = 200; el->color.g = 200; el->color.b = 200; el->die = gpGlobals->curtime + 0.1; } } else if ( m_pFlashlightBeam ) { ReleaseFlashlight(); } } }
//----------------------------------------------------------------------------- // Purpose: Tesla effect //----------------------------------------------------------------------------- void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset ) { Vector vecOrigin; QAngle vecAngles; MatrixGetColumn( hitboxToWorld, 3, vecOrigin ); MatrixAngles( hitboxToWorld, vecAngles.Base() ); C_BaseEntity *pEntity = GetMoveParent(); // Make a couple of tries at it int iTries = -1; Vector vecForward; trace_t tr; do { iTries++; // Some beams are deliberatly aimed around the point, the rest are random. if ( !bRandom ) { QAngle vecTemp = vecAngles; vecTemp[YAW] += flYawOffset; AngleVectors( vecTemp, &vecForward ); // Randomly angle it up or down vecForward.z = RandomFloat( -1, 1 ); } else { vecForward = RandomVector( -1, 1 ); } UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr ); } while ( tr.fraction >= 1.0 && iTries < 3 ); Vector vecEnd = tr.endpos - (vecForward * 8); // Only spark & glow if we hit something if ( tr.fraction < 1.0 ) { if ( !EffectOccluded( tr.endpos ) ) { int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT(); // Move it towards the camera Vector vecFlash = tr.endpos; Vector vecForward; AngleVectors( MainViewAngles(nSlot), &vecForward ); vecFlash -= (vecForward * 8); g_pEffects->EnergySplash( vecFlash, -vecForward, false ); // End glow CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" ); pSimple->SetSortOrigin( vecFlash ); SimpleParticle *pParticle; pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = RandomFloat( 0.5, 1 ); pParticle->m_vecVelocity = vec3_origin; Vector color( 1,1,1 ); float colorRamp = RandomFloat( 0.75f, 1.25f ); pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f; pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f; pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f; pParticle->m_uchStartSize = RandomFloat( 6,13 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 10; pParticle->m_flRoll = RandomFloat( 0,360 ); pParticle->m_flRollDelta = 0; } } } // Build the tesla FX_BuildTesla( pEntity, vecOrigin, tr.endpos ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CASW_PropJeep::FireChargedCannon( void ) { bool penetrated = false; m_bCannonCharging = false; m_flCannonTime = gpGlobals->curtime + 0.5f; StopChargeSound(); CPASAttenuationFilter sndFilter( this, "PropJeep.FireChargedCannon" ); EmitSound( sndFilter, entindex(), "PropJeep.FireChargedCannon" ); //Find the direction the gun is pointing in Vector aimDir; GetCannonAim( &aimDir ); Vector endPos = m_vecGunOrigin + ( aimDir * MAX_TRACE_LENGTH ); //Shoot a shot straight out trace_t tr; UTIL_TraceLine( m_vecGunOrigin, endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); ClearMultiDamage(); //Find how much damage to do float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME; //Clamp this if ( flChargeAmount > 1.0f ) { flChargeAmount = 1.0f; } //Determine the damage amount //FIXME: Use ConVars! float flDamage = 15 + ( ( 250 - 15 ) * flChargeAmount ); CBaseEntity *pHit = tr.m_pEnt; //Look for wall penetration if ( tr.DidHitWorld() && !(tr.surface.flags & SURF_SKY) ) { //Try wall penetration UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); UTIL_DecalTrace( &tr, "RedGlowFade" ); CPVSFilter filter( tr.endpos ); te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); Vector testPos = tr.endpos + ( aimDir * 48.0f ); UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, GetDriver(), COLLISION_GROUP_NONE, &tr ); if ( tr.allsolid == false ) { UTIL_DecalTrace( &tr, "RedGlowFade" ); penetrated = true; } } else if ( pHit != NULL ) { CTakeDamageInfo dmgInfo( this, GetDriver(), flDamage, DMG_SHOCK ); CalculateBulletDamageForce( &dmgInfo, GetAmmoDef()->Index("GaussEnergy"), aimDir, tr.endpos, 1.0f + flChargeAmount * 4.0f ); //Do direct damage to anything in our path pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr ); } ApplyMultiDamage(); //Kick up an effect if ( !(tr.surface.flags & SURF_SKY) ) { UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); //Do a gauss explosion CPVSFilter filter( tr.endpos ); te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); } //Show the effect DrawBeam( m_vecGunOrigin, tr.endpos, 9.6 ); // Register a muzzleflash for the AI if ( m_hPlayer ) { m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5f ); } //Rock the car IPhysicsObject *pObj = VPhysicsGetObject(); if ( pObj != NULL ) { Vector shoveDir = aimDir * -( flDamage * 500.0f ); pObj->ApplyForceOffset( shoveDir, m_vecGunOrigin ); } //Do radius damage if we didn't penetrate the wall if ( penetrated == true ) { RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL ); } }
void CSDKPlayer::FireBullet( Vector vecSrc, // shooting postion const QAngle &shootAngles, //shooting angle float vecSpread, // spread vector int iDamage, // base damage int iBulletType, // ammo type CBaseEntity *pevAttacker, // shooter bool bDoEffects, // create impact effect ? float x, // spread x factor float y // spread y factor ) { float fCurrentDamage = iDamage; // damage of the bullet at it's current trajectory float flCurrentDistance = 0.0; //distance that the bullet has traveled so far Vector vecDirShooting, vecRight, vecUp; AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp ); if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves // add the spray Vector vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; VectorNormalize( vecDir ); float flMaxRange = 8000; Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units trace_t tr; // main enter bullet trace UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1.0f ) return; // we didn't hit anything, stop tracing shoot if ( sv_showimpacts.GetBool() ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 4, true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( 4, true ); } #endif } //calculate the damage based on the distance the bullet travelled. flCurrentDistance += tr.fraction * flMaxRange; // damage get weaker of distance fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500)); int iDamageType = DMG_BULLET | DMG_NEVERGIB; if( bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { trace_t waterTrace; UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) { data.m_fFlags |= FX_WATER_IN_SLIME; } DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; if ( !( !friendlyfire.GetBool() && pEntity && pEntity->IsPlayer() && pEntity->GetTeamNumber() == GetTeamNumber() ) ) { UTIL_ImpactTrace( &tr, iDamageType ); } } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL ClearMultiDamage(); CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType ); CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr ); TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir ); ApplyMultiDamage(); #endif }
//----------------------------------------------------------------------------- // Purpose: Aim Gun at a target //----------------------------------------------------------------------------- void CASW_PropJeep::AimGunAt( Vector *endPos, float flInterval ) { Vector aimPos = *endPos; // See if the gun should be allowed to aim if ( IsOverturned() || m_bEngineLocked || m_bHasGun == false ) { SetPoseParameter( JEEP_GUN_YAW, 0 ); SetPoseParameter( JEEP_GUN_PITCH, 0 ); SetPoseParameter( JEEP_GUN_SPIN, 0 ); return; // Make the gun go limp and look "down" Vector v_forward, v_up; AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up ); aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f ); } matrix3x4_t gunMatrix; GetAttachment( LookupAttachment("gun_ref"), gunMatrix ); // transform the enemy into gun space Vector localEnemyPosition; VectorITransform( aimPos, gunMatrix, localEnemyPosition ); // do a look at in gun space (essentially a delta-lookat) QAngle localEnemyAngles; VectorAngles( localEnemyPosition, localEnemyAngles ); // convert to +/- 180 degrees localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 ); localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 ); float targetYaw = m_aimYaw + localEnemyAngles.y; float targetPitch = m_aimPitch + localEnemyAngles.x; // Constrain our angles float newTargetYaw = clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW ); float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH ); // If the angles have been clamped, we're looking outside of our valid range if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 ) { m_bUnableToFire = true; } targetYaw = newTargetYaw; targetPitch = newTargetPitch; // Exponentially approach the target float yawSpeed = 8; float pitchSpeed = 8; m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed ); m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed ); SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw); SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch ); InvalidateBoneCache(); // read back to avoid drift when hitting limits // as long as the velocity is less than the delta between the limit and 180, this is fine. m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH ); m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW ); // Now draw crosshair for actual aiming point Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); trace_t tr; UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); // see if we hit something, if so, adjust endPos to hit location if ( tr.fraction < 1.0 ) { m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CASW_PropJeep::Think(void) { m_VehiclePhysics.Think(); // Derived classes of CPropVehicle have their own code to determine how frequently to think. // But the prop_vehicle entity native to this class will only think one time, so this flag // was added to allow prop_vehicle to always think without affecting the derived classes. if( HasSpawnFlags(SF_PROP_VEHICLE_ALWAYSTHINK) ) { SetNextThink(gpGlobals->curtime); } if ( ShouldThink() ) { SetNextThink( gpGlobals->curtime ); } // If we have an NPC Driver, tell him to drive if ( m_hNPCDriver ) { GetServerVehicle()->NPC_DriveVehicle(); } // Keep thinking while we're waiting to turn off the keep upright if ( m_flTurnOffKeepUpright ) { SetNextThink( gpGlobals->curtime ); // Time up? if ( m_hKeepUpright != NULL && m_flTurnOffKeepUpright < gpGlobals->curtime ) { variant_t emptyVariant; m_hKeepUpright->AcceptInput( "TurnOff", this, this, emptyVariant, USE_TOGGLE ); m_flTurnOffKeepUpright = 0; UTIL_Remove( m_hKeepUpright ); } } /* CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if ( m_bEngineLocked ) { m_bUnableToFire = true; if ( pPlayer != NULL ) { pPlayer->m_Local.m_iHideHUD |= HIDEHUD_VEHICLE_CROSSHAIR; } } else if ( m_bHasGun ) { // Start this as false and update it again each frame m_bUnableToFire = false; if ( pPlayer != NULL ) { pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_VEHICLE_CROSSHAIR; } }*/ // Water!? HandleWater(); SetSimulationTime( gpGlobals->curtime ); SetNextThink( gpGlobals->curtime ); SetAnimatedEveryTick( true ); if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake { m_bInitialHandbrake = true; m_VehiclePhysics.SetHandbrake( true ); m_VehiclePhysics.Think(); } // Check overturned status. if ( !IsOverturned() ) { m_flOverturnedTime = 0.0f; } else { m_flOverturnedTime += gpGlobals->frametime; } // spin gun if charging cannon //FIXME: Don't bother for E3 if ( m_bCannonCharging ) { m_nSpinPos += JEEP_GUN_SPIN_RATE; SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); } // Aim gun based on the player view direction. if ( m_hPlayer && !m_bExitAnimOn && !m_bEnterAnimOn ) { Vector vecEyeDir, vecEyePos; m_hPlayer->EyePositionAndVectors( &vecEyePos, &vecEyeDir, NULL, NULL ); // Trace out from the player's eye point. Vector vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH ); trace_t trace; UTIL_TraceLine( vecEyePos, vecEndPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &trace ); // See if we hit something, if so, adjust end position to hit location. if ( trace.fraction < 1.0 ) { vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH * trace.fraction ); } //m_vecLookCrosshair = vecEndPos; AimGunAt( &vecEndPos, 0.1f ); } StudioFrameAdvance(); // If the enter or exit animation has finished, tell the server vehicle if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) { if ( m_bEnterAnimOn ) { m_VehiclePhysics.ReleaseHandbrake(); StartEngine(); // HACKHACK: This forces the jeep to play a sound when it gets entered underwater if ( m_VehiclePhysics.IsEngineDisabled() ) { CBaseServerVehicle *pServerVehicle = dynamic_cast<CBaseServerVehicle *>(GetServerVehicle()); if ( pServerVehicle ) { pServerVehicle->SoundStartDisabled(); } } // The first few time we get into the jeep, print the jeep help if ( m_iNumberOfEntries < asw_hud_jeephint_numentries.GetInt() ) { UTIL_HudHintText( m_hPlayer, "#Valve_Hint_JeepKeys" ); m_iNumberOfEntries++; } } // If we're exiting and have had the tau cannon removed, we don't want to reset the animation GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, !(m_bExitAnimOn && TauCannonHasBeenCutOff()) ); } // See if the ammo crate needs to close if ( ( m_flAmmoCrateCloseTime < gpGlobals->curtime ) && ( GetSequence() == LookupSequence( "ammo_open" ) ) ) { m_flAnimTime = gpGlobals->curtime; m_flPlaybackRate = 0.0; SetCycle( 0 ); ResetSequence( LookupSequence( "ammo_close" ) ); } else if ( ( GetSequence() == LookupSequence( "ammo_close" ) ) && IsSequenceFinished() ) { m_flAnimTime = gpGlobals->curtime; m_flPlaybackRate = 0.0; SetCycle( 0 ); ResetSequence( LookupSequence( "idle" ) ); CPASAttenuationFilter sndFilter( this, "PropJeep.AmmoClose" ); EmitSound( sndFilter, entindex(), "PropJeep.AmmoClose" ); } }
void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage ) { m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME; Vector vecSrc = vecOrigSrc; Vector vecDest = vecSrc + vecDir * 8192; edict_t *pentIgnore; TraceResult tr, beam_tr; float flMaxFrac = 1.0; int nTotal = 0; int fHasPunched = 0; int fFirstBeam = 1; int nMaxHits = 10; pentIgnore = ENT( m_pPlayer->pev ); #ifdef CLIENT_DLL if ( !m_fPrimaryFire ) g_brunninggausspred = true; #endif // The main firing event is sent unreliably so it won't be delayed. PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usGaussFire, 0.0, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, flDamage, 0.0, 0, 0, m_fPrimaryFire ? 1 : 0, 0 ); // This reliable event is used to stop the spinning sound // It's delayed by a fraction of second to make sure it is delayed by 1 frame on the client // It's sent reliably anyway, which could lead to other delays PLAYBACK_EVENT_FULL( FEV_NOTHOST | FEV_RELIABLE, m_pPlayer->edict(), m_usGaussFire, 0.01, (float *)&m_pPlayer->pev->origin, (float *)&m_pPlayer->pev->angles, 0.0, 0.0, 0, 0, 0, 1 ); /*ALERT( at_console, "%f %f %f\n%f %f %f\n", vecSrc.x, vecSrc.y, vecSrc.z, vecDest.x, vecDest.y, vecDest.z );*/ // ALERT( at_console, "%f %f\n", tr.flFraction, flMaxFrac ); #ifndef CLIENT_DLL while (flDamage > 10 && nMaxHits > 0) { nMaxHits--; // ALERT( at_console, "." ); UTIL_TraceLine(vecSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr); if (tr.fAllSolid) break; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); if (pEntity == NULL) break; if ( fFirstBeam ) { m_pPlayer->pev->effects |= EF_MUZZLEFLASH; fFirstBeam = 0; nTotal += 26; } if (pEntity->pev->takedamage) { g_MultiDamage.Clear(); pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET ); g_MultiDamage.ApplyMultiDamage( m_pPlayer, m_pPlayer ); } if ( pEntity->ReflectGauss() ) { float n; pentIgnore = NULL; n = -DotProduct(tr.vecPlaneNormal, vecDir); if (n < 0.5) // 60 degrees { // ALERT( at_console, "reflect %f\n", n ); // reflect Vector r; r = 2.0 * tr.vecPlaneNormal * n + vecDir; flMaxFrac = flMaxFrac - tr.flFraction; vecDir = r; vecSrc = tr.vecEndPos + vecDir * 8; vecDest = vecSrc + vecDir * 8192; // explode a bit m_pPlayer->RadiusDamage( tr.vecEndPos, this, m_pPlayer, flDamage * n, CLASS_NONE, DMG_BLAST ); nTotal += 34; // lose energy if (n == 0) n = 0.1; flDamage = flDamage * (1 - n); } else { nTotal += 13; // limit it to one hole punch if (fHasPunched) break; fHasPunched = 1; // try punching through wall if secondary attack (primary is incapable of breaking through) if ( !m_fPrimaryFire ) { UTIL_TraceLine( tr.vecEndPos + vecDir * 8, vecDest, dont_ignore_monsters, pentIgnore, &beam_tr); if (!beam_tr.fAllSolid) { // trace backwards to find exit point UTIL_TraceLine( beam_tr.vecEndPos, tr.vecEndPos, dont_ignore_monsters, pentIgnore, &beam_tr); float n = (beam_tr.vecEndPos - tr.vecEndPos).Length( ); if (n < flDamage) { if (n == 0) n = 1; flDamage -= n; // ALERT( at_console, "punch %f\n", n ); nTotal += 21; // exit blast damage //m_pPlayer->RadiusDamage( beam_tr.vecEndPos + vecDir * 8, pev, m_pPlayer->pev, flDamage, CLASS_NONE, DMG_BLAST ); float damage_radius; if ( g_pGameRules->IsMultiplayer() ) { damage_radius = flDamage * 1.75; // Old code == 2.5 } else { damage_radius = flDamage * 2.5; } ::RadiusDamage( beam_tr.vecEndPos + vecDir * 8, this, m_pPlayer, flDamage, damage_radius, CLASS_NONE, DMG_BLAST ); CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 ); nTotal += 53; vecSrc = beam_tr.vecEndPos + vecDir; } } else { //ALERT( at_console, "blocked %f\n", n ); flDamage = 0; } } else { //ALERT( at_console, "blocked solid\n" ); flDamage = 0; } } } else { vecSrc = tr.vecEndPos + vecDir; pentIgnore = ENT( pEntity->pev ); } } #endif // ALERT( at_console, "%d bytes\n", nTotal ); }
float CWeaponPortalgun::TraceFirePortal( bool bPortal2, const Vector &vTraceStart, const Vector &vDirection, trace_t &tr, Vector &vFinalPosition, QAngle &qFinalAngles, int iPlacedBy, bool bTest /*= false*/ ) { CTraceFilterSimpleClassnameList baseFilter( this, COLLISION_GROUP_NONE ); UTIL_Portal_Trace_Filter( &baseFilter ); CTraceFilterTranslateClones traceFilterPortalShot( &baseFilter ); Ray_t rayEyeArea; rayEyeArea.Init( vTraceStart + vDirection * 24.0f, vTraceStart + vDirection * -24.0f ); float fMustBeCloserThan = 2.0f; CProp_Portal *pNearPortal = UTIL_Portal_FirstAlongRay( rayEyeArea, fMustBeCloserThan ); if ( !pNearPortal ) { // Check for portal near and infront of you rayEyeArea.Init( vTraceStart + vDirection * -24.0f, vTraceStart + vDirection * 48.0f ); fMustBeCloserThan = 2.0f; pNearPortal = UTIL_Portal_FirstAlongRay( rayEyeArea, fMustBeCloserThan ); } if ( pNearPortal && pNearPortal->IsActivedAndLinked() ) { iPlacedBy = PORTAL_PLACED_BY_PEDESTAL; Vector vPortalForward; pNearPortal->GetVectors( &vPortalForward, 0, 0 ); if ( vDirection.Dot( vPortalForward ) < 0.01f ) { // If shooting out of the world, fizzle if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = ( ( pNearPortal->m_bIsPortal2 ) ? ( PORTAL_FIZZLE_NEAR_RED ) : ( PORTAL_FIZZLE_NEAR_BLUE ) ); VectorAngles( vPortalForward, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = pNearPortal->GetAbsOrigin(); vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; UTIL_TraceLine( vTraceStart - vDirection * 16.0f, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); return PORTAL_ANALOG_SUCCESS_NEAR; } UTIL_TraceLine( vTraceStart - vDirection * 16.0f, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); return PORTAL_ANALOG_SUCCESS_OVERLAP_LINKED; } } // Trace to see where the portal hit UTIL_TraceLine( vTraceStart, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); if ( !tr.DidHit() || tr.startsolid ) { // If it didn't hit anything, fizzle if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_NONE; VectorAngles( -vDirection, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = tr.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_PASSTHROUGH_SURFACE; } // Trace to the surface to see if there's a rotating door in the way CBaseEntity *list[1024]; Ray_t ray; ray.Init( vTraceStart, tr.endpos ); int nCount = UTIL_EntitiesAlongRay( list, 1024, ray, 0 ); // Loop through all entities along the ray between the gun and the surface for ( int i = 0; i < nCount; i++ ) { // If the entity is a rotating door if( FClassnameIs( list[i], "prop_door_rotating" ) ) { // Check more precise door collision CBasePropDoor *pRotatingDoor = static_cast<CBasePropDoor *>( list[i] ); Ray_t rayDoor; rayDoor.Init( vTraceStart, vTraceStart + (vDirection * m_fMaxRange1) ); trace_t trDoor; pRotatingDoor->TestCollision( rayDoor, 0, trDoor ); if ( trDoor.DidHit() ) { // There's a door in the way tr = trDoor; if ( sv_portal_placement_debug.GetBool() ) { Vector vMin; Vector vMax; Vector vZero = Vector( 0.0f, 0.0f, 0.0f ); list[ i ]->GetCollideable()->WorldSpaceSurroundingBounds( &vMin, &vMax ); NDebugOverlay::Box( vZero, vMin, vMax, 0, 255, 0, 128, 0.5f ); } if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_CANT_FIT; VectorAngles( tr.plane.normal, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = trDoor.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_CANT_FIT; } } else if ( FClassnameIs( list[i], "trigger_portal_cleanser" ) ) { CBaseTrigger *pTrigger = static_cast<CBaseTrigger*>( list[i] ); if ( pTrigger && !pTrigger->m_bDisabled ) { Vector vMin; Vector vMax; pTrigger->GetCollideable()->WorldSpaceSurroundingBounds( &vMin, &vMax ); IntersectRayWithBox( ray.m_Start, ray.m_Delta, vMin, vMax, 0.0f, &tr ); tr.plane.normal = -vDirection; if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_CLEANSER; VectorAngles( tr.plane.normal, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = tr.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_CLEANSER; } } } Vector vUp( 0.0f, 0.0f, 1.0f ); if( ( tr.plane.normal.x > -0.001f && tr.plane.normal.x < 0.001f ) && ( tr.plane.normal.y > -0.001f && tr.plane.normal.y < 0.001f ) ) { //plane is a level floor/ceiling vUp = vDirection; } // Check that the placement succeed VectorAngles( tr.plane.normal, vUp, qFinalAngles ); vFinalPosition = tr.endpos; return VerifyPortalPlacement( CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2 ), vFinalPosition, qFinalAngles, iPlacedBy, bTest ); }
void CMortar::MortarExplode( void ) { #if 1 // mortar beam MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_BEAMPOINTS ); WRITE_COORD(pev->origin.x); WRITE_COORD(pev->origin.y); WRITE_COORD(pev->origin.z); WRITE_COORD(pev->origin.x); WRITE_COORD(pev->origin.y); WRITE_COORD(pev->origin.z + 1024); WRITE_SHORT(m_spriteTexture ); WRITE_BYTE( 0 ); // framerate WRITE_BYTE( 0 ); // framerate WRITE_BYTE( 1 ); // life WRITE_BYTE( 40 ); // width WRITE_BYTE( 0 ); // noise WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 160 ); // r, g, b WRITE_BYTE( 100 ); // r, g, b WRITE_BYTE( 128 ); // brightness WRITE_BYTE( 0 ); // speed MESSAGE_END(); #endif #if 0 // blast circle MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_BEAMTORUS); WRITE_COORD(pev->origin.x); WRITE_COORD(pev->origin.y); WRITE_COORD(pev->origin.z + 32); WRITE_COORD(pev->origin.x); WRITE_COORD(pev->origin.y); WRITE_COORD(pev->origin.z + 32 + pev->dmg * 2 / .2); // reach damage radius over .3 seconds WRITE_SHORT(m_spriteTexture ); WRITE_BYTE( 0 ); // startframe WRITE_BYTE( 0 ); // framerate WRITE_BYTE( 2 ); // life WRITE_BYTE( 12 ); // width WRITE_BYTE( 0 ); // noise WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 160 ); // r, g, b WRITE_BYTE( 100 ); // r, g, b WRITE_BYTE( 255 ); // brightness WRITE_BYTE( 0 ); // speed MESSAGE_END(); #endif TraceResult tr; UTIL_TraceLine( pev->origin + Vector( 0, 0, 1024 ), pev->origin - Vector( 0, 0, 1024 ), dont_ignore_monsters, ENT(pev), &tr ); Explode( &tr, DMG_BLAST | DMG_MORTAR ); UTIL_ScreenShake( tr.vecEndPos, 25.0, 150.0, 1.0, 750 ); #if 0 int pitch = RANDOM_LONG(95,124); EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/mortarhit.wav", 1.0, 0.55, 0, pitch); // ForceSound( SNDRADIUS_MP5, bits_SOUND_COMBAT ); // ExplodeModel( pev->origin, 400, g_sModelIndexShrapnel, 30 ); RadiusDamage ( pev, VARS(pev->owner), pev->dmg, CLASS_NONE, DMG_BLAST ); /* if ( RANDOM_FLOAT ( 0 , 1 ) < 0.5 ) { UTIL_DecalTrace( pTrace, DECAL_SCORCH1 ); } else { UTIL_DecalTrace( pTrace, DECAL_SCORCH2 ); } */ SetThink( &CMortar::SUB_Remove ); pev->nextthink = gpGlobals->time + 0.1; #endif }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CGrenade_Brickbat::BrickbatThink( void ) { // ----------------------------------------------------------- // Might be physically simulated so get my velocity manually // ----------------------------------------------------------- Vector vVelocity; AngularImpulse vAngVel; GetVelocity(&vVelocity,&vAngVel); // See if I can lose my owner (has dropper moved out of way?) // Want do this so owner can throw the brickbat if (GetOwnerEntity()) { trace_t tr; Vector vUpABit = GetAbsOrigin(); vUpABit.z += 5.0; CBaseEntity* saveOwner = GetOwnerEntity(); SetOwnerEntity( NULL ); UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); if ( tr.startsolid || tr.fraction != 1.0 ) { SetOwnerEntity( saveOwner ); } } // --------------------------------------------------------------- // Make sure we're not resting on a living thing's bounding box // --------------------------------------------------------------- if (vVelocity.Length() < 0.01) { trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0 && tr.m_pEnt) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC)) { // -------------------- // Bounce me off // -------------------- Vector vNewVel; vNewVel.y = 100; vNewVel.x = random->RandomInt(-100,100); vNewVel.z = random->RandomInt(-100,100); // If physically simulated IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity( &vNewVel, &vAngVel ); } // Otherwise else { SetAbsVelocity( vNewVel ); } } } } if (vVelocity.Length() < 0.01) { SpawnBrickbatWeapon(); } SetNextThink( gpGlobals->curtime + 0.1f ); }
//========================================================= // 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 ( pev->angles ); // is the way ahead clear? if ( !FPathBlocked () ) { // if the boid is turning, stop the trend. if ( m_fTurning ) { m_fTurning = FALSE; pev->avelocity.y = 0; } m_fPathBlocked = FALSE; if (pev->speed <= AFLOCK_FLY_SPEED ) pev->speed+= 5; pev->velocity = 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(pev->origin, pev->origin + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - pev->origin); flRightSide = vecDist.Length(); UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - pev->origin); flLeftSide = vecDist.Length(); // turn right if more clearance on right side if ( flRightSide > flLeftSide ) { pev->avelocity.y = -AFLOCK_TURN_RATE; m_fTurning = TRUE; } // default to left turn :) else if ( flLeftSide > flRightSide ) { pev->avelocity.y = AFLOCK_TURN_RATE; m_fTurning = TRUE; } else { // equidistant. Pick randomly between left and right. m_fTurning = TRUE; if ( RANDOM_LONG( 0, 1 ) == 0 ) { pev->avelocity.y = AFLOCK_TURN_RATE; } else { pev->avelocity.y = -AFLOCK_TURN_RATE; } } } SpreadFlock( ); pev->velocity = 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(pev->origin, pev->origin - gpGlobals->v_up * 16, ignore_monsters, ENT(pev), &tr); if (tr.flFraction != 1.0 && pev->velocity.z < 0 ) pev->velocity.z = 0; // maybe it did, though. if ( FBitSet (pev->flags, FL_ONGROUND) ) { UTIL_SetOrigin (pev, pev->origin + Vector ( 0 , 0 , 1 ) ); pev->velocity.z = 0; } if ( m_flFlockNextSoundTime < gpGlobals->time ) { MakeSound(); m_flFlockNextSoundTime = gpGlobals->time + RANDOM_FLOAT( 1, 3 ); } BoidAdvanceFrame( ); return; }
void C_PropVehicleDriveable::DrawHudElements( ) { CHudTexture *pIcon; int iIconX, iIconY; if (m_bHasGun) { // draw crosshairs for vehicle gun pIcon = gHUD.GetIcon( "gunhair" ); if ( pIcon != NULL ) { float x, y; if( UseVR() ) { C_BasePlayer *pPlayer = (C_BasePlayer *)GetPassenger( VEHICLE_ROLE_DRIVER ); Vector vecStart, vecDirection; pPlayer->EyePositionAndVectors( &vecStart, &vecDirection, NULL, NULL ); Vector vecEnd = vecStart + vecDirection * MAX_TRACE_LENGTH; trace_t tr; UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); Vector screen; screen.Init(); ScreenTransform(tr.endpos, screen); int vx, vy, vw, vh; vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh ); float screenWidth = vw; float screenHeight = vh; x = 0.5f * ( 1.0f + screen[0] ) * screenWidth + 0.5f; y = 0.5f * ( 1.0f - screen[1] ) * screenHeight + 0.5f; } else { Vector screen; x = ScreenWidth()/2; y = ScreenHeight()/2; #if TRIANGULATED_CROSSHAIR ScreenTransform( m_vecGunCrosshair, screen ); x += 0.5 * screen[0] * ScreenWidth() + 0.5; y -= 0.5 * screen[1] * ScreenHeight() + 0.5; #endif } x -= pIcon->Width() / 2; y -= pIcon->Height() / 2; Color clr = ( m_bUnableToFire ) ? gHUD.m_clrCaution : gHUD.m_clrNormal; pIcon->DrawSelf( x, y, clr ); } if ( m_nScannerDisabledWeapons ) { // Draw icons for scanners "weps disabled" pIcon = gHUD.GetIcon( "dmg_bio" ); if ( pIcon ) { iIconY = 467 - pIcon->Height() / 2; iIconX = 385; if ( !m_bScannerWepIcon ) { pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, 255, 255 ) ); m_bScannerWepIcon = true; m_iScannerWepFlashTimer = 0; m_bScannerWepDim = true; } else { pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, GetFlashColorIntensity(55, 255, m_bScannerWepDim, 10, m_iScannerWepFlashTimer), 255 ) ); m_iScannerWepFlashTimer++; m_iScannerWepFlashTimer %= 20; if(!m_iScannerWepFlashTimer) m_bScannerWepDim ^= 1; } } } } if ( m_nScannerDisabledVehicle ) { // Draw icons for scanners "vehicle disabled" pIcon = gHUD.GetIcon( "dmg_bio" ); if ( pIcon ) { iIconY = 467 - pIcon->Height() / 2; iIconX = 410; if ( !m_bScannerVehicleIcon ) { pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, 255, 255 ) ); m_bScannerVehicleIcon = true; m_iScannerVehicleFlashTimer = 0; m_bScannerVehicleDim = true; } else { pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, GetFlashColorIntensity(55, 255, m_bScannerVehicleDim, 10, m_iScannerVehicleFlashTimer), 255 ) ); m_iScannerVehicleFlashTimer++; m_iScannerVehicleFlashTimer %= 20; if(!m_iScannerVehicleFlashTimer) m_bScannerVehicleDim ^= 1; } } } }
void CAPCController::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { m_hTarget = FindTarget( m_targetEntityName, NULL ); if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 sec s } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) { m_bFireDelayed = false; return; } UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); AngleVectors(angles, &forward); if ( lineOfSight == TRUE ) { // FIXME: This will ultimately have to deal with NPCs being in the vehicle as well // See if the target is in a vehicle. If so, check its relationship CBasePlayer *pPlayer = ToBasePlayer( pTarget ); if ( pPlayer && pPlayer->IsInAVehicle() ) { IServerVehicle *pVehicle = pPlayer->GetVehicle(); if ( pVehicle->ClassifyPassenger( pPlayer, CLASS_PLAYER ) == CLASS_PLAYER) { if ( !m_bFireDelayed ) { m_bFireDelayed = true; m_flFiringDelay = gpGlobals->curtime + 1.5; // setup delay time before we start firing return; } if ( gpGlobals->curtime > m_flFiringDelay ) { m_OnFireAtTarget.Set(forward, this, this); // tell apc to fire rockets, and what direction } } } } else { m_bFireDelayed = false; // reset flag since we can no longer see target } }
// CONSIDER: if player in water state, autoset and underwater soundscape? void CEnvSoundscape::UpdateForPlayer( ss_update_t &update ) { if ( !IsEnabled() ) { if ( update.pCurrentSoundscape == this ) { update.pCurrentSoundscape = NULL; update.currentDistance = 0; update.bInRange = false; } return; } // calc range from sound entity to player Vector target = EarPosition(); float range = (update.playerPosition - target).Length(); if ( update.pCurrentSoundscape == this ) { update.currentDistance = range; update.bInRange = false; if ( m_flRadius > range || m_flRadius == -1 ) { trace_t tr; update.traceCount++; UTIL_TraceLine( target, update.playerPosition, MASK_SOLID_BRUSHONLY|MASK_WATER, update.pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1 && !tr.startsolid ) { update.bInRange = true; } } } else { if ( (!update.bInRange || range < update.currentDistance ) && (m_flRadius > range || m_flRadius == -1) ) { trace_t tr; update.traceCount++; UTIL_TraceLine( target, update.playerPosition, MASK_SOLID_BRUSHONLY|MASK_WATER, update.pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1 && !tr.startsolid ) { audioparams_t &audio = update.pPlayer->GetAudioParams(); WriteAudioParamsTo( audio ); update.pCurrentSoundscape = this; update.bInRange = true; update.currentDistance = range; } } } if ( soundscape_debug.GetBool() ) { // draw myself NDebugOverlay::Box(GetAbsOrigin(), Vector(-10,-10,-10), Vector(10,10,10), 255, 0, 255, 64, NDEBUG_PERSIST_TILL_NEXT_SERVER ); #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); #else // Don't use GetLocalPlayer(), because that prevents multiplayer games using this for testing with a single client in the game CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( update.pPlayer ) { audioparams_t &audio = update.pPlayer->GetAudioParams(); if ( audio.ent.Get() != this ) { if ( InRangeOfPlayer( update.pPlayer ) ) { NDebugOverlay::Line( GetAbsOrigin(), update.pPlayer->WorldSpaceCenter(), 255, 255, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } else { NDebugOverlay::Line( GetAbsOrigin(), update.pPlayer->WorldSpaceCenter(), 255, 0, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } else { if ( InRangeOfPlayer( update.pPlayer ) ) { NDebugOverlay::Line( GetAbsOrigin(), update.pPlayer->WorldSpaceCenter(), 0, 255, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } else { NDebugOverlay::Line( GetAbsOrigin(), update.pPlayer->WorldSpaceCenter(), 255, 170, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } // also draw lines to each sound position. // we don't store the number of local sound positions, just a bitvector of which ones are on. unsigned int soundbits = audio.localBits.Get(); float periodic = 2.0f * sin((fmod(gpGlobals->curtime,2.0f) - 1.0f) * M_PI); // = -4f .. 4f for (int ii = 0 ; ii < NUM_AUDIO_LOCAL_SOUNDS ; ++ii ) { if ( soundbits & (1 << ii) ) { const Vector &soundLoc = audio.localSound.Get(ii); NDebugOverlay::Line( GetAbsOrigin(), soundLoc, 0, 32 , 255 , false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); NDebugOverlay::Cross3D( soundLoc, 16.0f + periodic, 0, 0, 255, false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } } } NDebugOverlay::EntityTextAtPosition( GetAbsOrigin(), 0, STRING(m_soundscapeName), NDEBUG_PERSIST_TILL_NEXT_SERVER ); } }
void CControllerHeadBall :: HuntThink( void ) { pev->nextthink = gpGlobals->time + 0.1; pev->renderamt -= 5; MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); 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, SVC_TEMPENTITY ); 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( DieThink ); pev->nextthink = gpGlobals->time + 0.3; } Crawl( ); }
void CFuncTank::TrackTarget( void ) { trace_t tr; bool updateTime = FALSE, lineOfSight; QAngle angles; Vector barrelEnd; CBaseEntity *pTarget = NULL; barrelEnd.Init(); // Get a position to aim for if (m_pController) { // Tanks attempt to mirror the player's angles angles = m_pController->EyeAngles(); SetNextThink( gpGlobals->curtime + 0.05 ); } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 0.1f ); } else { return; } // ----------------------------------- // Get world target position // ----------------------------------- barrelEnd = WorldBarrelPosition(); Vector worldTargetPosition; if (m_spawnflags & SF_TANK_AIM_AT_POS) { worldTargetPosition = m_vTargetPosition; } else { CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) { if ( m_targetEntityName != NULL_STRING ) // New HL2 behavior { m_hTarget = FindTarget( m_targetEntityName, NULL ); } else // HL1 style { m_hTarget = ToBasePlayer( GetContainingEntity( UTIL_FindClientInPVS( edict() ) ) ); } if ( m_hTarget != NULL ) { SetNextThink( gpGlobals->curtime ); // Think again immediately } else { if ( IsActive() ) { SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 secs } if ( m_fireLast !=0 ) { m_OnLoseTarget.FireOutput(this, this); m_fireLast = 0; } } return; } pTarget = pEntity; // Calculate angle needed to aim at target worldTargetPosition = pEntity->EyePosition(); } float range = (worldTargetPosition - barrelEnd).Length(); if ( !InRange( range ) ) return; UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if (m_spawnflags & SF_TANK_AIM_AT_POS) { updateTime = TRUE; m_sightOrigin = m_vTargetPosition; } else { lineOfSight = FALSE; // No line of sight, don't track if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) { lineOfSight = TRUE; CBaseEntity *pInstance = pTarget; if ( InRange( range ) && pInstance && pInstance->IsAlive() ) { updateTime = TRUE; // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); } } } // Convert targetPosition to parent angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); } // Force the angles to be relative to the center position float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); angles.y = m_yawCenter + offsetY; angles.x = m_pitchCenter + offsetX; // Limit against range in y if ( ( fabs( offsetY ) > m_yawRange + m_yawTolerance ) || ( fabs( offsetX ) > m_pitchRange + m_pitchTolerance ) ) { // Don't update if you saw the player, but out of range updateTime = false; if ( angles.y > m_yawCenter + m_yawRange ) { angles.y = m_yawCenter + m_yawRange; } else if ( angles.y < (m_yawCenter - m_yawRange) ) { angles.y = (m_yawCenter - m_yawRange); } } if ( updateTime ) { m_lastSightTime = gpGlobals->curtime; m_persist2burst = 0; } // Move toward target at rate or less float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); QAngle vecAngVel = GetLocalAngularVelocity(); vecAngVel.y = distY * 10; vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); // Limit against range in x angles.x = clamp( angles.x, m_pitchCenter - m_pitchRange, m_pitchCenter + m_pitchRange ); // Move toward target at rate or less float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); vecAngVel.x = distX * 10; vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); SetLocalAngularVelocity( vecAngVel ); SetMoveDoneTime( 0.1 ); if ( m_pController ) return; if ( CanFire() && ( (fabs(distX) < m_pitchTolerance && fabs(distY) < m_yawTolerance) || (m_spawnflags & SF_TANK_LINEOFSIGHT) ) ) { bool fire = FALSE; Vector forward; AngleVectors( GetLocalAngles(), &forward ); forward = m_parentMatrix.ApplyRotation( forward ); if ( m_spawnflags & SF_TANK_LINEOFSIGHT ) { float length = (m_maxRange > 0) ? m_maxRange : MAX_TRACE_LENGTH; UTIL_TraceLine( barrelEnd, barrelEnd + forward * length, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if ( tr.m_pEnt == pTarget ) fire = TRUE; } else fire = TRUE; if ( fire ) { if (m_fireLast == 0) { m_OnAquireTarget.FireOutput(this, this); } FiringSequence( barrelEnd, forward, this ); } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } } else { if (m_fireLast !=0) { m_OnLoseTarget.FireOutput(this, this); } m_fireLast = 0; } }
bool RadioCreate( edict_t *pEntity ) { // Create the radio and stick to the wall entvars_t *pPev = VARS( pEntity ); if (pPev->iuser1 > 0) return 0; // make sure we dont already have a radio int radiocount = 0; int i = 1; char *pClassname; edict_t *frontEnt; for (i; i < 1025; i++) { frontEnt = INDEXENT ( i ); if (frontEnt) { pClassname = (char *)STRING(frontEnt->v.classname); if (FStrEq("building_radio", pClassname)) { if (frontEnt->v.euser4 == pEntity) { radiocount++; } } } } if (AdminLoggedIn[ENTINDEX(pEntity)] == 0) { if (radiocount >= 2) { ClientPrint( pPev, HUD_PRINTTALK, "* Cant have more than 2 radios!\n"); return 0; } } UTIL_MakeVectors( pPev->v_angle + pPev->punchangle ); Vector vecSrc = GetGunPosition( pEntity ); Vector vecAiming = gpGlobals->v_forward; TraceResult tr; UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, pEntity , &tr ); if (tr.flFraction < 1.0 || AdminLoggedIn[ENTINDEX(pEntity)]) { if (tr.pHit && !(tr.pHit->v.flags & FL_CONVEYOR) && (FStrEq((char *)STRING(tr.pHit->v.classname), "worldspawn") || FStrEq((char *)STRING(tr.pHit->v.classname), "func_wall") || AdminLoggedIn[ENTINDEX(pEntity)] || FStrEq((char *)STRING(tr.pHit->v.classname), "building_dancemachine"))) // Make sure it isnt a conveyor! { Vector angles = UTIL_VecToAngles( tr.vecPlaneNormal ); if ((angles.x > 30 || angles.x < -30) && AdminLoggedIn[ENTINDEX(pEntity)] == 0) { ClientPrint( pPev, HUD_PRINTTALK, "* Can't place radios on floors or cielings!\n"); return 0; } // Create the camera here! Vector vecOri = tr.vecEndPos + tr.vecPlaneNormal * 14; //Vector vecOri = tr.vecEndPos + tr.vecPlaneNormal * 15; int maxdist = (int)CVAR_GET_FLOAT("sa_radiospread"); // make sure we arent placing it within 400 units of another radio for (i=1; i < 1025; i++) { frontEnt = INDEXENT ( i ); if (frontEnt) { pClassname = (char *)STRING(frontEnt->v.classname); if (FStrEq("building_radio", pClassname)) { if ((frontEnt->v.origin - vecOri).Length() < maxdist && AdminLoggedIn[ENTINDEX(pEntity)] == 0) { ClientPrint( pPev, HUD_PRINTTALK, "* Can't place a radio so close to another radio!\n"); return 0; } } } } KeyValueData kvd; //edict_t *pent = CREATE_ENTITY(); //edict_t *pent = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); edict_t *tEntity; tEntity = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); entvars_t *pRunOnPev; pRunOnPev = VARS(tEntity); char buf[80]; sprintf( buf, "%s", "building_radio"); // Set the KEYVALUES here! kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = buf; DispatchKeyValue( tEntity, &kvd ); // place this in front pRunOnPev->origin = vecOri; SET_ORIGIN( tEntity , vecOri ); pRunOnPev->angles = angles; //DispatchSpawn( ENT( pRunOnPev ) ); pRunOnPev->solid = SOLID_BBOX; SET_MODEL( ENT( pRunOnPev ) , "avatar-x/avadd16.avfil"); UTIL_SetSize( pRunOnPev, Vector( -2, -2 ,-2) - (tr.vecPlaneNormal * 15), Vector(2, 2, 16) - (tr.vecPlaneNormal * 15)); pRunOnPev->takedamage = DAMAGE_YES; pRunOnPev->max_health = 40 + 10000; pRunOnPev->health = 40 + 10000; pRunOnPev->euser4 = pEntity; /* edict_t *pent; pent = CREATE_NAMED_ENTITY(MAKE_STRING("xen_tree")); entvars_t *pv = VARS( pent ); pv->origin = vecOri; SET_ORIGIN(pent, vecOri); kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = "xen_tree"; DispatchKeyValue( pent, &kvd ); DispatchSpawn(pent); //pev->angles = angles; */ //pev->iuser1 = angles.y; //pv->vuser3 = angles; // for now don't take damage //pev->takedamage = DAMAGE_YES; //pev->max_health = 40 + 10000; //pev->health = 40 + 10000; /* // Call the SPAWN routine to set more stuff kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = "building_radio"; //DispatchKeyValue( pent, &kvd ); kvd.fHandled = FALSE; */ RadioSpawn( tEntity ); return 1; } else { ClientPrint( pPev, HUD_PRINTTALK, "* Couldn't place radio here!\n"); return 0; } } else { ClientPrint( pPev, HUD_PRINTTALK, "* Couldn't place radio here!\n"); } return 0; }
void CLightning::StrikeThink( void ) { if ( m_life != 0 ) { if ( pev->spawnflags & SF_BEAM_RANDOM ) pev->nextthink = gpGlobals->time + m_life + RANDOM_FLOAT( 0, m_restrike ); else pev->nextthink = gpGlobals->time + m_life + m_restrike; } m_active = 1; if (FStringNull(m_iszEndEntity)) { if (FStringNull(m_iszStartEntity)) { RandomArea( ); } else { CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) ); if (pStart != NULL) RandomPoint( pStart->pev->origin ); else ALERT( at_console, "env_beam: unknown entity \"%s\"\n", STRING(m_iszStartEntity) ); } return; } CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) ); CBaseEntity *pEnd = RandomTargetname( STRING(m_iszEndEntity) ); if ( pStart != NULL && pEnd != NULL ) { if ( IsPointEntity( pStart ) || IsPointEntity( pEnd ) ) { if ( pev->spawnflags & SF_BEAM_RING) { // don't work return; } } MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); if ( IsPointEntity( pStart ) || IsPointEntity( pEnd ) ) { if ( !IsPointEntity( pEnd ) ) // One point entity must be in pEnd { CBaseEntity *pTemp; pTemp = pStart; pStart = pEnd; pEnd = pTemp; } if ( !IsPointEntity( pStart ) ) // One sided { WRITE_BYTE( TE_BEAMENTPOINT ); WRITE_SHORT( pStart->entindex() ); WRITE_COORD( pEnd->pev->origin.x); WRITE_COORD( pEnd->pev->origin.y); WRITE_COORD( pEnd->pev->origin.z); } else { WRITE_BYTE( TE_BEAMPOINTS); WRITE_COORD( pStart->pev->origin.x); WRITE_COORD( pStart->pev->origin.y); WRITE_COORD( pStart->pev->origin.z); WRITE_COORD( pEnd->pev->origin.x); WRITE_COORD( pEnd->pev->origin.y); WRITE_COORD( pEnd->pev->origin.z); } } else { if ( pev->spawnflags & SF_BEAM_RING) WRITE_BYTE( TE_BEAMRING ); else WRITE_BYTE( TE_BEAMENTS ); WRITE_SHORT( pStart->entindex() ); WRITE_SHORT( pEnd->entindex() ); } WRITE_SHORT( m_spriteTexture ); WRITE_BYTE( m_frameStart ); // framestart WRITE_BYTE( (int)pev->framerate); // framerate WRITE_BYTE( (int)(m_life*10.0) ); // life WRITE_BYTE( m_boltWidth ); // width WRITE_BYTE( m_noiseAmplitude ); // noise WRITE_BYTE( (int)pev->rendercolor.x ); // r, g, b WRITE_BYTE( (int)pev->rendercolor.y ); // r, g, b WRITE_BYTE( (int)pev->rendercolor.z ); // r, g, b WRITE_BYTE( pev->renderamt ); // brightness WRITE_BYTE( m_speed ); // speed MESSAGE_END(); DoSparks( pStart->pev->origin, pEnd->pev->origin ); if ( pev->dmg > 0 ) { TraceResult tr; UTIL_TraceLine( pStart->pev->origin, pEnd->pev->origin, dont_ignore_monsters, NULL, &tr ); BeamDamageInstant( &tr, pev->dmg ); } } }
//----------------------------------------------------------------------------- // Purpose: For create nodes in wc edit mode // Input : // Output : //----------------------------------------------------------------------------- void NWCEdit::CreateAINode( CBasePlayer *pPlayer ) { // ------------------------------------------------------------- // Check that WC is running with the right map version // ------------------------------------------------------------- if ( !IsWCVersionValid() || !pPlayer ) return; pPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); int hullType = g_pAINetworkManager->GetEditOps()->m_iHullDrawNum; // ----------------------------------- // Get position of node to create // ----------------------------------- Vector vNewNodePos = vec3_origin; bool bPositionValid = false; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { vNewNodePos = NWCEdit::AirNodePlacementPosition(); // Make sure we can see the node trace_t tr; UTIL_TraceLine(pPlayer->EyePosition(), vNewNodePos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); if (tr.fraction == 1.0) { bPositionValid = true; } } else { // Place node by where the player is looking Vector forward; pPlayer->EyeVectors( &forward ); Vector startTrace = pPlayer->EyePosition(); Vector endTrace = pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH; trace_t tr; UTIL_TraceLine(startTrace,endTrace,MASK_NPCSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0) { // Raise the end position up off the floor, place the node and drop him down tr.endpos.z += 48; vNewNodePos = tr.endpos; bPositionValid = true; } } // ------------------------------------------------------------------------------- // Now check that this is a valid location for the new node bu using test hull // ------------------------------------------------------------------------------- if (bPositionValid) { CBaseEntity *testHull = (CBaseEntity*)CAI_TestHull::GetTestHull(); // Set the size of the test hull UTIL_SetSize(testHull, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType)); // Set origin of test hull testHull->SetLocalOrigin( vNewNodePos ); // ----------------------------------------------------------------------- // If a ground node, drop to floor and make sure can stand at test postion // ----------------------------------------------------------------------- if (!g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { UTIL_DropToFloor( testHull, MASK_NPCSOLID ); vNewNodePos = testHull->GetAbsOrigin(); CTraceFilterSimple traceFilter( testHull, COLLISION_GROUP_NONE ); if (!UTIL_CheckBottom(testHull, &traceFilter, sv_stepsize.GetFloat())) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } } // ----------------------------------------------------------------------- // Make sure hull fits at location by seeing if it can move up a fraction // ----------------------------------------------------------------------- Vector vUpBit = testHull->GetAbsOrigin(); vUpBit.z += 1; trace_t tr; UTIL_TraceHull( testHull->GetAbsOrigin(), vUpBit, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), MASK_NPCSOLID, testHull, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid || tr.fraction != 1.0) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } // <<TEMP>> Round position till DS fixed WC bug testHull->SetLocalOrigin( Vector( floor(testHull->GetAbsOrigin().x), floor(testHull->GetAbsOrigin().y ), floor(testHull->GetAbsOrigin().z) ) ); // --------------------------------------- // Send new node to WC // --------------------------------------- int status; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { status = Editor_CreateNode("info_node_air", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } else { // Create slightly higher in WC so it can be dropped when its loaded again Vector origin = testHull->GetLocalOrigin(); origin.z += 24.0; testHull->SetLocalOrigin( origin ); status = Editor_CreateNode("info_node", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } if (status == Editor_BadCommand) { Msg( "Worldcraft failed on creation...\n" ); CAI_TestHull::ReturnTestHull(); } else if (status == Editor_OK) { // ----------------------- // Create a new ai node // ----------------------- CNodeEnt *pNodeEnt; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node_air"); } else { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node"); } // Note this is a new entity being created as part of wc editing pNodeEnt->SetLocalOrigin( testHull->GetLocalOrigin() ); CAI_TestHull::ReturnTestHull(); pNodeEnt->m_NodeData.nWCNodeID = g_pAINetworkManager->GetEditOps()->m_nNextWCIndex; pNodeEnt->m_debugOverlays |= OVERLAY_WC_CHANGE_ENTITY; pNodeEnt->Spawn(); } } DoneCreate: // ---------------------------------------------------------- // Flash a red box as a warning that the hull won't fit here // ---------------------------------------------------------- if (!bPositionValid) { NDebugOverlay::Box(vNewNodePos, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), 255,0,0,0,0.1); } // Restore player collidability pPlayer->SetSolid( SOLID_BBOX ); }
//----------------------------------------------------------------------------- // Purpose: Return the origin & angles for a projectile fired from the player's gun //----------------------------------------------------------------------------- void CTFWeaponBaseGun::GetProjectileFireSetup( CTFPlayer *pPlayer, Vector vecOffset, Vector *vecSrc, QAngle *angForward, bool bHitTeammates /* = true */ ) { Vector vecForward, vecRight, vecUp; AngleVectors( pPlayer->EyeAngles(), &vecForward, &vecRight, &vecUp ); Vector vecShootPos = pPlayer->Weapon_ShootPosition(); // Estimate end point Vector endPos = vecShootPos + vecForward * 2000; // Trace forward and find what's in front of us, and aim at that trace_t tr; if ( bHitTeammates ) { CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE ); UTIL_TraceLine( vecShootPos, endPos, MASK_SOLID, &filter, &tr ); } else { CTraceFilterIgnoreTeammates filter( pPlayer, COLLISION_GROUP_NONE, pPlayer->GetTeamNumber() ); UTIL_TraceLine( vecShootPos, endPos, MASK_SOLID, &filter, &tr ); } #ifndef CLIENT_DLL // Offset actual start point *vecSrc = vecShootPos + (vecForward * vecOffset.x) + (vecRight * vecOffset.y) + (vecUp * vecOffset.z); #else // If we're seeing another player shooting the projectile, move their start point to the weapon origin if ( pPlayer ) { C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( pLocalPlayer != pPlayer || ::input->CAM_IsThirdPerson() ) { if ( pPlayer->GetActiveWeapon() ) { pPlayer->GetActiveWeapon()->GetAttachment( "muzzle", *vecSrc ); } } else { C_BaseEntity *pViewModel = pLocalPlayer->GetViewModel(); if ( pViewModel ) { QAngle vecAngles; int iMuzzleFlashAttachment = pViewModel->LookupAttachment( "muzzle" ); pViewModel->GetAttachment( iMuzzleFlashAttachment, *vecSrc, vecAngles ); Vector vForward; AngleVectors( vecAngles, &vForward ); trace_t trace; UTIL_TraceLine( *vecSrc + vForward * -50, *vecSrc, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); *vecSrc = trace.endpos; } } } #endif // Find angles that will get us to our desired end point // Only use the trace end if it wasn't too close, which results // in visually bizarre forward angles if ( tr.fraction > 0.1 ) { VectorAngles( tr.endpos - *vecSrc, *angForward ); } else { VectorAngles( endPos - *vecSrc, *angForward ); } }
int CAK74::Swing( int fFirst ) { int fDidHit = FALSE; TraceResult tr; UTIL_MakeVectors (m_pPlayer->pev->v_angle); Vector vecSrc = m_pPlayer->GetGunPosition( ); Vector vecEnd = vecSrc + gpGlobals->v_forward * 32; UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr ); #ifndef CLIENT_DLL if ( tr.flFraction >= 1.0 ) { UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr ); if ( tr.flFraction < 1.0 ) { // Calculate the point of intersection of the line (or hull) and the object we hit // This is and approximation of the "best" intersection CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit ); if ( !pHit || pHit->IsBSPModel() ) FindHullIntersection_AK( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() ); vecEnd = tr.vecEndPos; // This is the point on the actual surface (the hull could have hit space) } } #endif PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usAk_stab, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, 0.0, 0, 0.0 ); if ( tr.flFraction >= 1.0 ) { if (fFirst) { // miss m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5;//0.5 // player "shoot" animation //m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); } } else { switch( ((m_iSwing++) % 2) + 1 )// + 1 { case 0: SendWeaponAnim( AK_NMC_STAB ); break; case 1: SendWeaponAnim( AK_NMC_STAB ); break; case 2: SendWeaponAnim( AK_NMC_STAB ); break; } // player "shoot" animation // m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); // Naaaa #ifndef CLIENT_DLL // hit fDidHit = TRUE; CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit); ClearMultiDamage( ); if ( (m_flNextSecondaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) { // first swing does full damage pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgKnifeStab, gpGlobals->v_forward, &tr, DMG_CLUB | DMG_NEVERGIB ); //DMG_CLUB ); } else { // subsequent swings do half pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgKnifeStab /*/ 2*/, gpGlobals->v_forward, &tr, DMG_CLUB | DMG_NEVERGIB ); //DMG_CLUB ); } ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev ); // play thwack, smack, or dong sound float flVol = 1.0; int fHitWorld = TRUE; if (pEntity) { if ( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE ) { // play thwack or smack sound switch( RANDOM_LONG(0,2) ) { case 0: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/ak-47/AK47_stab_hit-1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/ak-47/AK47_stab_hit-2.wav", 1, ATTN_NORM); break; case 2: EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/ak-47/AK47_stab_hit-1.wav", 1, ATTN_NORM); break; } m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME; if ( !pEntity->IsAlive() ) return TRUE; else flVol = 0.1; fHitWorld = FALSE; } } // play texture hit sound // UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line if (fHitWorld) { float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd-vecSrc)*2, BULLET_PLAYER_CROWBAR); if ( g_pGameRules->IsMultiplayer() ) { // override the volume here, cause we don't play texture sounds in multiplayer, // and fvolbar is going to be 0 from the above call. fvolbar = 1; } // also play crowbar strike switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/ak-47/AK47_stab_hitwall-1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; case 1: EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/ak-47/AK47_stab_hitwall-2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); break; } // delay the decal a bit m_trHit = tr; } m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME; #endif m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.7; //UTIL_WeaponTimeBase() + 0.25; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.9; SetThink( Smack ); pev->nextthink = UTIL_WeaponTimeBase() + 0.8; //0.2; //0.7 } return fDidHit; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CWeaponImmolator::Update() { float flDuration = gpGlobals->curtime - m_flTimeLastUpdatedRadius; if( flDuration != 0.0 ) { m_flBurnRadius += RADIUS_GROW_RATE * flDuration; } // Clamp m_flBurnRadius = MIN( m_flBurnRadius, MAX_BURN_RADIUS ); CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); Vector vecSrc; Vector vecAiming; if( pOwner ) { vecSrc = pOwner->Weapon_ShootPosition( ); vecAiming = pOwner->GetAutoaimVector(AUTOAIM_2DEGREES); } else { CBaseCombatCharacter *pOwner = GetOwner(); vecSrc = pOwner->Weapon_ShootPosition( ); vecAiming = m_vecImmolatorTarget - vecSrc; VectorNormalize( vecAiming ); } trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + vecAiming * MAX_TRACE_LENGTH, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); int brightness; brightness = 255 * (m_flBurnRadius/MAX_BURN_RADIUS); UTIL_Beam( vecSrc, tr.endpos, m_beamIndex, 0, //halo index 0, //frame start 2.0f, //framerate 0.1f, //life 20, // width 1, // endwidth 0, // fadelength, 1, // noise 0, // red 255, // green 0, // blue, brightness, // bright 100 // speed ); if( tr.DidHitWorld() ) { int beams; for( beams = 0 ; beams < 5 ; beams++ ) { Vector vecDest; // Random unit vector vecDest.x = random->RandomFloat( -1, 1 ); vecDest.y = random->RandomFloat( -1, 1 ); vecDest.z = random->RandomFloat( 0, 1 ); // Push out to radius dist. vecDest = tr.endpos + vecDest * m_flBurnRadius; UTIL_Beam( tr.endpos, vecDest, m_beamIndex, 0, //halo index 0, //frame start 2.0f, //framerate 0.15f, //life 20, // width 1.75, // endwidth 0.75, // fadelength, 15, // noise 0, // red 255, // green 0, // blue, 128, // bright 100 // speed ); } // Immolator starts to hurt a few seconds after the effect is seen if( m_flBurnRadius > 64.0 ) { ImmolationDamage( CTakeDamageInfo( this, this, 1, DMG_BURN ), tr.endpos, m_flBurnRadius, CLASS_NONE ); } } else { // The attack beam struck some kind of entity directly. } m_flTimeLastUpdatedRadius = gpGlobals->curtime; if( m_flBurnRadius >= MAX_BURN_RADIUS ) { StopImmolating(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponExtinguisher::ItemPostFrame( void ) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; //Only shoot if we have ammo if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0 ) { //CWeaponExtinguisher::StopJet(); return; } //See if we should try and extinguish fires if ( pOwner->m_nButtons & IN_ATTACK ) { //Drain ammo if ( m_flNextPrimaryAttack < gpGlobals->curtime ) { pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); m_flNextPrimaryAttack = gpGlobals->curtime + EXTINGUISHER_AMMO_RATE; } //If we're just run out... if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0 ) { // CWeaponExtinguisher::StopJet(); return; } //Turn the jet on // CWeaponExtinguisher::StartJet(); Vector vTestPos, vMuzzlePos; Vector vForward, vRight, vUp; pOwner->EyeVectors( &vForward, &vRight, &vUp ); QAngle tmp; pOwner->GetActiveWeapon()->GetAttachment("muzzle", vMuzzlePos, tmp); //FIXME: Need to get the exact same muzzle point! //FIXME: This needs to be adjusted so the server collision matches the visuals on the client vMuzzlePos += vForward * 15.0f; vMuzzlePos += vRight * 6.0f; vMuzzlePos += vUp * -4.0f; QAngle aTmp; VectorAngles( vForward, aTmp ); aTmp[PITCH] += 10; AngleVectors( aTmp, &vForward ); vTestPos = vMuzzlePos + ( vForward * fire_extinguisher_distance.GetInt() ); trace_t tr; UTIL_TraceLine( vMuzzlePos, vTestPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); //Extinguish the fire where we hit FireSystem_ExtinguishInRadius( tr.endpos, fire_extinguisher_radius.GetInt(), fire_extinguisher_strength.GetFloat() ); //Debug visualization if ( fire_extinguisher_debug.GetInt() ) { int radius = fire_extinguisher_radius.GetInt(); NDebugOverlay::Line( vMuzzlePos, tr.endpos, 0, 0, 128, false, 0.0f ); NDebugOverlay::Box( vMuzzlePos, Vector(-1, -1, -1), Vector(1, 1, 1), 0, 0, 128, false, 0.0f ); NDebugOverlay::Box( tr.endpos, Vector(-2, -2, -2), Vector(2, 2, 2), 0, 0, 128, false, 0.0f ); NDebugOverlay::Box( tr.endpos, Vector(-radius, -radius, -radius), Vector(radius, radius, radius), 0, 0, 255, false, 0.0f ); } } else { //CWeaponExtinguisher::StopJet(); } }
void CGETKnife::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) { // Call the baseclass first so we don't interfere with the normal running of things BaseClass::VPhysicsCollision( index, pEvent ); // Grab what we hit CBaseEntity *pOther = pEvent->pEntities[!index]; if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( !PassServerEntityFilter( this, pOther) ) return; if ( !g_pGameRules->ShouldCollide( GetCollisionGroup(), pOther->GetCollisionGroup() ) ) return; trace_t tr; CollisionEventToTrace( index, pEvent, tr ); Vector vecAiming = pEvent->preVelocity[index]; VectorNormalize( vecAiming ); if ( pOther->m_takedamage != DAMAGE_NO && (pOther->IsPlayer() || pOther->IsNPC()) ) { ClearMultiDamage(); CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), GetDamage(), DMG_SLASH | DMG_NEVERGIB ); CalculateMeleeDamageForce( &dmgInfo, vecAiming, tr.endpos, TKNIFE_FORCE_SCALE ); dmgInfo.SetDamagePosition( tr.endpos ); if ( this->GetOwnerEntity() && this->GetOwnerEntity()->IsPlayer() ) { CBasePlayer *pPlayer = ToBasePlayer( this->GetOwnerEntity() ); dmgInfo.SetWeapon( pPlayer->Weapon_OwnsThisType( "weapon_throwing_knife" ) ); } pOther->DispatchTraceAttack( dmgInfo, vecAiming, &tr ); ApplyMultiDamage(); PhysCallbackSetVelocity( pEvent->pObjects[index], vec3_origin ); SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); } else { if ( pOther->IsWorld() ) { // We hit the world, we have to check if this is sky trace_t tr2; Vector origin; pEvent->pInternalData->GetContactPoint( origin ); UTIL_TraceLine( origin, origin + (vecAiming * 4), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr2 ); if ( tr2.surface.flags & SURF_SKY ) { // We hit sky, remove us NOW SetTouch( NULL ); SetThink( NULL ); PhysCallbackRemove( this->NetworkProp() ); return; } } m_bInAir = false; CollisionProp()->UseTriggerBounds( true, 24 ); g_PostSimulationQueue.QueueCall( this, &CBaseEntity::SetOwnerEntity, (CBaseEntity*)NULL ); // const CBaseEntity *host = te->GetSuppressHost(); // te->SetSuppressHost( NULL ); // StopParticleEffects( this ); // te->SetSuppressHost( (CBaseEntity*)host ); SetTouch( &CGETKnife::PickupTouch ); SetThink( &CGETKnife::RemoveThink ); g_PostSimulationQueue.QueueCall(this, &CBaseEntity::SetCollisionGroup, COLLISION_GROUP_DROPPEDWEAPON); SetNextThink( gpGlobals->curtime + 10.0f ); } }
void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) { const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX); CBaseEntity *pEntity = NULL; trace_t tr; float flAdjustedDamage, falloff; Vector vecSpot; Vector vecSrc = vecSrcIn; if ( flRadius ) falloff = info.GetDamage() / flRadius; else falloff = 1.0; int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; #ifdef HL2_DLL if( bInWater ) { // Only muffle the explosion if deeper than 2 feet in water. if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) ) { bInWater = false; } } #endif // HL2_DLL vecSrc.z += 1;// in case grenade is lying on the ground float flHalfRadiusSqr = Square( flRadius / 2.0f ); // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) { // This value is used to scale damage when the explosion is blocked by some other object. float flBlockedDamagePercent = 0.0f; if ( pEntity == pEntityIgnore ) continue; if ( pEntity->m_takedamage == DAMAGE_NO ) continue; // UNDONE: this should check a damage mask, not an ignore if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) {// houndeyes don't hurt other houndeyes with their attack continue; } // blast's don't tavel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; // Check that the explosion can 'see' this entity. vecSpot = pEntity->BodyTarget( vecSrc, false ); UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if( old_radius_damage.GetBool() ) { if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) continue; } else { if ( tr.fraction != 1.0 ) { if ( IsExplosionTraceBlocked(&tr) ) { if( ShouldUseRobustRadiusDamage( pEntity ) ) { if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr ) { // Only use robust model on a target within one-half of the explosion's radius. continue; } Vector vecToTarget = vecSpot - tr.endpos; VectorNormalize( vecToTarget ); // We're going to deflect the blast along the surface that // interrupted a trace from explosion to this target. Vector vecUp, vecDeflect; CrossProduct( vecToTarget, tr.plane.normal, vecUp ); CrossProduct( tr.plane.normal, vecUp, vecDeflect ); VectorNormalize( vecDeflect ); // Trace along the surface that intercepted the blast... UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 ); // ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated. UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 ); if( tr.fraction != 1.0 && tr.DidHitWorld() ) { // Still can't reach the target. continue; } // else fall through } else { continue; } } // UNDONE: Probably shouldn't let children block parents either? Or maybe those guys should set their owner if they want this behavior? // HL2 - Dissolve damage is not reduced by interposing non-world objects if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity ) { // Some entity was hit by the trace, meaning the explosion does not have clear // line of sight to the entity that it's trying to hurt. If the world is also // blocking, we do no damage. CBaseEntity *pBlockingEntity = tr.m_pEnt; //Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() ); UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if( tr.fraction != 1.0 ) { continue; } // Now, if the interposing object is physics, block some explosion force based on its mass. if( pBlockingEntity->VPhysicsGetObject() ) { const float MASS_ABSORB_ALL_DAMAGE = 350.0f; float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass(); float scale = flMass / MASS_ABSORB_ALL_DAMAGE; // Absorbed all the damage. if( scale >= 1.0f ) { continue; } ASSERT( scale > 0.0f ); flBlockedDamagePercent = scale; //Msg(" Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f); } else { // Some object that's not the world and not physics. Generically block 25% damage flBlockedDamagePercent = 0.25f; } } } } // decrease damage for an ent that's farther from the bomb. flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff; flAdjustedDamage = info.GetDamage() - flAdjustedDamage; if ( flAdjustedDamage <= 0 ) { continue; } // the explosion can 'see' this entity, so hurt them! if (tr.startsolid) { // if we're stuck inside them, fixup the position and distance tr.endpos = vecSrc; tr.fraction = 0.0; } CTakeDamageInfo adjustedInfo = info; //Msg("%s: Blocked damage: %f percent (in:%f out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); // Now make a consideration for skill level! if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() ) { // An explosion set off by the player is harming an NPC. Adjust damage accordingly. adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel(); } Vector dir = vecSpot - vecSrc; VectorNormalize( dir ); // If we don't have a damage force, manufacture one if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) { if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) ) { CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc ); } } else { // Assume the force passed in is the maximum force. Decay it based on falloff. float flForce = adjustedInfo.GetDamageForce().Length() * falloff; adjustedInfo.SetDamageForce( dir * flForce ); adjustedInfo.SetDamagePosition( vecSrc ); } if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt ) { ClearMultiDamage( ); pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr ); ApplyMultiDamage(); } else { pEntity->TakeDamage( adjustedInfo ); } // Now hit all triggers along the way that respond to damage... pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir ); #if defined( GAME_DLL ) if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) ) { // This is a total hack!!! bool bIsPrimary = true; CBasePlayer *player = ToBasePlayer( info.GetAttacker() ); CBaseCombatWeapon *pWeapon = player->GetActiveWeapon(); if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) ) { bIsPrimary = false; } gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info ); } #endif } }