void C_WeaponPortalgun::OnDataChanged( DataUpdateType_t updateType ) { BaseClass::OnDataChanged( updateType ); if ( updateType == DATA_UPDATE_CREATED ) { // Start thinking (Baseclass stops it) SetNextClientThink( CLIENT_THINK_ALWAYS ); { C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true ); StartEffects(); } DoEffect( m_EffectState ); } // Update effect state when out of parity with the server else if ( m_nOldEffectState != m_EffectState || m_bOldCanFirePortal1 != m_bCanFirePortal1 || m_bOldCanFirePortal2 != m_bCanFirePortal2 ) { DoEffect( m_EffectState ); m_nOldEffectState = m_EffectState; m_bOldCanFirePortal1 = m_bCanFirePortal1; m_bOldCanFirePortal2 = m_bCanFirePortal2; } }
bool ForceFeedback::SetDeviceForcesFailsafe(XINPUT_VIBRATION* pVibration) { DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y }; LONG rglDirection[2] = { 0, 0 }; //As we cannot properly emulate 2 separate motor force in DirectInput we should try to combine forces; u32 force = (int)((pVibration->wLeftMotorSpeed + pVibration->wRightMotorSpeed) * m_ForcePercent); force = MulDiv(force, DI_FFNOMINALMAX, UINT16_MAX * 2); force = clamp(force, 0, DI_FFNOMINALMAX); DICONSTANTFORCE contantForce; contantForce.lMagnitude = force; // PrintLog("=========== %u", contantForce.lMagnitude); DIEFFECT effectType; ZeroMemory(&effectType, sizeof(DIEFFECT)); effectType.dwSize = sizeof(DIEFFECT); effectType.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; effectType.dwDuration = INFINITE; effectType.dwSamplePeriod = 0; effectType.dwGain = DI_FFNOMINALMAX; effectType.dwTriggerButton = DIEB_NOTRIGGER; effectType.dwTriggerRepeatInterval = 0; effectType.cAxes = m_Axes; effectType.rgdwAxes = rgdwAxes; effectType.rglDirection = rglDirection; effectType.lpEnvelope = 0; effectType.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); effectType.lpvTypeSpecificParams = &contantForce; effectType.dwStartDelay = 0; // we want only one effect for now if (m_effects.size() < 1) { LPDIRECTINPUTEFFECT effect; HRESULT hr = m_pController->m_pDevice->CreateEffect(GUID_ConstantForce, &effectType, &effect, NULL); if (FAILED(hr)) { PrintLog("[PAD%d] CreateEffect failed with code HR = %X, FFBType = %u", m_pController->m_user + 1, hr, m_Type); return false; } else { m_effects.push_back(effect); } } StartEffects(&effectType); return true; }
//----------------------------------------------------------------------------- // Purpose: Idle effect (pulsing) //----------------------------------------------------------------------------- void C_WeaponPortalgun::DoEffectIdle( void ) { StartEffects(); int i; // Turn on the glow sprites for ( i = PORTALGUN_GLOW1; i < (PORTALGUN_GLOW1+NUM_GLOW_SPRITES); i++ ) { m_Parameters[i].GetScale().InitFromCurrent( RandomFloat( 0.0075f, 0.05f ) * SPRITE_SCALE, 0.1f ); m_Parameters[i].GetAlpha().SetAbsolute( RandomInt( 10, 24 ) ); } // Turn on the world glow sprites for ( i = PORTALGUN_GLOW1_WORLD; i < (PORTALGUN_GLOW1_WORLD+NUM_GLOW_SPRITES_WORLD); i++ ) { m_Parameters[i].GetScale().InitFromCurrent( RandomFloat( 0.015f, 0.1f ) * SPRITE_SCALE, 0.1f ); m_Parameters[i].GetAlpha().SetAbsolute( RandomInt( 10, 24 ) ); } // Turn on the endcap sprites for ( i = PORTALGUN_ENDCAP1; i < (PORTALGUN_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) { m_Parameters[i].GetScale().SetAbsolute( RandomFloat( 1.0f, 3.0f ) ); m_Parameters[i].GetAlpha().SetAbsolute( RandomInt( 96, 128 ) ); } // Turn on the world endcap sprites for ( i = PORTALGUN_ENDCAP1_WORLD; i < (PORTALGUN_ENDCAP1_WORLD+NUM_ENDCAP_SPRITES_WORLD); i++ ) { m_Parameters[i].GetScale().SetAbsolute( RandomFloat( 2.0f, 6.0f ) ); m_Parameters[i].GetAlpha().SetAbsolute( RandomInt( 96, 128 ) ); } // Turn on the internal sprites i = PORTALGUN_MUZZLE_GLOW; if ( m_bPulseUp ) { m_fPulse += gpGlobals->frametime; if ( m_fPulse > 1.0f ) { m_fPulse = 1.0f; m_bPulseUp = !m_bPulseUp; } } else { m_fPulse -= gpGlobals->frametime; if ( m_fPulse < 0.0f ) { m_fPulse = 0.0f; m_bPulseUp = !m_bPulseUp; } } m_Parameters[i].GetScale().SetAbsolute( cl_portalgun_effects_min_size.GetFloat() + ( m_fEffectsMaxSize1 - cl_portalgun_effects_min_size.GetFloat() ) * m_fPulse ); m_Parameters[i].GetAlpha().SetAbsolute( cl_portalgun_effects_min_alpha.GetInt() + ( cl_portalgun_effects_max_alpha.GetInt() - cl_portalgun_effects_min_alpha.GetInt() ) * m_fPulse ); Vector colorMagSprites = GetEffectColor( i ); m_Parameters[i].SetColor( colorMagSprites ); // Turn on the world internal sprites i = PORTALGUN_MUZZLE_GLOW_WORLD; m_Parameters[i].GetScale().SetAbsolute( cl_portalgun_effects_min_size.GetFloat() + ( m_fEffectsMaxSize1 - cl_portalgun_effects_min_size.GetFloat() ) * m_fPulse ); m_Parameters[i].GetAlpha().SetAbsolute( cl_portalgun_effects_min_alpha.GetInt() + ( cl_portalgun_effects_max_alpha.GetInt() - cl_portalgun_effects_min_alpha.GetInt() ) * m_fPulse ); m_Parameters[i].SetColor( colorMagSprites ); // Turn on the tube beam sprites for ( i = PORTALGUN_TUBE_BEAM1; i < (PORTALGUN_TUBE_BEAM1+NUM_TUBE_BEAM_SPRITES); i++ ) { m_Parameters[i].GetAlpha().SetAbsolute( cl_portalgun_effects_min_alpha.GetInt() + ( cl_portalgun_effects_max_alpha.GetInt() - cl_portalgun_effects_min_alpha.GetInt() ) * m_fPulse ); m_Parameters[i].SetColor( colorMagSprites ); } // Turn on the world tube beam sprites for ( i = PORTALGUN_TUBE_BEAM1_WORLD; i < (PORTALGUN_TUBE_BEAM1_WORLD+NUM_TUBE_BEAM_SPRITES_WORLD); i++ ) { m_Parameters[i].GetAlpha().SetAbsolute( cl_portalgun_effects_min_alpha.GetInt() + ( cl_portalgun_effects_max_alpha.GetInt() - cl_portalgun_effects_min_alpha.GetInt() ) * m_fPulse ); m_Parameters[i].SetColor( colorMagSprites ); } }
bool ForceFeedback::SetDeviceForcesEjocys(XINPUT_VIBRATION* pVibration) { DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y }; LONG rglDirection[2] = { 0, 0 }; DIPERIODIC periodicForce; ZeroMemory(&periodicForce, sizeof(DIPERIODIC)); DIEFFECT effectType; ZeroMemory(&effectType, sizeof(DIEFFECT)); effectType.dwSize = sizeof(DIEFFECT); effectType.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; effectType.cAxes = m_Axes; effectType.lpEnvelope = 0; effectType.dwStartDelay = 0; effectType.cbTypeSpecificParams = sizeof(DIPERIODIC); effectType.dwDuration = INFINITE; effectType.dwSamplePeriod = 0; effectType.dwGain = DI_FFNOMINALMAX; effectType.dwTriggerButton = DIEB_NOTRIGGER; effectType.dwTriggerRepeatInterval = 0; effectType.rgdwAxes = rgdwAxes; effectType.rglDirection = rglDirection; effectType.lpvTypeSpecificParams = &periodicForce; // NOTE: This will not work as expected, because both motors can have speeds at once. if (pVibration->wLeftMotorSpeed) periodicForce.dwPeriod = m_LeftPeriod * 1000; else periodicForce.dwPeriod = m_RightPeriod * 1000; //As we cannot properly emulate 2 separate motor force in DirectInput we should try to combine forces; u32 force = (int)((pVibration->wLeftMotorSpeed + pVibration->wRightMotorSpeed) * m_ForcePercent); force = MulDiv(force, DI_FFNOMINALMAX, UINT16_MAX * 2); force = clamp(force, 0, DI_FFNOMINALMAX); // PrintLog("=========== %u", force); if (m_Axes == 1) { periodicForce.dwMagnitude = std::max(pVibration->wLeftMotorSpeed, pVibration->wRightMotorSpeed); periodicForce.dwPeriod = (m_LeftPeriod * 1000 * pVibration->wLeftMotorSpeed + m_RightPeriod * 1000 * pVibration->wRightMotorSpeed) / (pVibration->wLeftMotorSpeed + pVibration->wRightMotorSpeed); effectType.rglDirection[0] = 0; effectType.rglDirection[1] = 0; } else { periodicForce.dwMagnitude = force; effectType.rglDirection[0] = pVibration->wLeftMotorSpeed; effectType.rglDirection[1] = pVibration->wRightMotorSpeed; } // we want only one effect for now if (m_effects.size() < 1) { LPDIRECTINPUTEFFECT effect; HRESULT hr = m_pController->m_pDevice->CreateEffect(GUID_Sine, &effectType, &effect, NULL); if (FAILED(hr)) { PrintLog("[PAD%d] CreateEffect failed with code HR = %X, FFBType = %u", m_pController->m_user + 1, hr, m_Type); return false; } else { m_effects.push_back(effect); } } StartEffects(&effectType); return true; }