bool CDeferredManagerClient::Init() { AssertMsg( g_pCurrentViewRender == NULL, "viewrender already allocated?!" ); // Make sure deferred lighting setting is read out at this point ReadVideoCfgExt(); const bool bLowPerfSystem = GetGPULevel() <= GPU_LEVEL_LOW || GetGPUMemLevel() <= GPU_MEM_LEVEL_LOW || GetCPULevel() <= CPU_LEVEL_LOW; const int iDeferredLevel = CommandLine() ? CommandLine()->ParmValue("-deferred", 1) : 1; const bool bAllowDeferred = deferred_lighting_enabled.GetBool() && !bLowPerfSystem && (!CommandLine() || CommandLine()->FindParm("-disabledeferred") == 0); const bool bForceDeferred = CommandLine() && CommandLine()->FindParm("-forcedeferred") != 0; bool bSM30 = g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 95; if ( !bSM30 ) { Warning( "The engine doesn't recognize your GPU to support SM3.0, running deferred anyway...\n" ); bSM30 = true; } if ( bAllowDeferred && (bSM30 || bForceDeferred) ) { bool bGotDefShaderDll = ConnectDeferredExt(); if ( bGotDefShaderDll ) { m_bDefRenderingEnabled = true; GetDeferredExt()->EnableDeferredLighting(); if( iDeferredLevel > 1 ) g_pCurrentViewRender = new CDeferredViewRender(); else g_pCurrentViewRender = new CViewRender(); ConVarRef r_shadows( "r_shadows" ); r_shadows.SetValue( "0" ); InitDeferredRTs( true ); materials->AddModeChangeCallBack( &DefRTsOnModeChanged ); InitializeDeferredMaterials(); } } if ( !m_bDefRenderingEnabled ) { Assert( g_pCurrentViewRender == NULL ); if( bAllowDeferred ) Warning( "Your hardware does not seem to support shader model 3.0. If you think that this is an error (hybrid GPUs), add -forcedeferred as start parameter.\n" ); g_pCurrentViewRender = new CViewRender(); } else { #define VENDOR_NVIDIA 0x10DE #define VENDOR_INTEL 0x8086 #define VENDOR_ATI 0x1002 #define VENDOR_AMD 0x1022 #ifndef SHADOWMAPPING_USE_COLOR MaterialAdapterInfo_t info; materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), info ); if ( info.m_VendorID == VENDOR_ATI || info.m_VendorID == VENDOR_AMD ) { vgui::MessageBox *pATIWarning = new vgui::MessageBox("UNSUPPORTED HARDWARE", VarArgs( "AMD/ATI IS NOT YET SUPPORTED IN HARDWARE FILTERING MODE\n" "(cdeferred_manager_client.cpp #%i).", __LINE__ ) ); pATIWarning->InvalidateLayout(); pATIWarning->DoModal(); } #endif } return true; }
bool CP3DRenderer::InitRenderer(HWND hWnd) { I_RegisterModule("rendererDX9"); // memory leaks detection _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); //_CrtSetBreakAlloc(152); g_pConsole = (IP3DConsole*)I_GetClass(IP3DENGINE_CONSOLE); g_pConsole->RegisterLastConVar(g_pLastConVar); // zaregistrovat ConVary tohoto dll projektu - NUTNÉ! g_pFS = (IP3DFileSystem*)I_GetClass(IP3DENGINE_FILESYSTEM); //get filesystem g_pEngine = (IP3DEngine*)I_GetClass(IP3DENGINE_ENGINE); g_pTimer = (IP3DTimer*)I_GetClass(IP3DENGINE_TIMER); // profiler Prof_stackPTR = g_pEngine->GetProf_stack(); Prof_dummyPTR = g_pEngine->GetProf_dummy(); Prof_StackAppendPTR = g_pEngine->GetProf_StackAppendFn(); g_pEngSet.Width = CVr_width.GetInt(); g_pEngSet.Height = CVr_height.GetInt(); g_pEngSet.Windowed = CVr_windowed.GetBool(); g_pEngSet.hWnd = hWnd; // zkontroluj, zda se shoduji verze .h a DLL if (!D3DXCheckVersion(D3D_SDK_VERSION, D3DX_SDK_VERSION)) CON(MSG_CON_ERR, "Warning: Wrong DirectX DLL versions, please install latest DirectX!"); // Vytvoø D3D objekt if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) CON(MSG_ERR_FATAL, "Can't create Direct3D object! Please install DirectX 9..."); // test for depth buffer support - zatial sa nepouziva stencil // D3DFMT_D32, D3DFMT_D24X8, D3DFMT_D16 D3DFORMAT DepthBufFormat = D3DFMT_D16; if (SUCCEEDED (g_pD3D->GetDeviceCaps (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_caps))) if (SUCCEEDED (g_pD3D->CheckDeviceFormat(m_caps.AdapterOrdinal, D3DDEVTYPE_HAL, \ D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8))) DepthBufFormat = D3DFMT_D24X8; // test na vs a ps 2.0 if(m_caps.VertexShaderVersion<D3DVS_VERSION(1,1) || m_caps.PixelShaderVersion<D3DPS_VERSION(2,0)) { CON(MSG_ERR_FATAL, "Pixel shaders 2.0 not supported!"); } // test na format backbufferu if(FAILED(g_pD3D->CheckDeviceType(D3DADAPTER_DEFAULT, CVr_ref.GetBool() ? D3DDEVTYPE_REF : D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, g_pEngSet.Windowed))) { CON(MSG_ERR_FATAL, "Backbuffer format A8R8G8B8 not supported!"); } // ziskej caps do member promennych m_caps_max_anisotr = (int)m_caps.MaxAnisotropy; // Set up the structure used to create the D3DDevice ZeroMemory( &m_pparams, sizeof(m_pparams) ); m_pparams.Windowed = g_pEngSet.Windowed; m_pparams.hDeviceWindow = hWnd; m_pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; m_pparams.BackBufferCount = 1; m_pparams.BackBufferFormat = D3DFMT_A8R8G8B8; m_pparams.EnableAutoDepthStencil = TRUE; m_pparams.AutoDepthStencilFormat = DepthBufFormat; m_pparams.BackBufferWidth = g_pEngSet.Width; m_pparams.BackBufferHeight = g_pEngSet.Height; m_pparams.MultiSampleType = CVr_multisample.GetInt() ? D3DMULTISAMPLE_NONMASKABLE : D3DMULTISAMPLE_NONE; m_pparams.MultiSampleQuality = CVr_multisample.GetInt(); m_pparams.PresentationInterval = CVr_vsync.GetBool() ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; m_pparams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER | D3DPRESENT_LINEAR_CONTENT; m_nWidth = g_pEngSet.Width; m_nHeight = g_pEngSet.Height; #ifdef _DEBUG CON(MSG_CON_INFO, "= DirectX 9 (D3D%d, D3DX%d) Renderer (%s, %s, DEBUG) initialization =", D3D_SDK_VERSION, D3DX_SDK_VERSION,__DATE__, __TIME__); #else CON(MSG_CON_INFO, "= DirectX 9 (D3D%d, D3DX%d) Renderer (%s, %s) initialization =", D3D_SDK_VERSION, D3DX_SDK_VERSION, __DATE__, __TIME__); #endif // vypis nazev a info o grafarne do konzole D3DADAPTER_IDENTIFIER9 ai; if(SUCCEEDED(g_pD3D->GetAdapterIdentifier(CVr_adapter.GetInt(), 0, &ai))) { CON(MSG_CON_INFO, "Renderer: %s", ai.Description); } // vytvoreni zarizeni #ifdef USE_PERFHUD // debug pre NVPerfHUD if (FAILED (g_pD3D->CreateDevice (g_pD3D->GetAdapterCount()-1, D3DDEVTYPE_REF, hWnd, \ D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_pparams, &g_pD3DDevice))) #else if (FAILED (g_pD3D->CreateDevice( CVr_adapter.GetInt(), CVr_ref.GetBool() ? D3DDEVTYPE_REF : D3DDEVTYPE_HAL, hWnd, \ D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_pparams, &g_pD3DDevice))) #endif { CON(MSG_ERR_FATAL, "Renderer: Can't create rendering device!\n\rTry restart or reinstall game...\n\rTry reinstall DirectX and graphic drivers..."); return false; } g_pResMgr = new CP3DResourceManager; g_pResMgr->Initialize(); g_pFrustum = (IP3DFrustum*)I_GetClass(IP3DRENDERER_FRUSTUM); if (g_pFrustum == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain Frustum class!"); return false; } g_pMeshLoader = (IP3DMeshLoader*)I_GetClass(IP3DRENDERER_MESHLOADER); if (g_pMeshLoader == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain MeshLoader!"); return false; } g_pAlphaManager = (IP3DAlphaManager*)I_GetClass(IP3DRENDERER_ALPHAMANAGER); if (g_pAlphaManager == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain AlphaManager!"); return false; } g_pXML = (IP3DXML*)I_GetClass(IP3DENGINE_XML); if (g_pXML == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain XML class!"); return false; } g_pMaterialManager = (IP3DMaterialManager*)I_GetClass(IP3DRENDERER_MATERIALMANAGER); if (g_pMaterialManager == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain MaterialManager!"); return false; } float ViewportSize[2]; ViewportSize[0] = 1.0f / float(g_pEngSet.Width); ViewportSize[1] = 1.0f / float(g_pEngSet.Height); g_pMaterialManager->OnViewportSizeChange (ViewportSize); g_pPostProcessMgr = (IP3DPostprocessManager*)I_GetClass(IP3DRENDERER_POSTPROCESSMANAGER); if (g_pPostProcessMgr == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain PostProcessManager!"); return false; } g_pPhysEngine = (IP3DPhysEngine*)I_GetClass(IP3DPHYS_PHYSENGINE); if (g_pPhysEngine == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain Physics Engine Class!"); return false; } g_pLightManager = (IP3DLightManager*)I_GetClass(IP3DRENDERER_LIGHTMANAGER); if (g_pLightManager == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain DynlightManager!"); return false; } if ( !g_TextureLoader.Init() ) { CON(MSG_ERR_FATAL, "Renderer: Can't initialize TextureLoader!"); return false; } g_pSoundMan = (IP3DSoundManager*)I_GetClass(IP3DSOUND_SOUNDMANAGER); if (g_pSoundMan == NULL) { CON(MSG_ERR_FATAL, "Renderer: Can't obtain SoundManager!"); return false; } SetDefaultRenderStates (); // nastavenie sampler states pre potreby shader modelu 3.0 g_pD3DDevice->SetSamplerState(4, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(4, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(4, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(5, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(5, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(5, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(6, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(6, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(6, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(7, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(7, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState(7, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); // --- get original parameters g_pD3DDevice->GetGammaRamp(0, &m_origGama); // get default render target if(FAILED(g_pD3DDevice->GetRenderTarget(0, &m_pBackBufferSurf))) CON(MSG_CON_INFO, "Renderer: DX9 %d x %d %s initialized!", m_pparams.BackBufferWidth, m_pparams.BackBufferHeight, m_pparams.Windowed ? "windowed" : "fullscreen"); // nastavit callbacky ConVar-ov CVr_wireframe.SetChangeCallback(CV_wireframe); CVr_gamma.SetChangeCallback(&CP3DRenderer::CV_SetGamma); #ifdef _DEBUG g_stats.Init(); // STATS #endif ///////////////// tmpVertPosClr myvert[] = { {P3DXPoint3D(-50,0,0), P3DXPoint3D(1,0,0)}, {P3DXPoint3D(-50,50,0), P3DXPoint3D(0,1,0)}, {P3DXPoint3D(50,50,0), P3DXPoint3D(0,0,1)} }; P3DVertexElement ve[3]; ve[0] = P3DVertexElement(P3DVD_FLOAT3, P3DVU_POSITION); ve[1] = P3DVertexElement(P3DVD_FLOAT3, P3DVU_COLOR); ve[2] = P3DVE_END(); vb.CreateVB(3, ve, sizeof(tmpVertPosClr)); tmpVertPosClr *pv = 0; vb.Lock((void**)&pv); pv[0] = myvert[0]; pv[1] = myvert[1]; pv[2] = myvert[2]; vb.UnLock(); effect.Create("solid.fx"); //////////////// return true; }
void CASW_Parasite::InfestMarine(CASW_Marine* pMarine) { if ( !pMarine ) return; pMarine->BecomeInfested(this); // attach int attachment = pMarine->LookupAttachment( "chest" ); if ( attachment ) { SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); QAngle current(0,0,0); Vector diff = pMarine->GetAbsOrigin() - GetAbsOrigin(); float angle = UTIL_VecToYaw(diff); angle -= pMarine->GetAbsAngles()[YAW]; // get the diff between our angle from the marine and the marine's facing; current = GetAbsAngles(); Vector vAttachmentPos; pMarine->GetAttachment( attachment, vAttachmentPos ); // Make sure it's near the chest attachement before parenting Teleport( &vAttachmentPos, &vec3_angle, &vec3_origin ); SetParent( pMarine, attachment ); float flRaise = RandomFloat( 15.0f, 18.0f ); float flForward = RandomFloat( -3.0f, 0.0f ); float flSide = RandomFloat( 1.75f, 3.0f ) * ( RandomInt( 0, 1 ) == 0 ? 1.0f : -1.0f ); if ( asw_debug_alien_damage.GetBool() ) { Msg( "INFEST: flRaise = %f flForward = %f flSide = %f yaw = %f\n", flRaise, flForward, flSide, angle + asw_infest_angle.GetFloat() ); } SetLocalOrigin( Vector( flForward, flSide, flRaise ) ); SetLocalAngles( QAngle( asw_infest_pitch.GetFloat(), angle + asw_infest_angle.GetFloat(), 0 ) ); // play our infesting anim if ( asw_parasite_inside.GetBool() ) { SetActivity(ACT_RANGE_ATTACK2); } else { int iInfestAttack = LookupSequence("Infest_attack"); if (GetSequence() != iInfestAttack) { ResetSequence(iInfestAttack); } } AddFlag( FL_NOTARGET ); SetThink( &CASW_Parasite::InfestThink ); SetTouch( NULL ); m_bInfesting = true; } else { FinishedInfesting(); } }
//----------------------------------------------------------------------------- // Purpose: Debris flecks caused by impacts // Input : origin - start // *trace - trace information // *materialName - material hit // materialType - type of material hit //----------------------------------------------------------------------------- void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks ) { VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); if ( !fx_drawimpactdebris.GetBool() ) return; #ifdef _XBOX // // XBox version // Vector offset; float spread = 0.2f; CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" ); pSimple->SetSortOrigin( origin ); // Lock the bbox pSimple->GetBinding().SetBBox( origin - ( Vector( 16, 16, 16 ) * iScale ), origin + ( Vector( 16, 16, 16 ) * iScale ) ); // Get the color of the surface we've impacted Vector color; float colorRamp; GetColorForSurface( tr, &color ); int i; SimpleParticle *pParticle; for ( i = 0; i < 4; i++ ) { if ( i == 3 ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin ); } else { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin ); } if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 250, 500 ) * i * 0.5f; // scaled pParticle->m_vecVelocity *= fForce * iScale; // Ramp the color colorRamp = random->RandomFloat( 0.5f, 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; // scaled pParticle->m_uchStartSize = (iScale*0.5f) * random->RandomInt( 3, 4 ) * (i+1); // scaled pParticle->m_uchEndSize = (iScale*0.5f) * pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 200, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); } } // Covers the impact spot with flecks pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin ); if ( pParticle != NULL ) { offset = origin; offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); spread = 1.0f; pParticle->m_vecVelocity.Init(); colorRamp = random->RandomFloat( 0.5f, 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 = random->RandomInt( 4, 8 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f ); } #else // // PC version // Vector color; GetColorForSurface( tr, &color ); if ( !bNoFlecks ) { CreateFleckParticles( origin, color, tr, materialType, iScale ); } // // Dust trail // Vector offset = tr->endpos + ( tr->plane.normal * 2.0f ); SimpleParticle newParticle; int i; for ( i = 0; i < 2; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = 1.0f; Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 2, 4 ) * iScale; newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8 * iScale; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1); newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1); newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -1, 1 ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); } for ( i = 0; i < 4; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 1, 4 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4; newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f ); newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f ); newParticle.m_uchStartAlpha = 255; newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2.0f, 2.0f ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] ); } // // Bullet hole capper // newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f ); Vector dir; dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 4, 8 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f ); newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f ); newParticle.m_uchStartAlpha = random->RandomInt( 100, 200 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2, 2 ); float colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFWeaponBaseGrenadeProj::Explode( trace_t *pTrace, int bitsDamageType ) { SetModelName( NULL_STRING );//invisible AddSolidFlags( FSOLID_NOT_SOLID ); m_takedamage = DAMAGE_NO; // Pull out of the wall a bit if ( pTrace->fraction != 1.0 ) { SetAbsOrigin( pTrace->endpos + ( pTrace->plane.normal * 1.0f ) ); } CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 ); // Explosion effect on client Vector vecOrigin = GetAbsOrigin(); CPVSFilter filter( vecOrigin ); if ( UseImpactNormal() ) { if ( pTrace->m_pEnt && pTrace->m_pEnt->IsPlayer() ) { TE_TFExplosion( filter, 0.0f, vecOrigin, GetImpactNormal(), GetWeaponID(), pTrace->m_pEnt->entindex() ); } else { TE_TFExplosion( filter, 0.0f, vecOrigin, GetImpactNormal(), GetWeaponID(), -1 ); } } else { if ( pTrace->m_pEnt && pTrace->m_pEnt->IsPlayer() ) { TE_TFExplosion( filter, 0.0f, vecOrigin, pTrace->plane.normal, GetWeaponID(), pTrace->m_pEnt->entindex() ); } else { TE_TFExplosion( filter, 0.0f, vecOrigin, pTrace->plane.normal, GetWeaponID(), -1 ); } } // Use the thrower's position as the reported position Vector vecReported = GetThrower() ? GetThrower()->GetAbsOrigin() : vec3_origin; CTakeDamageInfo info( this, GetThrower(), GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported ); float flRadius = GetDamageRadius(); if ( tf_grenade_show_radius.GetBool() ) { DrawRadius( flRadius ); } RadiusDamage( info, vecOrigin, flRadius, CLASS_NONE, NULL ); // Don't decal players with scorch. if ( pTrace->m_pEnt && !pTrace->m_pEnt->IsPlayer() ) { UTIL_DecalTrace( pTrace, "Scorch" ); } SetThink( &CBaseGrenade::SUB_Remove ); SetTouch( NULL ); AddEffects( EF_NODRAW ); SetAbsVelocity( vec3_origin ); SetNextThink( gpGlobals->curtime ); }
//-------------------------------------------------------------------------------------------------------------- void CNavNode::Draw( void ) { #if DEBUG_NAV_NODES if ( !nav_show_nodes.GetBool() ) return; int r = 0, g = 0, b = 0; if ( m_isCovered ) { if ( GetAttributes() & NAV_MESH_CROUCH ) { b = 255; } else { r = 255; } } else { if ( GetAttributes() & NAV_MESH_CROUCH ) { b = 255; } g = 255; } NDebugOverlay::Cross3D( m_pos, 2, r, g, b, true, 0.1f ); if ( (!m_isCovered && nav_show_node_id.GetBool()) || (m_isCovered && nav_show_node_id.GetInt() < 0) ) { char text[16]; Q_snprintf( text, sizeof( text ), "%d", m_id ); NDebugOverlay::Text( m_pos, text, true, 0.1f ); } if ( (unsigned int)(nav_test_node.GetInt()) == m_id ) { TheNavMesh->TestArea( this, 1, 1 ); nav_test_node.SetValue( 0 ); } if ( (unsigned int)(nav_test_node_crouch.GetInt()) == m_id ) { CheckCrouch(); nav_test_node_crouch.SetValue( 0 ); } if ( GetAttributes() & NAV_MESH_CROUCH ) { int i; for( i=0; i<NUM_CORNERS; i++ ) { if ( m_crouch[i] ) { Vector2D dir; CornerToVector2D( (NavCornerType)i, &dir ); const float scale = 3.0f; Vector scaled( dir.x * scale, dir.y * scale, 0 ); NDebugOverlay::HorzArrow( m_pos, m_pos + scaled, 0.5, 0, 0, 255, 255, true, 0.1f ); } } } #endif // DEBUG_NAV_NODES }
void C_GlobalLight::ClientThink() { VPROF("C_GlobalLight::ClientThink"); bool bSupressWorldLights = false; if ( cl_globallight_freeze.GetBool() == true ) { return; } if ( m_bEnabled ) { Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b ); float flLinearFloatLightAlpha = m_LightColor.a; if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha ) { float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f; m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed ); m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed ); m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed ); m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed ); } FlashlightState_t state; Vector vDirection = m_shadowDirection; VectorNormalize( vDirection ); //Vector vViewUp = Vector( 0.0f, 1.0f, 0.0f ); Vector vSunDirection2D = vDirection; vSunDirection2D.z = 0.0f; HACK_GETLOCALPLAYER_GUARD( "C_GlobalLight::ClientThink" ); if ( !C_BasePlayer::GetLocalPlayer() ) return; Vector vPos; QAngle EyeAngles; float flZNear, flZFar, flFov; C_BasePlayer::GetLocalPlayer()->CalcView( vPos, EyeAngles, flZNear, flZFar, flFov ); // Vector vPos = C_BasePlayer::GetLocalPlayer()->GetAbsOrigin(); // vPos = Vector( 0.0f, 0.0f, 500.0f ); vPos = ( vPos + vSunDirection2D * m_flNorthOffset ) - vDirection * m_flSunDistance; vPos += Vector( cl_globallight_xoffset.GetFloat(), cl_globallight_yoffset.GetFloat(), 0.0f ); QAngle angAngles; VectorAngles( vDirection, angAngles ); Vector vForward, vRight, vUp; AngleVectors( angAngles, &vForward, &vRight, &vUp ); state.m_fHorizontalFOVDegrees = m_flFOV; state.m_fVerticalFOVDegrees = m_flFOV; state.m_vecLightOrigin = vPos; BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation ); state.m_fQuadraticAtten = 0.0f; state.m_fLinearAtten = m_flSunDistance * 2.0f; state.m_fConstantAtten = 0.0f; state.m_FarZAtten = m_flSunDistance * 2.0f; state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_NearZ = 4.0f; state.m_FarZ = m_flSunDistance * 2.0f; state.m_fBrightnessScale = 2.0f; state.m_bGlobalLight = true; float flOrthoSize = 1000.0f; if ( flOrthoSize > 0 ) { state.m_bOrtho = true; state.m_fOrthoLeft = -flOrthoSize; state.m_fOrthoTop = -flOrthoSize; state.m_fOrthoRight = flOrthoSize; state.m_fOrthoBottom = flOrthoSize; } else { state.m_bOrtho = false; } state.m_bDrawShadowFrustum = true; state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();; state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias(); state.m_bEnableShadows = m_bEnableShadows; state.m_pSpotlightTexture = m_SpotlightTexture; state.m_pProjectedMaterial = NULL; // don't complain cause we aren't using simple projection in this class state.m_nSpotlightTextureFrame = 0; state.m_nShadowQuality = 1; // Allow entity to affect shadow quality // state.m_bShadowHighRes = true; if ( m_bOldEnableShadows != m_bEnableShadows ) { // If they change the shadow enable/disable, we need to make a new handle if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE ) { g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle ); m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE; } m_bOldEnableShadows = m_bEnableShadows; } if( m_LocalFlashlightHandle == CLIENTSHADOW_INVALID_HANDLE ) { m_LocalFlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } else { g_pClientShadowMgr->UpdateFlashlightState( m_LocalFlashlightHandle, state ); g_pClientShadowMgr->UpdateProjectedTexture( m_LocalFlashlightHandle, true ); } bSupressWorldLights = m_bEnableShadows; } else if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE ) { g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle ); m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE; } g_pClientShadowMgr->SetShadowFromWorldLightsEnabled( !bSupressWorldLights ); BaseClass::ClientThink(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNetGraphPanel::Paint() { VPROF( "CNetGraphPanel::Paint" ); // Don't display net_graph if taking freezecam screenshot and hud_freezecamhide is enabled extern ConVar hud_freezecamhide; if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() ) return; int graphtype; int x, y; int w; vrect_t vrect; int maxmsgbytes = 0; float avg_message = 0.0f; float warning_threshold = 0.0f; if ( ( graphtype = GraphValue() ) == 0 ) return; // Since we divide by scale, make sure it's sensible if ( net_scale.GetFloat() <= 0 ) { net_scale.SetValue( 0.1f ); } int sw, sh; surface()->GetScreenSize( sw, sh ); // Get screen rectangle vrect.x = 0; vrect.y = 0; vrect.width = sw; vrect.height = sh; w = MIN( (int)TIMINGS, m_EstimatedWidth ); if ( vrect.width < w + 10 ) { w = vrect.width - 10; } // get current client netchannel INetChannelInfo interface INetChannelInfo *nci = engine->GetNetChannelInfo(); if ( nci ) { // update incoming data GetFrameData( nci, &maxmsgbytes, &avg_message, &warning_threshold ); // update outgoing data GetCommandInfo( nci, m_Cmdinfo ); UpdateEstimatedServerFramerate( nci ); } GraphGetXY( &vrect, w, &x, &y ); if ( graphtype > 1 ) { PaintLineArt( x, y, w, graphtype, maxmsgbytes ); DrawLargePacketSizes( x, w, graphtype, warning_threshold ); } // Draw client frame timing info DrawTimes( vrect, m_Cmdinfo, x, w, graphtype ); DrawTextFields( graphtype, x, y, w, m_Graph, m_Cmdinfo ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNetGraphPanel::PaintLineArt( int x, int y, int w, int graphtype, int maxmsgbytes ) { VPROF( "CNetGraphPanel::PaintLineArt" ); ResetLineSegments(); int lastvalidh = 0; byte color[3]; int ping; byte alpha; vrect_t rcFill = {0,0,0,0}; int pingheight = m_nNetGraphHeight - LERP_HEIGHT - 2; if (net_graphmsecs.GetInt() < 50 ) { net_graphmsecs.SetValue( 50 ); } bool bShowLatency = net_graphshowlatency.GetBool() && graphtype >= 2; for (int a=0 ; a<w ; a++) { int i = (m_IncomingSequence-a) & ( TIMINGS - 1 ); int h = bShowLatency ? m_PacketLatency[i].latency : 0; packet_latency_t *pl = &m_PacketLatency[ i ]; ColorForHeight( pl, color, &ping, &alpha ); // Skipped if ( !ping ) { // Re-use the last latency h = lastvalidh; } else { h = pingheight * (float)h/net_graphmsecs.GetFloat(); lastvalidh = h; } if ( h > pingheight ) { h = pingheight; } rcFill.x = x + w -a -1; rcFill.y = y - h; rcFill.width = 1; rcFill.height = h; if ( ping ) { rcFill.height = pl->choked ? 2 : 1; } if ( !ping ) { DrawLine2(&rcFill, color, color, alpha, 31 ); } else { DrawLine(&rcFill, color, alpha ); } rcFill.y = y; rcFill.height = 1; color[0] = 0; color[1] = 255; color[2] = 0; DrawLine( &rcFill, color, 160 ); if ( graphtype < 2 ) continue; // Draw a separator. rcFill.y = y - m_nNetGraphHeight - 1; rcFill.height = 1; color[0] = 255; color[1] = 255; color[2] = 255; DrawLine(&rcFill, color, 255 ); // Move up for begining of data rcFill.y -= 1; // Packet didn't have any real data... if ( m_PacketLatency[i].latency > 9995 ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::LOCALPLAYER], 0, 0, 255 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::OTHERPLAYERS], 0, 255, 0 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::ENTITIES], 255, 0, 0 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::SOUNDS], 255, 255, 0) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::EVENTS], 0, 255, 255 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::USERMESSAGES], 128, 128, 0 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::ENTMESSAGES], 0, 128, 128 ) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::STRINGCMD], 128, 0, 0) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::STRINGTABLE], 0, 128, 0) ) continue; if ( !DrawDataSegment( &rcFill, m_Graph[ i ].msgbytes[INetChannelInfo::VOICE], 0, 0, 128 ) ) continue; // Final data chunk is total size, don't use solid line routine for this h = m_Graph[i].msgbytes[INetChannelInfo::TOTAL] / net_scale.GetFloat(); color[ 0 ] = color[ 1 ] = color[ 2 ] = 240; rcFill.height = 1; rcFill.y = y - m_nNetGraphHeight - 1 - h; if ( rcFill.y < 2 ) continue; DrawLine(&rcFill, color, 128 ); // Cache off height m_Graph[i].sampleY = rcFill.y; m_Graph[i].sampleHeight = rcFill.height; } if ( graphtype >= 2 ) { // Draw hatches for first one: // on the far right side DrawHatches( x, y - m_nNetGraphHeight - 1, maxmsgbytes ); DrawStreamProgress( x, y, w ); } DrawLineSegments(); }
bool CAI_TacticalServices::FindLateralCover( const Vector &vNearPos, const Vector &vecThreat, float flMinDist, float distToCheck, int numChecksPerDir, Vector *pResult ) { AI_PROFILE_SCOPE( CAI_TacticalServices_FindLateralCover ); MARK_TASK_EXPENSIVE(); Vector vecLeftTest; Vector vecRightTest; Vector vecStepRight; Vector vecCheckStart; int i; if ( TestLateralCover( vecThreat, vNearPos, flMinDist ) ) { *pResult = GetLocalOrigin(); return true; } if( !ai_find_lateral_cover.GetBool() ) { // Force the NPC to use the nodegraph to find cover. NOTE: We let the above code run // to detect the case where the NPC may already be standing in cover, but we don't // make any additional lateral checks. return false; } Vector right = vecThreat - vNearPos; float temp; right.z = 0; VectorNormalize( right ); temp = right.x; right.x = -right.y; right.y = temp; vecStepRight = right * (distToCheck / (float)numChecksPerDir); vecStepRight.z = 0; vecLeftTest = vecRightTest = vNearPos; vecCheckStart = vecThreat; for ( i = 0 ; i < numChecksPerDir ; i++ ) { vecLeftTest = vecLeftTest - vecStepRight; vecRightTest = vecRightTest + vecStepRight; if (TestLateralCover( vecCheckStart, vecLeftTest, flMinDist )) { *pResult = vecLeftTest; return true; } if (TestLateralCover( vecCheckStart, vecRightTest, flMinDist )) { *pResult = vecRightTest; return true; } } return false; }
bool CAI_TacticalServices::FindLateralLos( const Vector &vecThreat, Vector *pResult ) { AI_PROFILE_SCOPE( CAI_TacticalServices_FindLateralLos ); if( !m_bAllowFindLateralLos ) { return false; } MARK_TASK_EXPENSIVE(); Vector vecLeftTest; Vector vecRightTest; Vector vecStepRight; Vector vecCheckStart; bool bLookingForEnemy = GetEnemy() && VectorsAreEqual(vecThreat, GetEnemy()->EyePosition(), 0.1f); int i; if( !bLookingForEnemy || GetOuter()->HasCondition(COND_SEE_ENEMY) || GetOuter()->HasCondition(COND_HAVE_ENEMY_LOS) || GetOuter()->GetTimeScheduleStarted() == gpGlobals->curtime ) // Conditions get nuked before tasks run, assume should try { // My current position might already be valid. if ( TestLateralLos(vecThreat, GetLocalOrigin()) ) { *pResult = GetLocalOrigin(); return true; } } if( !ai_find_lateral_los.GetBool() ) { // Allows us to turn off lateral LOS at the console. Allow the above code to run // just in case the NPC has line of sight to begin with. return false; } int iChecks = COVER_CHECKS; int iDelta = COVER_DELTA; // If we're limited in how far we're allowed to move laterally, don't bother checking past it int iMaxLateralDelta = GetOuter()->GetMaxTacticalLateralMovement(); if ( iMaxLateralDelta != MAXTACLAT_IGNORE && iMaxLateralDelta < iDelta ) { iChecks = 1; iDelta = iMaxLateralDelta; } Vector right; AngleVectors( GetLocalAngles(), NULL, &right, NULL ); vecStepRight = right * iDelta; vecStepRight.z = 0; vecLeftTest = vecRightTest = GetLocalOrigin(); vecCheckStart = vecThreat; for ( i = 0 ; i < iChecks; i++ ) { vecLeftTest = vecLeftTest - vecStepRight; vecRightTest = vecRightTest + vecStepRight; if (TestLateralLos( vecCheckStart, vecLeftTest )) { *pResult = vecLeftTest; return true; } if (TestLateralLos( vecCheckStart, vecRightTest )) { *pResult = vecRightTest; return true; } } return false; }
void CNPC_Dog::SetPlayerAvoidState( void ) { bool bIntersectingBoneFollowers = false; bool bIntersectingNPCBox = false; Vector vNothing; GetSequenceLinearMotion( GetSequence(), &vNothing ); bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); //If we are coming out of a script, check if we are stuck inside the player. if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) { trace_t trace; Vector vMins, vMaxs; Vector vWorldMins, vWorldMaxs; Vector vPlayerMins, vPlayerMaxs; physfollower_t *pBone; int i; #ifdef SecobMod__Enable_Fixed_Multiplayer_AI CBasePlayer *pLocalPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); #else CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); #endif //SecobMod__Enable_Fixed_Multiplayer_AI if ( pLocalPlayer ) { vWorldMins = WorldAlignMins(); vWorldMaxs = WorldAlignMaxs(); vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(); vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs(); // check if the player intersects the bounds of any of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) { bIntersectingBoneFollowers = true; break; } } } bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs ); if ( ai_debug_avoidancebounds.GetBool() ) { int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0; NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 ); // draw the bounds of the bone followers for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) { pBone = m_BoneFollowerManager.GetBoneFollower( i ); if ( pBone && pBone->hFollower ) { pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0; NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); } } } } } m_bPlayerAvoidState = ShouldPlayerAvoid(); m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers; if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) { if ( bIntersectingNPCBox == true ) { SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); } else { SetCollisionGroup( COLLISION_GROUP_NPC ); } if ( bIntersectingBoneFollowers == true ) { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR ); } else { MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC ); } } }
bool CNPC_Dog::FindPhysicsObject( const char *pPickupName, CBaseEntity *pIgnore ) { CBaseEntity *pEnt = NULL; CBaseEntity *pNearest = NULL; float flDist; IPhysicsObject *pPhysObj = NULL; float flNearestDist = 99999; if ( pPickupName != NULL && strlen( pPickupName ) > 0 ) { pEnt = gEntList.FindEntityByName( NULL, pPickupName ); if ( m_hUnreachableObjects.Find( pEnt ) == -1 ) { m_bHasObject = false; m_hPhysicsEnt = pEnt; return true; } } while ( ( pEnt = gEntList.FindEntityByClassname( pEnt, "prop_physics" ) ) != NULL ) { //We don't want this one. if ( pEnt == pIgnore ) continue; if ( m_hUnreachableObjects.Find( pEnt ) != -1 ) continue; pPhysObj = pEnt->VPhysicsGetObject(); if( pPhysObj == NULL ) continue; if ( pPhysObj->GetMass() > DOG_MAX_THROW_MASS ) continue; Vector center = pEnt->WorldSpaceCenter(); flDist = UTIL_DistApprox2D( GetAbsOrigin(), center ); vcollide_t *pCollide = modelinfo->GetVCollide( pEnt->GetModelIndex() ); if ( pCollide == NULL ) continue; if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) continue; if ( pPhysObj->IsMoveable() == false ) continue; if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_DEBRIS || pEnt->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) continue; if ( center.z > EyePosition().z ) continue; if ( flDist >= flNearestDist ) continue; if ( FVisible( pEnt ) == false ) continue; pNearest = pEnt; flNearestDist = flDist; } m_bHasObject = false; m_hPhysicsEnt = pNearest; if ( dog_debug.GetBool() == true ) { if ( pNearest ) NDebugOverlay::Box( pNearest->WorldSpaceCenter(), pNearest->CollisionProp()->OBBMins(), pNearest->CollisionProp()->OBBMaxs(), 255, 0, 255, true, 3 ); } if( m_hPhysicsEnt == NULL ) { return false; } else { return true; } }
void CBliinkPlayer::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 // Increasing damage based on the player's stats. fCurrentDamage *= GetBliinkPlayerStats().GetDamagePercent(); 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; #ifndef CLIENT_DLL CBliinkPlayer* pAttacker = static_cast<CBliinkPlayer*> ( pevAttacker ); int iActiveAmmo = GetAmmoDef()->Index( pAttacker->GetActiveWeapon()->GetWpnData().szAmmo1 ); int iAmmoSubtype = pAttacker->GetBliinkInventory().GetAmmoSubtype( iActiveAmmo ); switch( iAmmoSubtype ) { case ITEM_STYPE_AMMO_NORMAL: break; case ITEM_STYPE_AMMO_POISON: iDamageType &= DMG_POISON; break; case ITEM_STYPE_AMMO_FOGGED: iDamageType &= DMG_NERVEGAS; break; case ITEM_STYPE_AMMO_FIRE: iDamageType &= DMG_BURN; break; case ITEM_STYPE_AMMO_SLOW: iDamageType &= DMG_PARALYZE; break; } #endif 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; 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 }
void CASW_Weapon::ItemBusyFrame( void ) { CASW_Marine* pMarine = GetMarine(); if ( !pMarine ) return; bool bAttack1, bAttack2, bReload, bOldReload, bOldAttack1; GetButtons(bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 ); // check for clearing our weapon switching bool if (m_bSwitchingWeapons && gpGlobals->curtime > m_flNextPrimaryAttack) { m_bSwitchingWeapons = false; } // check for clearing our firing bool from reloading if (m_bInReload && gpGlobals->curtime > m_fReloadClearFiringTime) { ClearIsFiring(); } if ( (bReload && !bOldReload) && UsesClipsForAmmo1() && asw_fast_reload_enabled.GetBool() ) { if ( m_bInReload ) { // check for a fast reload //Msg("%f Check for fast reload while busy\n", gpGlobals->curtime); if (gpGlobals->curtime >= m_fFastReloadStart && gpGlobals->curtime <= m_fFastReloadEnd) { // todo: reduce next attack time m_fFastReloadEnd = 0; m_fFastReloadStart = 0; CBaseCombatCharacter *pOwner = GetOwner(); if ( pOwner ) { float flSucceedDelay = gpGlobals->curtime + 0.5f; pOwner->SetNextAttack( flSucceedDelay ); m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSucceedDelay; } // TODO: hook up anim //pMarine->DoAnimationEvent( PLAYERANIMEVENT_RELOAD_SUCCEED ); DispatchParticleEffect( "fast_reload", PATTACH_POINT_FOLLOW, this, "muzzle" ); pMarine->m_flPreventLaserSightTime = gpGlobals->curtime + 2.5f; #ifdef GAME_DLL pMarine->m_nFastReloadsInARow++; IGameEvent * event = gameeventmanager->CreateEvent( "fast_reload" ); if ( event ) { event->SetInt( "marine", pMarine->entindex() ); event->SetInt( "reloads", pMarine->m_nFastReloadsInARow ); gameeventmanager->FireEvent( event ); } if ( pMarine->m_nFastReloadsInARow >= 4 && pMarine->IsInhabited() ) { if ( pMarine->GetMarineResource() ) { pMarine->GetMarineResource()->m_bDidFastReloadsInARow = true; } if ( pMarine->GetCommander() ) { pMarine->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_FAST_RELOADS_IN_A_ROW ); } } #endif CSoundParameters params; if ( !GetParametersForSound( "FastReload.Success", params, NULL ) ) return; EmitSound_t playparams(params); playparams.m_nPitch = params.pitch; CASW_Player *pPlayer = GetCommander(); if ( pPlayer ) { CSingleUserRecipientFilter filter( pMarine->GetCommander() ); if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() ) { filter.UsePredictionRules(); } EmitSound(filter, entindex(), playparams); } //Msg("%f RELOAD SUCCESS! - bAttack1 = %d, bOldAttack1 = %d\n", gpGlobals->curtime, bAttack1, bOldAttack1 ); //Msg( "S: %f - %f - %f RELOAD SUCCESS! -- Progress = %f\n", gpGlobals->curtime, fFastStart, fFastEnd, flProgress ); #ifdef GAME_DLL pMarine->GetMarineSpeech()->PersonalChatter(CHATTER_SELECTION); #endif m_bFastReloadSuccess = true; m_bFastReloadFailure = false; } else if (m_fFastReloadStart != 0) { CSoundParameters params; if ( !GetParametersForSound( "FastReload.Miss", params, NULL ) ) return; EmitSound_t playparams(params); playparams.m_nPitch = params.pitch; CASW_Player *pPlayer = GetCommander(); if ( pPlayer ) { CSingleUserRecipientFilter filter( pMarine->GetCommander() ); if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() ) { filter.UsePredictionRules(); } EmitSound(filter, entindex(), playparams); } //Msg("%f RELOAD MISSED! - bAttack1 = %d, bOldAttack1 = %d\n", gpGlobals->curtime, bAttack1, bOldAttack1 ); //Msg( "S: %f - %f - %f RELOAD MISSED! -- Progress = %f\n", gpGlobals->curtime, fFastStart, fFastEnd, flProgress ); m_fFastReloadEnd = 0; m_fFastReloadStart = 0; CBaseCombatCharacter *pOwner = GetOwner(); if ( pOwner ) { float flMissDelay = MAX( gpGlobals->curtime + 2.0f, m_flNextPrimaryAttack + 1.0f ); pOwner->SetNextAttack( flMissDelay ); m_flNextPrimaryAttack = m_flNextSecondaryAttack = flMissDelay; m_flReloadFailTime = m_flNextPrimaryAttack - gpGlobals->curtime; } // TODO: hook up anim //pMarine->DoAnimationEvent( PLAYERANIMEVENT_RELOAD_FAIL ); #ifdef GAME_DLL pMarine->m_nFastReloadsInARow = 0; #endif DispatchParticleEffect( "reload_fail", PATTACH_POINT_FOLLOW, this, "muzzle" ); #ifdef GAME_DLL pMarine->GetMarineSpeech()->PersonalChatter(CHATTER_PAIN_SMALL); #endif m_bFastReloadSuccess = false; m_bFastReloadFailure = true; } } } #ifdef CLIENT_DLL if ( m_bInReload ) { float fStart = m_fReloadStart; float fNext = MAX( m_flNextPrimaryAttack, GetOwner() ? GetOwner()->GetNextAttack() : 0 ); float fTotalTime = fNext - fStart; if (fTotalTime <= 0) fTotalTime = 0.1f; m_fReloadProgress = (gpGlobals->curtime - fStart) / fTotalTime; } else { m_fReloadProgress = 0; } //Msg( "S: %f Reload Progress = %f\n", gpGlobals->curtime, m_fReloadProgress ); #endif //CLIENT_DLL }
HFont GetNetgraphFont() { return net_graphproportionalfont.GetBool() ? m_hFontProportional : m_hFont; }
void CASW_Weapon::PrimaryAttack( void ) { // If my clip is empty (and I use clips) start reload if ( UsesClipsForAmmo1() && !m_iClip1 ) { Reload(); return; } CASW_Player *pPlayer = GetCommander(); CASW_Marine *pMarine = GetMarine(); if ( !pMarine ) return; m_bIsFiring = true; // MUST call sound before removing a round from the clip of a CMachineGun WeaponSound(SINGLE); if (m_iClip1 <= AmmoClickPoint()) { LowAmmoSound(); } // tell the marine to tell its weapon to draw the muzzle flash pMarine->DoMuzzleFlash(); // sets the animation on the weapon model itself SendWeaponAnim( GetPrimaryAttackActivity() ); // sets the animation on the marine holding this weapon //pMarine->SetAnimation( PLAYER_ATTACK1 ); #ifdef GAME_DLL // check for turning on lag compensation if (pPlayer && pMarine->IsInhabited()) { CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() ); } #endif FireBulletsInfo_t info; info.m_vecSrc = pMarine->Weapon_ShootPosition( ); if ( pPlayer && pMarine->IsInhabited() ) { info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount()); // 45 degrees = 0.707106781187 } else { #ifdef CLIENT_DLL Msg("Error, clientside firing of a weapon that's being controlled by an AI marine\n"); #else info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc ); #endif } // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, // especially if the weapon we're firing has a really fast rate of fire. info.m_iShots = 0; float fireRate = GetFireRate(); while ( m_flNextPrimaryAttack <= gpGlobals->curtime ) { m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate; info.m_iShots++; if ( !fireRate ) break; } // Make sure we don't fire more than the amount in the clip if ( UsesClipsForAmmo1() ) { info.m_iShots = MIN( info.m_iShots, m_iClip1 ); m_iClip1 -= info.m_iShots; #ifdef GAME_DLL CASW_Marine *pMarine = GetMarine(); if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) { // check he doesn't have ammo in an ammo bay CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0)); if (!pAmmoBag) pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1)); if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this)) pMarine->OnWeaponOutOfAmmo(true); } #endif } else { info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) ); pMarine->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType ); } info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat(); info.m_iAmmoType = m_iPrimaryAmmoType; info.m_iTracerFreq = 1; // asw tracer test everytime info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat(); info.m_vecSpread = pMarine->GetActiveWeapon()->GetBulletSpread(); info.m_flDamage = GetWeaponDamage(); #ifndef CLIENT_DLL if (asw_debug_marine_damage.GetBool()) Msg("Weapon dmg = %f\n", info.m_flDamage); info.m_flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale(); if (asw_DebugAutoAim.GetBool()) { NDebugOverlay::Line(info.m_vecSrc, info.m_vecSrc + info.m_vecDirShooting * info.m_flDistance, 64, 0, 64, true, 1.0); } #endif pMarine->FireBullets( info ); // increment shooting stats #ifndef CLIENT_DLL if (pMarine && pMarine->GetMarineResource()) { pMarine->GetMarineResource()->UsedWeapon(this, info.m_iShots); pMarine->OnWeaponFired( this, info.m_iShots ); } #endif }
void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w, int graphtype ) { if ( !net_graphshowinterp.GetBool() || graphtype <= 1 ) return; int i; int j; int extrap_point; int a, h; vrect_t rcFill; ResetLineSegments(); extrap_point = LERP_HEIGHT / 3; for (a=0 ; a<w ; a++) { i = ( m_OutgoingSequence - a ) & ( TIMINGS - 1 ); h = MIN( ( cmdinfo[i].cmd_lerp / 3.0 ) * LERP_HEIGHT, LERP_HEIGHT ); rcFill.x = x + w -a - 1; rcFill.width = 1; rcFill.height = 1; rcFill.y = vrect.y + vrect.height - 4; if ( h >= extrap_point ) { int start = 0; h -= extrap_point; rcFill.y -= extrap_point; if ( !net_graphsolid.GetInt() ) { rcFill.y -= (h - 1); start = (h - 1); } for ( j = start; j < h; j++ ) { DrawLine(&rcFill, colors[j + extrap_point], 255 ); rcFill.y--; } } else { int oldh; oldh = h; rcFill.y -= h; h = extrap_point - h; if ( !net_graphsolid.GetInt() ) { h = 1; } for ( j = 0; j < h; j++ ) { DrawLine(&rcFill, colors[j + oldh], 255 ); rcFill.y--; } } rcFill.y = vrect.y + vrect.height - 4 - extrap_point; DrawLine( &rcFill, extrap_base_color, 255 ); rcFill.y = vrect.y + vrect.height - 3; if ( cmdinfo[ i ].sent ) { DrawLine( &rcFill, sendcolor, 255 ); } else { DrawLine( &rcFill, holdcolor, 200 ); } } DrawLineSegments(); }
//-------------------------------------------------------------------------------------------------------------- void CNavNode::CheckCrouch( void ) { CTraceFilterWalkableEntities filter( NULL, COLLISION_GROUP_PLAYER_MOVEMENT, WALK_THRU_EVERYTHING ); trace_t tr; // Trace downward from duck height to find the max floor height for the node's surroundings Vector mins( -HalfHumanWidth, -HalfHumanWidth, 0 ); Vector maxs( HalfHumanWidth, HalfHumanWidth, 0 ); Vector start( m_pos.x, m_pos.y, m_pos.z + VEC_DUCK_HULL_MAX.z - 0.1f ); UTIL_TraceHull( start, m_pos, mins, maxs, MASK_PLAYERSOLID_BRUSHONLY, &filter, &tr ); Vector groundPos = tr.endpos; if ( tr.startsolid && !tr.allsolid ) { // Try going down out of the solid and re-check for the floor height start.z -= tr.endpos.z - 0.1f; UTIL_TraceHull( start, m_pos, mins, maxs, MASK_PLAYERSOLID_BRUSHONLY, &filter, &tr ); groundPos = tr.endpos; } if ( tr.startsolid ) { // we don't even have duck height clear. try a simple check to find floor height. float x, y; // Find the highest floor z - for a player to stand in this area, we need a full // VEC_HULL_MAX.z of clearance above this height at all points. float maxFloorZ = m_pos.z; for( y = -HalfHumanWidth; y <= HalfHumanWidth + 0.1f; y += HalfHumanWidth ) { for( x = -HalfHumanWidth; x <= HalfHumanWidth + 0.1f; x += HalfHumanWidth ) { float floorZ; if ( TheNavMesh->GetGroundHeight( m_pos, &floorZ ) ) { maxFloorZ = max( maxFloorZ, floorZ + 0.1f ); } } } groundPos.Init( m_pos.x, m_pos.y, maxFloorZ ); } // For each direction, trace upwards from our best ground height to VEC_HULL_MAX.z to see if we have standing room. for ( int i=0; i<NUM_CORNERS; ++i ) { #if DEBUG_NAV_NODES if ( nav_test_node_crouch_dir.GetInt() != NUM_CORNERS && i != nav_test_node_crouch_dir.GetInt() ) continue; #endif // DEBUG_NAV_NODES NavCornerType corner = (NavCornerType)i; Vector2D cornerVec; CornerToVector2D( corner, &cornerVec ); Vector actualGroundPos = groundPos; // we might need to adjust this if the tracehull failed above and we fell back to m_pos.z // Build a mins/maxs pair for the HumanWidth x HalfHumanWidth box facing the appropriate direction mins.Init(); maxs.Init( cornerVec.x * HalfHumanWidth, cornerVec.y * HalfHumanWidth, 0 ); // now make sure that mins is smaller than maxs for ( int j=0; j<3; ++j ) { if ( mins[j] > maxs[j] ) { float tmp = mins[j]; mins[j] = maxs[j]; maxs[j] = tmp; } } UTIL_TraceHull( actualGroundPos + Vector( 0, 0, 0.1f ), actualGroundPos + Vector( 0, 0, VEC_HULL_MAX.z - 0.2f ), mins, maxs, MASK_PLAYERSOLID_BRUSHONLY, &filter, &tr ); actualGroundPos.z += tr.fractionleftsolid * VEC_HULL_MAX.z; float maxHeight = actualGroundPos.z + VEC_DUCK_HULL_MAX.z; for ( ; tr.startsolid && actualGroundPos.z <= maxHeight; actualGroundPos.z += 1.0f ) { // In case we didn't find a good ground pos above, we could start in the ground. Move us up some. UTIL_TraceHull( actualGroundPos + Vector( 0, 0, 0.1f ), actualGroundPos + Vector( 0, 0, VEC_HULL_MAX.z - 0.2f ), mins, maxs, MASK_PLAYERSOLID_BRUSHONLY, &filter, &tr ); } if (tr.startsolid || tr.fraction != 1.0f) { SetAttributes( NAV_MESH_CROUCH ); m_crouch[corner] = true; } #if DEBUG_NAV_NODES if ( nav_show_nodes.GetBool() ) { if ( nav_test_node_crouch_dir.GetInt() == i || nav_test_node_crouch_dir.GetInt() == NUM_CORNERS ) { if ( tr.startsolid ) { NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 255, 0, 0, 10, 20.0f ); } else if ( m_crouch[corner] ) { NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 0, 0, 255, 10, 20.0f ); } else { NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 0, 255, 0, 10, 10.0f ); } } } #endif // DEBUG_NAV_NODES } }
//----------------------------------------------------------------------------- // Purpose: Draws overlay text fields showing framerate, latency, bandwidth breakdowns, // and, optionally, packet loss and choked packet percentages // Input : graphvalue - // x - // y - // *graph - // *cmdinfo - // count - // avg - // *framerate - // 0.0 - // avg - //----------------------------------------------------------------------------- void CNetGraphPanel::DrawTextFields( int graphvalue, int x, int y, int w, netbandwidthgraph_t *graph, cmdinfo_t *cmdinfo ) { if ( !net_graphtext.GetBool() ) return; static int lastout; char sz[ 256 ]; int out; HFont font = GetNetgraphFont(); // Move rolling average m_Framerate = FRAMERATE_AVG_FRAC * m_Framerate + ( 1.0 - FRAMERATE_AVG_FRAC ) * gpGlobals->absoluteframetime; // Print it out y -= m_nNetGraphHeight; int saveY = y; if ( m_Framerate <= 0.0f ) m_Framerate = 1.0f; if ( engine->IsPlayingDemo() ) m_AvgLatency = 0.0f; int textTall = surface()->GetFontTall( font ); Q_snprintf( sz, sizeof( sz ), "fps:%4i ping: %i ms", (int)(1.0f / m_Framerate), (int)(m_AvgLatency*1000.0f) ); g_pMatSystemSurface->DrawColoredText( font, x, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); // Draw update rate DrawUpdateRate( x + w, y ); y += textTall; out = cmdinfo[ ( ( m_OutgoingSequence - 1 ) & ( TIMINGS - 1 ) ) ].size; if ( !out ) { out = lastout; } else { lastout = out; } int totalsize = graph[ ( m_IncomingSequence & ( TIMINGS - 1 ) ) ].msgbytes[INetChannelInfo::TOTAL]; Q_snprintf( sz, sizeof( sz ), "in :%4i %2.2f k/s ", totalsize, m_IncomingData ); int textWidth = g_pMatSystemSurface->DrawTextLen( font, "%s", sz ); g_pMatSystemSurface->DrawColoredText( font, x, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); Q_snprintf( sz, sizeof( sz ), "lerp: %5.1f ms", GetClientInterpAmount() * 1000.0f ); int interpcolor[ 3 ] = { GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE }; float flInterp = GetClientInterpAmount(); if ( flInterp > 0.001f ) { // Server framerate is lower than interp can possibly deal with if ( m_flServerFramerate < ( 1.0f / flInterp ) ) { interpcolor[ 0 ] = 255; interpcolor[ 1 ] = 255; interpcolor[ 2 ] = 31; } // flInterp is below recommended setting!!! else if ( flInterp < ( 2.0f / cl_updaterate->GetFloat() ) ) { interpcolor[ 0 ] = 255; interpcolor[ 1 ] = 125; interpcolor[ 2 ] = 31; } } g_pMatSystemSurface->DrawColoredText( font, x + textWidth, y, interpcolor[ 0 ], interpcolor[ 1 ], interpcolor[ 2 ], 255, sz ); Q_snprintf( sz, sizeof( sz ), "%3.1f/s", m_AvgPacketIn ); textWidth = g_pMatSystemSurface->DrawTextLen( font, "%s", sz ); g_pMatSystemSurface->DrawColoredText( font, x + w - textWidth - 1, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); y += textTall; Q_snprintf( sz, sizeof( sz ), "out:%4i %2.2f k/s", out, m_OutgoingData ); g_pMatSystemSurface->DrawColoredText( font, x, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); Q_snprintf( sz, sizeof( sz ), "%3.1f/s", m_AvgPacketOut ); textWidth = g_pMatSystemSurface->DrawTextLen( font, "%s", sz ); g_pMatSystemSurface->DrawColoredText( font, x + w - textWidth - 1, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); y += textTall; DrawCmdRate( x + w, y ); if ( graphvalue > 2 ) { Q_snprintf( sz, sizeof( sz ), "loss:%3i choke: %2i ", (int)(m_AvgPacketLoss*100.0f), (int)(m_AvgPacketChoke*100.0f) ); textWidth = g_pMatSystemSurface->DrawTextLen( font, "%s", sz ); g_pMatSystemSurface->DrawColoredText( font, x, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, sz ); y += textTall; if ( graphvalue > 3 ) { Q_snprintf( sz, sizeof( sz ), "sv : %5.1f var: %4.2f msec", m_flServerFramerate, m_flServerFramerateStdDeviation * 1000.0f ); int servercolor[ 3 ] = { GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE }; if ( m_flServerFramerate < 10.0f ) { servercolor[ 0 ] = 255; servercolor[ 1 ] = 31; servercolor[ 2 ] = 31; } else if ( m_flServerFramerate < 20.0f ) { servercolor[ 0 ] = 255; servercolor[ 1 ] = 255; servercolor[ 2 ] = 0; } g_pMatSystemSurface->DrawColoredText( font, x, y, servercolor[ 0 ], servercolor[ 1 ], servercolor[ 2 ], 255, sz ); y += textTall; } } // Draw legend if ( graphvalue >= 3 ) { int textTall = g_pMatSystemSurface->GetFontTall( m_hFontSmall ); y = saveY - textTall - 5; int cw, ch; g_pMatSystemSurface->GetTextSize( m_hFontSmall, L"otherplayersWWW", cw, ch ); if ( x - cw < 0 ) { x += w + 5; } else { x -= cw; } g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 0, 255, 255, "localplayer" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 255, 0, 255, "otherplayers" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 255, 0, 0, 255, "entities" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 255, 255, 0, 255, "sounds" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 255, 255, 255, "events" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 128, 128, 0, 255, "usermessages" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 128, 128, 255, "entmessages" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 128, 0, 0, 255, "stringcmds" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 128, 0, 255, "stringtables" ); y -= textTall; g_pMatSystemSurface->DrawColoredText( m_hFontSmall, x, y, 0, 0, 128, 255, "voice" ); y -= textTall; } }
//----------------------------------------------------------------------------- // Purpose: Do the headlight //----------------------------------------------------------------------------- void CFlashlightEffect::UpdateLightNew(const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp ) { VPROF_BUDGET( "CFlashlightEffect::UpdateLightNew", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ); FlashlightState_t state; // We will lock some of the flashlight params if player is on a ladder, to prevent oscillations due to the trace-rays bool bPlayerOnLadder = ( C_BasePlayer::GetLocalPlayer()->GetMoveType() == MOVETYPE_LADDER ); const float flEpsilon = 0.1f; // Offset flashlight position along vecUp const float flDistCutoff = 128.0f; const float flDistDrag = 0.2; CTraceFilterSkipPlayerAndViewModel traceFilter; float flOffsetY = r_flashlightoffsety.GetFloat(); if( r_swingflashlight.GetBool() ) { // This projects the view direction backwards, attempting to raise the vertical // offset of the flashlight, but only when the player is looking down. Vector vecSwingLight = vecPos + vecForward * -12.0f; if( vecSwingLight.z > vecPos.z ) { flOffsetY += (vecSwingLight.z - vecPos.z); } } Vector vOrigin = vecPos + flOffsetY * vecUp; // Not on ladder...trace a hull if ( !bPlayerOnLadder ) { trace_t pmOriginTrace; UTIL_TraceHull( vecPos, vOrigin, Vector(-4, -4, -4), Vector(4, 4, 4), MASK_SOLID & ~(CONTENTS_HITBOX), &traceFilter, &pmOriginTrace ); if ( pmOriginTrace.DidHit() ) { vOrigin = vecPos; } } else // on ladder...skip the above hull trace { vOrigin = vecPos; } // Now do a trace along the flashlight direction to ensure there is nothing within range to pull back from int iMask = MASK_OPAQUE_AND_NPCS; iMask &= ~CONTENTS_HITBOX; iMask |= CONTENTS_WINDOW; Vector vTarget = vecPos + vecForward * r_flashlightfar.GetFloat(); // Work with these local copies of the basis for the rest of the function Vector vDir = vTarget - vOrigin; Vector vRight = vecRight; Vector vUp = vecUp; VectorNormalize( vDir ); VectorNormalize( vRight ); VectorNormalize( vUp ); // Orthonormalize the basis, since the flashlight texture projection will require this later... vUp -= DotProduct( vDir, vUp ) * vDir; VectorNormalize( vUp ); vRight -= DotProduct( vDir, vRight ) * vDir; VectorNormalize( vRight ); vRight -= DotProduct( vUp, vRight ) * vUp; VectorNormalize( vRight ); AssertFloatEquals( DotProduct( vDir, vRight ), 0.0f, 1e-3 ); AssertFloatEquals( DotProduct( vDir, vUp ), 0.0f, 1e-3 ); AssertFloatEquals( DotProduct( vRight, vUp ), 0.0f, 1e-3 ); trace_t pmDirectionTrace; UTIL_TraceHull( vOrigin, vTarget, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmDirectionTrace ); if ( r_flashlightvisualizetrace.GetBool() == true ) { debugoverlay->AddBoxOverlay( pmDirectionTrace.endpos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 ); debugoverlay->AddLineOverlay( vOrigin, pmDirectionTrace.endpos, 255, 0, 0, false, 0 ); } float flDist = (pmDirectionTrace.endpos - vOrigin).Length(); if ( flDist < flDistCutoff ) { // We have an intersection with our cutoff range // Determine how far to pull back, then trace to see if we are clear float flPullBackDist = bPlayerOnLadder ? r_flashlightladderdist.GetFloat() : flDistCutoff - flDist; // Fixed pull-back distance if on ladder m_flDistMod = Lerp( flDistDrag, m_flDistMod, flPullBackDist ); if ( !bPlayerOnLadder ) { trace_t pmBackTrace; UTIL_TraceHull( vOrigin, vOrigin - vDir*(flPullBackDist-flEpsilon), Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), iMask, &traceFilter, &pmBackTrace ); if( pmBackTrace.DidHit() ) { // We have an intersection behind us as well, so limit our m_flDistMod float flMaxDist = (pmBackTrace.endpos - vOrigin).Length() - flEpsilon; if( m_flDistMod > flMaxDist ) m_flDistMod = flMaxDist; } } } else { m_flDistMod = Lerp( flDistDrag, m_flDistMod, 0.0f ); } vOrigin = vOrigin - vDir * m_flDistMod; state.m_vecLightOrigin = vOrigin; BasisToQuaternion( vDir, vRight, vUp, state.m_quatOrientation ); state.m_fQuadraticAtten = r_flashlightquadratic.GetFloat(); bool bFlicker = false; #ifdef HL2_EPISODIC C_BaseHLPlayer *pPlayer = (C_BaseHLPlayer *)C_BasePlayer::GetLocalPlayer(); if ( pPlayer ) { float flBatteryPower = ( pPlayer->m_HL2Local.m_flFlashBattery >= 0.0f ) ? ( pPlayer->m_HL2Local.m_flFlashBattery ) : pPlayer->m_HL2Local.m_flSuitPower; if ( flBatteryPower <= 10.0f ) { float flScale; if ( flBatteryPower >= 0.0f ) { flScale = ( flBatteryPower <= 4.5f ) ? SimpleSplineRemapVal( flBatteryPower, 4.5f, 0.0f, 1.0f, 0.0f ) : 1.0f; } else { flScale = SimpleSplineRemapVal( flBatteryPower, 10.0f, 4.8f, 1.0f, 0.0f ); } flScale = clamp( flScale, 0.0f, 1.0f ); if ( flScale < 0.35f ) { float flFlicker = cosf( gpGlobals->curtime * 6.0f ) * sinf( gpGlobals->curtime * 15.0f ); if ( flFlicker > 0.25f && flFlicker < 0.75f ) { // On state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale; } else { // Off state.m_fLinearAtten = 0.0f; } } else { float flNoise = cosf( gpGlobals->curtime * 7.0f ) * sinf( gpGlobals->curtime * 25.0f ); state.m_fLinearAtten = r_flashlightlinear.GetFloat() * flScale + 1.5f * flNoise; } state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) ); state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat() - ( 16.0f * (1.0f-flScale) ); bFlicker = true; } } #endif // HL2_EPISODIC if ( bFlicker == false ) { state.m_fLinearAtten = r_flashlightlinear.GetFloat(); state.m_fHorizontalFOVDegrees = r_flashlightfov.GetFloat(); state.m_fVerticalFOVDegrees = r_flashlightfov.GetFloat(); } state.m_fConstantAtten = r_flashlightconstant.GetFloat(); state.m_Color[0] = 1.0f; state.m_Color[1] = 1.0f; state.m_Color[2] = 1.0f; state.m_Color[3] = r_flashlightambient.GetFloat(); state.m_NearZ = r_flashlightnear.GetFloat() + m_flDistMod; // Push near plane out so that we don't clip the world when the flashlight pulls back state.m_FarZ = r_flashlightfar.GetFloat(); state.m_bEnableShadows = r_flashlightdepthtexture.GetBool(); state.m_flShadowMapResolution = r_flashlightdepthres.GetInt(); state.m_pSpotlightTexture = m_FlashlightTexture; state.m_nSpotlightTextureFrame = 0; state.m_flShadowAtten = r_flashlightshadowatten.GetFloat(); state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); if( m_FlashlightHandle == CLIENTSHADOW_INVALID_HANDLE ) { m_FlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } else { if( !r_flashlightlockposition.GetBool() ) { g_pClientShadowMgr->UpdateFlashlightState( m_FlashlightHandle, state ); } } g_pClientShadowMgr->UpdateProjectedTexture( m_FlashlightHandle, true ); // Kill the old flashlight method if we have one. LightOffOld(); #ifndef NO_TOOLFRAMEWORK if ( clienttools->IsInRecordingMode() ) { KeyValues *msg = new KeyValues( "FlashlightState" ); msg->SetFloat( "time", gpGlobals->curtime ); msg->SetInt( "entindex", m_nEntIndex ); msg->SetInt( "flashlightHandle", m_FlashlightHandle ); msg->SetPtr( "flashlightState", &state ); ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg ); msg->deleteThis(); } #endif }
//------------------------------------------------------------------------------ // Is color correction active? //------------------------------------------------------------------------------ bool CColorCorrectionMgr::HasNonZeroColorCorrectionWeights() const { return ( m_nActiveWeightCount != 0 ) || mat_colcorrection_editor.GetBool(); }
//----------------------------------------------------------------------------- // Purpose: Dust impact // Input : &origin - position // &tr - trace information //----------------------------------------------------------------------------- void FX_DustImpact( const Vector &origin, trace_t *tr, int iScale ) { if ( !fx_drawimpactdust.GetBool() ) return; #ifdef _XBOX // // XBox version // VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); Vector offset; float spread = 0.2f; CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" ); pSimple->SetSortOrigin( origin ); pSimple->GetBinding().SetBBox( origin - ( Vector( 32, 32, 32 ) * iScale ), origin + ( Vector( 32, 32, 32 ) * iScale ) ); Vector color; float colorRamp; GetColorForSurface( tr, &color ); int i; SimpleParticle *pParticle; for ( i = 0; i < 4; i++ ) { // Last puff is gritty (hides end) if ( i == 3 ) { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin ); } else { pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin ); } if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_vecVelocity.Random( -spread, spread ); pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) ); VectorNormalize( pParticle->m_vecVelocity ); float fForce = random->RandomFloat( 250, 500 ) * i; // scaled pParticle->m_vecVelocity *= fForce * iScale; colorRamp = random->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; // scaled pParticle->m_uchStartSize = iScale * random->RandomInt( 3, 4 ) * (i+1); // scaled pParticle->m_uchEndSize = iScale * pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 32, 255 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); if ( i == 3 ) { pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f ); pParticle->m_flDieTime = 0.5f; } else { pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f ); pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); } } } //Impact hit pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, origin ); if ( pParticle != NULL ) { offset = origin; offset[0] += random->RandomFloat( -8.0f, 8.0f ); offset[1] += random->RandomFloat( -8.0f, 8.0f ); pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f ); pParticle->m_vecVelocity.Init(); colorRamp = random->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 = random->RandomInt( 4, 8 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4; pParticle->m_uchStartAlpha = random->RandomInt( 32, 64 ); pParticle->m_uchEndAlpha = 0; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f ); } #else FX_DustImpact( origin, tr, (float)iScale ); #endif // _XBOX }
void CBaseAnimatingOverlay::StudioFrameAdvance () { float flAdvance = GetAnimTimeInterval(); VerifyOrder(); BaseClass::StudioFrameAdvance(); for ( int i = 0; i < m_AnimOverlay.Count(); i++ ) { CAnimationLayer *pLayer = &m_AnimOverlay[i]; if (pLayer->IsActive()) { // Assert( !m_AnimOverlay[ i ].IsAbandoned() ); if (pLayer->IsKillMe()) { if (pLayer->m_flKillDelay > 0) { pLayer->m_flKillDelay -= flAdvance; pLayer->m_flKillDelay = clamp( pLayer->m_flKillDelay, 0.0f, 1.0f ); } else if (pLayer->m_flWeight != 0.0f) { // give it at least one frame advance cycle to propagate 0.0 to client pLayer->m_flWeight -= pLayer->m_flKillRate * flAdvance; pLayer->m_flWeight = clamp( (float) pLayer->m_flWeight, 0.0f, 1.0f ); } else { // shift the other layers down in order if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) { Msg("removing %d (%d): %s : %5.3f (%.3f)\n", i, pLayer->m_nOrder.Get(), GetSequenceName( pLayer->m_nSequence ), pLayer->m_flCycle.Get(), pLayer->m_flWeight.Get() ); } FastRemoveLayer( i ); // needs at least one thing cycle dead to trigger sequence change pLayer->Dying(); continue; } } pLayer->StudioFrameAdvance( flAdvance, this ); if ( pLayer->m_bSequenceFinished && (pLayer->IsAutokill()) ) { pLayer->m_flWeight = 0.0f; pLayer->KillMe(); } } else if (pLayer->IsDying()) { pLayer->Dead(); } else if (pLayer->m_flWeight > 0.0) { // Now that the server blends, it is turning off layers all the time. Having a weight left over // when you're no longer marked as active is now harmless and commonplace. Just clean up. pLayer->Init( this ); pLayer->Dying(); } } if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) { for ( int i = 0; i < m_AnimOverlay.Count(); i++ ) { if (m_AnimOverlay[ i ].IsActive()) { /* if (m_AnimOverlay[ i ].IsAbandoned()) { Msg(" %d abandoned %.2f (%.2f)\n", i, gpGlobals->curtime, m_AnimOverlay[ i ].m_flLastAccess ); } */ Msg(" %d (%d): %s : %5.3f (%.3f)\n", i, m_AnimOverlay[ i ].m_nOrder.Get(), GetSequenceName( m_AnimOverlay[ i ].m_nSequence ), m_AnimOverlay[ i ].m_flCycle.Get(), m_AnimOverlay[ i ].m_flWeight.Get() ); } } } VerifyOrder(); }
bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll ) { if ( g_RagdollLVManager.IsLowViolence() ) { return true; } #ifdef CLIENT_DLL /* we no longer ignore enemies just because they are on fire -- a ragdoll in front of me is always a higher priority for retention than a flaming zombie behind me. At the time I put this in, the ragdolls do clean up their own effects if culled via SUB_Remove(). If you're encountering trouble with ragdolls leaving effects behind, try renabling the code below. ///////////////////// //Just ignore it until we're done burning/dissolving. if ( pRagdoll->GetEffectEntity() ) return false; */ Vector vMins, vMaxs; Vector origin = pRagdoll->m_pRagdoll->GetRagdollOrigin(); pRagdoll->m_pRagdoll->GetRagdollBounds( vMins, vMaxs ); if( engine->IsBoxInViewCluster( vMins + origin, vMaxs + origin) == false ) { if ( g_debug_ragdoll_removal.GetBool() ) { debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 255, 0, 16, 5 ); debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 ); } return true; } else if( engine->CullBox( vMins + origin, vMaxs + origin ) == true ) { if ( g_debug_ragdoll_removal.GetBool() ) { debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 0, 255, 16, 5 ); debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 ); } return true; } #else // CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if( !UTIL_FindClientInPVS( pRagdoll->edict() ) ) { if ( g_debug_ragdoll_removal.GetBool() ) NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 ); return true; } /* else if( !pPlayer->FInViewCone( pRagdoll ) ) { if ( g_debug_ragdoll_removal.GetBool() ) NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 ); return true; }*/ #endif return false; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CNPC_Blob::RunAI() { BaseClass::RunAI(); if( !m_bInitialized ) { // m_bInitialized is set to false in the constructor. So this bit of // code runs one time, the first time I think. Msg("I need to initialize\n"); InitializeElements(); m_bInitialized = true; return; } int iIdealNumElements = blob_numelements.GetInt(); if( iIdealNumElements != m_iNumElements ) { int delta = iIdealNumElements - m_iNumElements; if( delta < 0 ) { delta = -delta; delta = MIN(delta, 5 ); RemoveExcessElements( delta ); if( m_iReconfigureElement > m_iNumElements ) { // Start this index over at zero, if it is past the new end of the utlvector. m_iReconfigureElement = 0; } } else { delta = MIN(delta, 5 ); AddNewElements( delta ); } RecomputeIdealElementDist(); } ComputeCentroid(); if( npc_blob_show_centroid.GetBool() ) { NDebugOverlay::Cross3D( m_vecCentroid + Vector( 0, 0, 12 ), 32, 0, 255, 0, false, 0.025f ); } if( npc_blob_use_threading.GetBool() ) { IterRangeParallel( this, &CNPC_Blob::DoBlobBatchedAI, 0, m_Elements.Count() ); } else { DoBlobBatchedAI( 0, m_Elements.Count() ); } if( GetEnemy() != NULL ) { float flEnemyDistSqr = m_vecCentroid.DistToSqr( GetEnemy()->GetAbsOrigin() ); if( flEnemyDistSqr <= Square( 32.0f ) ) { if( GetEnemy()->Classify() == CLASS_COMBINE ) { if( !m_bEatCombineHack ) { variant_t var; var.SetFloat( 0 ); g_EventQueue.AddEvent( GetEnemy(), "HitByBugBait", 0.0f, this, this ); g_EventQueue.AddEvent( GetEnemy(), "SetHealth", var, 3.0f, this, this ); m_bEatCombineHack = true; blob_radius.SetValue( 48.0f ); RecomputeIdealElementDist(); } } else { CTakeDamageInfo info; info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamage( 5 ); info.SetDamageType( DMG_SLASH ); info.SetDamageForce( Vector( 0, 0, 1 ) ); GetEnemy()->TakeDamage( info ); } } } SetNextThink( gpGlobals->curtime + npc_blob_think_interval.GetFloat() ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFGrenadeEmpProjectile::Detonate() { if ( ShouldNotDetonate() ) { RemoveGrenade(); return; } // Explosion effect on client // SendDispatchEffect(); float flRadius = 180; float flDamage = 1; if ( tf_grenade_show_radius.GetBool() ) { DrawRadius( flRadius ); } // Apply some amount of EMP damage to every entity in the radius. They will calculate // their own damage based on how much ammo they have or some other wacky calculation. CTakeDamageInfo info( this, GetThrower(), vec3_origin, GetAbsOrigin(), flDamage, /* DMG_EMP |*/ DMG_PREVENT_PHYSICS_FORCE ); CBaseEntity *pEntityList[100]; int nEntityCount = UTIL_EntitiesInSphere( pEntityList, 100, GetAbsOrigin(), flRadius, 0 ); int iEntity; for ( iEntity = 0; iEntity < nEntityCount; ++iEntity ) { CBaseEntity *pEntity = pEntityList[iEntity]; if ( pEntity == this ) continue; if ( pEntity && pEntity->IsPlayer() ) continue; if ( pEntity && ( pEntity->m_takedamage == DAMAGE_YES || pEntity->m_takedamage == DAMAGE_EVENTS_ONLY ) ) { pEntity->TakeDamage( info ); //if ( pEntity->IsPlayer() /* || is ammo box || is enemy object */ ) { CBeam *pBeam = CBeam::BeamCreate( "sprites/physcannon_bluelight1b.vmt", 3.0 ); if ( !pBeam ) return; pBeam->PointsInit( GetAbsOrigin(), pEntity->WorldSpaceCenter() ); pBeam->SetColor( 255, 255, 255 ); pBeam->SetBrightness( 128 ); pBeam->SetNoise( 12.0f ); pBeam->SetEndWidth( 3.0f ); pBeam->SetWidth( 3.0f ); pBeam->LiveForTime( 0.5f ); // Fail-safe pBeam->SetFrameRate( 25.0f ); pBeam->SetFrame( random->RandomInt( 0, 2 ) ); } } } DispatchParticleEffect( "emp_shockwave", GetAbsOrigin(), vec3_angle ); UTIL_Remove( this ); #if 0 // Tell the bots an HE grenade has exploded CTFPlayer *pPlayer = ToTFPlayer( GetThrower() ); if ( pPlayer ) { KeyValues *pEvent = new KeyValues( "tf_weapon_grenade_detonate" ); pEvent->SetInt( "userid", pPlayer->GetUserID() ); gameeventmanager->FireEventServerOnly( pEvent ); } #endif }
//----------------------------------------------------------------------------- // Run all of the AI for elements within the range iStart to iEnd //----------------------------------------------------------------------------- void CNPC_Blob::DoBlobBatchedAI( int iStart, int iEnd ) { float flInterval = gpGlobals->curtime - GetLastThink(); // Local fields for sin-wave movement variance float flMySine; float flAmplitude = npc_blob_sin_amplitude.GetFloat(); float flMyAmplitude; Vector vecRight; Vector vecForward; // Local fields for attract/repel float minDistSqr = Square( m_flMinElementDist ); float flBlobSpeed = blob_element_speed.GetFloat(); float flSpeed; // Local fields for speed limiting float flMinSpeed = blob_element_speed.GetFloat() * 0.5f; float flMaxSpeed = blob_element_speed.GetFloat() * 1.5f; bool bEnforceSpeedLimit; bool bEnforceRelativePositions; bool bDoMovementVariation; bool bDoOrientation = npc_blob_use_orientation.GetBool(); float flIdleSpeedFactor = npc_blob_idle_speed_factor.GetFloat(); // Group cohesion float flBlobRadiusSqr = Square( blob_radius.GetFloat() + 48.0f ); // Four feet of fudge // Build a right-hand vector along which we'll add some sine wave data to give each // element a unique insect-like undulation along an axis perpendicular to their path, // which makes the entire group look far less orderly if( GetEnemy() != NULL ) { // If I have an enemy, the right-hand vector is perpendicular to a straight line // from the group's centroid to the enemy's origin. vecForward = GetEnemy()->GetAbsOrigin() - m_vecCentroid; VectorNormalize( vecForward ); vecRight.x = vecForward.y; vecRight.y = -vecForward.x; } else { // If there is no enemy, wobble along the axis from the centroid to me. vecForward = GetAbsOrigin() - m_vecCentroid; VectorNormalize( vecForward ); vecRight.x = vecForward.y; vecRight.y = -vecForward.x; } //-- // MAIN LOOP - Run all of the elements in the set iStart to iEnd //-- for( int i = iStart ; i < iEnd ; i++ ) { CBlobElement *pThisElement = m_Elements[ i ]; //-- // Initial movement //-- // Start out with bEnforceSpeedLimit set to false. This is because an element // can't overspeed if it's moving undisturbed towards its target entity or // target location. An element can only under or overspeed when it is repelled // by multiple other elements in the group. See "Relative Positions" below. // // Initialize some 'defaults' that may be changed for each iteration of this loop bEnforceSpeedLimit = false; bEnforceRelativePositions = true; bDoMovementVariation = true; flSpeed = flBlobSpeed; switch( pThisElement->GetActiveMovementRule() ) { case BLOB_MOVE_DONT_MOVE: { pThisElement->SetElementVelocity( vec3_origin, true ); trace_t tr; Vector vecOrigin = pThisElement->GetAbsOrigin(); UTIL_TraceLine( vecOrigin, vecOrigin - Vector( 0, 0, 16), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if( tr.fraction < 1.0f ) { QAngle angles; VectorAngles( tr.plane.normal, angles ); float flSwap = angles.x; angles.x = -angles.y; angles.y = flSwap; pThisElement->SetAbsAngles( angles ); } } continue; break; case BLOB_MOVE_TO_TARGET_LOCATION: { Vector vecDiff = pThisElement->GetAbsOrigin() - pThisElement->m_vecTargetLocation; if( vecDiff.Length2DSqr() <= Square(80.0f) ) { // Don't shove this guy around any more, let him get to his goal position. flSpeed *= 0.5f; bEnforceRelativePositions = false; bDoMovementVariation = false; } pThisElement->MoveTowardsTargetLocation( flSpeed ); } break; case BLOB_MOVE_TO_TARGET_ENTITY: { if( !IsMoving() && GetEnemy() == NULL ) { if( pThisElement->GetAbsOrigin().DistToSqr( GetAbsOrigin() ) <= flBlobRadiusSqr ) { flSpeed = (flSpeed * flIdleSpeedFactor) * pThisElement->m_flRandomEightyPercent; } } pThisElement->MoveTowardsTargetEntity( flSpeed ); } break; default: Msg("ERROR: Blob Element with unspecified Movement Rule\n"); break; } //--- // Relative positions //-- // Check this element against ALL other elements. If the two elements are closer // than the allowed minimum distance, repel this element away. (The other element // will repel when its AI runs). A single element can be repelled by many other // elements. This is why bEnforceSpeedLimit is set to true if any of the repelling // code runs for this element. Multiple attempts to repel an element in the same // direction will cause overspeed. Conflicting attempts to repel an element in opposite // directions will cause underspeed. Vector vecDir = Vector( 0, 0, 0 ); Vector vecThisElementOrigin = pThisElement->GetAbsOrigin(); if( bEnforceRelativePositions ) { for( int j = 0 ; j < m_Elements.Count() ; j++ ) { // This is the innermost loop! We should optimize here, if anywhere. // If this element is on the wall, then don't be repelled by anyone. Repelling // elements that are trying to climb a wall usually make them look like they // fall off the wall a few times while climbing. if( pThisElement->m_bOnWall ) continue; CBlobElement *pThatElement = m_Elements[ j ]; if( i != j ) { Vector vecThatElementOrigin = pThatElement->GetAbsOrigin(); float distSqr = vecThisElementOrigin.DistToSqr( vecThatElementOrigin ); if( distSqr < minDistSqr ) { // Too close to the other element. Move away. float flRepelSpeed; Vector vecRepelDir = ( vecThisElementOrigin - vecThatElementOrigin ); vecRepelDir.NormalizeInPlace(); flRepelSpeed = (flSpeed * ( 1.0f - ( distSqr / minDistSqr ) ) ) * pThatElement->GetSinePhase(); pThisElement->AddElementVelocity( vecRepelDir * flRepelSpeed, true ); // Since we altered this element's velocity after it was initially set, there's a chance // that the sums of multiple vectors will cause the element to over or underspeed, so // mark it for speed limit enforcement bEnforceSpeedLimit = true; } } } } //-- // Movement variation //-- if( bDoMovementVariation ) { flMySine = sin( gpGlobals->curtime * pThisElement->GetSineFrequency() ); flMyAmplitude = flAmplitude * pThisElement->GetSineAmplitude(); pThisElement->AddElementVelocity( vecRight * (flMySine * flMyAmplitude), true ); } // Avoidance for( int a = 0 ; a < m_iNumAvoidOrigins ; a++ ) { Vector vecAvoidDir = pThisElement->GetAbsOrigin() - m_vecAvoidOrigin[ a ]; if( vecAvoidDir.LengthSqr() <= (m_flAvoidRadiusSqr * pThisElement->m_flRandomEightyPercent) ) { VectorNormalize( vecAvoidDir ); pThisElement->AddElementVelocity( vecAvoidDir * (flSpeed * 2.0f), true ); break; } } //-- // Speed limits //--- if( bEnforceSpeedLimit == true ) { pThisElement->EnforceSpeedLimits( flMinSpeed, flMaxSpeed ); } //-- // Wall crawling //-- pThisElement->ModifyVelocityForSurface( flInterval, flSpeed ); // For identifying stuck elements. pThisElement->m_vecPrevOrigin = pThisElement->GetAbsOrigin(); pThisElement->m_flDistFromCentroidSqr = pThisElement->m_vecPrevOrigin.DistToSqr( m_vecCentroid ); // Orientation if( bDoOrientation ) { QAngle angles; VectorAngles( pThisElement->GetAbsVelocity(), angles ); pThisElement->SetAbsAngles( angles ); } /* //-- // Stragglers/Group integrity // if( pThisElement->m_flDistFromCentroidSqr > flStragglerDistSqr ) { NDebugOverlay::Line( pThisElement->GetAbsOrigin(), m_vecCentroid, 255, 0, 0, false, 0.025f ); } */ } }
void CASW_Parasite::InfestColonist(CASW_Colonist* pColonist) { if (m_bDefanged || !pColonist) // no infesting if we've been defanged return; if (!IsOnFire()) // don't actually infest if we're on fire, since we'll die very shortly pColonist->BecomeInfested(this); // attach int attachment = pColonist->LookupAttachment( "chest" ); if ( attachment ) { //SetAbsAngles( GetOwnerEntity()->GetAbsAngles() ); SetSolid( SOLID_NONE ); SetMoveType( MOVETYPE_NONE ); QAngle current(0,0,0); Vector diff = pColonist->GetAbsOrigin() - GetAbsOrigin(); float angle = UTIL_VecToYaw(diff); angle -= pColonist->GetAbsAngles()[YAW]; // get the diff between our angle from the marine and the marine's facing; current = GetAbsAngles(); Vector vAttachmentPos; pColonist->GetAttachment( attachment, vAttachmentPos ); Teleport( &vAttachmentPos, &vec3_angle, &vec3_origin ); SetParent( pColonist, attachment ); Vector vecPosition; float flRaise = RandomFloat( 12.0f, 15.0f ); float flForward = RandomFloat( -1.0f, 0.0f ); float flSide = RandomFloat( 0.0f, 0.2f ) * ( RandomInt( 0, 1 ) == 0 ? 1.0f : -1.0f ); SetLocalOrigin( Vector( flForward, flSide, flRaise ) ); SetLocalAngles( QAngle( asw_infest_pitch.GetFloat(), angle + asw_infest_angle.GetFloat(), 0 ) ); // play our infesting anim if ( asw_parasite_inside.GetBool() ) { SetActivity(ACT_RANGE_ATTACK2); } else { int iInfestAttack = LookupSequence("Infest_attack"); if (GetSequence() != iInfestAttack) { ResetSequence(iInfestAttack); } } // don't do anymore thinking - need to think still to animate? AddFlag( FL_NOTARGET ); SetThink( &CASW_Parasite::InfestThink ); SetTouch( NULL ); m_bInfesting = true; } else { FinishedInfesting(); } }
void DrawPassComposite( const defParms_composite &info, CBaseVSShader *pShader, IMaterialVar **params, IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CDeferredPerMaterialContextData *pDeferredContext ) { const bool bModel = info.bModel; const bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL ); const bool bFastVTex = g_pHardwareConfig->HasFastVertexTextures(); const bool bAlbedo = PARM_TEX( info.iAlbedo ); const bool bAlbedo2 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo2 ); const bool bAlbedo3 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo3 ); const bool bAlbedo4 = !bModel && bAlbedo && PARM_TEX( info.iAlbedo4 ); const bool bAlphatest = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) && bAlbedo; const bool bTranslucent = IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ) && bAlbedo && !bAlphatest; const bool bNoCull = IS_FLAG_SET( MATERIAL_VAR_NOCULL ); const bool bUseSRGB = DEFCFG_USE_SRGB_CONVERSION != 0; const bool bPhongFresnel = PARM_SET( info.iPhongFresnel ); const bool bEnvmap = PARM_TEX( info.iEnvmap ); const bool bEnvmapMask = bEnvmap && PARM_TEX( info.iEnvmapMask ); const bool bEnvmapMask2 = bEnvmapMask && PARM_TEX( info.iEnvmapMask2 ); const bool bEnvmapFresnel = bEnvmap && PARM_SET( info.iEnvmapFresnel ); const bool bRimLight = PARM_SET( info.iRimlightEnable ); const bool bRimLightModLight = bRimLight && PARM_SET( info.iRimlightModLight ); const bool bBlendmodulate = bAlbedo2 && PARM_TEX( info.iBlendmodulate ); const bool bBlendmodulate2 = bBlendmodulate && PARM_TEX( info.iBlendmodulate2 ); const bool bBlendmodulate3 = bBlendmodulate && PARM_TEX( info.iBlendmodulate3 ); const bool bSelfIllum = !bAlbedo2 && IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ); const bool bSelfIllumMaskInEnvmapMask = bSelfIllum && bEnvmapMask && PARM_SET( info.iSelfIllumMaskInEnvmapAlpha ); const bool bSelfIllumMask = bSelfIllum && !bSelfIllumMaskInEnvmapMask && !bEnvmapMask && PARM_TEX( info.iSelfIllumMask ); const bool bMultiBlend = PARM_SET( info.iMultiblend ) && bAlbedo && bAlbedo2 && bAlbedo3 && !bEnvmapMask && !bSelfIllumMask; const bool bNeedsFresnel = bPhongFresnel || bEnvmapFresnel; const bool bGBufferNormal = bEnvmap || bRimLight || bNeedsFresnel; const bool bWorldEyeVec = bGBufferNormal; AssertMsgOnce( !(bTranslucent || bAlphatest) || !bAlbedo2, "blended albedo not supported by gbuffer pass!" ); AssertMsgOnce( IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) == false, "Normal map sampling should stay out of composition pass." ); AssertMsgOnce( !PARM_TEX( info.iSelfIllumMask ) || !bEnvmapMask, "Can't use separate selfillum mask with envmap mask - use SELFILLUM_ENVMAPMASK_ALPHA instead." ); AssertMsgOnce( PARM_SET( info.iMultiblend ) == bMultiBlend, "Multiblend forced off due to invalid usage! May cause vertexformat mis-matches between passes." ); SHADOW_STATE { pShaderShadow->SetDefaultState(); pShaderShadow->EnableSRGBWrite( bUseSRGB ); if ( bNoCull ) { pShaderShadow->EnableCulling( false ); } int iVFmtFlags = VERTEX_POSITION; int iUserDataSize = 0; int *pTexCoordDim; int iTexCoordNum; GetTexcoordSettings( ( bModel && bIsDecal && bFastVTex ), bMultiBlend, iTexCoordNum, &pTexCoordDim ); if ( bModel ) { iVFmtFlags |= VERTEX_NORMAL; iVFmtFlags |= VERTEX_FORMAT_COMPRESSED; } else { if ( bAlbedo2 ) iVFmtFlags |= VERTEX_COLOR; } pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bUseSRGB ); if ( bGBufferNormal ) { pShaderShadow->EnableTexture( SHADER_SAMPLER1, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, false ); } if ( bTranslucent ) { pShader->EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA ); } pShaderShadow->EnableTexture( SHADER_SAMPLER2, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false ); if ( bEnvmap ) { pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); if( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ) pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, true ); if ( bEnvmapMask ) { pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); if ( bAlbedo2 ) pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); } } else if ( bSelfIllumMask ) { pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); } if ( bAlbedo2 ) { pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, bUseSRGB ); if ( bBlendmodulate ) pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); } if ( bMultiBlend ) { pShaderShadow->EnableTexture( SHADER_SAMPLER7, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER7, bUseSRGB ); if ( bAlbedo4 ) { pShaderShadow->EnableTexture( SHADER_SAMPLER8, true ); pShaderShadow->EnableSRGBRead( SHADER_SAMPLER8, bUseSRGB ); } if ( bBlendmodulate ) { pShaderShadow->EnableTexture( SHADER_SAMPLER9, true ); pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); } } pShaderShadow->EnableAlphaWrites( false ); pShaderShadow->EnableDepthWrites( !bTranslucent ); pShader->DefaultFog(); pShaderShadow->VertexShaderVertexFormat( iVFmtFlags, iTexCoordNum, pTexCoordDim, iUserDataSize ); DECLARE_STATIC_VERTEX_SHADER( composite_vs30 ); SET_STATIC_VERTEX_SHADER_COMBO( MODEL, bModel ); SET_STATIC_VERTEX_SHADER_COMBO( MORPHING_VTEX, bModel && bFastVTex ); SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bModel && bIsDecal ); SET_STATIC_VERTEX_SHADER_COMBO( EYEVEC, bWorldEyeVec ); SET_STATIC_VERTEX_SHADER_COMBO( BASETEXTURE2, bAlbedo2 && !bMultiBlend ); SET_STATIC_VERTEX_SHADER_COMBO( BLENDMODULATE, bBlendmodulate ); SET_STATIC_VERTEX_SHADER_COMBO( MULTIBLEND, bMultiBlend ); SET_STATIC_VERTEX_SHADER( composite_vs30 ); DECLARE_STATIC_PIXEL_SHADER( composite_ps30 ); SET_STATIC_PIXEL_SHADER_COMBO( ALPHATEST, bAlphatest ); SET_STATIC_PIXEL_SHADER_COMBO( TRANSLUCENT, bTranslucent ); SET_STATIC_PIXEL_SHADER_COMBO( READNORMAL, bGBufferNormal ); SET_STATIC_PIXEL_SHADER_COMBO( NOCULL, bNoCull ); SET_STATIC_PIXEL_SHADER_COMBO( ENVMAP, bEnvmap ); SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPMASK, bEnvmapMask ); SET_STATIC_PIXEL_SHADER_COMBO( ENVMAPFRESNEL, bEnvmapFresnel ); SET_STATIC_PIXEL_SHADER_COMBO( PHONGFRESNEL, bPhongFresnel ); SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, bRimLight ); SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHTMODULATELIGHT, bRimLightModLight ); SET_STATIC_PIXEL_SHADER_COMBO( BASETEXTURE2, bAlbedo2 && !bMultiBlend ); SET_STATIC_PIXEL_SHADER_COMBO( BLENDMODULATE, bBlendmodulate ); SET_STATIC_PIXEL_SHADER_COMBO( MULTIBLEND, bMultiBlend ); SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, bSelfIllum ); SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_MASK, bSelfIllumMask ); SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM_ENVMAP_ALPHA, bSelfIllumMaskInEnvmapMask ); SET_STATIC_PIXEL_SHADER( composite_ps30 ); } DYNAMIC_STATE { Assert( pDeferredContext != NULL ); if ( pDeferredContext->m_bMaterialVarsChanged || !pDeferredContext->HasCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE ) || building_cubemaps.GetBool() ) { tmpBuf.Reset(); if ( bAlphatest ) { PARM_VALIDATE( info.iAlphatestRef ); tmpBuf.SetPixelShaderConstant1( 0, PARM_FLOAT( info.iAlphatestRef ) ); } if ( bAlbedo ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER0, info.iAlbedo ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY ); if ( bEnvmap ) { if ( building_cubemaps.GetBool() ) tmpBuf.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_BLACK ); else { if ( PARM_TEX( info.iEnvmap ) && !bModel ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER3, info.iEnvmap ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_LOCAL_ENV_CUBEMAP ); } if ( bEnvmapMask ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER4, info.iEnvmapMask ); if ( bAlbedo2 ) { if ( bEnvmapMask2 ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER7, info.iEnvmapMask2 ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_WHITE ); } tmpBuf.SetPixelShaderConstant( 5, info.iEnvmapTint ); float fl6[4] = { 0 }; fl6[0] = PARM_FLOAT( info.iEnvmapSaturation ); fl6[1] = PARM_FLOAT( info.iEnvmapContrast ); tmpBuf.SetPixelShaderConstant( 6, fl6 ); } if ( bNeedsFresnel ) { tmpBuf.SetPixelShaderConstant( 7, info.iFresnelRanges ); } if ( bRimLight ) { float fl9[4] = { 0 }; fl9[0] = PARM_FLOAT( info.iRimlightExponent ); fl9[1] = PARM_FLOAT( info.iRimlightAlbedoScale ); tmpBuf.SetPixelShaderConstant( 9, fl9 ); } if ( bAlbedo2 ) { tmpBuf.BindTexture( pShader, SHADER_SAMPLER5, info.iAlbedo2 ); if ( bBlendmodulate ) { tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, info.iBlendmodulateTransform ); tmpBuf.BindTexture( pShader, SHADER_SAMPLER6, info.iBlendmodulate ); } } if ( bMultiBlend ) { tmpBuf.BindTexture( pShader, SHADER_SAMPLER7, info.iAlbedo3 ); if ( bAlbedo4 ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER8, info.iAlbedo4 ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER8, TEXTURE_WHITE ); if ( bBlendmodulate ) { tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_3, info.iBlendmodulateTransform2 ); tmpBuf.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_5, info.iBlendmodulateTransform3 ); if ( bBlendmodulate2 ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER9, info.iBlendmodulate2 ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER9, TEXTURE_BLACK ); if ( bBlendmodulate3 ) tmpBuf.BindTexture( pShader, SHADER_SAMPLER10, info.iBlendmodulate3 ); else tmpBuf.BindStandardTexture( SHADER_SAMPLER10, TEXTURE_BLACK ); } } if ( bSelfIllum && bSelfIllumMask ) { tmpBuf.BindTexture( pShader, SHADER_SAMPLER4, info.iSelfIllumMask ); } int x, y, w, t; pShaderAPI->GetCurrentViewport( x, y, w, t ); float fl1[4] = { 1.0f / w, 1.0f / t, 0, 0 }; tmpBuf.SetPixelShaderConstant( 1, fl1 ); tmpBuf.SetPixelShaderFogParams( 2 ); float fl4 = { PARM_FLOAT( info.iPhongScale ) }; tmpBuf.SetPixelShaderConstant1( 4, fl4 ); tmpBuf.End(); pDeferredContext->SetCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE, tmpBuf.Copy() ); } pShaderAPI->SetDefaultState(); if ( bModel && bFastVTex ) pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, VERTEX_SHADER_SHADER_SPECIFIC_CONST_11, SHADER_VERTEXTEXTURE_SAMPLER0 ); DECLARE_DYNAMIC_VERTEX_SHADER( composite_vs30 ); SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (bModel && (int)vertexCompression) ? 1 : 0 ); SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, (bModel && pShaderAPI->GetCurrentNumBones() > 0) ? 1 : 0 ); SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, (bModel && pShaderAPI->IsHWMorphingEnabled()) ? 1 : 0 ); SET_DYNAMIC_VERTEX_SHADER( composite_vs30 ); DECLARE_DYNAMIC_PIXEL_SHADER( composite_ps30 ); SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); SET_DYNAMIC_PIXEL_SHADER( composite_ps30 ); if ( bModel && bFastVTex ) { bool bUnusedTexCoords[3] = { false, true, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; pShaderAPI->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords ); } pShaderAPI->ExecuteCommandBuffer( pDeferredContext->GetCommands( CDeferredPerMaterialContextData::DEFSTAGE_COMPOSITE ) ); if ( bGBufferNormal ) pShader->BindTexture( SHADER_SAMPLER1, GetDeferredExt()->GetTexture_Normals() ); pShader->BindTexture( SHADER_SAMPLER2, GetDeferredExt()->GetTexture_LightAccum() ); CommitBaseDeferredConstants_Origin( pShaderAPI, 3 ); if ( bWorldEyeVec ) { float vEyepos[4] = {0,0,0,0}; pShaderAPI->GetWorldSpaceCameraPosition( vEyepos ); pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, vEyepos ); } if ( bRimLight ) { pShaderAPI->SetPixelShaderConstant( 8, params[ info.iRimlightTint ]->GetVecValue() ); } if ( bSelfIllum ) { pShaderAPI->SetPixelShaderConstant( 10, params[ info.iSelfIllumTint ]->GetVecValue() ); } } pShader->Draw(); }