void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( ToBasePlayer(pActivator) == m_pPlayer ) { CBaseEntity *pAttached = m_grabController.GetAttached(); // UNDONE: Use vphysics stress to decide to drop objects // UNDONE: Must fix case of forcing objects into the ground you're standing on (causes stress) before that will work if ( !pAttached || useType == USE_OFF || (m_pPlayer->m_nButtons & IN_ATTACK2) || m_grabController.ComputeError() > 12 ) { Shutdown(); return; } //Adrian: Oops, our object became motion disabled, let go! IPhysicsObject *pPhys = pAttached->VPhysicsGetObject(); if ( pPhys && pPhys->IsMoveable() == false ) { Shutdown(); return; } #if STRESS_TEST vphysics_objectstress_t stress; CalculateObjectStress( pPhys, pAttached, &stress ); if ( stress.exertedStress > 250 ) { Shutdown(); return; } #endif #ifndef PLAYER_DISABLE_THROWING // +ATTACK will throw phys objects if ( m_pPlayer->m_nButtons & IN_ATTACK ) { Shutdown( true ); Vector vecLaunch; m_pPlayer->EyeVectors( &vecLaunch ); // JAY: Scale this with mass because some small objects really go flying float massFactor = clamp( pPhys->GetMass(), 0.5, 15 ); massFactor = RemapVal( massFactor, 0.5, 15, 0.5, 4 ); vecLaunch *= player_throwforce.GetFloat() * massFactor; pPhys->ApplyForceCenter( vecLaunch ); AngularImpulse aVel = RandomAngularImpulse( -10, 10 ) * massFactor; pPhys->ApplyTorqueCenter( aVel ); return; } #endif if ( useType == USE_SET ) { // update position m_grabController.UpdateObject( m_pPlayer, 12 ); } } }
//--------------------------------------------------------- // A different bounce behavior for the citizen-modified mine. Detonates at the top of its apex, // and does not attempt to track enemies. //--------------------------------------------------------- void CBounceBomb::CavernBounceThink() { SetNextThink( gpGlobals->curtime + 0.1 ); StudioFrameAdvance(); IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { const float MINE_MAX_JUMP_HEIGHT = 78; // Figure out how much headroom the mine has, and hop to within a few inches of that. trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, MINE_MAX_JUMP_HEIGHT ), MASK_SHOT, this, COLLISION_GROUP_INTERACTIVE, &tr ); float height; if( tr.m_pEnt && tr.m_pEnt->VPhysicsGetObject() ) { // Physics object resting on me. Jump as hard as allowed to try to knock it away. height = MINE_MAX_JUMP_HEIGHT; } else { height = tr.endpos.z - GetAbsOrigin().z; height -= BOUNCEBOMB_RADIUS; if ( height < 0.1 ) height = 0.1; } float time = sqrt( height / (0.5 * sv_gravity.GetFloat()) ); float velocity = sv_gravity.GetFloat() * time; // or you can just AddVelocity to the object instead of ApplyForce float force = velocity * pPhysicsObject->GetMass(); Vector up; GetVectors( NULL, NULL, &up ); pPhysicsObject->Wake(); pPhysicsObject->ApplyForceCenter( up * force ); if( m_hNearestNPC ) { Vector vecPredict = m_hNearestNPC->GetSmoothedVelocity(); pPhysicsObject->ApplyForceCenter( vecPredict * (pPhysicsObject->GetMass() * 0.65f) ); } pPhysicsObject->ApplyTorqueCenter( AngularImpulse( random->RandomFloat( 15, 40 ), random->RandomFloat( 15, 40 ), random->RandomFloat( 30, 60 ) ) ); EmitSound( "NPC_CombineMine.Hop" ); SetThink( &CBounceBomb::ExplodeThink ); SetNextThink( gpGlobals->curtime + 0.33f ); } }
//========================================================= // SonicAttack //========================================================= void CNPC_Houndeye::SonicAttack ( void ) { EmitSound( "NPC_Houndeye.SonicAttack" ); if (m_pEnergyWave) { UTIL_Remove(m_pEnergyWave); } Vector vFacingDir = EyeDirection3D( ); m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() ); m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<<TEMP>> magic m_pEnergyWave->SetAbsVelocity( 100*vFacingDir ); CBaseEntity *pEntity = NULL; // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) { if (pEntity->Classify() == CLASS_HOUNDEYE) { continue; } if (pEntity->GetFlags() & FL_NOTARGET) { continue; } IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject) { // -------------------------- // Adjust damage by distance // -------------------------- float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length(); float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS ); // -------------------------- // Adjust damage by direction // -------------------------- Vector forward; AngleVectors( GetAbsAngles(), &forward ); Vector vEntDir = (pEntity->GetAbsOrigin() - GetAbsOrigin()); VectorNormalize(vEntDir); float flDotPr = DotProduct(forward,vEntDir); flDamageAdjuster *= flDotPr; if (flDamageAdjuster < 0) { continue; } // -------------------------- // Adjust damage by visibility // -------------------------- if ( !FVisible( pEntity ) ) { if ( pEntity->IsPlayer() ) { // if this entity is a client, and is not in full view, inflict half damage. We do this so that players still // take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients // so that monsters in other parts of the level don't take the damage and get pissed. flDamageAdjuster *= 0.5; } else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) { // do not hurt nonclients through walls, but allow damage to be done to breakables continue; } } // ------------------------------ // Apply the damage // ------------------------------ if (pEntity->m_takedamage != DAMAGE_NO) { CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB ); CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); // Throw the player if ( pEntity->IsPlayer() ) { Vector forward; AngleVectors( GetLocalAngles(), &forward ); Vector vecVelocity = pEntity->GetAbsVelocity(); vecVelocity += forward * 250 * flDamageAdjuster; vecVelocity.z = 300 * flDamageAdjuster; pEntity->SetAbsVelocity( vecVelocity ); pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) ); } } // ------------------------------ // Apply physics foces // ------------------------------ IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if (pPhysicsObject) { float flForce = flDamageAdjuster * 8000; pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce ); pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce ); } } } }