void CWeaponGravityGun::EffectUpdate( void ) { Vector start, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); TraceLine( &tr ); Vector end = tr.endpos; float distance = tr.fraction * 4096; if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; AttachObject( pEntity, GetPhysObjFromPhysicsBone( pEntity, tr.physicsbone ), tr.physicsbone, start, tr.endpos, distance ); } // Add the incremental player yaw to the target transform QAngle angles = m_gravCallback.TransformAnglesFromPlayerSpace( m_gravCallback.m_targetRotation, pOwner ); CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { #ifndef CLIENT_DLL pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); #endif if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = Approach( 1024, m_distance, m_distance * 0.1 ); } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = Approach( 40, m_distance, m_distance * 0.1 ); } IPhysicsObject *pPhys = GetPhysObjFromPhysicsBone( pObject, m_physicsBone ); if ( pPhys ) { if ( pPhys->IsAsleep() ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); } Vector newPosition = start + forward * m_distance; Vector offset; pPhys->LocalToWorld( &offset, m_worldPosition ); Vector vecOrigin; pPhys->GetPosition( &vecOrigin, NULL ); m_gravCallback.SetTargetPosition( newPosition + (vecOrigin - offset), angles ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } } else { m_targetPosition = end; //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); } }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, angles, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; m_viewModelIndex = pOwner->entindex(); // Make sure I've got a view model CBaseViewModel *vm = pOwner->GetViewModel(); if ( vm ) { m_viewModelIndex = vm->entindex(); } pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); Vector end = start + forward * 4096; UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); end = tr.endpos; float distance = tr.fraction * 4096; if ( tr.fraction != 1 ) { // too close to the player, drop the object if ( distance < 36 ) { DetachObject(); return; } } if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; // inform the object what was hit ClearMultiDamage(); pEntity->DispatchTraceAttack( CTakeDamageInfo( pOwner, pOwner, 0, DMG_PHYSGUN ), forward, &tr ); ApplyMultiDamage(); AttachObject( pEntity, start, tr.endpos, distance ); m_lastYaw = pOwner->EyeAngles().y; } // Add the incremental player yaw to the target transform matrix3x4_t curMatrix, incMatrix, nextMatrix; QAngle ang(0.0f, pOwner->EyeAngles().y - m_lastYaw, 0.0f); AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); AngleMatrix( ang, incMatrix ); ConcatTransforms( incMatrix, curMatrix, nextMatrix ); MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); m_lastYaw = pOwner->EyeAngles().y; CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = UTIL_Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = UTIL_Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = UTIL_Approach( 1024, m_distance, m_distance * 0.1 ); } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = UTIL_Approach( 40, m_distance, m_distance * 0.1 ); } // Send the object a physics damage message (0 damage). Some objects interpret this // as something else being in control of their physics temporarily. pObject->TakeDamage( CTakeDamageInfo( this, pOwner, 0, DMG_PHYSGUN ) ); Vector newPosition = start + forward * m_distance; // 24 is a little larger than 16 * sqrt(2) (extent of player bbox) // HACKHACK: We do this so we can "ignore" the player and the object we're manipulating // If we had a filter for tracelines, we could simply filter both ents and start from "start" Vector awayfromPlayer = start + forward * 24; UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1 ) { UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr ); Vector dir = tr.endpos - newPosition; float distance = VectorNormalize(dir); float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime; if ( distance > maxDist ) { newPosition += dir * maxDist; } else { newPosition = tr.endpos; } } else { newPosition = tr.endpos; } CreatePelletAttraction( phys_gunglueradius.GetFloat(), pObject ); // If I'm looking more than 20 degrees away from the glue point, then give up // This lets the player "gesture" for the glue to let go. Vector pelletDir = m_gravCallback.m_worldPosition - start; VectorNormalize(pelletDir); if ( DotProduct( pelletDir, forward ) < 0.939 ) // 0.939 ~= cos(20deg) { // lose attach for 2 seconds if you're too far away m_glueTime = gpGlobals->curtime + 1; } if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) { CGravityPellet *pPelletAttract = m_activePellets[m_pelletAttract].pellet; g_pEffects->Sparks( pPelletAttract->GetAbsOrigin() ); } m_gravCallback.SetTargetPosition( newPosition ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } else { m_gravCallback.SetTargetPosition( end ); } if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) { Vector worldNormal, worldPos; GetPelletWorldCoords( m_pelletAttract, &worldPos, &worldNormal ); m_gravCallback.SetAutoAlign( m_activePellets[m_pelletHeld].localNormal, m_activePellets[m_pelletHeld].pellet->GetLocalOrigin(), worldNormal, worldPos ); } else { m_gravCallback.ClearAutoAlign(); } }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); TraceLine( &tr ); Vector end = tr.endpos; float distance = tr.fraction * 4096; if ( tr.fraction != 1 ) { // too close to the player, drop the object if ( distance < 36 ) { DetachObject(); return; } } if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; AttachObject( pEntity, start, tr.endpos, distance ); m_lastYaw = pOwner->EyeAngles().y; } // Add the incremental player yaw to the target transform matrix3x4_t curMatrix, incMatrix, nextMatrix; AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); AngleMatrix( QAngle(0,pOwner->EyeAngles().y - m_lastYaw,0), incMatrix ); ConcatTransforms( incMatrix, curMatrix, nextMatrix ); MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); m_lastYaw = pOwner->EyeAngles().y; CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { #ifndef CLIENT_DLL pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); #endif if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = Approach( 1024, m_distance, m_distance * 0.1 ); #ifdef CLIENT_DLL if ( gpGlobals->maxClients > 1 ) { gHUD.m_bSkipClear = false; } #endif } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = Approach( 40, m_distance, m_distance * 0.1 ); #ifdef CLIENT_DLL if ( gpGlobals->maxClients > 1 ) { gHUD.m_bSkipClear = false; } #endif } IPhysicsObject *pPhys = pObject->VPhysicsGetObject(); if ( pPhys && pPhys->IsAsleep() ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); } Vector newPosition = start + forward * m_distance; Vector offset; pObject->EntityToWorldSpace( m_worldPosition, &offset ); m_gravCallback.SetTargetPosition( newPosition + (pObject->GetAbsOrigin() - offset), m_gravCallback.m_targetRotation ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } else { m_targetPosition = end; //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); } }