void CGunTarget::Wait( void ) { CBaseEntity *pTarget = m_hTargetEnt; if ( !pTarget ) { Stop(); return; } variant_t emptyVariant; pTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); m_flWait = pTarget->GetDelay(); m_target = pTarget->m_target; SetMoveDone( &CGunTarget::Next ); if (m_flWait != 0) {// -1 wait will wait forever! SetMoveDoneTime( m_flWait ); } else { Next();// do it RIGHT now! } }
void CSmokeGrenadeProjectile::Think_Detonate() { if ( GetAbsVelocity().Length() > 0.1 ) { // Still moving. Don't detonate yet. SetNextThink( gpGlobals->curtime + 0.2 ); return; } TheBots->SetGrenadeRadius( this, SmokeGrenadeRadius ); // Ok, we've stopped rolling or whatever. Now detonate. ParticleSmokeGrenade *pGren = (ParticleSmokeGrenade*)CBaseEntity::Create( PARTICLESMOKEGRENADE_ENTITYNAME, GetAbsOrigin(), QAngle(0,0,0), NULL ); if ( pGren ) { pGren->FillVolume(); pGren->SetFadeTime( 17, 22 ); pGren->SetAbsOrigin( GetAbsOrigin() ); //tell the hostages about the smoke! CBaseEntity *pEntity = NULL; variant_t var; //send the location of the smoke? var.SetVector3D( GetAbsOrigin() ); while ( ( pEntity = gEntList.FindEntityByClassname( pEntity, "hostage_entity" ) ) != NULL) { //send to hostages that have a resonable chance of being in it while its still smoking if( (GetAbsOrigin() - pEntity->GetAbsOrigin()).Length() < 1000 ) pEntity->AcceptInput( "smokegrenade", this, this, var, 0 ); } // tell the bots a smoke grenade has exploded CCSPlayer *player = ToCSPlayer(GetThrower()); if ( player ) { IGameEvent * event = gameeventmanager->CreateEvent( "smokegrenade_detonate" ); if ( event ) { event->SetInt( "userid", player->GetUserID() ); event->SetFloat( "x", GetAbsOrigin().x ); event->SetFloat( "y", GetAbsOrigin().y ); event->SetFloat( "z", GetAbsOrigin().z ); gameeventmanager->FireEvent( event ); } } } m_hSmokeEffect = pGren; m_bDidSmokeEffect = true; EmitSound( "BaseSmokeEffect.Sound" ); m_nRenderMode = kRenderTransColor; SetNextThink( gpGlobals->curtime + 5 ); SetThink( &CSmokeGrenadeProjectile::Think_Fade ); }
void CTankTargetChange::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target, NULL, pActivator, pCaller ); // UNDONE: This should use more of the event system while ( pTarget ) { // Change the target over pTarget->AcceptInput( "TargetEntity", this, this, m_newTarget, 0 ); pTarget = gEntList.FindEntityByName( pTarget, m_target, NULL, pActivator, pCaller ); } }
//----------------------------------------------------------------------------- // Purpose: fires off any events in the queue who's fire time is (or before) the present time //----------------------------------------------------------------------------- void CEventQueue::ServiceEvents( void ) { if (!CBaseEntity::Debug_ShouldStep()) { return; } EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime ) { MDLCACHE_CRITICAL_SECTION(); bool targetFound = false; // find the targets if ( pe->m_iTarget != NULL_STRING ) { // In the context the event, the searching entity is also the caller CBaseEntity *pSearchingEntity = pe->m_pCaller; CBaseEntity *target = NULL; while ( 1 ) { target = gEntList.FindEntityByName( target, pe->m_iTarget, pSearchingEntity, pe->m_pActivator, pe->m_pCaller ); if ( !target ) break; // pump the action into the target target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); targetFound = true; } } // direct pointer if ( pe->m_pEntTarget != NULL ) { pe->m_pEntTarget->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); targetFound = true; } if ( !targetFound ) { // See if we can find a target if we treat the target as a classname if ( pe->m_iTarget != NULL_STRING ) { CBaseEntity *target = NULL; while ( 1 ) { target = gEntList.FindEntityByClassname( target, STRING(pe->m_iTarget) ); if ( !target ) break; // pump the action into the target target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); targetFound = true; } } } if ( !targetFound ) { const char *pClass ="", *pName = ""; // might be NULL if ( pe->m_pCaller ) { pClass = STRING(pe->m_pCaller->m_iClassname); pName = STRING(pe->m_pCaller->GetEntityName()); } char szBuffer[256]; Q_snprintf( szBuffer, sizeof(szBuffer), "unhandled input: (%s) -> (%s), from (%s,%s); target entity not found\n", STRING(pe->m_iTargetInput), STRING(pe->m_iTarget), pClass, pName ); DevMsg( 2, "%s", szBuffer ); ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); } // remove the event from the list (remembering that the queue may have been added to) RemoveEvent( pe ); delete pe; // // If we are in debug mode, exit the loop if we have fired the correct number of events. // if (CBaseEntity::Debug_IsPaused()) { if (!CBaseEntity::Debug_Step()) { break; } } // restart the list (to catch any new items have probably been added to the queue) pe = m_Events.m_pNext; } }
//----------------------------------------------------------------------------- // Purpose: Handles USE keypress //----------------------------------------------------------------------------- void CBasePlayer::PlayerUse ( void ) { #ifdef GAME_DLL // Was use pressed or released? if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) return; if ( IsObserver() ) { // do special use operation in oberserver mode if ( m_afButtonPressed & IN_USE ) ObserverUse( true ); else if ( m_afButtonReleased & IN_USE ) ObserverUse( false ); return; } #if !defined(_XBOX) // push objects in turbo physics mode if ( (m_nButtons & IN_USE) && sv_turbophysics.GetBool() ) { Vector forward, up; EyeVectors( &forward, NULL, &up ); trace_t tr; // Search for objects in a sphere (tests for entities that are not solid, yet still useable) Vector searchCenter = EyePosition(); CUsePushFilter filter; UTIL_TraceLine( searchCenter, searchCenter + forward * 96.0f, MASK_SOLID, &filter, &tr ); // try the hit entity if there is one, or the ground entity if there isn't. CBaseEntity *entity = tr.m_pEnt; if ( entity ) { IPhysicsObject *pObj = entity->VPhysicsGetObject(); if ( pObj ) { Vector vPushAway = (entity->WorldSpaceCenter() - WorldSpaceCenter()); vPushAway.z = 0; float flDist = VectorNormalize( vPushAway ); flDist = max( flDist, 1 ); float flForce = sv_pushaway_force.GetFloat() / flDist; flForce = min( flForce, sv_pushaway_max_force.GetFloat() ); pObj->ApplyForceOffset( vPushAway * flForce, WorldSpaceCenter() ); } } } #endif if ( m_afButtonPressed & IN_USE ) { // Controlling some latched entity? if ( ClearUseEntity() ) { return; } else { if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) { m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; m_iTrain = TRAIN_NEW|TRAIN_OFF; return; } else { // Start controlling the train! CBaseEntity *pTrain = GetGroundEntity(); if ( pTrain && !(m_nButtons & IN_JUMP) && (GetFlags() & FL_ONGROUND) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) && pTrain->OnControls(this) ) { m_afPhysicsFlags |= PFLAG_DIROVERRIDE; m_iTrain = TrainSpeed(pTrain->m_flSpeed, ((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); m_iTrain |= TRAIN_NEW; EmitSound( "Player.UseTrain" ); return; } } } } CBaseEntity *pUseEntity = FindUseEntity(); // Found an object if ( pUseEntity ) { //!!!UNDONE: traceline here to prevent +USEing buttons through walls int caps = pUseEntity->ObjectCaps(); variant_t emptyVariant; if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) || ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) ) { if ( caps & FCAP_CONTINUOUS_USE ) { m_afPhysicsFlags |= PFLAG_USING; } if ( pUseEntity->ObjectCaps() & FCAP_ONOFF_USE ) { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_ON ); } else { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); } } // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_OFF ); } } else if ( m_afButtonPressed & IN_USE ) { PlayUseDenySound(); } #endif }
void RadiusFlash( Vector vecSrc, CBaseEntity *pevInflictor, CBaseEntity *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType) { vecSrc.z += 1;// in case grenade is lying on the ground if (!pevAttacker) pevAttacker = pevInflictor; trace_t tr; float flAdjustedDamage; variant_t var; Vector vecEyePos; float fadeTime, fadeHold; Vector vForward; Vector vecLOS; float flDot; CBaseEntity *pEntity = NULL; static float flRadius = 1500; float falloff = flDamage / flRadius; bool bInWater = (UTIL_PointContents(vecSrc) == CONTENTS_WATER); // iterate on all entities in the vicinity. while ((pEntity = gEntList.FindEntityInSphere(pEntity, vecSrc, flRadius)) != NULL) { bool bPlayer = pEntity->IsPlayer(); bool bHostage = (Q_stricmp(pEntity->GetClassname(), "hostage_entity") == 0); if (!bPlayer && !bHostage) continue; vecEyePos = pEntity->EyePosition(); // blasts don't travel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; float percentageOfFlash = PercentageOfFlashForPlayer(pEntity, vecSrc, pevInflictor); if (percentageOfFlash > 0.0) { // decrease damage for an ent that's farther from the grenade flAdjustedDamage = flDamage - (vecSrc - pEntity->EyePosition()).Length() * falloff; if (flAdjustedDamage > 0) { // See if we were facing the flash AngleVectors(pEntity->EyeAngles(), &vForward); vecLOS = (vecSrc - vecEyePos); //float flDistance = vecLOS.Length(); // Normalize both vectors so the dotproduct is in the range -1.0 <= x <= 1.0 vecLOS.NormalizeInPlace(); flDot = DotProduct(vecLOS, vForward); float startingAlpha = 255; // if target is facing the bomb, the effect lasts longer if (flDot >= 0.5) { // looking at the flashbang fadeTime = flAdjustedDamage * 2.5f; fadeHold = flAdjustedDamage * 1.25f; } else if (flDot >= -0.5) { // looking to the side fadeTime = flAdjustedDamage * 1.75f; fadeHold = flAdjustedDamage * 0.8f; } else { // facing away fadeTime = flAdjustedDamage * 1.0f; fadeHold = flAdjustedDamage * 0.75f; startingAlpha = 200; } fadeTime *= percentageOfFlash; fadeHold *= percentageOfFlash; if (bPlayer) { //MOM_TODO: do we want this functionality? // blind players and bots //CMomentumPlayer *player = static_cast<CMomentumPlayer *>(pEntity); //player->Blind( fadeHold, fadeTime, startingAlpha ); // deafen players and bots //player->Deafen( flDistance ); } else if (bHostage) { variant_t val; val.SetFloat(fadeTime); pEntity->AcceptInput("flashbang", pevInflictor, pevAttacker, val, 0); } } } } CPVSFilter filter(vecSrc); te->DynamicLight(filter, 0.0, &vecSrc, 255, 255, 255, 2, 400, 0.1, 768); }
bool CSDKPlayer::PlayerUse() { #ifdef GAME_DLL // Was use pressed or released? if ( ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) && !IsObserver() ) { Vector forward, up; EyeVectors( &forward, NULL, &up ); Vector vecSearchCenter = EyePosition(); CBaseEntity *pObject = nullptr; CBaseEntity *pNearest = nullptr; float flNearest = FLT_MAX; // Look for grenades so we can prioritize picking them up first. for ( CEntitySphereQuery sphere( vecSearchCenter, PLAYER_USE_RADIUS ); ( pObject = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if ( !pObject ) continue; if ( !IsUseableEntity( pObject, FCAP_USE_IN_RADIUS ) ) continue; CWeaponSDKBase* pWeapon = dynamic_cast<CWeaponSDKBase*>(pObject); if (!pWeapon) continue; if (pWeapon->GetWeaponID() != SDK_WEAPON_GRENADE) continue; // If we're full up on grenades, pass over to whatever other weapons are lying around. if (!g_pGameRules->CanHavePlayerItem(this, pWeapon)) continue; // see if it's more roughly in front of the player than previous guess Vector point; pObject->CollisionProp()->CalcNearestPoint( vecSearchCenter, &point ); Vector dir = point - vecSearchCenter; VectorNormalize(dir); float dot = DotProduct( dir, forward ); // Need to be looking at the object more or less if ( dot < 0.8 ) continue; float dist = CalcDistanceToLine( point, vecSearchCenter, forward ); ConVarRef sv_debug_player_use("sv_debug_player_use"); if ( sv_debug_player_use.GetBool() ) { Msg("Radius found %s, dist %.2f\n", pObject->GetClassname(), dist ); } // Not worried about shit being behind a wall at this point. // Just greedily gobble up all nearby grenades since there's // no penalty to the player for doing so. if ( dist < flNearest ) { pNearest = pObject; flNearest = dist; } } if (pNearest) { // This is a grenade. Use it to pick it up. variant_t emptyVariant; pNearest->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); return true; } } #endif bool bUsed = BaseClass::PlayerUse(); if (bUsed) return bUsed; if (!(m_afButtonPressed & IN_USE)) return false; if (!IsAlive()) return false; return false; }
// Regular explosions void CPlantedC4::Explode( trace_t *pTrace, int bitsDamageType ) { // Check to see if the round is over after the bomb went off... CSGameRules()->m_bTargetBombed = true; m_bBombTicking = false; CSGameRules()->CheckWinConditions(); // Do the Damage float flBombRadius = 500; if ( g_pMapInfo ) flBombRadius = g_pMapInfo->m_flBombRadius; // Output to the bomb target ent CBaseEntity *pTarget = NULL; variant_t emptyVariant; while ((pTarget = gEntList.FindEntityByClassname( pTarget, "func_bomb_target" )) != NULL) { //Adrian - But only to the one we want! if ( pTarget->entindex() != m_iBombSiteIndex ) continue; pTarget->AcceptInput( "BombExplode", this, this, emptyVariant, 0 ); break; } // Pull out of the wall a bit if ( pTrace->fraction != 1.0 ) { SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) ); } { Vector pos = GetAbsOrigin() + Vector( 0,0,8 ); // add an explosion TE so it affects clientside physics CPASFilter filter( pos ); te->Explosion( filter, 0.0, &pos, g_sModelIndexFireball, 50.0, 25, TE_EXPLFLAG_NONE, flBombRadius * 3.5, 200 ); } // Fireball sprite and sound!! { Vector fireballPos = GetAbsOrigin(); CPVSFilter filter( fireballPos ); te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 ); } { Vector fireballPos = GetAbsOrigin() + Vector( random->RandomFloat( -512, 512 ), random->RandomFloat( -512, 512 ), random->RandomFloat( -10, 10 ) ); CPVSFilter filter( fireballPos ); te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 ); } { Vector fireballPos = GetAbsOrigin() + Vector( random->RandomFloat( -512, 512 ), random->RandomFloat( -512, 512 ), random->RandomFloat( -10, 10 ) ); CPVSFilter filter( fireballPos ); te->Sprite( filter, 0, &fireballPos, g_sModelIndexFireball, 100, 150 ); } // Sound! for everyone CBroadcastRecipientFilter filter; EmitSound( filter, entindex(), "c4.explode" ); // Decal! UTIL_DecalTrace( pTrace, "Scorch" ); // Shake! UTIL_ScreenShake( pTrace->endpos, 25.0, 150.0, 1.0, 3000, SHAKE_START ); SetOwnerEntity( NULL ); // can't traceline attack owner if this is set CSGameRules()->RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), flBombRadius, bitsDamageType ), GetAbsOrigin(), flBombRadius * 3.5, //Matt - don't ask me, this is how CS does it. CLASS_NONE, true ); // IGNORE THE WORLD!! // send director message, that something important happed here /* MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR ); WRITE_BYTE ( 9 ); // command length in bytes WRITE_BYTE ( DRC_CMD_EVENT ); // bomb explode WRITE_SHORT( ENTINDEX(this->edict()) ); // index number of primary entity WRITE_SHORT( 0 ); // index number of secondary entity WRITE_LONG( 15 | DRC_FLAG_FINAL ); // eventflags (priority and flags) MESSAGE_END(); */ UTIL_Remove( this ); }
void CSDKPlayer::PlayerUse ( void ) { // Was use pressed or released? if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) return; if ( m_afButtonPressed & IN_USE ) { // Currently using a latched entity? if ( ClearUseEntity() ) { if (m_bPlayerPickedUpObject) { m_bPlayerPickedUpObject = false; } return; } else { if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) { m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; m_iTrain = TRAIN_NEW|TRAIN_OFF; return; } } // Tracker 3926: We can't +USE something if we're climbing a ladder if ( GetMoveType() == MOVETYPE_LADDER ) { return; } } if( m_flTimeUseSuspended > gpGlobals->curtime ) { // Something has temporarily stopped us being able to USE things. // Obviously, this should be used very carefully.(sjb) return; } CBaseEntity *pUseEntity = FindUseEntity(); bool usedSomething = false; // Found an object if ( pUseEntity ) { //!!!UNDONE: traceline here to prevent +USEing buttons through walls int caps = pUseEntity->ObjectCaps(); variant_t emptyVariant; if ( m_afButtonPressed & IN_USE ) { // Robin: Don't play sounds for NPCs, because NPCs will allow respond with speech. if ( !pUseEntity->MyNPCPointer() ) { EmitSound( SOUND_USE ); } } if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) || ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) ) { if ( caps & FCAP_CONTINUOUS_USE ) m_afPhysicsFlags |= PFLAG_USING; pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); usedSomething = true; } // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); usedSomething = true; } } else if ( m_afButtonPressed & IN_USE ) { // Signal that we want to play the deny sound, unless the user is +USEing on a ladder! // The sound is emitted in ItemPostFrame, since that occurs after GameMovement::ProcessMove which // lets the ladder code unset this flag. m_bPlayUseDenySound = true; } // Debounce the use key if ( usedSomething && pUseEntity ) { m_Local.m_nOldButtons |= IN_USE; m_afButtonPressed &= ~IN_USE; } }